aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Wollman <wollman@FreeBSD.org>1994-09-29 23:04:24 +0000
committerGarrett Wollman <wollman@FreeBSD.org>1994-09-29 23:04:24 +0000
commitdaa35edbd086b27357d8f048ede7c84dcc520748 (patch)
tree8dd520f3dfb7df4f73618d886e20c1154f3e5e5f
parentd2d2eed18837c57f97405aa88134457f8d97640d (diff)
downloadsrc-daa35edbd086b27357d8f048ede7c84dcc520748.tar.gz
src-daa35edbd086b27357d8f048ede7c84dcc520748.zip
xntp 3.4e from Dave Mills @ UDel
Notes
Notes: svn path=/vendor/ntpd/dist/; revision=3215
-rw-r--r--usr.sbin/xntpd/COPYRIGHT10
-rw-r--r--usr.sbin/xntpd/Config.local96
-rw-r--r--usr.sbin/xntpd/Config.local.dist89
-rw-r--r--usr.sbin/xntpd/Makefile17
-rw-r--r--usr.sbin/xntpd/RELNOTES4
-rw-r--r--usr.sbin/xntpd/VERSION2
-rw-r--r--usr.sbin/xntpd/authstuff/Makefile.tmpl2
-rw-r--r--usr.sbin/xntpd/authstuff/auth.samplekeys1
-rw-r--r--usr.sbin/xntpd/authstuff/auth.speed33
-rw-r--r--usr.sbin/xntpd/authstuff/authcert.c55
-rw-r--r--usr.sbin/xntpd/authstuff/authspeed.c10
-rw-r--r--usr.sbin/xntpd/authstuff/keyparity.c20
-rw-r--r--usr.sbin/xntpd/authstuff/makeIPFP.c26
-rw-r--r--usr.sbin/xntpd/authstuff/makePC1.c30
-rw-r--r--usr.sbin/xntpd/authstuff/makePC2.c22
-rw-r--r--usr.sbin/xntpd/authstuff/makeSP.c14
-rw-r--r--usr.sbin/xntpd/authstuff/md5driver.c12
-rw-r--r--usr.sbin/xntpd/authstuff/mkrandkeys.c16
-rw-r--r--usr.sbin/xntpd/authstuff/omakeIPFP.c24
-rw-r--r--usr.sbin/xntpd/authstuff/unixcert.c2
-rw-r--r--usr.sbin/xntpd/conf/Config.HP-UX7
-rw-r--r--usr.sbin/xntpd/conf/Config.OSF17
-rw-r--r--usr.sbin/xntpd/conf/Config.SunOS7
-rw-r--r--usr.sbin/xntpd/conf/Config.ULTRIX7
-rw-r--r--usr.sbin/xntpd/conf/Config.VAX7
-rw-r--r--usr.sbin/xntpd/conf/Config.solaris7
-rw-r--r--usr.sbin/xntpd/conf/README3
-rw-r--r--usr.sbin/xntpd/conf/baldwin.conf40
-rw-r--r--usr.sbin/xntpd/conf/dewey.conf42
-rw-r--r--usr.sbin/xntpd/conf/grundoon.conf179
-rw-r--r--usr.sbin/xntpd/conf/maccarony.conf33
-rw-r--r--usr.sbin/xntpd/conf/malarky.conf35
-rw-r--r--usr.sbin/xntpd/conf/pogo.conf32
-rw-r--r--usr.sbin/xntpd/conf/rackety.conf30
-rw-r--r--usr.sbin/xntpd/doc/README.refclock1416
-rw-r--r--usr.sbin/xntpd/doc/acts.c878
-rw-r--r--usr.sbin/xntpd/doc/ntpq.8319
-rw-r--r--usr.sbin/xntpd/doc/xntpd.81622
-rw-r--r--usr.sbin/xntpd/doc/xntpdc.8557
-rw-r--r--usr.sbin/xntpd/include/README15
-rw-r--r--usr.sbin/xntpd/include/in.h256
-rw-r--r--usr.sbin/xntpd/include/l_stdlib.h66
-rw-r--r--usr.sbin/xntpd/include/md5.h2
-rw-r--r--usr.sbin/xntpd/include/mx4200.h2
-rw-r--r--usr.sbin/xntpd/include/ntp.h132
-rw-r--r--usr.sbin/xntpd/include/ntp_calendar.h10
-rw-r--r--usr.sbin/xntpd/include/ntp_control.h10
-rw-r--r--usr.sbin/xntpd/include/ntp_datum.h30
-rw-r--r--usr.sbin/xntpd/include/ntp_filegen.h6
-rw-r--r--usr.sbin/xntpd/include/ntp_fp.h13
-rw-r--r--usr.sbin/xntpd/include/ntp_if.h2
-rw-r--r--usr.sbin/xntpd/include/ntp_machine.h50
-rw-r--r--usr.sbin/xntpd/include/ntp_refclock.h226
-rw-r--r--usr.sbin/xntpd/include/ntp_request.h88
-rw-r--r--usr.sbin/xntpd/include/ntp_stdlib.h86
-rw-r--r--usr.sbin/xntpd/include/ntp_syslog.h2
-rw-r--r--usr.sbin/xntpd/include/ntp_types.h2
-rw-r--r--usr.sbin/xntpd/include/ntp_unixtime.h22
-rw-r--r--usr.sbin/xntpd/include/ntpd.h17
-rw-r--r--usr.sbin/xntpd/include/parse.h118
-rw-r--r--usr.sbin/xntpd/include/parse_conf.h8
-rw-r--r--usr.sbin/xntpd/include/sys/bsd_audioirig.h10
-rw-r--r--usr.sbin/xntpd/include/sys/chudefs.h2
-rw-r--r--usr.sbin/xntpd/include/sys/clkdefs.h15
-rw-r--r--usr.sbin/xntpd/include/sys/parsestreams.h8
-rw-r--r--usr.sbin/xntpd/include/sys/ppsclock.h1
-rw-r--r--usr.sbin/xntpd/include/sys/timex.h290
-rw-r--r--usr.sbin/xntpd/include/sys/tpro.h2
-rw-r--r--usr.sbin/xntpd/kernel/Makefile.tmpl25
-rw-r--r--usr.sbin/xntpd/kernel/chuinit.c76
-rw-r--r--usr.sbin/xntpd/kernel/clkinit.c76
-rw-r--r--usr.sbin/xntpd/kernel/tty_clk.c14
-rw-r--r--usr.sbin/xntpd/kernel/tty_clk_STREAMS.c1
-rw-r--r--usr.sbin/xntpd/lib/Makefile.tmpl2
-rw-r--r--usr.sbin/xntpd/lib/a_md512crypt.c9
-rw-r--r--usr.sbin/xntpd/lib/a_md5decrypt.c7
-rw-r--r--usr.sbin/xntpd/lib/a_md5encrypt.c7
-rw-r--r--usr.sbin/xntpd/lib/atoint.c10
-rw-r--r--usr.sbin/xntpd/lib/atolfp.c14
-rw-r--r--usr.sbin/xntpd/lib/atouint.c6
-rw-r--r--usr.sbin/xntpd/lib/auth12crypt.c8
-rw-r--r--usr.sbin/xntpd/lib/authdecrypt.c11
-rw-r--r--usr.sbin/xntpd/lib/authdes.c2
-rw-r--r--usr.sbin/xntpd/lib/authdes.c.export2
-rw-r--r--usr.sbin/xntpd/lib/authencrypt.c6
-rw-r--r--usr.sbin/xntpd/lib/authkeys.c31
-rw-r--r--usr.sbin/xntpd/lib/authparity.c2
-rw-r--r--usr.sbin/xntpd/lib/authreadkeys.c16
-rw-r--r--usr.sbin/xntpd/lib/authusekey.c4
-rw-r--r--usr.sbin/xntpd/lib/buftvtots.c40
-rw-r--r--usr.sbin/xntpd/lib/caljulian.c6
-rw-r--r--usr.sbin/xntpd/lib/calleapwhen.c18
-rw-r--r--usr.sbin/xntpd/lib/caltontp.c16
-rw-r--r--usr.sbin/xntpd/lib/calyearstart.c12
-rw-r--r--usr.sbin/xntpd/lib/clocktime.c26
-rw-r--r--usr.sbin/xntpd/lib/clocktypes.c80
-rw-r--r--usr.sbin/xntpd/lib/decodenetnum.c4
-rw-r--r--usr.sbin/xntpd/lib/dofptoa.c4
-rw-r--r--usr.sbin/xntpd/lib/dolfptoa.c55
-rw-r--r--usr.sbin/xntpd/lib/emalloc.c4
-rw-r--r--usr.sbin/xntpd/lib/fptoa.c2
-rw-r--r--usr.sbin/xntpd/lib/fptoms.c2
-rw-r--r--usr.sbin/xntpd/lib/getopt.c2
-rw-r--r--usr.sbin/xntpd/lib/gettstamp.c2
-rw-r--r--usr.sbin/xntpd/lib/hextoint.c6
-rw-r--r--usr.sbin/xntpd/lib/hextolfp.c6
-rw-r--r--usr.sbin/xntpd/lib/humandate.c8
-rw-r--r--usr.sbin/xntpd/lib/inttoa.c6
-rw-r--r--usr.sbin/xntpd/lib/lib_strbuf.c2
-rw-r--r--usr.sbin/xntpd/lib/lib_strbuf.h2
-rw-r--r--usr.sbin/xntpd/lib/machines.c18
-rw-r--r--usr.sbin/xntpd/lib/md5.c2
-rw-r--r--usr.sbin/xntpd/lib/mfptoa.c8
-rw-r--r--usr.sbin/xntpd/lib/mfptoms.c8
-rw-r--r--usr.sbin/xntpd/lib/modetoa.c2
-rw-r--r--usr.sbin/xntpd/lib/mstolfp.c2
-rw-r--r--usr.sbin/xntpd/lib/msutotsf.c6
-rw-r--r--usr.sbin/xntpd/lib/msyslog.c2
-rw-r--r--usr.sbin/xntpd/lib/netof.c9
-rw-r--r--usr.sbin/xntpd/lib/numtoa.c12
-rw-r--r--usr.sbin/xntpd/lib/numtohost.c2
-rw-r--r--usr.sbin/xntpd/lib/octtoint.c6
-rw-r--r--usr.sbin/xntpd/lib/prettydate.c18
-rw-r--r--usr.sbin/xntpd/lib/ranny.c40
-rw-r--r--usr.sbin/xntpd/lib/refnumtoa.c18
-rw-r--r--usr.sbin/xntpd/lib/systime.c36
-rw-r--r--usr.sbin/xntpd/lib/tsftomsu.c8
-rw-r--r--usr.sbin/xntpd/lib/tstotv.c8
-rw-r--r--usr.sbin/xntpd/lib/tvtoa.c6
-rw-r--r--usr.sbin/xntpd/lib/tvtots.c8
-rw-r--r--usr.sbin/xntpd/lib/uglydate.c14
-rw-r--r--usr.sbin/xntpd/lib/uinttoa.c6
-rw-r--r--usr.sbin/xntpd/lib/utvtoa.c6
-rw-r--r--usr.sbin/xntpd/ntpdate/Makefile.tmpl2
-rw-r--r--usr.sbin/xntpd/ntpdate/ntpdate.c118
-rw-r--r--usr.sbin/xntpd/ntpdate/ntpdate.h7
-rw-r--r--usr.sbin/xntpd/ntpq/Makefile.tmpl2
-rw-r--r--usr.sbin/xntpd/ntpq/ntpq.c154
-rw-r--r--usr.sbin/xntpd/ntpq/ntpq.h16
-rw-r--r--usr.sbin/xntpd/ntpq/ntpq_ops.c87
-rw-r--r--usr.sbin/xntpd/ntptrace/Makefile.tmpl2
-rw-r--r--usr.sbin/xntpd/ntptrace/ntptrace.c65
-rw-r--r--usr.sbin/xntpd/ntptrace/ntptrace.h2
-rw-r--r--usr.sbin/xntpd/parse/Makefile.kernel14
-rw-r--r--usr.sbin/xntpd/parse/Makefile.tmpl4
-rw-r--r--usr.sbin/xntpd/parse/README.new_clocks44
-rw-r--r--usr.sbin/xntpd/parse/clk_dcf7000.c19
-rw-r--r--usr.sbin/xntpd/parse/clk_meinberg.c29
-rw-r--r--usr.sbin/xntpd/parse/clk_rawdcf.c45
-rw-r--r--usr.sbin/xntpd/parse/clk_schmid.c30
-rw-r--r--usr.sbin/xntpd/parse/clk_trimtaip.c140
-rw-r--r--usr.sbin/xntpd/parse/clk_trimtsip.c471
-rw-r--r--usr.sbin/xntpd/parse/parse.c361
-rw-r--r--usr.sbin/xntpd/parse/parse_conf.c15
-rw-r--r--usr.sbin/xntpd/parse/parsesolaris.c61
-rw-r--r--usr.sbin/xntpd/parse/parsestreams.c61
-rw-r--r--usr.sbin/xntpd/parse/util/dcfd.c47
-rw-r--r--usr.sbin/xntpd/parse/util/parsetest.c34
-rw-r--r--usr.sbin/xntpd/parse/util/testdcf.c16
-rw-r--r--usr.sbin/xntpd/refclocks/rclk.DATUM22
-rw-r--r--usr.sbin/xntpd/refclocks/rclk.MOTO29
-rw-r--r--usr.sbin/xntpd/refclocks/rclk.NMEA23
-rw-r--r--usr.sbin/xntpd/refclocks/rclk.PARSE12
-rw-r--r--usr.sbin/xntpd/refclocks/rconfig15
-rwxr-xr-xusr.sbin/xntpd/scripts/Guess.sh8
-rwxr-xr-xusr.sbin/xntpd/scripts/install.sh2
-rw-r--r--usr.sbin/xntpd/util/Makefile.tmpl2
-rw-r--r--usr.sbin/xntpd/util/ntptime.c27
-rw-r--r--usr.sbin/xntpd/util/precision.c87
-rw-r--r--usr.sbin/xntpd/util/tickadj.c12
-rw-r--r--usr.sbin/xntpd/util/timetrim.c2
-rw-r--r--usr.sbin/xntpd/xntpd/Makefile.tmpl52
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_config.c882
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_control.c317
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_filegen.c32
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_intres.c21
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_io.c388
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_leap.c38
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_loopfilter.c1180
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_monitor.c130
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_peer.c68
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_proto.c1239
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_refclock.c1185
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_request.c400
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_restrict.c40
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_timer.c18
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_unixclock.c79
-rw-r--r--usr.sbin/xntpd/xntpd/ntp_util.c149
-rw-r--r--usr.sbin/xntpd/xntpd/ntpd.c22
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_acts.c895
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_as2201.c986
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_atom.c499
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_chu.c777
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_conf.c95
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_datum.c871
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_goes.c1188
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_gpstm.c78
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_heath.c393
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_irig.c569
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_leitch.c64
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_local.c357
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_moto.c2
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_msfees.c135
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_mx4200.c72
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_new/refclock_datum.c593
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_new/refclock_gpstm.c999
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_new/refclock_leitch.c718
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_new/refclock_msfees.c1575
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_new/refclock_mx4200.c977
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_new/refclock_omega.c999
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_new/refclock_parse.c3617
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_nmea.c391
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_old/refclock_datum.c645
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_old/refclock_gpstm.c998
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_old/refclock_leitch.c709
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_old/refclock_msfees.c1575
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_old/refclock_mx4200.c1342
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_old/refclock_omega.c999
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_old/refclock_parse.c3605
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_omega.c70
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_parse.c344
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_pst.c1893
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_tpro.c501
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_trak.c1083
-rw-r--r--usr.sbin/xntpd/xntpd/refclock_wwvb.c1121
-rw-r--r--usr.sbin/xntpd/xntpdc/Makefile.tmpl2
-rw-r--r--usr.sbin/xntpd/xntpdc/ntpdc.c98
-rw-r--r--usr.sbin/xntpd/xntpdc/ntpdc.h14
-rw-r--r--usr.sbin/xntpd/xntpdc/ntpdc_ops.c905
229 files changed, 35900 insertions, 13262 deletions
diff --git a/usr.sbin/xntpd/COPYRIGHT b/usr.sbin/xntpd/COPYRIGHT
index b9ce773f163a..b5d6282c2aa9 100644
--- a/usr.sbin/xntpd/COPYRIGHT
+++ b/usr.sbin/xntpd/COPYRIGHT
@@ -29,9 +29,9 @@
* Craig Leres <leres@ee.lbl.gov> (port to 4.4BSD operating system,
* ppsclock, Maganavox GPS clock driver)
* Nick Sayer <mrapple@quack.kfu.com> (SunOS streams modules)
- * Frank Kardel <Frank.Kardel@informatik.uni-erlangen.de>
- * (PARSE (GENERIC) driver, STREAMS module for PARSE, support scripts,
- * reference clock configuration scripts, Makefile cleanup)
+ * Frank Kardel <Frank.Kardel@informatik.uni-erlangen.de>(PARSE (GENERIC)
+ * driver, STREAMS module for PARSE, support scripts, reference clock
+ * configuration scripts, Makefile cleanup)
* Rainer Pruy <Rainer.Pruy@informatik.uni-erlangen.de> (monitoring/trap
* scripts, statistics file handling)
* Glenn Hollinger <glenn@herald.usask.ca> (GOES clock driver)
@@ -41,7 +41,7 @@
* modifications, HPUX modifications)
* John A. Dundas III <dundas@salt.jpl.nasa.gov> (Apple A/UX port)
* David L. Mills <mills@udel.edu> (Spectractom WWVB, Austron GPS,
- * and KSI/Odetics IRIG-B clock drivers; pps support)
+ * Heath, ATOM, ACTS, KSI/Odetics IRIG-B clock drivers; pps support)
* Jeffrey Mogul <mogul@pa.dec.com> (ntptrace utility)
* Steve Clift (clift@ml.csiro.au) OMEGA clock driver)
* Mike Iglesias (iglesias@uci.edu) (DEC Alpha changes)
@@ -57,4 +57,6 @@
* 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)
+ * Jeff Steinman <jss@pebbles.jpl.nasa.gov> (Datum PTS clock driver)
+ * Tomoaki TSURUOKA <tsuruoka@nc.fukuoka-u.ac.jp> (TRAK clock driver)
*/
diff --git a/usr.sbin/xntpd/Config.local b/usr.sbin/xntpd/Config.local
index 22c12a36e90a..50bbe3a85f9e 100644
--- a/usr.sbin/xntpd/Config.local
+++ b/usr.sbin/xntpd/Config.local
@@ -27,15 +27,17 @@
# -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
+# reported via syslog() 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.
+# HAVE_BSD_TTYS for 4.3bsd compatibility.
+# Use HAVE_TERMIOS for POSIX (termios.h) without System V Streams.
+# 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
@@ -78,7 +80,7 @@ DEFS_OPT=-DDEBUG
# special distribution.
#
# Note: following line must always start with DEFS_LOCAL= $(DEFS_OPT)
-DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DKERNEL_PLL -DMCAST
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK #TEST -DPPSPPS -DKERNEL_PLL
#
# Radio clock support definitions (these only make sense if -DREFCLOCK
@@ -112,13 +114,10 @@ DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DKERNEL_PLL -DMCAST
# 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 -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 -DCHU for a special CHU receiver using an ordinary shortwave
# radio. This requires the chu_clk line discipline or chu_clk_STREAMS
@@ -127,62 +126,71 @@ DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DKERNEL_PLL -DMCAST
# 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 -DGPSTM for a Kinemetrics/TrueTime GPS-TM/TMD receiver. It
+# should work in all systems with a serial port.
#
-# 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 -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.
#
# 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 -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 -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.
+# 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 -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 -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 -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 -DTRAK for a 8810 GPS Receiver with Buffered RS-232-C Interface
+# Module. 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.
#
# 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.
+# under Ultrix 4.2a/3 and DEC # OSF/1 Alpha.
#
-CLOCKDEFS= -DLOCAL_CLOCK -DAS2201PPS -DCHUPPS -DGOES -DIRIG -DMX4200PPS -DOMEGA -DPSTCLK -DTPRO -DWWVBCLK -DLEITCH
+CLOCKDEFS= -DLOCAL_CLOCK #TEST -DAS2201PPS -DCHU -DATUM -DGOES -DGPSTM -DIRIG -DLEITCH -DMSFEES -DMX4200PPS -DOMEGA -DPST -DTPRO -TRAK -DWWVB -DPARSE -DPARSEPPS -DCLOCK_MEINBERG -DCLOCK_RAWDCF -DCLOCK_SCHMID -DCLOCK_DCF7000 -DCLOCK_TRIMSV6
#
# Directory into which binaries should be installed (default /usr/local)
diff --git a/usr.sbin/xntpd/Config.local.dist b/usr.sbin/xntpd/Config.local.dist
index 7e540a327b21..2f7386687d87 100644
--- a/usr.sbin/xntpd/Config.local.dist
+++ b/usr.sbin/xntpd/Config.local.dist
@@ -114,17 +114,10 @@ DEFS_LOCAL= $(DEFS_OPT) #GREEN -DREFCLOCK #TEST -DPPSPPS -DKERNEL_PLL
# by default when using the "make makeconfig" script and greenhorn
# configuraiton.
#
-# Define -DTRAK for a 8810 GPS Receiver with Buffered RS-232-C Interface
-# Module. The driver supports both the CLK and PPS modes. It should work
-# in all systems with a serial port.
-#
-# 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 -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 -DCHU for a special CHU receiver using an ordinary shortwave
# radio. This requires the chu_clk line discipline or chu_clk_STREAMS
@@ -133,25 +126,6 @@ DEFS_LOCAL= $(DEFS_OPT) #GREEN -DREFCLOCK #TEST -DPPSPPS -DKERNEL_PLL
# 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
@@ -161,37 +135,62 @@ DEFS_LOCAL= $(DEFS_OPT) #GREEN -DREFCLOCK #TEST -DPPSPPS -DKERNEL_PLL
# Define -DGPSTM for a Kinemetrics/TrueTime GPS-TM/TMD receiver. It
# should work in all systems with a serial port.
#
-# 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 -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.
#
# 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 -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 -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.
+# 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 -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 -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 -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 -DTRAK for a 8810 GPS Receiver with Buffered RS-232-C Interface
+# Module. 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.
#
# 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.
+# under Ultrix 4.2a/3 and DEC # OSF/1 Alpha.
#
-CLOCKDEFS= #GREEN -DLOCAL_CLOCK #TEST -DAS2201PPS -DCHU -DGOES -DIRIG -DMX4200PPS -DOMEGA -DPST -DPSTCLK -DTPRO -DWWVBCLK -DMSFEESPPS -DLEITCH -DPARSE -DPARSEPPS -DCLOCK_MEINBERG -DCLOCK_RAWDCF -DCLOCK_SCHMID -DCLOCK_DCF7000 -DCLOCK_TRIMSV6
+CLOCKDEFS= #GREEN -DLOCAL_CLOCK #TEST -DAS2201PPS -DCHU -DATUM -DGOES -DGPSTM -DIRIG -DLEITCH -DMSFEES -DMX4200PPS -DOMEGA -DPST -DTPRO -TRAK -DWWVB -DPARSE -DPARSEPPS -DCLOCK_MEINBERG -DCLOCK_RAWDCF -DCLOCK_SCHMID -DCLOCK_DCF7000 -DCLOCK_TRIMSV6
#
# Directory into which binaries should be installed (default /usr/local)
diff --git a/usr.sbin/xntpd/Makefile b/usr.sbin/xntpd/Makefile
index ba92f47bd4d2..b9b0e88f9d2d 100644
--- a/usr.sbin/xntpd/Makefile
+++ b/usr.sbin/xntpd/Makefile
@@ -62,7 +62,7 @@ CONF = Config
CONFL = $(CONF).local
CONFLD= $(CONFL).dist
TARGETS = xntpd/xntpd xntpdc/xntpdc ntpq/ntpq ntpdate/ntpdate \
- ntptrace/ntptrace xntpres/xntpres authstuff/authspeed util/tickadj
+ ntptrace/ntptrace authstuff/authspeed util/tickadj
OPTTARG = adjtime/adjtimed util/ntptime util/precision
REFCONF=
COMPRESSOR=compress
@@ -139,11 +139,6 @@ authstuff/authspeed: lib/libntp.a authstuff/Makefile FRC
@echo '###' creating AUTH utilities
@cd authstuff && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" MAKE="$(MAKE)"
-xntpres/xntpres: lib/libntp.a xntpres/Makefile FRC
- @echo
- @echo '###' creating XNTPRES utility
- @cd xntpres && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" MAKE="$(MAKE)"
-
util/tickadj: util/Makefile lib/libntp.a FRC
@echo
@echo '###' creating TICKADJ utility
@@ -216,8 +211,6 @@ clean: neat
@cd xntpd && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" -f Makefile.tmpl MAKE="$(MAKE)" $@
@echo '###' cleaning xntpdc
@cd xntpdc && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" -f Makefile.tmpl MAKE="$(MAKE)" $@
- @echo '###' cleaning xntpres
- @cd xntpres && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" -f Makefile.tmpl MAKE="$(MAKE)" $@
@echo '###' cleaning parse
@cd parse && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" -f Makefile.tmpl MAKE="$(MAKE)" $@
@@ -232,8 +225,6 @@ install: all
@cd ntptrace && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" MAKE="$(MAKE)" install
@echo installing from ntpdate
@cd ntpdate && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" MAKE="$(MAKE)" install
- @echo installing from xntpres
- @cd xntpres && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" MAKE="$(MAKE)" install
@echo installing from util
@cd util && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" MAKE="$(MAKE)" install
@echo installing from parse
@@ -339,12 +330,6 @@ xntpdc/Makefile: xntpdc/Makefile.tmpl ${CONF}.sed
@sed -f ${CONF}.sed < $@.tmpl > $@
@echo '###' cleaning in xntpdc
@cd xntpdc && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" -f Makefile.tmpl MAKE="$(MAKE)" clean
-xntpres/Makefile: xntpres/Makefile.tmpl ${CONF}.sed
- @echo
- @echo '###' updating Makefile in xntpres
- @sed -f ${CONF}.sed < $@.tmpl > $@
- @echo '###' cleaning in xntpres
- @cd xntpres && $(MAKE) $(MFLAGS) MFLAGS="$(MFLAGS)" -f Makefile.tmpl MAKE="$(MAKE)" clean
parse/util/Makefile: parse/util/Makefile.tmpl ${CONF}.sed
@echo
@echo '###' updating Makefile in parse/util
diff --git a/usr.sbin/xntpd/RELNOTES b/usr.sbin/xntpd/RELNOTES
index 411ef452195b..ab3aebe25bd1 100644
--- a/usr.sbin/xntpd/RELNOTES
+++ b/usr.sbin/xntpd/RELNOTES
@@ -112,7 +112,9 @@ archive.
The distribution has been compiled and run on at least the following
machines, operating systems and compilers. In all known cases, if
the gcc compiler eats it with some success, the cc compiler also enjoys
-the meal. The converse is not always true.
+the meal. The converse is not always true. See the conf directory for
+test suites known to compile with various radio clocks; however, not all
+the combinations that compile have been tested.
VAX-11/785 4.3 tahoe cc no REFCLOCK (dm 93/11/20)
Sun3 SunOS 4.1.1 gcc no REFCLOCK (pb 93/10/25)
diff --git a/usr.sbin/xntpd/VERSION b/usr.sbin/xntpd/VERSION
index c145b870451f..a51bf7747d66 100644
--- a/usr.sbin/xntpd/VERSION
+++ b/usr.sbin/xntpd/VERSION
@@ -1 +1 @@
-version=3.3s (beta multicast)
+version=3.4e (beta multicast)
diff --git a/usr.sbin/xntpd/authstuff/Makefile.tmpl b/usr.sbin/xntpd/authstuff/Makefile.tmpl
index 4c8ca57e2c0c..ccafc5b6b25f 100644
--- a/usr.sbin/xntpd/authstuff/Makefile.tmpl
+++ b/usr.sbin/xntpd/authstuff/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:04:48 jbj Exp
+# Makefile.tmpl
#
PROGRAM= authcert authspeed md5
#
diff --git a/usr.sbin/xntpd/authstuff/auth.samplekeys b/usr.sbin/xntpd/authstuff/auth.samplekeys
index c46d283405f2..761c7c251a66 100644
--- a/usr.sbin/xntpd/authstuff/auth.samplekeys
+++ b/usr.sbin/xntpd/authstuff/auth.samplekeys
@@ -1,4 +1,3 @@
-# auth.samplekeys,v 3.1 1993/07/06 01:04:49 jbj Exp
#
# Sample key file, also used for testing.
#
diff --git a/usr.sbin/xntpd/authstuff/auth.speed b/usr.sbin/xntpd/authstuff/auth.speed
index b55f20cbd821..ccf89938e522 100644
--- a/usr.sbin/xntpd/authstuff/auth.speed
+++ b/usr.sbin/xntpd/authstuff/auth.speed
@@ -1,20 +1,33 @@
Authentication delays (us) DES MD5
+-------------------------------------------
+IBM RS6000/990 10 28
+IBM RS6000/590 10 29
+HP 9000/735 hpux9.03 snavely 10 33
DEC 3000/400 OSF/1 bunnylou 14 35
-HP9000/735 hpux9.0 na 30
-HP9000/730 hpux8.07(+OV) 16 55
-SGI Indigo R4000 19 48
-HP9000/720 hpux8.07 21 66
+HP 9000/730 hpux8.07(+OV) 16 55
+SGI Indigo R4000 19 48
+HP 9000/720 hpux8.07 21 66
+IBM RS6000/250 20 39
+IBM RS6000/370 21 43
+IBM RS6000/580 22 43
SGI 4/35 38 110
-DECstation 5000/240 cowbird 39 81
+DECstation 5000/240 cowbird 39 81
+IBM RS6000/530H 40 83
Sun4c/75 SS2 43 96
-Sun4c/50 IPX malarky 47 94
-DECstation 5000/33 sundeck 49 106
+Sun4c/50 IPX malarky 47 94
+DECstation 5000/33 sundeck 49 106
+IBM RS6000/530 51 107
SGI Indigo 54 115
-DECstation 5000/125 herald 63 136
-Sun4c/65 SS1+ pogo 72 159
+DECstation 5000/125 herald 63 136
+IBM RS6000/320 69 139
+Sun4c/65 SS1+ pogo 72 159
Sun4c/40 IPC grundoon 73 163
Sun4c/60 SS1 albert 95 199
Sun4c/20 SLC 95 203
-DECstation 3100 sheol 98 214
+DECstation 3100 sheol 98 214
DECstation 2100 circus 126 278
VAX 780 985 ?
+
+Updated 26 April 1994
+David L. Mills
+
diff --git a/usr.sbin/xntpd/authstuff/authcert.c b/usr.sbin/xntpd/authstuff/authcert.c
index 6f6e42c220c8..0f04d61b5f01 100644
--- a/usr.sbin/xntpd/authstuff/authcert.c
+++ b/usr.sbin/xntpd/authstuff/authcert.c
@@ -1,4 +1,4 @@
-/* authcert.c,v 3.1 1993/07/06 01:04:52 jbj Exp
+/*
* This file, and the certdata file, shamelessly stolen
* from Phil Karn's DES implementation.
*/
@@ -20,44 +20,44 @@ static void put8 P((U_LONG *));
void
main()
{
- U_LONG key[2], plain[2], cipher[2], answer[2];
+ U_LONG key[2], plain[2], cipher[2], answer[2], temp;
int i;
int test;
int fail;
- for(test=0;!feof(stdin);test++){
+ for(test = 0; !feof(stdin); test++){
get8(key);
DESauth_subkeys(key, ekeys, dkeys);
printf(" K: "); put8(key);
-
get8(plain);
printf(" P: "); put8(plain);
-
get8(answer);
printf(" C: "); put8(answer);
-
-
- for(i=0;i<2;i++)
+ for (i = 0; i < 2; i++)
cipher[i] = htonl(plain[i]);
DESauth_des(cipher, ekeys);
-
- for(i=0;i<2;i++)
- if(ntohl(cipher[i]) != answer[i])
+ for (i = 0; i < 2; i++) {
+ temp = ntohl(cipher[i]);
+ if (temp != answer[i])
break;
+ }
+
fail = 0;
- if(i != 2){
+ if (i != 2) {
printf(" Encrypt FAIL");
fail++;
}
DESauth_des(cipher, dkeys);
- for(i=0;i<2;i++)
- if(ntohl(cipher[i]) != plain[i])
+ for (i = 0; i < 2; i++) {
+ temp = ntohl(cipher[i]);
+ if (temp != plain[i])
break;
- if(i != 2){
+ }
+ if (i != 2) {
printf(" Decrypt FAIL");
fail++;
}
- if(fail == 0)
+ if (fail == 0)
printf(" OK");
printf("\n");
}
@@ -65,32 +65,31 @@ main()
static void
get8(lp)
-U_LONG *lp;
+ U_LONG *lp;
{
int t;
U_LONG l[2];
int i;
- l[0] = l[1] = 0L;
- for(i=0;i<8;i++){
- scanf("%2x",&t);
- if(feof(stdin))
+ l[0] = l[1] = 0;
+ for (i = 0; i < 8; i++) {
+ scanf("%2x", &t);
+ if (feof(stdin))
exit(0);
- l[i/4] <<= 8;
- l[i/4] |= (U_LONG)(t & 0xff);
+ l[i / 4] <<= 8;
+ l[i / 4] |= (U_LONG)(t & 0xff);
}
*lp = l[0];
- *(lp+1) = l[1];
+ *(lp + 1) = l[1];
}
static void
put8(lp)
-U_LONG *lp;
+ U_LONG *lp;
{
int i;
- for(i=0;i<2;i++){
- printf("%08x",*lp++);
- }
+ for(i = 0; i < 2; i++)
+ printf("%08lx", (u_long)(*lp++));
}
diff --git a/usr.sbin/xntpd/authstuff/authspeed.c b/usr.sbin/xntpd/authstuff/authspeed.c
index ecddbcd96ba1..a6362a85b768 100644
--- a/usr.sbin/xntpd/authstuff/authspeed.c
+++ b/usr.sbin/xntpd/authstuff/authspeed.c
@@ -1,5 +1,5 @@
-/* authspeed.c,v 3.1 1993/07/06 01:04:54 jbj Exp
- * authspeed - figure out how LONG it takes to do an NTP encryption
+/*
+ * 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) || defined(SYS_UNIXWARE1)
@@ -38,7 +38,7 @@ struct rusage rstart, rend;
#endif
l_fp dummy1, dummy2;
-U_LONG dummy3;
+u_long dummy3;
U_LONG pkt[15];
@@ -299,8 +299,8 @@ subtime(tvs, tve, res)
struct timeval *tvs, *tve;
double *res;
{
- LONG sec;
- LONG usec;
+ long sec;
+ long usec;
sec = tve->tv_sec - tvs->tv_sec;
usec = tve->tv_usec - tvs->tv_usec;
diff --git a/usr.sbin/xntpd/authstuff/keyparity.c b/usr.sbin/xntpd/authstuff/keyparity.c
index 424fade71745..aed05d9c5ccb 100644
--- a/usr.sbin/xntpd/authstuff/keyparity.c
+++ b/usr.sbin/xntpd/authstuff/keyparity.c
@@ -1,4 +1,4 @@
-/* keyparity.c,v 3.1 1993/07/06 01:04:57 jbj Exp
+/*
* keyparity - add parity bits to key and/or change an ascii key to binary
*/
@@ -33,9 +33,9 @@ int asciiflag = 0;
int ntpoutflag = 0;
int gotoopt = 0;
-static int parity P((U_LONG *));
-static int decodekey P((int, char *, U_LONG *));
-static void output P((U_LONG *, int));
+static int parity P((u_long *));
+static int decodekey P((int, char *, u_long *));
+static void output P((u_long *, int));
/*
* main - parse arguments and handle options
@@ -48,7 +48,7 @@ char *argv[];
int c;
int errflg = 0;
int keytype;
- U_LONG key[2];
+ u_long key[2];
extern int ntp_optind;
extern char *ntp_optarg;
@@ -138,9 +138,9 @@ char *argv[];
*/
static int
parity(key)
- U_LONG *key;
+ u_long *key;
{
- U_LONG mask;
+ u_long mask;
int parity_err;
int bitcount;
int half;
@@ -193,7 +193,7 @@ static int
decodekey(keytype, str, key)
int keytype;
char *str;
- U_LONG *key;
+ u_long *key;
{
u_char keybytes[8];
char *cp;
@@ -225,7 +225,7 @@ decodekey(keytype, str, key)
if (xdigit == 0)
return 0;
key[i>>3] <<= 4;
- key[i>>3] |= (U_LONG)(xdigit - hex) & 0xf;
+ key[i>>3] |= (u_long)(xdigit - hex) & 0xf;
}
/*
@@ -265,7 +265,7 @@ decodekey(keytype, str, key)
*/
static void
output(key, ntpformat)
- U_LONG *key;
+ u_long *key;
int ntpformat;
{
int i;
diff --git a/usr.sbin/xntpd/authstuff/makeIPFP.c b/usr.sbin/xntpd/authstuff/makeIPFP.c
index 50b31f4f2513..8fabdb77de7c 100644
--- a/usr.sbin/xntpd/authstuff/makeIPFP.c
+++ b/usr.sbin/xntpd/authstuff/makeIPFP.c
@@ -1,4 +1,4 @@
-/* makeIPFP.c,v 3.1 1993/07/06 01:04:58 jbj Exp
+/*
* makeIPFP - make fast DES IP and FP tables
*/
@@ -9,13 +9,13 @@
#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
-U_LONG IPL[256];
-U_LONG FPL[256];
+u_long IPL[256];
+u_long FPL[256];
char *progname;
int debug;
-static void perm P((u_char *, u_char *, U_LONG *, U_LONG *));
+static void perm P((u_char *, u_char *, u_long *, u_long *));
static void doit P((void));
/*
@@ -138,11 +138,11 @@ static void
perm(databits, permtab, leftp, rightp)
u_char *databits;
u_char *permtab;
- U_LONG *leftp;
- U_LONG *rightp;
+ u_long *leftp;
+ u_long *rightp;
{
- register U_LONG left;
- register U_LONG right;
+ register u_long left;
+ register u_long right;
register u_char *PT;
register u_char *bits;
register int i;
@@ -175,8 +175,8 @@ static void
doit()
{
u_char bits[64];
- U_LONG left;
- U_LONG right;
+ u_long left;
+ u_long right;
int tabno;
int i;
int ind0, ind1, ind2, ind3;
@@ -190,7 +190,7 @@ doit()
* this as well as printing them. Note that this is the
* left-half table, the right half table will be identical.
*/
- printf("static U_LONG IP[256] = {");
+ printf("static u_long IP[256] = {");
for (tabno = 0; tabno < 4; tabno++) {
i = tabno * 8;
ind7 = IPLbits[i] - 1;
@@ -258,7 +258,7 @@ doit()
/*
* Next is the FP table, in big endian order
*/
- printf("#if BYTE_ORDER == LITTLE_ENDIAN\nstatic U_LONG FP[256] = {");
+ printf("#if BYTE_ORDER == LITTLE_ENDIAN\nstatic u_long FP[256] = {");
for (tabno = 3; tabno >= 0; tabno--) {
i = tabno * 8;
ind7 = FPLbits[i] - 1;
@@ -327,7 +327,7 @@ doit()
* Now reouput the FP table in order appropriate for little
* endian machines
*/
- printf("#else\nstatic U_LONG FP[256] = {");
+ printf("#else\nstatic u_long FP[256] = {");
for (octbits = 0; octbits < 256; octbits++) {
left = ((FPL[octbits] >> 24) & 0x000000ff)
| ((FPL[octbits] >> 8) & 0x0000ff00)
diff --git a/usr.sbin/xntpd/authstuff/makePC1.c b/usr.sbin/xntpd/authstuff/makePC1.c
index 337353c1516b..8a49ec902e94 100644
--- a/usr.sbin/xntpd/authstuff/makePC1.c
+++ b/usr.sbin/xntpd/authstuff/makePC1.c
@@ -1,4 +1,4 @@
-/* makePC1.c,v 3.1 1993/07/06 01:04:59 jbj Exp
+/*
* makePC1 - build custom permutted choice 1 tables
*/
@@ -12,7 +12,7 @@
char *progname;
int debug;
-static void permute P((u_char *, U_LONG *, U_LONG *));
+static void permute P((u_char *, u_long *, u_long *));
static void doit P((void));
/*
@@ -74,11 +74,11 @@ static u_char PC1_D[28] = {
static void
permute(bits, cp, dp)
u_char *bits;
- U_LONG *cp;
- U_LONG *dp;
+ u_long *cp;
+ u_long *dp;
{
register int i;
- register U_LONG mask;
+ register u_long mask;
u_char c[28];
u_char d[28];
@@ -122,10 +122,10 @@ static int rc4[4] = { 32, 40, 48, 56 };
*/
static int rd3[4] = { 36, 44, 52, 60 };
-static U_LONG PC_CL[8];
-static U_LONG PC_DL[16];
-static U_LONG PC_CR[16];
-static U_LONG PC_DR[8];
+static u_long PC_CL[8];
+static u_long PC_DL[16];
+static u_long PC_CR[16];
+static u_long PC_DR[8];
/*
@@ -136,13 +136,13 @@ doit()
{
int i;
int comb;
- U_LONG c;
- U_LONG d;
+ u_long c;
+ u_long d;
u_char bits[64];
memset((char *)bits, 0, sizeof bits);
- printf("static U_LONG PC1_CL[8] = {");
+ printf("static u_long PC1_CL[8] = {");
for (i = 0; i < 4; i++) {
for (comb = 0; comb < 8; comb++) {
if (comb & 0x4)
@@ -176,7 +176,7 @@ doit()
}
}
- printf("static U_LONG PC1_DL[16] = {");
+ printf("static u_long PC1_DL[16] = {");
for (i = 0; i < 4; i++) {
for (comb = 0; comb < 16; comb++) {
if (comb & 0x8)
@@ -213,7 +213,7 @@ doit()
}
}
- printf("static U_LONG PC1_CR[16] = {");
+ printf("static u_long PC1_CR[16] = {");
for (i = 0; i < 4; i++) {
for (comb = 0; comb < 16; comb++) {
if (comb & 0x8)
@@ -250,7 +250,7 @@ doit()
}
}
- printf("static U_LONG PC1_DR[8] = {");
+ printf("static u_long PC1_DR[8] = {");
for (i = 0; i < 4; i++) {
for (comb = 0; comb < 8; comb++) {
if (comb & 0x4)
diff --git a/usr.sbin/xntpd/authstuff/makePC2.c b/usr.sbin/xntpd/authstuff/makePC2.c
index 9795b6215a20..e5121fd08364 100644
--- a/usr.sbin/xntpd/authstuff/makePC2.c
+++ b/usr.sbin/xntpd/authstuff/makePC2.c
@@ -1,4 +1,4 @@
-/* makePC2.c,v 3.1 1993/07/06 01:05:01 jbj Exp
+/*
* makePC2 - build custom permutted choice 2 tables
*/
@@ -12,8 +12,8 @@
char *progname;
int debug;
-static void permc P((u_char *, U_LONG *));
-static void permd P((u_char *, U_LONG *));
+static void permc P((u_char *, u_long *));
+static void permd P((u_char *, u_long *));
static void doit P((void));
/*
@@ -71,7 +71,7 @@ static u_char PC2_D[24] = {
17, 13, 21, 7, 0, 3
};
-U_LONG masks[4] = { 0x40000000, 0x400000, 0x4000, 0x40 };
+u_long masks[4] = { 0x40000000, 0x400000, 0x4000, 0x40 };
/*
@@ -80,11 +80,11 @@ U_LONG masks[4] = { 0x40000000, 0x400000, 0x4000, 0x40 };
static void
permc(bits, resp)
u_char *bits;
- U_LONG *resp;
+ u_long *resp;
{
register int part;
register int i;
- register U_LONG mask;
+ register u_long mask;
u_char res[24];
memset((char *)res, 0, sizeof res);
@@ -110,11 +110,11 @@ permc(bits, resp)
static void
permd(bits, resp)
u_char *bits;
- U_LONG *resp;
+ u_long *resp;
{
register int part;
register int i;
- register U_LONG mask;
+ register u_long mask;
u_char res[24];
memset((char *)res, 0, sizeof res);
@@ -165,12 +165,12 @@ doit()
{
int i;
int comb;
- U_LONG res;
+ u_long res;
u_char bits[28];
memset((char *)bits, 0, sizeof bits);
- printf("static U_LONG PC2_C[4][64] = {");
+ printf("static u_long PC2_C[4][64] = {");
for (i = 0; i < 4; i++) {
for (comb = 0; comb < 64; comb++) {
if (comb & 0x20)
@@ -203,7 +203,7 @@ doit()
}
}
- printf("static U_LONG PC2_D[4][64] = {");
+ printf("static u_long PC2_D[4][64] = {");
for (i = 0; i < 4; i++) {
for (comb = 0; comb < 64; comb++) {
if (comb & 0x20)
diff --git a/usr.sbin/xntpd/authstuff/makeSP.c b/usr.sbin/xntpd/authstuff/makeSP.c
index 7bfd93e2cbd6..4fcd78c35e3a 100644
--- a/usr.sbin/xntpd/authstuff/makeSP.c
+++ b/usr.sbin/xntpd/authstuff/makeSP.c
@@ -1,4 +1,4 @@
-/* makeSP.c,v 3.1 1993/07/06 01:05:02 jbj Exp
+/*
* makeSP - build combination S and P tables for quick DES computation
*/
@@ -12,7 +12,7 @@
char *progname;
int debug;
-static void selperm P((int, int, U_LONG *));
+static void selperm P((int, int, u_long *));
static void doit P((void));
/*
@@ -116,15 +116,15 @@ u_char bits[32];
/*
* selperm - run six bit data through the given selection table, then
- * through the PT table to produce a LONG output.
+ * through the PT table to produce a long output.
*/
static void
selperm(selnumber, sixbits, resp)
int selnumber;
int sixbits;
- U_LONG *resp;
+ u_long *resp;
{
- register U_LONG res;
+ register u_long res;
register int selno;
register int i;
register int ind;
@@ -162,11 +162,11 @@ static void
doit()
{
int selno;
- U_LONG result;
+ u_long result;
int sixbits;
memset((char *)bits, 0, sizeof bits);
- printf("static U_LONG SP[8][64] = {");
+ printf("static u_long SP[8][64] = {");
for (selno = 0; selno < 8; selno++) {
for (sixbits = 0; sixbits < 64; sixbits++) {
selperm(selno, sixbits, &result);
diff --git a/usr.sbin/xntpd/authstuff/md5driver.c b/usr.sbin/xntpd/authstuff/md5driver.c
index a608add35f4a..0d7e13254f14 100644
--- a/usr.sbin/xntpd/authstuff/md5driver.c
+++ b/usr.sbin/xntpd/authstuff/md5driver.c
@@ -1,4 +1,4 @@
-/* md5driver.c,v 3.1 1993/07/06 01:05:07 jbj Exp
+/*
***********************************************************************
** md5driver.c -- sample test routines **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
@@ -25,7 +25,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
-#ifdef SYS_BSDI
+#if defined(SYS_BSDI) || defined(SYS_44BSD)
#include <sys/time.h>
#endif /* SYS_BSDI */
#include "md5.h"
@@ -57,7 +57,7 @@ MD5_CTX *mdContext;
#define TEST_BLOCKS 10000
/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
-static LONG TEST_BYTES = (LONG)TEST_BLOCK_SIZE * (LONG)TEST_BLOCKS;
+static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS;
/* A time trial routine, to measure the speed of MD5.
Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
@@ -76,7 +76,7 @@ MDTimeTrial ()
data[i] = (unsigned char)(i & 0xFF);
/* start timer */
- printf ("MD5 time trial. Processing %ld characters...\n", TEST_BYTES);
+ printf ("MD5 time trial. Processing %ld characters...\n", (long)TEST_BYTES);
time (&startTime);
/* digest data in TEST_BLOCK_SIZE byte blocks */
@@ -90,10 +90,10 @@ MDTimeTrial ()
MDPrint (&mdContext);
printf (" is digest of test input.\n");
printf
- ("Seconds to process test input: %ld\n", (LONG)(endTime-startTime));
+ ("Seconds to process test input: %ld\n", (long)endTime-startTime);
printf
("Characters processed per second: %ld\n",
- TEST_BYTES/(endTime-startTime));
+ (long)(TEST_BYTES/(endTime-startTime)));
}
/* Computes the message digest for string inString.
diff --git a/usr.sbin/xntpd/authstuff/mkrandkeys.c b/usr.sbin/xntpd/authstuff/mkrandkeys.c
index 454b3418bbb1..0edf733ac6a4 100644
--- a/usr.sbin/xntpd/authstuff/mkrandkeys.c
+++ b/usr.sbin/xntpd/authstuff/mkrandkeys.c
@@ -1,4 +1,4 @@
-/* mkrandkeys.c,v 3.1 1993/07/06 01:05:08 jbj Exp
+/*
* mkrandkeys - make a key file for xntpd with some quite random keys
*/
#include <stdio.h>
@@ -12,12 +12,12 @@
char *progname;
int debug;
-U_LONG keydata[2];
+u_long keydata[2];
int std = 1; /* DES standard key format */
u_char dokey[16] = { 0 };
-static void rand_data P((U_LONG *));
+static void rand_data P((u_long *));
/*
* main - parse arguments and handle options
@@ -32,7 +32,7 @@ char *argv[];
int j;
int errflg = 0;
int numkeys;
- U_LONG tmp;
+ u_long tmp;
char *passwd;
extern int ntp_optind;
extern char *ntp_optarg;
@@ -89,7 +89,7 @@ char *argv[];
keydata[0] = keydata[1] = 0;
for (i = 0; i < 8 && *passwd != '\0'; i++) {
- keydata[i/4] |= ((((U_LONG)(*passwd))&0xff)<<(1+((3-(i%4))*8)));
+ keydata[i/4] |= ((((u_long)(*passwd))&0xff)<<(1+((3-(i%4))*8)));
passwd++;
}
@@ -139,18 +139,18 @@ char *volatile_file[] = {
static void
rand_data(data)
- U_LONG *data;
+ u_long *data;
{
register i;
struct stat buf;
- extern LONG time();
+ extern long time();
char ekeys[128], dkeys[128];
*data ^= 0x9662f394;
*(data+1) ^= 0x9f17c55f;
DESauth_subkeys(data, ekeys, dkeys);
*data ^= NEXT(getpid() + (getuid() << 16));
- *(data+1) ^= NEXT(time((LONG *)0));
+ *(data+1) ^= NEXT(time((long *)0));
DESauth_des(data, ekeys);
for (i = 0; strlen(volatile_file[i]); i++) {
if (stat(volatile_file[i], &buf) == -1)
diff --git a/usr.sbin/xntpd/authstuff/omakeIPFP.c b/usr.sbin/xntpd/authstuff/omakeIPFP.c
index 0751a5d96b9c..92d87be30ba0 100644
--- a/usr.sbin/xntpd/authstuff/omakeIPFP.c
+++ b/usr.sbin/xntpd/authstuff/omakeIPFP.c
@@ -1,4 +1,4 @@
-/* omakeIPFP.c,v 3.1 1993/07/06 01:05:10 jbj Exp
+/*
* makeIPFP - make fast DES IP and FP tables
*
* This is an older version which generated tables half the size of
@@ -15,13 +15,13 @@
#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
-U_LONG IPL[8][16];
-U_LONG FPL[8][16];
+u_long IPL[8][16];
+u_long FPL[8][16];
char *progname;
int debug;
-static void perm P((u_char *, u_char *, U_LONG *, U_LONG *));
+static void perm P((u_char *, u_char *, u_long *, u_long *));
static void doit P((void));
/*
@@ -144,11 +144,11 @@ static void
perm(databits, permtab, leftp, rightp)
u_char *databits;
u_char *permtab;
- U_LONG *leftp;
- U_LONG *rightp;
+ u_long *leftp;
+ u_long *rightp;
{
- register U_LONG left;
- register U_LONG right;
+ register u_long left;
+ register u_long right;
register u_char *PT;
register u_char *bits;
register int i;
@@ -181,8 +181,8 @@ static void
doit()
{
u_char bits[64];
- U_LONG left;
- U_LONG right;
+ u_long left;
+ u_long right;
int tabno;
int i;
int ind0, ind1, ind2, ind3;
@@ -195,7 +195,7 @@ doit()
* this as well as printing them. Note that this is the
* left-half table.
*/
- printf("static U_LONG IP[8][16] = {");
+ printf("static u_long IP[8][16] = {");
for (tabno = 0; tabno < 8; tabno++) {
i = tabno * 4;
ind3 = IPLbits[i] - 1;
@@ -279,7 +279,7 @@ doit()
/*
* Next are the FP tables
*/
- printf("static U_LONG FP[8][16] = {");
+ printf("static u_long FP[8][16] = {");
for (tabno = 0; tabno < 8; tabno++) {
i = tabno * 4;
ind3 = FPLbits[i] - 1;
diff --git a/usr.sbin/xntpd/authstuff/unixcert.c b/usr.sbin/xntpd/authstuff/unixcert.c
index 36234b13f55f..47c76f6fa93c 100644
--- a/usr.sbin/xntpd/authstuff/unixcert.c
+++ b/usr.sbin/xntpd/authstuff/unixcert.c
@@ -1,4 +1,4 @@
-/* unixcert.c,v 3.1 1993/07/06 01:05:14 jbj Exp
+/*
* This file, and the certdata file, shamelessly stolen
* from Phil Karn's DES implementation.
*
diff --git a/usr.sbin/xntpd/conf/Config.HP-UX b/usr.sbin/xntpd/conf/Config.HP-UX
new file mode 100644
index 000000000000..ef4fa302cb2c
--- /dev/null
+++ b/usr.sbin/xntpd/conf/Config.HP-UX
@@ -0,0 +1,7 @@
+#
+# Test suite for HPUX 9 (no multicast, kernel mods, disciplines, modem control)
+#
+DEFS_OPT=-DDEBUG
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK
+CLOCKDEFS= -DATOM -DAS2201 -DCHU -DGOES -DGPSTM -DIRIG -DLEITCH -DLOCAL_CLOCK -DMSFEES -DMX4200 -DNMEA -DOMEGA -DPST -DTPRO -DTRAK -DWWVB
+BINDIR= /usr/local/bin
diff --git a/usr.sbin/xntpd/conf/Config.OSF1 b/usr.sbin/xntpd/conf/Config.OSF1
new file mode 100644
index 000000000000..f460e9f934a7
--- /dev/null
+++ b/usr.sbin/xntpd/conf/Config.OSF1
@@ -0,0 +1,7 @@
+#
+# Test suite for DEC OSF/1 V1.x (no disciplines)
+#
+DEFS_OPT=-DDEBUG
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DKERNEL_PLL -DMCAST
+CLOCKDEFS= -DACTS -DATOM -DAS2201 -DCHU -DDATUM -DGOES -DGPSTM -DHEATH -DIRIG -DLEITCH -DLOCAL_CLOCK -DMSFEES -DMX4200 -DNMEA -DOMEGA -DPST -DTPRO -DTRAK -DWWVB
+BINDIR= /usr/local/bin
diff --git a/usr.sbin/xntpd/conf/Config.SunOS b/usr.sbin/xntpd/conf/Config.SunOS
new file mode 100644
index 000000000000..42fd1a5cee6f
--- /dev/null
+++ b/usr.sbin/xntpd/conf/Config.SunOS
@@ -0,0 +1,7 @@
+#
+# Test suite for SunOS 4.1.x (kitchen sink)
+#
+DEFS_OPT=-DDEBUG
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DMCAST -DKERNEL_PLL -DCLK -DCHU -DPPS
+CLOCKDEFS= -DACTS -DATOM -DAS2201 -DCHU -DDATUM -DGOES -DGPSTM -DHEATH -DIRIG -DLEITCH -DLOCAL_CLOCK -DMSFEES -DMX4200 -DNMEA -DOMEGA -DPST -DTPRO -DTRAK -DWWVB
+BINDIR= /usr/local/bin
diff --git a/usr.sbin/xntpd/conf/Config.ULTRIX b/usr.sbin/xntpd/conf/Config.ULTRIX
new file mode 100644
index 000000000000..4ead1be017a0
--- /dev/null
+++ b/usr.sbin/xntpd/conf/Config.ULTRIX
@@ -0,0 +1,7 @@
+#
+# Test suite for Ultrix 4.x (no disciplines)
+#
+DEFS_OPT=-DDEBUG
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DKERNEL_PLL -DMCAST
+CLOCKDEFS= -DACTS -DATOM -DAS2201 -DCHU -DDATUM -DGOES -DGPSTM -DHEATH -DIRIG -DLEITCH -DLOCAL_CLOCK -DMSFEES -DMX4200 -DNMEA -DOMEGA -DPST -DTPRO -DTRAK -DWWVB
+BINDIR= /usr/local/bin
diff --git a/usr.sbin/xntpd/conf/Config.VAX b/usr.sbin/xntpd/conf/Config.VAX
new file mode 100644
index 000000000000..66b9f91007bd
--- /dev/null
+++ b/usr.sbin/xntpd/conf/Config.VAX
@@ -0,0 +1,7 @@
+#
+# Test suite for 4.3bsd VAX tahoe (no multicast, kernel mods, disciplines)
+#
+DEFS_OPT=-DDEBUG
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK
+CLOCKDEFS= -DACTS -DATOM -DAS2201 -DCHU -DDATUM -DGOES -DGPSTM -DHEATH -DIRIG -DLEITCH -DLOCAL_CLOCK -DMSFEES -DMX4200 -DNMEA -DOMEGA -DPST -DTPRO -DTRAK -DWWVB
+BINDIR= /usr/local/bin
diff --git a/usr.sbin/xntpd/conf/Config.solaris b/usr.sbin/xntpd/conf/Config.solaris
new file mode 100644
index 000000000000..5db3cd0b050c
--- /dev/null
+++ b/usr.sbin/xntpd/conf/Config.solaris
@@ -0,0 +1,7 @@
+#
+# Test suite for SunOS 5.x (no kernel mods, disciplines)
+#
+DEFS_OPT=-DDEBUG
+DEFS_LOCAL= $(DEFS_OPT) -DREFCLOCK -DMCAST
+CLOCKDEFS= -DACTS -DATOM -DAS2201 -DCHU -DDATUM -DGOES -DGPSTM -DHEATH -DIRIG -DLEITCH -DLOCAL_CLOCK -DMSFEES -DMX4200 -DNMEA -DOMEGA -DPST -DTPRO -DTRAK -DWWVB
+BINDIR= /usr/local/bin
diff --git a/usr.sbin/xntpd/conf/README b/usr.sbin/xntpd/conf/README
index 19dcb795f80c..8d075916daf8 100644
--- a/usr.sbin/xntpd/conf/README
+++ b/usr.sbin/xntpd/conf/README
@@ -6,3 +6,6 @@ obtuse configurations you may run into. They are not likely to do
anything good if run on machines other than their native spot, so don't
just blindly copy something and put it up. Additional information can
be found in the ./doc directory of the base directory.
+
+See the Config.local.dist file in the base directory for an explanation
+of the defines used.
diff --git a/usr.sbin/xntpd/conf/baldwin.conf b/usr.sbin/xntpd/conf/baldwin.conf
new file mode 100644
index 000000000000..baaac95437cd
--- /dev/null
+++ b/usr.sbin/xntpd/conf/baldwin.conf
@@ -0,0 +1,40 @@
+#
+# NTP configuration file (ntp.conf)
+# baldwin.udel.edu (128.4.1.24)
+#
+# This illustrates the use of an external clock with the local clock
+# driver, as well as a multicast server. The prefer keyword on the
+# local clock driver declares an external clock and that the time of
+# this server should not be wiggled by an NTP peer, unless the
+# external clock comes unstuck. Note the use of the multicast group
+# ID assigned to NTP, 224.0.1.1, which identifies this as a multicast
+# server rather than a broadcast one. The other NTP peers are known
+# stratum-1 chimes intended as backup should the external clock croak.
+#
+peer 127.127.1.0 prefer # KSI/Odetics TPRO IRIG interface
+fudge 127.127.1.0 stratum 0 refid GPS
+broadcast 224.0.1.1 key 6 ttl 127
+peer 128.4.1.1 # rackety.udel.edu (Sun4c/40 IPC)
+peer 128.4.1.4 # barnstable.udel.edu (Sun4c/65 SS1+)
+peer 128.4.1.2 # mizbeaver.udel.edu (Bancomm bc700LAN)
+peer 128.4.1.20 # pogo.udel.edu (Sun4c/65 SS1+)
+
+#
+# Miscellaneous stuff
+#
+enable auth monitor # enable the good stuff
+driftfile /etc/ntp.drift # path for drift file
+statsdir /baldwin/ntpstats/ # directory for statistics files
+filegen peerstats file peerstats type day enable
+filegen loopstats file loopstats type day enable
+filegen clockstats file clockstats type day enable
+
+#
+# Authentication stuff
+#
+keys /usr/local/bin/ntp.keys # path for keys file
+trustedkey 3 4 5 6 14 15 # define trusted keys
+requestkey 15 # key (7) for accessing server variables
+controlkey 15 # key (6) for accessing server variables
+authdelay 0.000163 # authentication delay (SPARC4c/40 IPC MD5)
+
diff --git a/usr.sbin/xntpd/conf/dewey.conf b/usr.sbin/xntpd/conf/dewey.conf
index 523008fcdc82..2a7548c8151e 100644
--- a/usr.sbin/xntpd/conf/dewey.conf
+++ b/usr.sbin/xntpd/conf/dewey.conf
@@ -1,38 +1,46 @@
#
# NTP configuration file (ntp.conf)
-# dewey.udel.edu (128.175.1.2)
#
-# Stratum-1 peers
+# Generic configuration file for UDel NTP stratum-2 time servers. Don't
+# forget each server should have a /etc/ntp.drift and /etc/ntp.keys file.
+#
+# Stratum-1 peers. Each server should chime two different stratum-1
+# servers from the following list. Each stratum-1 server should be used
+# only once.
#
-#peer 128.4.1.5 # dcn5.udel.edu
#peer 128.8.10.1 # umd1.umd.edu
#peer 18.72.0.3 version 2 # bitsy.mit.edu
-peer 192.43.244.9 # ncar-fuzz.nsf.net
-peer 132.249.16.1 # sdsc-fuzz.nsf.net
+peer 132.249.16.1 # fuzz.sdsc.edu
peer 128.118.46.3 version 2 # otc1.psu.edu
-#peer 130.126.174.40 # truechimer.cso.uiuc.edu
#peer 128.9.2.129 # wwvb.isi.edu
#peer 130.43.2.2 version 2 # apple.com
+#peer 16.1.0.22 # clepsydra.dec.com
+#peer 130.105.1.156 version 2 # clock.osf.orga
+#peer 128.96.60.5 version 2 # pi.bellcore.com
+#peer 128.4.1.1 # rackety.udel.edu
+#peer 129.116.3.5 # shorty.chpc.utexas.edu
#
-# Stratum-2 peers
+# Stratum-2 peers. Each server should chime all of the others in this
+# list except itself.
#
-peer 128.175.1.1 # huey.udel.edu
-#peer 128.175.1.2 # dewey.udel.edu
-peer 128.175.1.3 # louie.udel.edu
-#peer 128.175.2.33 # louie.udel.edu
-#peer 128.175.7.39 # louie.udel.edu
+peer 128.175.1.1 # huey.udel.edu (VAX)
+#peer 128.175.1.2 # dewey.udel.edu (VAX)
+peer 128.175.1.3 # louie.udel.edu (SPARC)
+peer 128.175.2.15 # snow-white.ee.udel.edu (SPARC)
+peer 128.175.7.4 # sol.cis.udel.edu (SPARC)
#
# Miscellaneous stuff
#
-monitor yes # enable monitoring
-precision -7 # clock reading precision (10 msec)
-driftfile /etc/ntp.drift # path for drift file
+enable auth monitor # enable the good stuff
+driftfile /etc/ntp.drift # path for drift file
#
-# Authentication stuff
+# Authentication stuff. Note the different authentication delay on
+# VAX and SPARC.
#
authenticate yes # enable authentication
keys /etc/ntp.keys # path for key file
trustedkey 1 2 15 # define trusted keys
requestkey 15 # key (7) for accessing server variables
controlkey 15 # key (6) for accessing server variables
-authdelay 0.001501 # authentication delay (VAX 11/780)
+authdelay 0.001501 # authentication delay (VAX)
+#authdelay 0.000073 # authentication delay (SPARC)
diff --git a/usr.sbin/xntpd/conf/grundoon.conf b/usr.sbin/xntpd/conf/grundoon.conf
index c5aef6eb88e3..16003d59237b 100644
--- a/usr.sbin/xntpd/conf/grundoon.conf
+++ b/usr.sbin/xntpd/conf/grundoon.conf
@@ -2,43 +2,144 @@
# NTP configuration file (ntp.conf)
# grundoon.udel.edu (128.4.2.7)
#
-server 127.127.6.0 prefer # irig audio decoder
-fudge 127.127.6.0 time1 0.0005
-#pps delay -0.0004 # pps correction for CLK streams module
-server 127.127.4.1 # spectracom 8170/netclock-2 wwvb receiver
-# propagation delay: wwvb 0.0088; receiver delay 0.0173 os delay .0035
-fudge 127.127.4.1 time1 0.0035 flag4 1
-server 127.127.3.1 # pst/traconex 1020 wwv/h receiver
-# propagation delay: wwv 0.0088 wwvh 0.0281; receiver+os delay 0.0035
-fudge 127.127.3.1 time1 0.0123 time2 0.0316
-server 127.127.7.1 # scratchbuilt chu receiver/demodulator
-# propagtion delay: chu 0.0030; receiver+os delay 0.0060
-fudge 127.127.7.1 time1 0.0030 time2 0.0060
-#server 127.127.10.1 # austron 2201 gps receiver
-
-server 127.127.1.2 # local clock
-#server 127.127.12.2 # ksi/odetics tpr0-s irig-b reader
-
-#broadcast 128.4.2.255
-
-peer 128.4.1.1 key 3 # rackety.udel.edu (Sun4c/40 IPC)
-peer 128.4.1.4 # barnstable.udel.edu (Sun4c/65 SS1+)
-#peer 128.4.1.5 # churchy.udel.edu (Bancomm bc700LAN)
-#peer 128.4.2.7 key 3 # grundoon.udel.edu (Sun4c/40 IPC)
-peer 128.4.1.8 # bridgeport.udel.edu (Sun4c/40 IPC)
-peer 128.4.1.20 key 3 # pogo.udel.edu (Sun4c/65 SS1+)
-peer 128.4.1.22 # malarky.udel.edu (Sun4c/50 IPX)
-peer 128.4.1.23 # beauregard.udel.edu (Sun4/40 IPC)
-peer 128.4.1.24 # baldwin.udel.edu (Sun4/40 IPC)
-peer 128.4.1.25 # albert.udel.edu (Sun4c/60 SS1)
-peer 128.4.1.27 # bunnylou.udel.edu (Sun4c/40 IPC)
-peer 128.4.1.28 # cowbird.udel.edu (DEC 5000/240)
-peer 128.4.1.29 # porkypine.udel.edu (DEC 5000/240)
-#
-# Miscellaneous stuff
-#
-monitor yes # enable monitoring
-precision -18 # clock reading precision (usec)
+# This machine can best be described as the kitchen sink. It has, in
+# addition to the baseboard tty ports ttya and ttyb, an 8-line
+# Serial/Parallel Interface (SPIF) with ports ttyz00 through ttyz07. The
+# configuration includes the following drivers, clock addresses and Unix
+# device names.
+#
+# Local Clock 127.127.1.0 /dev/audio
+# PST 1020 WWV/WWVH Receiver 127.127.3.1 /dev/pst1
+# Spectracom 8170 WWVB Receiver 127.127.4.1 /dev/wwvb1
+# IRIG Audio Decoder 127.127.6.0 /dev/audio
+# Scratchbuilt CHU Receiver 127.127.7.1 /dev/chu1
+# NIST ACTS modem 127.127.18.1 /dev/acts1
+# Heath GC-1000 WWV Receiver 127.127.19.1 /dev/pst1
+# PPS Clock 127.127.22.1 none
+#
+# This machine has the kernel modifications described in the README.kern
+# file, as well as the tty_clk, tty_chu and ppsclock streams modules.
+#
+# Spectracom 8170/Netclock-2 WWVB receiver. This receiver is equipped
+# with a 1-pps and IRIG outputs. The 1-pps signal is connected via the
+# ppsclock streams module and the carrier detect line of the CHU
+# receiver below (ttyb). The IRIG signal is connected via an attenuator
+# to the audio port (/dev/audio). The propagation delay computed from
+# geographical coordinates is 8.8 ms, while the receiver delay
+# calibrated at the factory is 17.3 ms, for a total delay of 26.1 ms.
+# This is confirmed within 0.1 ms at the 1-pps signal output using a
+# portable cesium clock. We add a fudge time1 of 3.5 ms so the driver
+# time agrees with the 1-pps signal to within 1 ms. The fudge flag4 is
+# set to cause the receiver to dump the quality table once each day to
+# the clockstats file.
+
+#
+#server 127.127.4.1 # /dev/wwvb1 -> /dev/ttyz03
+#fudge 127.127.4.1 time1 0.0035 flag4 1
+#
+# IRIG Audio Decoder. The IRGI signal of the Spectracom WWVB receiver is
+# connected to the audio codec via a resistor attenuator. We add a fudge
+# time1 of 3.5 ms so the driver agrees with the calibrated 1-pps signal
+# to within 0.1 ms. We also specify a reference ID of WWVB to indicate
+# the signal origin. Note the prefer keyword in the server line, which
+# favors this driver over all others that survive the clock selection
+# algorithm. See README.refclock for further insight on this feature.
+#
+server 127.127.6.0 prefer # /dev/audio
+fudge 127.127.6.0 time1 0.0005 refid WWVB
+
+#
+# PST/Traconex 1020 WWV/WWVH Receier. The internal DIPswitches are set
+# as near as possible to the delays to WWV (8.8 ms) and WWVH (28.1 ms),
+# as computed from geographical coordinates. We add a fudge time1 of 5.9
+# ms so the driver time agrees with the 1-pps signal to within 1 ms for
+# WWV. We also set the stratum to 1, so this receiver will not normally
+# be selected, unless the primary WWVB receiver comes unstuck.
+#
+server 127.127.3.1 # /dev/pst1 -> ttyz05
+fudge 127.127.3.1 time1 0.0059 stratum 1
+
+#
+# Scratchbuilt CHU Receiver. The audio signal from a computer controlled
+# CHU receiver is connected to a gadget box, which contains a 103A modem
+# chip and level converter operating at 300 bps. The propagation delay
+# computed from geographical coordinates is 3.0 ms, which is the value
+# of the fudge time1 parameter. We add a fudge time2 of 9.9 ms so that
+# the driver time agrees with the 1-pps signal to within a few ms,
+# ordinarily the best possible with this receiver. The fudge flag3 is
+# set because the 1-pps signal happens to be connected vit the carrier
+# detect line on this port (ttyb). We also set the stratum to 1, so this
+# receiver will not normally be selected, unless the primary WWVB
+# receiver comes unstuck.
+#
+server 127.127.7.1 # /dev/chu1 -> /dev/ttyb
+fudge 127.127.7.1 time1 0.0030 time2 0.0099 flag3 1 stratum 1
+
+#
+# NIST Automated Computer Time Service. This driver calls a special
+# telephone number in Boulder, CO, to fetch the time directly from the
+# NIST cesium farm. The details of the complicated calling program are
+# in the README.refclock file. The Practical Peripherals 9600SA modem
+# does not work correctly with the ACTS echo-delay scheme for
+# automatically calculating the propagation delay, so the fudge flag2 is
+# set to disable the feature. Instead, we add a fudge time1 of 65.0 ms
+# so that the driver time agrees with th e1-pps signal to within 1 ms.
+# The phone command specifies three alternate telephone numbers,
+# including AT modem command prefix, which will be tried one after the
+# other at each measurement attempt. In this case, a cron job is used to
+# set fudge flag1, causing a measurement attempt, every six hours.
+#
+server 127.127.18.1 # /dev/acts1 -> /dev/ttyz00
+fudge 127.127.18.1 time1 0.0650 flag2 1
+phone atdt13034944774 atdt13034944785 atdt13034944774
+
+#
+# Heath GC-1000 Most Accurate Clock. This is a WWV receiver with a
+# claimed accuracy better than 100 ms under "hi spec" conditions, but
+# such conditions are not frequent. The propagation delay DIPswitchs are
+# set to 9 ms, as close as possible to the 8.8 ms computed from
+# geographical coordinates. We add a fudge time2 of 40.0 ms so that the
+# driver time agrees with the 1-pps signal to within 50 ms, ordinarily
+# the best possible with this receiver. We also set the stratum to 1, so
+# this receiver will not normally be selected, unless the primary WWVB
+# receiver comes unstuck.
+#
+server 127.127.19.1 # /dev/heath1 -> ttyz07
+fudge 127.127.19.1 time1 0.040 stratum 1
+
+#
+# Undisciplined Local Clock. This is a fake driver intended for backup
+# and when no outside source of synchronized time is available. The
+# default stratum is usually 3, but in this case we elect to use stratum
+# 0. Since the server line does not have the prefer keyword, this driver
+# is never used for synchronization, unless no other other
+# synchronization source is available. In case the local host is
+# controlled by some external source, such as an external oscillator or
+# another protocol, the prefer keyword would cause the local host to
+# disregard all other synchronization sources, unless the kernel
+# modifications are in use and declare an unsynchronized condition.
+#
+server 127.127.1.0 # local clock
+fudge 127.127.1.0 stratum 0
+
+#
+# PPS Clock. This driver is used to capture a 1-pps signal when the PPS
+# kernel modifications are not in use. It can be configured for the
+# tty_clk or ppsclock streams module or no module at all, assuming the
+# RS232 connector is properly wired. Normally, the 1-pps signal is
+# generated by a radio clock, in this cast the Spectracom clock
+# 127.127.4.1 also configured for this host. When used this way, the
+# associated radio clock normally has the prefer keyword in the serve
+# command line. The PPS driver then will be selected only if the prefer
+# peer is operating within nominal error bounds. See the README.refclock
+# file for further details.
+#
+#server 127.127.22.1 # pps clock
+
+#
+# Miscellaneous stuff. We enable authentication in order to prevent
+#
+enable auth monitor # enable the good stuff
driftfile /etc/ntp.drift # path for drift file
statsdir /grundoon/ntpstats/ # directory for statistics files
filegen peerstats file peerstats type day enable
@@ -48,11 +149,9 @@ filegen clockstats file clockstats type day enable
#
# Authentication stuff
#
-authenticate yes # enable authentication
keys /usr/local/ntp.keys # path for keys file
-trustedkey 1 2 3 4 14 15 # define trusted keys
+trustedkey 1 2 3 4 5 6 14 15 # define trusted keys
requestkey 15 # key (7) for accessing server variables
controlkey 15 # key (6) for accessing server variables
-#authdelay 0.000073 # authentication delay (SPARC4c/40 IPC DES)
authdelay 0.000163 # authentication delay (SPARC4c/40 IPC MD5)
diff --git a/usr.sbin/xntpd/conf/maccarony.conf b/usr.sbin/xntpd/conf/maccarony.conf
new file mode 100644
index 000000000000..6bd25c73ec11
--- /dev/null
+++ b/usr.sbin/xntpd/conf/maccarony.conf
@@ -0,0 +1,33 @@
+#
+# NTP configuration file (ntp.conf)
+#
+# This illustrates a multicast client. All that is really needed
+# here is the multicastclient command and the authentication stuff.
+# If the monitoring option and filgen statistics were not needed,
+# this could be done without a configuration file by including the
+# following snip in the rc.local startup file or equivalent:
+#
+#if [ -f /usr/local/bin/xntpd ]; then
+# /usr/local/bin/xntpd -m -a -k/usr/local/bin/ntp.keys -t3
+#fi
+#
+multicastclient # listen on default 224.0.1.1
+#
+# Miscellaneous stuff
+#
+enable auth monitor # enable the good stuff
+driftfile /etc/ntp.drift # path for drift file
+statsdir /malarky/ntpstats/ # directory for statistics files
+filegen peerstats file peerstats type day enable
+filegen loopstats file loopstats type day enable
+filegen clockstats file clockstats type day enable
+
+#
+# Authentication stuff
+#
+keys /usr/local/bin/ntp.keys # path for key file
+trustedkey 3 4 5 6 14 15 # define trusted keys
+requestkey 15 # key (7) for accessing server variables
+controlkey 15 # key (6) for accessing server variables
+authdelay 0.000094 # authentication delay (Sun4c/50 IPX MD5)
+
diff --git a/usr.sbin/xntpd/conf/malarky.conf b/usr.sbin/xntpd/conf/malarky.conf
index f887f839d1bb..9b1d7b2317e1 100644
--- a/usr.sbin/xntpd/conf/malarky.conf
+++ b/usr.sbin/xntpd/conf/malarky.conf
@@ -1,26 +1,16 @@
#
# NTP configuration file (ntp.conf)
-# malarky.udel.edu (128.4.1.22)
-#
-peer 128.4.1.1 # rackety.udel.edu
-peer 128.4.1.4 # barnstable.udel.edu
-#peer 128.4.1.5 #churchy.udel.edu
-peer 128.4.2.7 # grundoon.udel.edu
-peer 128.4.1.8 # bridgeport.udel.edu
-peer 128.4.1.20 prefer # pogo.udel.edu
-#peer 128.4.1.22 # malarky.udel.edu
-peer 128.4.1.23 # beauregard.udel.edu
-peer 128.4.1.24 # baldwin.udel.edu
-peer 128.4.1.25 # albert.udel.edu
-peer 128.4.1.27 # bunnylou.udel.edu
-peer 128.4.1.28 # cowbird.udel.edu
-peer 128.4.1.29 # porkypine.udel.edu
-
+#
+# This is for a broadcast/multicast client. Except for the statistics
+# stuff, this can be done with only a commmand line of the form
+#
+# /usr/local/bin/xntpd -a -k /usr/local/bin/ntp.keys -m -t 3
+#
+multicastclient # listen on default 224.0.1.1
#
# Miscellaneous stuff
#
-monitor yes # enable monitoring
-precision -18 # clock reading precision (usec)
+enable auth monitor # enable the good stuff
driftfile /etc/ntp.drift # path for drift file
statsdir /malarky/ntpstats/ # directory for statistics files
filegen peerstats file peerstats type day enable
@@ -30,11 +20,8 @@ filegen clockstats file clockstats type day enable
#
# Authentication stuff
#
-authenticate yes # enable authentication
keys /usr/local/bin/ntp.keys # path for key file
-trustedkey 1 2 3 4 14 15 # define trusted keys
-requestkey 15 # key (7) for accessing server variables
-controlkey 15 # key (6) for accessing server variables
-#authdelay 0.000047 # authentication delay (Sun4c/50 IPX DES)
+trustedkey 3 4 5 6 14 # define trusted keys
+requestkey 14 # key (7) for accessing server variables
+controlkey 14 # key (6) for accessing server variables
authdelay 0.000094 # authentication delay (Sun4c/50 IPX MD5)
-
diff --git a/usr.sbin/xntpd/conf/pogo.conf b/usr.sbin/xntpd/conf/pogo.conf
index 94ac6c84ea28..e557e44740a5 100644
--- a/usr.sbin/xntpd/conf/pogo.conf
+++ b/usr.sbin/xntpd/conf/pogo.conf
@@ -2,34 +2,21 @@
# NTP configuration file (ntp.conf)
# pogo.udel.edu (128.4.1.20)
#
-server 127.127.10.1 prefer # austron 2201 gps receiver
-#server 127.127.4.1 # spectracom 8170/netclock-2 wwvb receiver
-# propagation delay: wwvb 0.0088; receiver delay 0.0017
-#fudge 127.127.4.1 time1 0.0017
-
-peer 128.4.1.1 key 3 # rackety.udel.edu (Sun4c/40 IPC)
-peer 128.4.1.2 # mizbeaver.udel.edu
+server 127.127.10.1 prefer # austron 2201A gps receiver
+peer 128.4.1.1 # rackety.udel.edu (Sun4c/40 IPC)
+peer 128.4.1.2 # mizbeaver.udel.edu (Bancomm bc700LAN)
peer 128.4.1.4 # barnstable.udel.edu (Sun4c/65 SS1+)
-#peer 128.4.1.5 # churchy.udel.edu (Bancomm bc700LAN)
-peer 128.4.2.7 key 3 # grundoon.udel.edu (Sun4c/40 IPC)
peer 128.4.1.5 maxpoll 8 # churchy.udel.edu (cisco IGS router)
-#peer 128.4.1.8 # bridgeport.udel.edu (Sun4c/40 IPC)
-#peer 128.4.1.20 key 3 # pogo.udel.edu (Sun4c/65 SS1+)
-#peer 128.4.1.22 # malarky.udel.edu (Sun4c/50 IPX)
-#peer 128.4.1.23 # beauregard.udel.edu (Sun4/40 IPC)
-peer 128.4.1.24 # baldwin.udel.edu (Sun4/40 IPC)
-#peer 128.4.1.25 # albert.udel.edu (Sun4c/60 SS1)
-#peer 128.4.1.27 # maccarony.udel.edu (Sun4c/40 IPC)
-peer 128.4.1.29 # porkypine.udel.edu
-peer 132.163.135.130 maxpoll 8 # time_A.timefreq.bldrdoc.gov (ACTS)
+peer 132.163.135.130 maxpoll 8 # time_A.timefreq.bldrdoc.gov (Cesium)
peer 131.188.1.40 maxpoll 8 # ntps1-0.uni-erlangen.de (DCF77)
peer 129.132.2.21 maxpoll 8 # swisstime.ethz.ch (DCF77)
-peer 130.155.98.13 maxpoll 8 # terss.ml.csiro.au (OMEGA)
+peer 130.155.98.13 maxpoll 8 # terss.ml.csiro.au (Cesium)
+peer 192.36.143.150 maxpoll 8 # Time1.Stupi.SE (Cesium)
#
# Miscellaneous stuff
#
-monitor yes # enable monitoring
+enable auth monitor # enable the good stuff
precision -18 # clock reading precision (usec)
driftfile /etc/ntp.drift # path for drift file
statsdir /pogo/ntpstats/ # directory for statistics files
@@ -40,11 +27,8 @@ filegen clockstats file clockstats type day enable
#
# Authentication stuff
#
-authenticate yes # enable authentication
keys /usr/local/bin/ntp.keys # path for keys file
-trustedkey 1 2 3 4 14 15 # define trusted keys
+trustedkey 3 4 5 6 14 # define trusted keys
requestkey 15 # key (7) for accessing server variables
controlkey 15 # key (6) for accessing server variables
-#authdelay 0.000072 # authentication delay (SPARC4c/65 SS1+ DES)
authdelay 0.000159 # authentication delay (SPARC4c/65 SS1+ MD5)
-
diff --git a/usr.sbin/xntpd/conf/rackety.conf b/usr.sbin/xntpd/conf/rackety.conf
index 1a5181cd4b5c..48389dcb4529 100644
--- a/usr.sbin/xntpd/conf/rackety.conf
+++ b/usr.sbin/xntpd/conf/rackety.conf
@@ -2,11 +2,11 @@
# NTP configuration file (ntp.conf)
# rackety (128.4.1.1)
#
-server 127.127.10.1 prefer # austron 2201 gps receiver
+server 127.127.10.1 prefer # austron 2201A gps receiver
fudge 127.127.10.1 flag4 1 # enable statistics
-server 127.127.4.1 # spectracom 8170/netclock-2 wwvb receiver
-#propagation delay: wwvb 0.0088; receiver delay 0.0017
-fudge 127.127.4.1 time1 0.0017 value1 2
+server 127.127.4.1 # spectracom 8170/netclock-2 wwvb receiver
+# propagation delay: wwvb 0.0088, receiver delay 0.0173, os delay .0035
+fudge 127.127.4.1 time1 0.0035 stratum 1 flag4 1
#
# ee vaxen
@@ -18,10 +18,11 @@ peer 128.175.1.3 # dewey.udel.edu
#
# munchkins (stratum-1 only)
#
+broadcast 224.0.1.1 key 5 ttl 127 # multicast
+broadcast 128.4.1.0 key 3 # local broadcast
peer 128.4.1.2 # mizbeaver.udel.edu
-#peer 128.4.1.5 # churchy.udel.edu
-peer 128.4.2.7 key 3 # grundoon.udel.edu
-peer 128.4.1.20 key 3 # pogo.udel.edu
+peer 128.4.1.4 # barnstable.udel.edu
+peer 128.4.1.20 # pogo.udel.edu
#
# dartnet
@@ -47,14 +48,9 @@ server 140.222.141.1 version 2 # enss141 (boulder - ncar)
server 140.222.144.1 version 2 # enss144 (sunnyvale - nasa ames)
#
-# famous players
-#
-#peer 132.163.135.130 # time_A.timefreq.bldrdoc.gov
-
-#
# Miscellaneous stuff
#
-monitor yes # enable monitoring
+enable auth monitor # enable the good stuff
precision -18 # clock reading precision (usec)
driftfile /etc/ntp.drift # path for drift file
statsdir /rackety/ntpstats/ # directory for statistics files
@@ -65,11 +61,9 @@ filegen clockstats file clockstats type day enable
#
# Authentication stuff
#
-authenticate yes # enable authentication
keys /usr/local/bin/ntp.keys # path for keys file
-trustedkey 1 2 3 4 14 15 # define trusted keys
-requestkey 15 # key (7) for accessing server variables
-controlkey 15 # key (6) for accessing server variables
-#authdelay 0.000073 # authentication delay (SPARC4c/40 IPC DES)
+trustedkey 3 4 5 6 14 # define trusted keys
+requestkey 14 # key (7) for accessing server variables
+controlkey 14 # key (6) for accessing server variables
authdelay 0.000163 # authentication delay (SPARC4c/40 IPC MD5)
diff --git a/usr.sbin/xntpd/doc/README.refclock b/usr.sbin/xntpd/doc/README.refclock
new file mode 100644
index 000000000000..1b9a51034b6b
--- /dev/null
+++ b/usr.sbin/xntpd/doc/README.refclock
@@ -0,0 +1,1416 @@
+ Information on Reference Clock Drivers
+
+ Revised 5 August 1994
+
+Support for most of the commonly available radio clocks is included in
+the default configuration of xntpd. Individual clocks can be activated
+by configuration file commands, specifically the server and fudge
+commands described in the xntpd.8 man page. This file contains
+information useful in configuring and operating these clocks. Note that
+the man pages and documentation files mentioned in this note can be
+found in the ./doc directory of the xntp3 distribution.
+
+Radio clocks by convention have addresses in the form 127.127.t.u, where
+"t" is the clock type and "u" is a unit number in the range 0-3 used to
+distinguish multiple instances of clocks of the same type. Most of these
+clocks require support in the form of a serial port or special bus
+peripheral. The particular device is normally specified by adding a soft
+link /dev/device%d to the particular hardware device involved. The name
+"device" is compiled in the driver according to the table below. The
+table shows the type number, device name, short description used in some
+displays, and long description used in other displays.
+
+Type Device Name Description
+-------------------------------------------------------
+1 (none) LOCAL Undisciplined Local Clock
+2 trak GPS_TRAK TRAK 8820 GPS Receiver
+3 pst WWV_PST PSTI/Traconex WWV/WWVH Receiver
+4 wwvb WWVB_SPEC Spectracom WWVB Receiver
+5 goes GPS_GOES_TRUE TrueTime GPS/GOES Receivers
+6 irig IRIG_AUDIO IRIG Audio Decoder
+7 chu CHU Scratchbuilt CHU Receiver
+8 refclock- GENERIC Generic Reference Clock Driver
+9 gps GPS_MX4200 Magnavox MX4200 GPS Receiver
+10 gps GPS_AS2201 Austron 2201A GPS Receiver
+11 omega OMEGA_TRUE TrueTime OM-DC OMEGA Receiver
+12 tpro IRIG_TPRO KSI/Odetics TPRO/S IRIG Interface
+13 leitch ATOM_LEITCH Leitch CSD 5300 Master Clock Controller
+14 ees MSF_EES EES M201 MSF Receiver
+15 gpstm GPS_TRUE TrueTime GPS/TM-TMD Receiver
+16 * GPS_BANC Bancomm GPS/IRIG Receiver
+17 datum GPS_DATUM Datum Precision Time System
+18 acts NIST_ACTS NIST Automated Computer Time Service
+19 heath WWV_HEATH Heath WWV/WWVH Receiver
+20 nmea GPS_NMEA Generic NMEA GPS Receiver
+21 * GPS_MOTO Motorola Six Gun GPS Receiver
+22 pps ATOM_PPS PPS Clock Discipline
+
+* Not yet available.
+
+A radio clock is specified in the configuration using the server command
+
+ server 127.127.t.u [ prefer ] [ mode m ]
+
+where t is the type number above and u can be in the range 0-3,
+conventionally 1. Ordinarily, this is the only command necessary to
+configure a radio clock. The optional prefer keyword can be used to
+modify the clock selection algorithm as described in Appendix B. For
+those clock drivers that support multiple modes of operation, the
+optional mode parameter selects which one. This parameter affects the
+operation of each driver as described in Appendix A.
+
+In rare cases a fudge command is necessary to specify additional
+details. This command has the following syntax
+
+fudge 127.127.t.u [stratum s] [refid r] [time1 t1] [time2 t2] [flags]
+and must follow the corresponding server command in the configuration
+file. The optional fields following the clock address are interpreted as
+follows:
+
+stratum s The s, a decimal number in the range 0-15, overrides the
+ default stratum assigned by the driver.
+
+refid r The r, a 4-character, null-terminated ASCII string, overrides
+ the reference identifier assigned by the driver.
+
+time1 t1 The t1, a fixed-point decimal number in seconds, specifies a
+ constant to be added to the time offset produced by the
+ driver. This provides a way to correct a systematic error or
+ bias on the part of the particular clock.
+
+time2 t2 The t2, a fixed-point decimal number, is interpreted in a
+ driver-dependent way. See the descriptions of specific clock
+ drivers in Appendix A.
+
+There are four optional flags named flag1, flag2, flag3 and flag4. A
+flag is specified in the form <keyword> <value>, where <keyword> is one
+of the flag names and <value> is either 0 or 1, as appropriate. Two of
+the flags are generic and are interpreted by all applicable drivers, and
+two are driver dependent. The generic ones are as follows:
+
+flag4 This flag is used to enable detailed status monitoring and
+ event recording. The data collected are written to the
+ clockstats file maintained by the filegen utility (See the
+ xntpd.8 man page). This file is normally processed by a cron
+ job run once per day to produce summary statistics and
+ performance data. The ./scripts/stats directory contains a
+ number of shell and awk scripts for this, as well as S-
+ language programs that produce PostScript plots of performance
+ data.
+
+flag3 This flag is used with Sun SPARCstation baseboard serial ports
+ to assign the ppsclock streams driver for a 1-pps signal
+ produced by some radio clocks and timekeeping devices. See the
+ dscription of the PPS Clock Discipline Driver (type 22) in
+ Appendix A for further information.
+
+Note that the fudge factors above can be changed at run time using the
+xntpdc program (see the xntpdc.8 man page). This program does not have
+to be run on the server machine itself, since it communicates with the
+xntpd daemon using cryptographically authenticated messages.
+
+The PPS Signal
+
+Some radio clocks and related timekeeping gear have a pulse-per-second
+(PPS) signal that can be used to discipline the local clock oscillator
+to a high degree of precision, typically to the order less than 50 us in
+time and 0.1 ppm in frequency. The PPS signal can be connected in either
+of two ways, either via the data leads of a serial port or via the modem
+control leads. Either way requires conversion of the PPS signal, usually
+at TTL levels, to RS232 levels, which can be done using a circuit such
+as described in the ./gadget directory of the xntp3 distribution.
+
+The data leads interface requires regenerating the PPS pulse and
+converting to RS232 signal levels, so that the pulse looks like a
+legitimate ASCII character. The tty_clk module in the ./kernel directory
+inserts a timestamp following this character in the input data stream.
+The driver uses this timestamp to determine the time of arrival of the
+PPS pulse to within 26 us at 38.4 kbps while eliminating error due to
+operating system queues and service times. In order to use the tty_clk
+module, the xntp3 distribution must be compiled with CLK defined.
+The modem control leads interface requires converting to RS232 levels
+and connecting to the carrier detect (CD) lead of a serial port. The
+ppsclock streams module in the ./ppsclock directory is used to capture a
+timestamp upon transition of the PPS signal. The driver reads the latest
+timestamp with a designated ioctl() system call to determine the time of
+arrival of the PPS pulse to within a few tens of microseconds. In order
+to use the ppsclock module, the xntp3 distribution must be compiled with
+PPS defined.
+
+Both of these mechanisms are supported by the ATOM_PPS reference clock
+driver described in Appendix A. This driver is ordinarily used in
+conjunction with another clock driver that supports the radio clock that
+produces the PPS pulse. This driver furnishes the coarse timecode used
+to disambiguate the seconds numbering of the PPS pulse itself. The NTP
+daemon mitigates between the radio clock driver and ATOM_PPS driver as
+described in Appendix B in order to provide the most accurate time,
+while respecting the various types of equipment failures that could
+happen.
+
+For the utmost time quality, a number of Unix system kernel
+modifications can be made as described in the README.magic and
+README.kernel files. Specifically, the ppsclock module can be used to
+interface the PPS signal directly to the kernel for use as discipline
+sources for both time and frequency. These sources can be separately
+enabled and monitored using the ntp_adjtime() system call described in
+README.kernel and the ./include/sys/timex.h header file in the xntp3
+distribution. In order to use the kernel PPS signal, the xntp3
+distribution must be compiled with KERNEL_PLL defined.
+
+In some configurations may have multiple radio clocks, each with PPS
+outputs, as well as a kernel modified to use the PPS signal. In order to
+provide the highest degree of redundancy and survivability, the kernel
+PPS discipline, tty_clk module and ppsclock module may all be in use at
+the same time, each backing up the other. The sometimes complicated
+mitigation rules are described in Appendix B.
+
+Debugging Hints
+
+The ntpq and xntpdc utility programs can be used to debug reference
+clocks, either on the server itself or from another machine elsewhere in
+the network. The server is compiled, installed and started using the
+command-line switches described in the xntpd.8 man page. The first thing
+to look for are error messages on the system log. If none occur, the
+daemon has started, opened the devices specified and waiting for peers
+and radios to come up.
+
+The next step is to be sure the RS232 messages, if used, are getting to
+and from the clock. The most reliable way to do this is with an RS232
+tester and to look for data flashes as the driver polls the clock and/or
+as data arrive from the clock. Our experience is that the overwhelming
+fraction of problems occurring during installation are due to problems
+such as miswired connectors or improperly configured radio clocks at
+this stage.
+
+If RS232 messages are getting to and from the clock, the variables of
+interest can be inspected using the ntpq program and various commands
+described in the ntpq.8 man page. First, use the pe and as commands to
+display a pair of billboards showing the peer configuration and
+association IDs for all peers, including the radio clock peers. The
+assigned clock address should appear in the pe billboard and the
+association ID for it at the same relative line position in the as
+billboard. If things are operating correctly, after a minute or two
+samples should show up in the pe display line for the clock.
+
+Additional information is available with the rv and clockvar commands,
+which take as argument the association ID shown in the as billboard. The
+rv command with no argument shows the system variables, while the rv
+command with argument shows the peer variables for the clock, as well as
+any other peers of interest. The clockvar command with argument shows
+the peer variables specific to reference clock peers, including the
+clock status, device name, last received timecode (if relevant), and
+various event counters. In addition, a subset of the fudge parameters is
+included.
+
+The xntpdc utility program can be used for detailed inspection of the
+clock driver status. The most useful are the clockstat and clkbug
+commands described in the xntpdc.8 man page. While these commands permit
+getting quite personal with the particular driver involved, their use is
+seldom necessary, unless an implementation bug shows up.
+
+Most drivers write a message to the clockstats file as each timecode or
+surrogate is received from the radio clock. By convention, this is the
+last ASCII timecode (or ASCII gloss of a binary-coded one) received from
+the radio. This file is managed by the filegen facility described in the
+xntpd.8 man page and requires specific commands in the configuration
+file. This forms a highly useful record to discover anomalies during
+regular operation of the clock. The scripts included in the
+./scripts/stats directory can be run from a cron job to collect and
+summarize these data on a daily or weekly basis. The summary files have
+proven invaluable to detect infrequent misbehavior due to clock
+implementation bugs in some radios.
+
+Appendix A. Individual Driver Descriptions
+
+Following are detailed descriptions of the clock drivers, together with
+configuration data useful for special circumstances.
+
+Type 1: Undisciplined Local Clock
+
+ This is a hack to allow a machine to use its own system clock as a
+ reference clock, i.e., to free-run using no outside clock
+ discipline source. This is useful if you want to use NTP in an
+ isolated environment with no radio clock or NIST modem available.
+ Pick a machine that you figure has a good clock oscillator and
+ configure it with this driver. Set the clock using the best means
+ available, like eyeball-and-wristwatch. Then, point all the other
+ machines at this one or use broadcast (not multicast) mode to
+ distribute time.
+
+ Another application for this driver is if you want to use a
+ particular server's clock as the clock of last resort when all
+ other normal synchronization sources have gone away. This is
+ especially useful if that server has an ovenized oscillator. For
+ this you would configure this driver at a higher stratum (say 3 or
+ 4) to prevent the server's stratum from falling below that.
+
+ A third application for this driver is when an external discipline
+ source is available, such as the NIST "lockclock" program, which
+ synchronizes the local clock via a telephone modem and the NIST
+ Automated Computer Time Service (ACTS), or the Digital Time
+ Synchronization Service (DTSS), which runs on DCE machines. In this
+ case the stratum should be set at zero, indicating a bona fide
+ stratum-1 source. Exercise some caution with this, since there is
+ no easy way to telegraph via NTP that something might be wrong in
+ the discipline source itself. In the case of DTSS, the local clock
+ can have a rather large jitter, depending on the interval between
+ corrections and the intrinsic frequency error of the clock
+ oscillator. In extreme cases, this can cause clients to exceed the
+ 128-ms slew window and drop off the NTP subnet.
+
+ In the default mode the behavior of the clock selection algorithm
+ is modified when this driver is in use. The algorithm is designed
+ so that this driver will never be selected unless no other
+ discipline source is available. This can be overridden with the
+ prefer keyword of the server configuration command, in which case
+ only this driver will be selected for synchronization and all other
+ discipline sources will be ignored. This behavior is intended for
+ use when an external discipline source controls the system clock.
+
+ Fudge Factors
+
+ The stratum for this driver LCLSTRATUM is set at 3 by default, but
+ can be changed by the fudge command and/or the xntpdc utility. The
+ reference ID is "LCL" by default, but can be changed using the same
+ mechanisms. *NEVER* configure this driver to operate at a stratum
+ which might possibly disrupt a client with access to a bona fide
+ primary server, unless the local clock oscillator is reliably
+ disciplined by another source. *NEVER NEVER* configure a server
+ which might devolve to an undisciplined local clock to use
+ multicast mode.
+
+ This driver provides a mechanism to trim the local clock in both
+ time and frequency, as well as a way to manipulate the leap bits.
+ The fudge time1 parameter adjusts the time, in seconds, and the
+ fudge time2 parameter adjusts the frequency, in ppm. Both
+ parameters are additive; that is, they add increments in time or
+ frequency to the present values. (Note: The frequency cannot be
+ changed when the kernel modifications are in use - see the
+ README.kern file). The fudge flag1 and fudge flag2 bits set the
+ corresponding leap bits; for example, setting flag1 causes a leap
+ second to be added at the end of the UTC day. These bits are not
+ reset automatically when the leap takes place; they must be turned
+ off manually after the leap event.
+
+Type 2: TRAK 8820 GPS Receiver
+
+ This driver supports the TRAK 8820 GPS Station Clock. The claimed
+ accuracy at the 1-pps output is 200-300 ns relative to the
+ broadcast signal; however, in most cases the actual accuracy is
+ limited by the precision of the timecode and the latencies of the
+ serial interface and operating system.
+
+ For best accuracy, this radio requires the LDISC_ACTS line
+ discipline, which captures a timestamp at the '*' on-time character
+ of the timecode. Using this discipline the jitter is in the order
+ of 1 ms and systematic error about 0.5 ms. If unavailable, the
+ buffer timestamp is used, which is captured at the \r ending the
+ timecode message. This introduces a systematic error of 23
+ character times, or about 24 ms at 9600 bps, together with a jitter
+ well over 8 ms on Sun IPC-class machines.
+
+ Using the menus, the radio should be set for 9600 bps, one stop bit
+ and no parity. It should be set to operate in computer (no echo)
+ mode. The timecode format includes neither the year nor leap-second
+ warning. No provisions are included in this preliminary version of
+ the driver to read and record detailed internal radio status.
+
+ In operation, this driver sends a RQTS\r request to the radio at
+ initialization in order to put it in continuous time output mode.
+ The radio then sends the following message once each second:
+
+ *RQTS U,ddd:hh:mm:ss.0,q<cr><lf>
+
+ on-time = '*'
+ ddd = day of year
+ hh:mm:ss = hours, minutes, seconds
+ q = quality indicator (phase error), 0-6:
+ 0 > 20 us
+ 6 > 10 us
+ 5 > 1 us
+ 4 > 100 ns
+ 3 > 10 ns
+ 2 < 10 ns
+
+ The alarm condition is indicated by '0' at Q, which means the radio
+ has a phase error than 20 usec relative to the broadcast time. The
+ absence of year, DST and leap-second warning in this format is also
+ alarming.
+
+ The continuous time mode is disabled using the RQTX<cr> request,
+ following which the radio sends a RQTX DONE<cr><lf> response. In
+ the normal mode, other control and status requests are effective,
+ including the leap-second status request RQLS<cr>. The radio
+ responds with RQLS yy,mm,dd<cr><lf>, where yy,mm,dd are the year,
+ month and day. Presumably, this gives the epoch of the next leap
+ second, RQLS 00,00,00 if none is specified in the GPS message.
+ Specified in this form, the information is generally useless and is
+ ignored by the driver.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic.
+
+Type 3: PSTI/Traconex WWV/WWVH Receiver
+
+ This driver supports the PSTI 1010 and Traconex 1020 WWV/WWVH
+ Receivers. No specific claim of accuracy is made for these
+ receiver, but actual experience suggests that 10 ms would be a
+ conservative assumption.
+
+ The DIPswitches should be set for 9600 bps line speed, 24-hour day-
+ of-year format and UTC time zone. Automatic correction for DST
+ should be disabled. It is very important that the year be set
+ correctly in the DIPswitches; otherwise, the day of year will be
+ incorrect after 28 April of a normal or leap year. The propagation
+ delay DIPswitches should be set according to the distance from the
+ transmitter for both WWV and WWVH, as described in the
+ instructions. While the delay can be set only to within 11 ms, the
+ fudge time1 parameter can be used for vernier corrections.
+
+ Using the poll sequence QTQDQM, the response timecode is in three
+ sections totalling 50 ASCII printing characters, as concatenated by
+ the driver, in the following format:
+
+ ahh:mm:ss.fffs<cr> yy/dd/mm/ddd<cr> frdzycchhSSFTttttuuxx<cr>
+
+ on-time = first <cr>
+ hh:mm:ss.fff = hours, minutes, seconds, milliseconds
+ a = AM/PM indicator (' ' for 24-hour mode)
+ yy = year (from DIPswitches)
+ dd/mm/ddd = day of month, month, day of year
+ s = daylight-saving indicator (' ' for 24-hour mode)
+ f = frequency enable (O = all frequencies enabled)
+ r = baud rate (3 = 1200, 6 = 9600)
+ d = features indicator (@ = month/day display enabled)
+ z = time zone (0 = UTC)
+ y = year (5 = 91)
+ cc = WWV propagation delay (52 = 22 ms)
+ hh = WWVH propagation delay (81 = 33 ms)
+ SS = status (80 or 82 = operating correctly)
+ F = current receive frequency (4 = 15 MHz)
+ T = transmitter (C = WWV, H = WWVH)
+ tttt = time since last update (0000 = minutes)
+ uu = flush character (03 = ^c)
+ xx = 94 (unknown)
+
+ The alarm condition is indicated by other than '8' at A, which
+ occurs during initial synchronization and when received signal is
+ lost for an extended period; unlock condition is indicated by other
+ than "0000" in the tttt subfield at Q.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic.
+
+Type 4: Spectracom WWVB Receiver
+
+ This driver supports the Spectracom Model 8170 and Netclock/2 WWVB
+ Synchronized Clock. This clock has proven a reliable source of
+ time, except in some cases of high ambient conductive RF
+ interference. The claimed accuracy of the clock is 100 usec
+ relative to the broadcast signal; however, in most cases the actual
+ accuracy is limited by the precision of the timecode and the
+ latencies of the serial interface and operating system.
+
+ The DIPswitches on this clock should be set to 24-hour display,
+ AUTO DST off, time zone 0 (UTC), data format 0 or 2 (see below) and
+ baud rate 9600. If this clock is to used as the source for the IRIG
+ Audio Decoder (refclock_irig.c in this distribution), set the
+ DIPswitches for AM IRIG output and IRIG format 1 (IRIG B with
+ signature control).
+
+ There are two timecode formats used by these clocks. Format 0,
+ which is available with both the Netclock/2 and 8170, and format 2,
+ which is available only with the Netclock/2 and specially modified
+ 8170.
+
+ Format 0 (22 ASCII printing characters):
+
+ <cr><lf>i ddd hh:mm:ss TZ=zz<cr><lf>
+
+ on-time = first <cr>
+ hh:mm:ss = hours, minutes, seconds
+ i = synchronization flag (' ' = in synch, '?' = out synch)
+
+ The alarm condition is indicated by other than ' ' at A, which
+ occurs during initial synchronization and when received signal is
+ lost for about ten hours.
+
+ Format 2 (24 ASCII printing characters):
+
+ <cr><lf>iqyy ddd hh:mm:ss.fff ld
+
+ on-time = <cr>
+ i = synchronization flag (' ' = in synch, '?' = out synch)
+ q = quality indicator (' ' = locked, 'A'...'D' = unlocked)
+ yy = year (as broadcast)
+ ddd = day of year
+ hh:mm:ss.fff = hours, minutes, seconds, milliseconds
+
+ The alarm condition is indicated by other than ' ' at A, which
+ occurs during initial synchronization and when received signal is
+ lost for about ten hours. The unlock condition is indicated by
+ other than ' ' at Q.
+
+ The Q is normally ' ' when the time error is less than 1 ms and a
+ character in the set 'A'...'D' when the time error is less than 10,
+ 100, 500 and greater than 500 ms respectively. The L is normally '
+ ', but is set to 'L' early in the month of an upcoming UTC leap
+ second and reset to ' ' on the first day of the following month.
+ The D is set to 'S' for standard time 'I' on the day preceding a
+ switch to daylight time, 'D' for daylight time and 'O' on the day
+ preceding a switch to standard time. The start bit of the first
+ <cr> is synchronized to the indicated time as returned.
+
+ This driver does not need to be told which format is in use - it
+ figures out which one from the length of the message. A three-stage
+ median filter is used to reduce jitter and provide a dispersion
+ measure. The driver makes no attempt to correct for the intrinsic
+ jitter of the radio itself, which is a known problem with the older
+ radios.
+
+ Fudge Factors
+
+ This driver can retrieve a table of quality data maintained
+ internally by the Netclock/2 receiver. If flag4 of the fudge
+ configuration command is set to 1, the driver will retrieve this
+ table and write it to the clockstats file on when the first
+ timecode message of a new day is received.
+
+Type 5: TrueTime GPS/GOES Receivers
+
+ This driver supports at least two models of Kinemetrics/TrueTime
+ Timing Receivers, the 468-DC MK III GOES Synchronized Clock and
+ GPS-DC MK III GPS Synchronized Clock and very likely others in the
+ same model family that use the same timecode formats. The clocks
+ are connected via a serial port. Up to four units, with unit
+ numbers in the range 0 through 3, can be configured. The driver
+ assumes the serial port device name is /dev/goes%d (i.e., unit 1 at
+ 127.127.5.1 opens the clock at /dev/goes1) and that the clock is
+ configured for 9600-baud operation.
+
+Type 6: IRIG Audio Decoder
+
+ This driver supports the Inter-Range Instrumentation Group standard
+ time-distribution signal IRIG-B using the audio codec native to the
+ Sun SPARCstation. This signal is generated by several radio clocks,
+ including those made by Austron, TrueTime, Odetics and Spectracom,
+ among others, although it is generally an add-on option. The signal
+ is connected via an attenuator box and cable to the audio codec
+ input on a Sun SPARCstation and requires a specially modified
+ kernel audio driver. Details are in the README.irig file.
+
+ Timing jitter using the decoder and a Sun IPC is in the order of a
+ few microseconds, although the overall timing accuracy is limited
+ by the wander of the CPU oscillator used for timing purposes to a
+ few hundred microseconds. These figures are comparable with what
+ can be achieved using the 1-pps discipline as describe elsewhere in
+ this note.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic. The
+ flag3 and flag4 flags are not applicable to this driver.
+
+Type 7: Scratchbuilt CHU Receiver
+
+ This driver supports a shortwave receiver and special modem
+ circuitry described in the ./gadget directory of the xntp3
+ distribution. It requires the chu-clk line discipline or chu_clk
+ STREAMS module described in the ./kernel directory of that
+ distribution. It is connected via a serial port operating at 300
+ baud.
+ Unlike the NIST time services, whose timecode requires quite
+ specialized hardware to interpret, the CHU timecode can be received
+ directly via a serial port after demodulation. While there are
+ currently no known commercial CHU receivers, the hardware required
+ to receive the CHU timecode is fairly simple to build. While it is
+ possible to configure several CHU units simultaneously, this is in
+ general not useful.
+
+ Fudge Factors
+
+ The time1 option can be used to set the CHU propagation delay,
+ compensate for inherent latencies in the serial port hardware and
+ operating system. The default value is 0.0025 seconds, which is
+ about right for Toronto. Values for other locations can be
+ calculated using the propdelay program in the util directory of the
+ xntp3 distribution or equivalent means.
+
+ The time2 option can be used to compensate for inherent latencies
+ in the serial port hardware and operating system. The value, which
+ defaults to zero, is in addition to the propagation delay provided
+ by the time1 option. The default value is 0.0002 seconds, which is
+ about right for typical telephone modem chips.
+
+ The flag1 option can be used to modify the averaging algorithm used
+ to smooth the clock indications. Ordinarily, the algorithm picks
+ the median of a set of samples, which is appropriate under
+ conditions of poor to fair radio propagation conditions. If the
+ clock is located relatively close to the WWV or WWVH transmitters,
+ setting this flag will cause the algorithm to average the set of
+ samples, which can reduce the residual jitter and improve accuracy.
+
+Type 8: Generic Reference Clock Driver
+
+ The timecode of these receivers is sampled via a STREAMS module in
+ the kernel (The STREAMS module has been designed for use with SUN
+ Systems under SunOS 4.1.x. It can be linked directly into the
+ kernel or loaded via the loadable driver mechanism). This STREAMS
+ module can be adapted to be able to convert different time code
+ formats. If the daemon is
+
+ compiled without the STREAM definition synchronization will work
+ without the Sun streams module, though accuracy is significantly
+ degraded.
+
+ The actual receiver status is mapped into various synchronization
+ states generally used by receivers. The STREAMS module is
+ configured to interpret the time codes of DCF U/A 31, PZF535,
+ GPS166, Trimble SV6 GPS, ELV DCF7000, Schmid and low cost receivers
+ (see list below).
+
+ The reference clock support in xntp contains the necessary
+ configuration tables for those receivers. In addition to supporting
+ up to 32 different clock types and 4 devices, the generation a a
+ PPS signal is also provided as an configuration option. The PPS
+ configuration option uses the receiver generated time stamps for
+ feeding the PPS loopfilter control for much finer clock
+ synchronization.
+
+ CAUTION: The PPS configuration option is different from the
+ hardware PPS signal, which is also supported (see below), as it
+ controls the way xntpd is synchronized to the reference clock,
+ while the hardware PPS signal controls the way time offsets are
+ determined.
+
+ The use of the PPS option requires receivers with an accuracy of
+ better than 1ms.
+ Fudge factors
+
+ Only two fudge factors are utilized. The time1 fudge factor defines
+ the phase offset of the synchronization character to the actual
+ time. On the availability of PPS information the time2 fudge factor
+ defines the skew between the PPS time stamp and the receiver
+ timestamp of the PPS signal. This parameter is usually zero, as
+ usually the PPS signal is believed in time and OS delays should be
+ corrected in the machine specific section of the kernel driver.
+ time2 needs only be set when the actual PPS signal is delayed for
+ some reason. The flag0 enables input filtering. This a median
+ filter with continuous sampling. The flag1 selects averaging of the
+ samples remaining after the filtering. Leap secondhandling is
+ controlled with the flag2. When set a leap second will be deleted
+ on receipt of a leap second indication from the receiver. Otherwise
+ the leap second will be added, (which is the default).
+
+ ntpq (8)
+
+ timecode variable
+
+ The ntpq program can read clock variables command list several
+ variables. These hold the following information: refclock_time is
+ the local time with the offset to UTC (format HHMM). The currently
+ active receiver flags are listed in refclock_status. Additional
+ feature flags of the receiver are optionally listed in parentheses.
+ The actual time code is listed in timecode. A qualification of the
+ decoded time code format is following in refclock_format. The last
+ piece of information is the overall running time and the
+ accumulated times for the clock event states in refclock_states.
+ When PPS information is present additional variable are available.
+ refclock_ppstime lists then the PPS timestamp and refclock_ppsskew
+ lists the difference between RS232 derived timestamp and the PPS
+ timestamp.
+
+ Unit encoding
+
+ The unit field <u> encodes the device, clock type and the PPS
+ generation option. There are 4 possible units, which are encoded in
+ the lower two bits of the <u> field. The devices are named
+ /dev/refclock-0 through /dev/refclock-3. Bits 2 thru 6 encode the
+ clock type. The fudge factors of the clock type are taken from a
+ table clockinfo in refclock_parse.c. The generation of PPS
+ information for disciplining the local NTP clock is encoded in bit
+ 7 of <u>.
+
+ Currently, nine clock types (devices /dev/refclock-0 -
+ /dev/refclock-3) are supported.
+
+ 127.127.8.0-3 16
+
+ Meinberg PZF535 receiver (FM demodulation/TCXO / 50us)
+
+ 127.127.8.4-7 16
+
+ Meinberg PZF535 receiver (FM demodulation/OCXO / 50us)
+
+ 127.127.8.8-11 16
+
+ Meinberg DCF U/A 31 receiver (AM demodulation / 4ms)
+
+ 127.127.8.12-15 16
+
+ ELV DCF7000 (sloppy AM demodulation / 50ms)
+
+ 127.127.8.16-19 16
+ Walter Schmid DCF receiver Kit (AM demodulation / 1ms)
+
+ 127.127.8.20-23 16
+
+ RAW DCF77 100/200ms pulses (Conrad DCF77 receiver module / 5ms)
+
+ 127.127.8.24-27 16
+
+ RAW DCF77 100/200ms pulses (TimeBrick DCF77 receiver module / 5ms)
+
+ 127.127.8.28-31 16
+
+ Meinberg GPS166 receiver (GPS / <<1us)
+
+ 127.127.8.32-35 16
+
+ Trimble SV6 GPS receiver (GPS / <<1us)
+
+ The reference clock support carefully monitors the state
+ transitions of the receiver. All state changes and exceptional
+ events such as loss of time code transmission are logged via the
+ syslog facility. Every hour a summary of the accumulated times for
+ the clock states is listed via syslog.
+
+ PPS support is only available when the receiver is completely
+ synchronized. The receiver is believed to deliver correct time for
+ an additional period of time after losing synchronizations, unless
+ a disruption in time code transmission is detected (possible power
+ loss). The trust period is dependent on the receiver oscillator and
+ thus a function of clock type. This is one of the parameters in the
+ clockinfo field of the reference clock implementation. This
+ parameter cannot be configured by xntpdc.
+
+ In addition to the PPS loopfilter control a true PPS hardware
+ signal can be applied on Sun Sparc stations via the CPU serial
+ ports on the CD pin. This signal is automatically detected and will
+ be used for offset calculation. The input signal must be the time
+ mark for the following time code. (The edge sensitivity can be
+ selected - look into the appropriate kernel/parsestreams.c for
+ details). Meinberg receivers can be connected by feeding the PPS
+ pulse of the receiver via a 1488 level converter to Pin 8 (CD) of a
+ Sun serial zs\-port.
+
+ There exists a special firmware release for the PZF535 Meinberg
+ receivers. This release (PZFUERL 4.6 (or higher - The UERL is
+ important)) is absolutely recommended for XNTP use, as it provides
+ LEAP warning, time code time zone information and alternate antenna
+ indication. Please check with Meinberg for this firmware release.
+ For the Meinberg GPS166 receiver is also a special firmware release
+ available (Uni-Erlangen). This release must be used for proper
+ operation.
+
+ The raw DCF77 pulses can be fed via a level converter directly into
+ Pin 3 (Rx) of the Sun. The telegrams will be decoded an used for
+ synchronization. AM DCF77 receivers are running as low as $25. The
+ accuracy is dependent on the receiver and is somewhere between 2ms
+ (expensive) to 10ms (cheap). Upon bad signal reception of DCF77
+ synchronizations will cease as no backup oscillator is available as
+ usually found in other reference clock receivers. So it is
+ important to have a good place for the DCF77 antenna. For
+ transmitter shutdowns you are out of luck unless you have other NTP
+ servers with alternate time sources available.
+
+Type 9: Magnavox MX4200 GPS Receiver
+
+ This driver supports the Magnavox MX4200 Navigation Receiver
+ adapted to precision timing applications. This requires an
+ interface box described in the ./ppsclock directory of the xntp3
+ distribution. It is connected via a serial port and requires the
+ ppsclock STREAMS module described in the same directory.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic.
+
+Type 10: Austron 2201A GPS Receiver
+
+ This driver supports the Austron 2200A/2201A GPS/LORAN Synchronized
+ Clock and Timing Receiver connected via a serial port. It supports
+ several special features of the clock, including the Input Buffer
+ Module, Output Buffer Module, IRIG-B Interface Module and LORAN
+ Assist Module. It requires the RS232 Serial Interface module for
+ communication with the driver.
+
+ This receiver is capable of a comprehensive and large volume of
+ statistics and operational data. The specific data collection
+ commands and attributes are embedded in the driver source code;
+ however, the collection process can be enabled or disabled using
+ the flag4 flag. If set, collection is enabled; if not, which is the
+ default, it is disabled. A comprehensive suite of data reduction
+ and summary scripts is in the ./scripts/stats directory of the
+ xntp3 distribution.
+
+ To achieve the high accuracy this device provides, it is necessary
+ to use the ppsclock feature of the xntp3 program distribution or,
+ alternatively, to install the kernel modifications described in the
+ README.kern. The clock can be wired to provide time to a single CPU
+ or bussed in parallel to several CPUs, with one CPU controlling the
+ receiver and the others just listening. Fair accuracy can be
+ achieved in the single-CPU configuration without use of the 1-pps
+ signal, but in multiple CPU configurations accuracy is severely
+ degraded without it.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic.
+
+Type 11: TrueTime OM-DC OMEGA Receiver
+
+ This driver supports the Kinemetrics/TrueTime OMEGA-DC OMEGA
+ Synchronized Clock connected via a serial port. This clock is
+ sufficiently different from other Kinemetrics/TrueTime models that
+ a separate driver is required. Up to four units, with unit numbers
+ in the range 0 through 3, can be configured. The driver assumes the
+ serial port device name is /dev/omega%d (i.e., unit 1 at
+ 127.127.11.1 opens the clock at /dev/omega1) and that the clock is
+ configured for 9600-baud operation.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic.
+
+Type 12: KSI/Odetics TPRO/S IRIG Interface
+
+ This driver supports the KSI/Odetics TPRO and TPRO-SAT IRIG-B
+ Decoder, which is a module connected directly to the SBus of a Sun
+ workstation. The module works with the IRIG-B signal generated by
+ several radio clocks, including those made by Austron, TrueTime,
+ Odetics and Spectracom, among others, although it is generally an
+ add-on option. In the case of the TPRO-SAT, the module is an
+ integral part of a GPS receiver, which serves as the primary timing
+ source.
+
+ Using the TPRO interface as a NTP reference clock provides
+ precision time only to xntpd and its clients. With suitable kernel
+ modifications, it is possible to use the TPRO as the CPU system
+ clock, avoiding errors introduced by the CPU clock oscillator
+ wander. See the README.kernel and kern.c files for further details.
+
+Type 13: Leitch CSD 5300 Master Clock Controller
+
+ Information not available.
+
+Type 14: EES M201 MSF Receiver
+
+ This driver supports the EES M201 MSF receiver connected to a Sun
+ SPARCstation running SunOS 4.x with the "ppsclock" STREAMS module.
+
+ Fudge Factors
+
+ If flag1 is set, then the system clock is assumed to be sloppy
+ (e.g. Sun4 with 20ms clock), so samples are averaged. If flag2 is
+ set, then leaphold is set. If flag3 is set, then the sample
+ information is dumped. If flag4 is set, then the input data is
+ smoothed, and all data points are used.
+
+Type 15: TrueTime GPS/TM-TMD Receiver
+
+ Information not available.
+
+Type 16: Bancomm GPS/IRIG Receiver
+
+ Information not available.
+
+Type 17: Datum Precision Time System
+
+ Information not available.
+
+Type 18: NIST Automated Computer Time Service
+
+ This driver supports the NIST Automated Computer Time Service
+ (ACTS). It periodically dials a prespecified telephone number,
+ receives the NIST timecode data and calculates the local clock
+ correction. It designed primarily for use when neither a radio
+ clock nor connectivity to Internet time servers is available. For
+ the best accuracy, the individual telephone line/modem delay needs
+ to be calibrated using outside sources.
+
+ The ACTS is located at NIST Boulder, CO, telephone 303 494 4774. A
+ toll call from Newark, DE, costs between three and four cents,
+ although it is not clear what carrier and time of day discounts
+ apply. The modem dial string will differ depending on local
+ telephone configuration, etc., and is specified by the phone
+ command in the configuration file. The argument to this command is
+ an AT command for a Hayes compatible modem.
+
+ The accuracy produced by this driver should be in the range of a
+ millisecond or two, but may need correction due to the delay
+ characteristics of the individual modem involved. For undetermined
+ reasons, some modems work with the ACTS echo-delay measurement
+ scheme and some don't. This driver tries to do the best it can with
+ what it gets. Initial experiments with a Practical Peripherals
+ 9600SA modem here in Delaware suggest an accuracy of a millisecond
+ or two can be achieved without the scheme by using a fudge time1
+ value of 65.0 ms. In either case, the dispersion for a single call
+ involving ten samples is about 1.3 ms.
+
+ The driver can operate in either of three modes, as determined by
+ the mode parameter in the server configuration command. In mode 0
+ (automatic) the driver operates continuously at intervals depending
+ on the prediction error, as measured by the driver, usually in the
+ order of several hours. In mode 1 (backup) the driver is enabled in
+ automatic mode only when no other source of synchronization is
+ available and when more than MAXOUTAGE (3600 s) have elapsed since
+ last synchronized by other sources. In mode 2 (manual) the driver
+ operates only when enabled using a fudge flags switch, as described
+ below.
+
+ For reliable call management, this driver requires a 1200-bps modem
+ with a Hayes-compatible command set and control over the modem data
+ terminal ready (DTR) control line. Present restrictions require the
+ use of a POSIX-compatible programming interface, although other
+ interfaces may work as well. The ACTS telephone number and modem
+ setup string are hard-coded in the driver and may require changes
+ for nonstandard modems or special circumstances.
+
+ Fudge Factors
+
+ Ordinarily, the propagation time correction is computed
+ automatically by ACTS and the driver. When this is not possible or
+ erratic due to individual modem characteristics, the fudge flag2
+ switch should be set to disable the ACTS echo-delay scheme. In any
+ case, the fudge time1 parameter can be used to adjust the
+ propagation delay as required.
+
+ The ACTS call interval is determined in one of three ways. In
+ manual mode a call is initiated by setting fudge flag1 using
+ xntpdc, either manually or via a cron job. In automatic mode this
+ flag is set by the peer timer, which is controlled by the sys_poll
+ variable in response to measured errors. In backup mode the driver
+ is ordinarily asleep, but awakes (in automatic mode) if all other
+ synchronization sources are lost. In either automatic or backup
+ modes, the call interval increases as long as the measured errors
+ do not exceed the value of the fudge time2 parameter.
+
+ When the fudge flag1 is set, the ACTS calling program is activated.
+ This program dials each number listed in the phones command of the
+ configuration file in turn. If a call attempt fails, the next
+ number in the list is dialed. The fudge flag1 and counter are reset
+ and the calling program terminated if (a) a valid clock update has
+ been determined, (b) no more numbers remain in the list, (c) a
+ device fault or timeout occurs, or (d) fudge flag1 is reset
+ manually using xntpdc.
+
+ The NIST timecode message is transmitted at 1200 bps in the
+ following format (see the driver source for more information):
+
+ jjjjj yy-mm-dd hh:mm:ss tt l uuu mmmmm UTC(NIST) *
+
+ jjjjj = modified Julian day
+ yy-mm-dd = year, month, day
+ hh:mm:ss = hours, minutes, seconds
+ tt = DST indicator (see driver listing)
+ l = leap-second warning (see driver listing)
+ uuu = DUT1 correction (see driver listing)
+ mmmmm = modem calibration (see driver listing)
+ on-time = '*'
+
+ The timecode message is transmitted continuously after a signon
+ banner, which this driver ignores. The driver also ignores all but
+ the yy-mm-dd, hh:mm:ss and on-time character '*' fields, although
+ it checks the format of all fields of the message. A timestamp is
+ captured at the '*' character, as required by the ACTS
+ specification, and used as the reference time of the timecode. If a
+ message with an on-time character of '#' is received, the driver
+ updates the propagation delay. The driver disconnects when (a) ten
+ valid messages have been received, (b) no message has been received
+ for 15 s, (c) an on-time character of '#' is received. These
+ messages are processed by a trimmed-mean filter to reduce timing
+ noise and then by the usual NTP algorithms to develop the clock
+ correction.
+
+ The behavior of the clock selection algorithm is modified when this
+ driver is in use. The algorithm is designed so that this driver
+ will never be selected unless no other discipline source is
+ available. This can be overridden with the prefer keyword of the
+ server configuration command, in which case only this driver will
+ be selected for synchronization and all other discipline sources
+ will be ignored. Ordinarily, the prefer keyword would be used only
+ in automatic mode ehen primary time is to be obtained via ACTS and
+ backup NTP peers used only when ACTS fails.
+
+ Call Management
+
+ Since ACTS will be a toll call in most areas of the country, it is
+ necessary to carefully manage the calling interval. The ACTS call
+ program is initiated by setting fudge flag1. This flag can be set
+ manually using xntpdc, by a cron job that calls xntpdc, or
+ automatically by the driver itself. The fudge flag1 is reset when
+ the program terminates after a time determination is comlete or
+ when no more numbers remain in the alternate path list, a device
+ fault or timeout has occured, or the fudge flag1 has been reset
+ using xntpdc.
+
+ In automatic and backup modes, the driver determines the call
+ interval using a procedure depending on the measured prediction
+ error and the fudge time2 parameter. If the error exceeds time2 for
+ a number of times depending on the current interval, the interval
+ is decreased, but not less than about 1000 s. If the error is less
+ than time2 for some number of times, the interval is increased, but
+ not more than about 18 h. With the default value of zero for fudge
+ time2, the interval will increase from 1000 s to the 4000-8000-s
+ range, in which the expected accuracy should be in the 1-2-ms
+ range. Setting fudge time2 to a large value, like 0.1 s, may result
+ in errors of that order, but increase the call interval to the
+ maximum. The exact value for each configuration will depend on the
+ modem and operating system involved, so some experimentation may be
+ necessary.
+
+ Manual call attempts can be made at any time by setting fudge flag1
+ using xntpdc. For example, the xntpdc command
+
+ fudge 127.127.18.1 flags 1
+
+ will ask for a key identifier and password and, if authenticated by
+ the server, will set flag1. There may be a short delay until the
+ expiration of the current poll timeout.
+
+ The flag1 can be set from a cron job in the following way.
+ Construct a file with contents
+
+ keyid 11
+ passwd dialup
+ fudge 127.127.18.1 flags 1
+ quit
+
+ Then, run the following program at specified times as required.
+
+ /usr/local/bin/xntpdc <file
+
+Type 19: Heath WWV/WWVH Receiver
+
+ This driver supports the Heath GC-1000 Most Accurate Clock, with
+ RS232C Output Accessory. This is a WWV/WWVH receiver somewhat less
+ robust than other supported receivers. Its claimed accuracy is 100
+ ms when actually synchronized to the broadcast signal, but this
+ doesn't happen even most of the time, due to propagation
+ conditions, ambient noise sources, etc. When not synchronized, the
+ accuracy is at the whim of the internal clock oscillator, which can
+ wander into the sunset without warning. Since the indicated
+ precision is 100 ms, expect a host synchronized only to this thing
+ to wander to and fro, occasionally being rudely stepped when the
+ offset exceeds the default CLOCK_MAX of 128 ms.
+
+ The internal DIPswitches should be set to operate at 1200 baud in
+ MANUAL mode and the current year. The external DIPswitches should
+ be set to GMT and 24-hour format. It is very important that the
+ year be set correctly in the DIPswitches. Otherwise, the day of
+ year will be incorrect after 28 April of a normal or leap year.
+
+ In MANUAL mode the clock responds to a rising edge of the request
+ to send (RTS) modem control line by sending the timecode.
+ Therefore, it is necessary that the operating system implement the
+ TIOCMBIC and TIOCMBIS ioctl system calls and TIOCM_RTS control bit.
+ Present restrictions require the use of a POSIX-compatible
+ programming interface, although other interfaces may work as well.
+
+ The clock message consists of 23 ASCII printing characters in the
+ following format:
+
+ hh:mm:ss.f dd/mm/yr<cr>
+
+ hh:mm:ss.f = hours, minutes, seconds
+ f = deciseconds ('?' when out of spec)
+ dd/mm/yr = day, month, year
+
+ The alarm condition is indicated by '?', rather than a digit, at A.
+ Note that 0?:??:??.? is displayed before synchronization is first
+ established and hh:mm:ss.? once synchronization is established and
+ then lost again for about a day.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic. A fudge
+ time1 value of .07 s appears to center the clock offset residuals.
+
+Type 20: Generic NMEA GPS Receiver
+
+ Information not available.
+
+Type 21: Motorola Six Gun GPS Receiver
+
+ Information not available.
+
+Type 22: PPS Clock Discipline
+
+ This driver furnishes an interface for pulse-per-second (PPS)
+ signals produced by a cesium clock, timing receiver or related
+ equipment. It can be used to remove accumulated jitter and retime a
+ secondary server when synchronized to a primary server over a
+ congested, wide-area network and before redistributing the time to
+ local clients. Note that this driver does not control the system
+ clock if the kernel modifications described in the README.kernel
+ file have been installed, but it can be useful as a monitoring
+ tool.
+
+ In order for this driver to work, the local clock must be set to
+ within +-500 ms by another means, such as a radio clock or NTP
+ itself. The 1-pps signal is connected via a serial port and gadget
+ box consisting of a one-shot and RS232 level converter. When
+ operated at 38.4 kbps with a SPARCstation IPC, this arrangement has
+ a worst-case jitter less than 26 us.
+
+ There are three ways in which this driver can be used. The first
+ way uses the LDISC_PPS line discipline and works only for the
+ baseboard serial ports of the Sun SPARCstation. The PPS signal is
+ connected via a gadget box to the carrier detect (CD) line of a
+ serial port and flag3 of the driver configured for that port is
+ set. This causes the ppsclock streams module to be configured for
+ that port and capture a timestamp at the on-time transition of the
+ PPS signal. This driver then reads the timestamp directly by a
+ designated ioctl() system call. This provides the most accurate
+ time and least jitter of any other scheme. There is no need to
+ configure a dedicated device for this purpose, which ordinarily is
+ the device used for the associated radio clock.
+
+ The second way uses the LDISC_CLKPPS line discipline and works for
+ any architecture supporting a serial port. If after a few seconds
+ this driver finds no ppsclock module configured, it attempts to
+ open a serial port device /dev/pps%d, where %d is the unit number,
+ and assign the LDISC_CLKPPS line discipline to it. If the line
+ discipline fails, no harm is done except the accuracy is reduced
+ somewhat. The pulse generator in the gadget box is adjusted to
+ produce a start bit of length 26 us at 38400 bps (or 104 us at 9600
+ bps). Used with the LDISC_CLKPPS line discipline, this produces an
+ ASCII DEL character ('\377') followed by a timestamp at each
+ seconds epoch.
+
+ The third way involves an auxiliary radio clock driver which calls
+ the PPS driver with a timestamp captured by that driver. This use
+ is documented in the source code for the driver(s) involved.
+
+ Fudge Factors
+
+ There are no special fudge factors other than the generic and those
+ explicitly defined above. The fudge time1 parameter can be used to
+ compensate for miscellaneous UART and OS delays. Allow about 247 us
+ for uart delays at 38400 bps and about 1 ms for SunOS streams
+ nonsense.
+
+Appendix B. Mitigation Rules
+
+In order to provide robust backup sources, stratum-1 peers are usually
+operated in a diversity configuration, in which the local server
+operates with a number of remote peers in addition with one or more
+radio clocks operating also as local peers. In these configurations the
+suite of algorithms used in NTP to refine the data from each peer
+separately and to select and weight the data from a number of peers can
+be used with the entire ensemble of remote peers and local radios.
+However, Because of small but significant systematic time offsets
+between the peers, it is in general not possible to achieve the lowest
+jitter and highest stability in these configurations. In addition, there
+are a number of special configurations involving auxiliary radio clock
+outputs, telephone backup services and other special cases, so that a
+set of mitigation rules becomes necessary.
+
+The mitigation rules are based on a set of special characteristics of
+the various reference clock drivers configured on the server. For
+instance, it is possible to designate a peer as "preferred," in which
+case, all other things being equal, this peer will be selected for
+synchronization over all other eligible candidates in the clock
+selection procedures. The precise characterization of the prefer peer is
+described below. In addition, when a pulse-per-second (PPS) signal is
+connected via the PPS Clock Discipline Driver (type 22), the
+corresponding peer is called the PPS peer. The manner in which this peer
+operates is described below. When the Undisciplined Local Clock Driver
+(type 1) is configured in the server, this becomes the local-clock peer.
+When the Automated Computer Time Service Driver (type 18) is configured
+in the server, this becomes the ACTS peer. Both the local-clock and ACTS
+peers operates in the manner described in Appendix A. Finally, where
+support is available, the PPS signal may be processed directly by the
+kernel. In the following this will be called the kernel discipline.
+
+The mitigation rules apply in the clock selection procedures following
+the sanity checks, intersection algorithm and clustering algorithm. The
+survivors at this point represent the subset of all peers which can
+provide the most accurate, stable time. In the general case, with no
+designated prefer peer, PPS peer or local-clock peer, the mitigation
+rules require all survivors be averaged according to a weight depending
+on the reciprocal of the dispersion, as provided in the NTP
+specification.
+
+The mitigation rules establish the choice of system peer, which
+determine the stratum, reference identifier and several other system
+variables which are visible to clients of the local server. In addition,
+they establish which source or combination of sources control the local
+clock. In detail, these rules operate as follows:
+
+1. If there is a prefer peer and it is the local-clock peer or the
+ ACTS peer; or, if there is a prefer peer and the kernel discipline
+ is active, choose the prefer peer as the system peer.
+
+2. If the above is not the case and there is a PPS peer, then choose
+ it as the system peer and its offset as the system clock offset.
+
+3. If the above is not the case and there is a prefer peer (not the
+ local-clock or ACTS peer in this case), then choose it as the
+ system peer and its offset as the system clock offset.
+
+4. If the above is not the case and the peer previously chosen as the
+ system peer is in the surviving population, then choose it as the
+ system peer and average its offset along with the other survivors
+ to determine the system clock offset. This behavior is designed to
+ avoid excess jitter due to "clockhopping," when switching the
+ system peer would not materially improve the time accuracy.
+
+5. If the above is not the case, then choose the first candidate in
+ the list of survivors ranked in order of synchronization distance
+ and average its offset along with the other survivors to determine
+ the system clock offset. This is the default case and the only case
+ considered in the current NTP specification.
+
+The specific interpretation of the prefer peer and PPS peer require some
+explanation, which is given in following sections.
+
+B.1. Using the prefer Keyword
+
+For the reasons stated previously, a scheme has been implemented in NTP
+to provide an intelligent mitigation between various classes of peers,
+one designed to provide the best quality time without compromising the
+normal operation of the NTP algorithms. This scheme in its present form
+is not an integral component of the NTP specification. but is likely to
+be included in future versions of the specification. The scheme is based
+on the "preferred peer," which is specified by including the prefer
+keyword with the associated server or peer command in the configuration
+file. This keyword can be used with any peer or server, but is most
+commonly used with a radio clock server.
+
+The prefer scheme works on the set of peers that have survived the
+sanity and intersection algorithms of the clock select procedures.
+Ordinarily, the members of this set can be considered truechimers and
+any one of them could in principle provide correct time; however, due to
+various error contributions, not all can provide the most stable time.
+The job of the clustering algorithm, which is invoked at this point, is
+to select the best subset of the survivors providing the least variance
+in the combined ensemble compared to the variance in each member of the
+subset. The detailed operation of the clustering algorithm, which are
+given in the specification, are not important here, other than to point
+out it operates in rounds, where a survivor, presumably the worst of the
+lot, is discarded in each round until one of several termination
+conditions is met.
+
+In the prefer scheme the clustering algorithm is modified so that the
+prefer peer is never discarded; on the contrary, its potential removal
+becomes a termination condition. If the original algorithm were about to
+toss out the prefer peer, the algorithm terminates right there. The
+prefer peer can still be discarded by the sanity and intersection
+algorithms, of course, but it will always survive the clustering
+algorithm. A preferred peer retains that designation as long as it
+survives the intersection algorithm. If for some reason the prefer peer
+fails to survive the intersection algorithm, either because it was
+declared a falseticker or became unreachable, it loses that designation
+and the clock selection remitigates as described above.
+
+Along with this behavior, the clock select procedures are modified so
+that the combining algorithm is not used when a prefer (or PPS) peer is
+present. Instead, the offset of the prefer (or PPS) peer is used
+exclusively as the synchronization source. In the usual case involving a
+radio clock and a flock of remote stratum-1 peers, and with the radio
+clock designated a prefer peer, the result is that the high quality
+radio time disciplines the server clock as long as the radio itself
+remains operational and with valid time, as determined from the remote
+peers, sanity algorithm and intersection algorithm.
+
+While the model does not forbid it, it does not seem useful to designate
+more than one peer as preferred, since the additional complexities to
+mitigate among them do not seem justified from on the air experience.
+Note that the prefer peer interacts with the PPS peer discussed in
+Appendix C. It also interacts with the Undisciplined Local Clock Driver
+(type 1), as described in Appendix A. See the main text for the
+mitigation rules applying to the general case.
+
+B.2. Using the Pulse-per-Second (PPS) Signal
+
+Most radio clocks are connected using a serial port operating at speeds
+of 9600 bps or lower. The accuracy using typical timecode formats, where
+the on-time epoch is indicated by a designated ASCII character, like
+carriage-return <cr>, is limited to a millisecond at best and a few
+milliseconds in typical cases. However, some radios produce a precision
+pulse-per-second (PPS) signal which can be used to improve the accuracy
+in typical workstation servers to the order of a few tens of
+microseconds. The details of how this can be accomplished are discussed
+in the README.magic file; the following discusses how this signal is
+implemented and configured in a typical working server.
+
+First, it should be pointed out that the PPS signal is inherently
+ambiguous, in that it provides a precise seconds epoch, but does not
+provide a way to number the seconds. In principle and most commonly,
+another source of synchronization, either the timecode from an
+associated radio clock, or even a set of remote peers, is available to
+perform that function. In all cases a specific, configured peer or
+server must be designated as associated with the PPS signal. This is
+done by including the prefer keyword with the associated server or peer
+command in the configuration file. This PPS signal can be associated in
+this way any peer or server, but is most commonly used with the radio
+clock generating the PPS signal.
+
+The PPS signal is processed by a special PPS Clock Discipline Driver
+(type 22) described in Appendix A. That description specifies the
+hardware configurations in which this signal can be connected to the
+server. This driver replaces the former scheme based on conditional
+compilation and the PPS, CLK and PPSCLK compile-time switches.
+Regardless of method, the driver, like all other drivers, is mitigated
+in the manner described for the prefer peer in Appendix B. However, in
+the case of the PPS peer, the behavior is slightly more complex.
+
+First, in order for the PPS peer to be considered at all, its associated
+prefer peer must have survived the sanity and intersection algorithms
+and have been designated the prefer peer. This insures that the radio
+clock hardware is operating correctly and that, presumably, the PPS
+signal is operating correctly as well. Second, the absolute time offset
+from that peer must be less than CLOCK_MAX, the gradual-adjustment
+range, which is ordinarily set at 128 ms, or well within the +-0.5-s
+unambiguous range of the PPS signal itself. Finally, the time offsets
+generated by the PPS peer are propagated via the clock filter to the
+clock selection procedures just like any other peer. Should these pass
+the sanity and intersection algorithms, they will show up along with the
+offsets of the prefer peer itself. Note that, unlike the prefer peer,
+the PPS peer samples are not protected from discard by the clustering
+algorithm. These complicated procedures insure that the PPS offsets
+developed in this way are the most accurate, reliable available for
+synchronization.
+
+A PPS peer retains that designation as long as it survives the
+intersection algorithm; however, like any other clock driver, it runs a
+reachability algortihm on the PPS signal itself. If for some reason the
+signal fails or displays gross errors, the PPS peer will either become
+unreachable or stray out of the survivor population. In this case the
+clock selection remitigates as described above.
+
+Finally, the mitigation procedures described above for the prefer peer
+are modified so that, if the PPS peer survives the clustering algorithm,
+its offset is mitigated over the prefer peer offset; in other words in
+case of ties, the PPS offset wins. See the main text for the mitigation
+rules applying to the general case.
+
+B.3. Using the Kernel Discipline
+
+Code to implement the kernel discipline is a special feature that can be
+incorporated in the kernel of some workstations as described in the
+README.kernel file. The discipline provides for the control of the local
+clock oscillator time and/or frequency by means of an external PPS
+signal interfaced via a modem control lead. As the PPS signal is derived
+from external equipment, cables, etc., which sometimes fail, a good deal
+of error checking is done in the kernel to detect signal failure and
+excessive noise.
+
+In order to operate, the kernel discipline must be enabled and the
+signal must be present and within nominal jitter and wander error
+tolerances. In the NTP daemon the kernel is enabled only when the prefer
+peer is among the survivors of the clustering algorithm, as described
+above. Then, the PPS peer is designated the prefer peer as long as the
+PPS signal is present and operating within tolerances. Under these
+conditions the kernel disregards updates produced by the NTP daemon and
+uses its internal PPS source instead. The kernel maintains a watchdog
+timer for the PPS signal; if the signal has not been heard or is out of
+tolerance for more than some interval, currently two minutes, the kernel
+discipline is declared inoperable and operation continues as if it were
+not present.
+Appendix C. NTP Local Clock Discipline
+
+Implementation of the ACTS driver caused somewhat of a shakeup in the
+NTP local clock model and implementation. The model described in the
+specification RFC-1305 is based on a phase-lock loop (PLL) design, which
+is optimum or near optimum for the update intervals used for NTP peers
+and radio clocks, ordinarily in the range 64-1024 s. However, the ACTS
+driver must operate with update intervals in the range well above 1024
+s, where the performance of the PLL model deteriorates. As suggested by
+Judah Levine of NIST and used in his "lockclock" algorithm, a hybrid
+frequency-lock loop (FLL) gives better performance at the longer update
+intervals up to a maximum depending on the acceptable error bound.
+
+In a series of experiments and simulations, it was verified that the PLL
+model provides better performance in the regime less than about 1000 s,
+while the FLL model provides better performance above that. The
+parameters of each model were optimized by simulation for the lowest
+time and frequency error using data collected on an undisciplined
+computer clock oscillator over a period of about two weeks. The PLL/FLL
+hybrid loop has been implemented in NTP, along with certain other
+refinements described below. While it was designed primarily with ACTS
+in mind, it can be used with any NTP peer or radio clock, should that
+prove useful.
+
+To take advantage of this feature for other than the ACTS driver, where
+it is automatic, note that the default minimum poll interval is 64 s and
+default maximum poll interval 1024 s (for the ACTS driver the default
+minimum is 1024 s and default maximum 16384 s). However, using the
+minpoll and/or maxpoll parameters of the server or peer commands in the
+configuration file, it is possible to set the minimum poll interval as
+low as 16 s and the maximum poll interval as high as 16384 s. Poll
+intervals less than 64 s are useful if an exceptionally quick lock is
+required, like in real-time or portable systems. Poll intervals above
+1024 s, other than ACTS, may be useful to reduce traffic in some
+situations, such as when charges are made on a per-packet basis.
+
+Another modification to the stock NTP local clock discipline is to avoid
+errors due to old data. From a study of the stability characteristics of
+typical computer clock oscillators using both experiment and simulation,
+it was determined that data used to discipline the PLL are not generally
+useful if older than about 1000 s. This corresponds roughly to the knee
+in the Allan variance characteristic measured for a typical workstation
+oscillator. The NTP clock filter algorithm was modified to adjust the
+effective length of the shift register so that samples older than about
+1000 s are not used to determine the filtered offset, delay and
+dispersion values. This design has the useful byproduct that the time to
+acquire lock when first coming up and to declare unreachability is
+independent of the poll interval.
+
+A problem which has recurred on every occasion a leap second has been
+inserted in the UTC timescale is that not all radio clocks detect and
+implement the leap event. As a result, some radios sail right through
+the leap, become confused for periods up to 15 minutes, then reacquire
+lock. In order to cope with this, as well as other occasions where
+atypically large offsets occur, the NTP clock discipline has been
+modified to disregard offsets over 128 ms, unless (a) first coming up,
+(b) first returning to service after a period when unsynchronized, or
+(c) an interval of about 15 minutes has elapsed since the last update
+less than 128 ms was received. In addition, the discipline has been
+modified so that, if the first offset received after coming up is less
+than 128 ms, the local clock is immediately reset to that offset without
+affecting the PLL variables.
+
+It has been the experience of some users that, when first installed in a
+system, the NTP clock discipline fails to reliably lock to other peers
+and servers as configured. The indications are that the daemon locks for
+some period of time, but is unable to stabilize the frequency estimate.
+As the result, the time offsets eventually climb above 128 ms and the
+discipline unlocks again. After the 15-minute timeout, the daemon locks
+again and the cycle repeats. The problem here is that the intrinsic
+frequency error of the local clock exceeds the design capture range of
+the PLL, 100 ppm. This particular limit was selected as a compromise
+between useful maximum error indications and the tolerances found in
+typical computer clock oscillators.
+
+In spite of the tolerance assumed in the NTP specification of 100 ppm,
+the NTP daemon for Unix can operate with an intrinsic frequency error of
+over 380 ppm, depending on the values of tick and tickadj selected by
+the tickadj program. However, with errors that large, the PLL will not
+reliably lock, and the behavior noted above can occur. Formerly, the
+only remedial in cases where this happens waas a somewhat painful manual
+process where the nominal oscillator frequency is measured by some other
+means, such as eyeball-and-wristwatch, and a specific drift file
+(ntp.drift) crafted.
+
+In order to avoid the above problem, the NTP clock discipline has been
+modified to measure the frequency during periods when not locked to
+another server or radio clock. Such periods occur when the time offset
+wanders through and beyond the 128-ms window as described above. When
+synchronization is reestablished, the working frequency used by NTP is
+initialized with the measured value. Since a precise frequency
+determination is not always possible under these chaotic conditions, it
+may take more than one cycle of this type to get the residual error
+below 100 ppm and reliable lock established.
+
+David L. Mills <mills@udel.edu>
+Electrical Engineering Department
+University of Delaware
+Newark, DE 19716
+302 831 8247 fax 302 831 4316
+
+3 July 1994
diff --git a/usr.sbin/xntpd/doc/acts.c b/usr.sbin/xntpd/doc/acts.c
new file mode 100644
index 000000000000..7d3733b477d1
--- /dev/null
+++ b/usr.sbin/xntpd/doc/acts.c
@@ -0,0 +1,878 @@
+/*
+ * refclock_acts - clock driver for the NIST Automated Computer Time
+ * Service aka Amalgamated Containerized Trash Service (ACTS)
+ */
+#if defined(REFCLOCK) && defined(ACTS)
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_unixtime.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the NIST Automated Computer Time Service (ACTS).
+ * It periodically dials a prespecified telephone number, receives the
+ * NIST timecode data and calculates the local clock correction. It is
+ * designed primarily for use as a backup when neither a radio clock nor
+ * connectivity to Internet time servers is available. For the best
+ * accuracy, the individual telephone line/modem delay needs to be
+ * calibrated using outside sources.
+ *
+ * The ACTS is located at NIST Boulder, CO, telephone 303 494 4774. A
+ * toll call from a residence telephone in Newark, DE, costs between 14
+ * and 27 cents, depending on time of day, and from a campus telephone
+ * between 3 and 4 cents, although it is not clear what carrier and time
+ * of day discounts apply in this case. The modem dial string will
+ * differ depending on local telephone configuration, etc., and is
+ * specified by the phone command in the configuration file. The
+ * argument to this command is an AT command for a Hayes compatible
+ * modem.
+ *
+ * The accuracy produced by this driver should be in the range of a
+ * millisecond or two, but may need correction due to the delay
+ * characteristics of the individual modem involved. For undetermined
+ * reasons, some modems work with the ACTS echo-delay measurement scheme
+ * and some don't. This driver tries to do the best it can with what it
+ * gets. Initial experiments with a Practical Peripherals 9600SA modem
+ * here in Delaware suggest an accuracy of a millisecond or two can be
+ * achieved without the scheme by using a fudge time1 value of 65.0 ms.
+ * In either case, the dispersion for a single call involving ten
+ * samples is about 1.3 ms.
+ *
+ * The driver can operate in either of two modes, as determined by the
+ * mode parameter in the server configuration command. In mode 0 the
+ * driver operates continuously at intervals determined by the fudge
+ * time1 parameter, as described above. In mode 1 the driver is enabled
+ * only when no other sources of synchronization are available and when
+ * we have gone more than MAXOUTAGE (3600 s) since last synchronized by
+ * other sources of synchronization.
+ *
+ * For reliable call management, this driver requires a 1200-bps modem
+ * with a Hayes-compatible command set and control over the modem data
+ * terminal ready (DTR) control line. Present restrictions require the
+ * use of a POSIX-compatible programming interface, although other
+ * interfaces may work as well. The modem setup string is hard-coded in
+ * the driver and may require changes for nonstandard modems or special
+ * circumstances.
+ *
+ * Further information can be found in the README.refclock file in the
+ * xntp3 distribution.
+ *
+ * Fudge Factors
+ *
+ * Ordinarily, the propagation time correction is computed automatically
+ * by ACTS and the driver. When this is not possible or erratic due to
+ * individual modem characteristics, the fudge flag2 switch should be
+ * set to disable the ACTS echo-delay scheme. In any case, the fudge
+ * time1 parameter can be used to adjust the propagation delay as
+ * required.
+ *
+ * The ACTS call interval is determined in one of three ways. In MANUAL
+ * mode a call is initiated by setting fudge flag1 using xntpdc, either
+ * manually or via a cron job. In AUTO mode this flag is set by the peer
+ * timer, which is controlled by the sys_poll variable in response to
+ * measured errors. In BACKUP mode the driver is ordinarily asleep, but
+ * awakes (in AUTO mode) if all other synchronization sources are lost.
+ * In either AUTO or BACKUP modes, the call interval increases as long
+ * as the measured errors do not exceed the value of the fudge time2
+ * parameter.
+ *
+ * When the fudge flag1 is set, the ACTS calling program is activated.
+ * This program dials each number listed in the phones command of the
+ * configuration file in turn. If a call attempt fails, the next number
+ * in the list is dialed. The fudge flag1 and counter are reset and the
+ * calling program terminated if (a) a valid clock update has been
+ * determined, (b) no more numbers remain in the list, (c) a device
+ * fault or timeout occurs or (d) fudge flag1 is reset manually using
+ * xntpdc.
+ */
+
+/*
+ * DESCRIPTION OF THE AUTOMATED COMPUTER TELEPHONE SERVICE (ACTS)
+ * (reformatted from ACTS on-line computer help information)
+ *
+ * The following is transmitted (at 1200 baud) following completion of
+ * the telephone connection.
+ *
+ * National Institute of Standards and Technology
+ * Telephone Time Service, Generator 3B
+ * Enter question mark "?" for HELP
+ * D L D
+ * MJD YR MO DA H M S ST S UT1 msADV <OTM>
+ * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:16 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:17 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:18 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:19 50 0 +.1 037.6 UTC(NIST) #
+ * 47999 90-04-18 21:39:20 50 0 +.1 037.6 UTC(NIST) #
+ * etc..etc...etc.......
+ *
+ * UTC = Universal Time Coordinated, the official world time referred to
+ * the zero meridian.
+ *
+ * DST Daylight savings time characters, valid for the continental
+ * U.S., are set as follows:
+ *
+ * 00 We are on standard time (ST).
+ * 01-49 Now on DST, go to ST when your local time is 2:00 am and
+ * the count is 01. The count is decremented daily at 00
+ * (UTC).
+ * 50 We are on DST.
+ * 51-99 Now on ST, go to DST when your local time is 2:00 am and
+ * the count is 51. The count is decremented daily at 00
+ * (UTC).
+ *
+ * The two DST characters provide up to 48 days advance notice of a
+ * change in time. The count remains at 00 or 50 at other times.
+ *
+ * LS Leap second flag is set to "1" to indicate that a leap second is
+ * to be added as 23:59:60 (UTC) on the last day of the current UTC
+ * month. The LS flag will be reset to "0" starting with 23:59:60
+ * (UTC). The flag will remain on for the entire month before the
+ * second is added. Leap seconds are added as needed at the end of
+ * any month. Usually June and/or December are chosen.
+ *
+ * The leap second flag will be set to a "2" to indicate that a
+ * leap second is to be deleted at 23:59:58--00:00:00 on the last
+ * day of the current month. (This latter provision is included per
+ * international recommendation, however it is not likely to be
+ * required in the near future.)
+ *
+ * DUT1 Approximate difference between earth rotation time (UT1) and
+ * UTC, in steps of 0.1 second: DUT1 = UT1 - UTC.
+ *
+ * MJD Modified Julian Date, often used to tag certain scientific data.
+ *
+ * The full time format is sent at 1200 baud, 8 bit, 1 stop, no parity.
+ * The format at 300 Baud is also 8 bit, 1 stop, no parity. At 300 Baud
+ * the MJD and DUT1 values are deleted and the time is transmitted only
+ * on even seconds.
+ *
+ * Maximum on line time will be 56 seconds. If all lines are busy at any
+ * time, the oldest call will be terminated if it has been on line more
+ * than 28 seconds, otherwise, the call that first reaches 28 seconds
+ * will be terminated.
+ *
+ * Current time is valid at the "on-time" marker (OTM), either "*" or
+ * "#". The nominal on-time marker (*) will be transmitted 45 ms early
+ * to account for the 8 ms required to send 1 character at 1200 Baud,
+ * plus an additional 7 ms for delay from NIST to the user, and
+ * approximately 30 ms "scrambler" delay inherent in 1200 Baud modems.
+ * If the caller echoes all characters, NIST will measure the round trip
+ * delay and advance the on-time marker so that the midpoint of the stop
+ * bit arrives at the user on time. The amount of msADV will reflect the
+ * actual required advance in milliseconds and the OTM will be a "#".
+ *
+ * (The NIST system requires 4 or 5 consecutive delay measurements which
+ * are consistent before switching from "*" to "#". If the user has a
+ * 1200 Baud modem with the same internal delay as that used by NIST,
+ * then the "#" OTM should arrive at the user within +-2 ms of the
+ * correct time.
+ *
+ * However, NIST has studied different brands of 1200 Baud modems and
+ * found internal delays from 24 ms to 40 ms and offsets of the "#" OTM
+ * of +-10 ms. For many computer users, +-10 ms accuracy should be more
+ * than adequate since many computer internal clocks can only be set
+ * with granularity of 20 to 50 ms. In any case, the repeatability of
+ * the offset for the "#" OTM should be within +-2 ms, if the dial-up
+ * path is reciprocal and the user doesn't change the brand or model of
+ * modem used.
+ *
+ * This should be true even if the dial-up path on one day is a land-
+ * line of less than 40 ms (one way) and on the next day is a satellite
+ * link of 260 to 300 ms. In the rare event that the path is one way by
+ * satellite and the other way by land line with a round trip
+ * measurement in the range of 90 to 260 ms, the OTM will remain a "*"
+ * indicating 45 ms advance.
+ *
+ * For user comments write:
+ * NIST-ACTS
+ * Time and Frequency Division
+ * Mail Stop 847
+ * 325 Broadway
+ * Boulder, CO 80303
+ *
+ * Software for setting (PC)DOS compatable machines is available on a
+ * 360-kbyte diskette for $35.00 from: NIST Office of Standard Reference
+ * Materials B311-Chemistry Bldg, NIST, Gaithersburg, MD, 20899, (301)
+ * 975-6776
+ */
+
+/*
+ * Interface definitions
+ */
+#define DEVICE "/dev/acts%d" /* device name and unit */
+#define SPEED232 B1200 /* uart speed (1200 cowardly baud) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define REFID "ACTS" /* reference ID */
+#define DESCRIPTION "NIST Automated Computer Time Service" /* WRU */
+
+#define MODE_AUTO 0 /* automatic mode */
+#define MODE_BACKUP 1 /* backup mode */
+#define MODE_MANUAL 2 /* manual mode */
+
+#define NSAMPLES 3 /* stages of median filter */
+#define MSGCNT 10 /* we need this many ACTS messages */
+#define SMAX 80 /* max token string length */
+#define LENCODE 50 /* length of valid timecode string */
+#define ACTS_MINPOLL 10 /* log2 min poll interval (1024 s) */
+#define ACTS_MAXPOLL 14 /* log2 max poll interval (16384 s) */
+#define MAXOUTAGE 3600 /* max outage before ACTS kicks in (s) */
+
+/*
+ * Modem control strings. These may have to be changed for some modems.
+ *
+ * AT command prefix
+ * B1 initiate call negotiation using Bell 212A
+ * &C1 enable carrier detect
+ * &D2 hang up and return to command mode on DTR transition
+ * E0 modem command echo disabled
+ * l1 set modem speaker volume to low level
+ * M1 speaker enabled untill carrier detect
+ * Q0 return result codes
+ * V1 return result codes as English words
+ */
+#define MODEM_SETUP "ATB1&C1&D2E0L1M1Q0V1" /* modem setup */
+#define MODEM_HANGUP "ATH" /* modem disconnect */
+
+/*
+ * Timeouts
+ */
+#define IDLE 60 /* idle timeout (s) */
+#define WAIT 2 /* wait timeout (s) */
+#define ANSWER 30 /* answer timeout (s) */
+#define CONNECT 10 /* connect timeout (s) */
+#define TIMECODE 15 /* timecode timeout (s) */
+
+/*
+ * Imported from ntp_timer module
+ */
+extern u_long current_time; /* current time (s) */
+extern u_long last_time; /* last clock update time (s) */
+extern struct event timerqueue[]; /* inner space */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * Imported from ntp_config module
+ */
+extern char sys_phone[][MAXDIAL]; /* modem dial strings */
+
+/*
+ * Imported from ntp_proto module
+ */
+extern struct peer *sys_peer; /* who is running the show */
+extern u_char sys_poll; /* log2 of system poll interval */
+extern struct peer *sys_peer; /* system peer structure pointer */
+
+/*
+ * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
+ * leap.
+ */
+static day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ * Unit control structure
+ */
+struct actsunit {
+ struct event timer; /* timeout timer */
+ int pollcnt; /* poll message counter */
+
+ int state; /* the first one was Delaware */
+ int run; /* call program run switch */
+ int msgcnt; /* count of ACTS messages received */
+ long redial; /* interval to next automatic call */
+ double msADV; /* millisecond advance of last message */
+};
+
+/*
+ * Function prototypes
+ */
+static int acts_start P((int, struct peer *));
+static void acts_shutdown P((int, struct peer *));
+static void acts_receive P((struct recvbuf *));
+static void acts_poll P((int, struct peer *));
+static void acts_timeout P((struct peer *));
+static void acts_disc P((struct peer *));
+static int acts_write P((struct peer *, char *));
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_acts = {
+ acts_start, /* start up driver */
+ acts_shutdown, /* shut down driver */
+ acts_poll, /* transmit poll message */
+ noentry, /* not used (old acts_control) */
+ noentry, /* not used (old acts_init) */
+ noentry, /* not used (old acts_buginfo) */
+ NOFLAGS /* not used */
+};
+
+
+/*
+ * acts_start - open the devices and initialize data for processing
+ */
+static int
+acts_start(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
+ int dtr = TIOCM_DTR;
+
+ /*
+ * Open serial port. Use ACTS line discipline, if available. It
+ * pumps a timestamp into the data stream at every on-time
+ * character '*' found. Note: the port must have modem control
+ * or deep pockets for the phone bill. HP-UX 9.03 users should
+ * have very deep pockets.
+ */
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS)))
+ return (0);
+ if (ioctl(fd, TIOCMBIC, (char *)&dtr) < 0) {
+ syslog(LOG_ERR, "clock %s ACTS no modem control",
+ ntoa(&peer->srcadr));
+ return (0);
+ }
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ if (!(up = (struct actsunit *)
+ emalloc(sizeof(struct actsunit)))) {
+ (void) close(fd);
+ return (0);
+ }
+ memset((char *)up, 0, sizeof(struct actsunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = acts_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+ pp->unitptr = (caddr_t)up;
+
+ /*
+ * Initialize miscellaneous variables
+ */
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ peer->minpoll = ACTS_MINPOLL;
+ peer->maxpoll = ACTS_MAXPOLL;
+
+ /*
+ * Initialize modem and kill DTR. We skedaddle if this comes
+ * bum.
+ */
+ if (!acts_write(peer, MODEM_SETUP)) {
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+
+ /*
+ * Set up the driver timeout
+ */
+ up->timer.peer = (struct peer *)peer;
+ up->timer.event_handler = acts_timeout;
+ up->timer.event_time = current_time + WAIT;
+ TIMER_INSERT(timerqueue, &up->timer);
+ return (1);
+}
+
+
+/*
+ * acts_shutdown - shut down the clock
+ */
+static void
+acts_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ TIMER_DEQUEUE(&up->timer);
+ io_closeclock(&pp->io);
+ free(up);
+}
+
+
+/*
+ * acts_receive - receive data from the serial interface
+ */
+static void
+acts_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ char str[SMAX];
+ int i;
+ l_fp tstmp;
+ u_fp disp;
+ char hangup = '%'; /* ACTS hangup */
+ int day; /* day of the month */
+ int month; /* month of the year */
+ u_long mjd; /* Modified Julian Day */
+ u_int dst; /* daylight/standard time indicator */
+ u_int leap; /* leap-second indicator */
+ double dut1; /* DUT adjustment */
+ double msADV; /* ACTS transmit advance (ms) */
+ char utc[10]; /* this is NIST and you're not */
+ char flag; /* calibration flag */
+
+ /*
+ * Initialize pointers and read the timecode and timestamp. If
+ * the OK modem status code, leave it where folks can find it.
+ */
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX,
+ &pp->lastrec);
+ if (pp->lencode == 0) {
+ if (strcmp(pp->lastcode, "OK") == 0)
+ pp->lencode = 2;
+ return;
+ }
+#ifdef DEBUG
+ if (debug)
+ printf("acts: timecode %d %s\n", pp->lencode,
+ pp->lastcode);
+#endif
+
+ switch (up->state) {
+
+ case 0:
+
+ /*
+ * State 0. We are not expecting anything. Probably
+ * modem disconnect noise. Go back to sleep.
+ */
+ return;
+
+ case 1:
+
+ /*
+ * State 1. We are waiting for the call to be answered.
+ * All we care about here is CONNECT as the first token
+ * in the string. If the modem signals BUSY, ERROR, NO
+ * ANSWER, NO CARRIER or NO DIALTONE, we immediately
+ * hang up the phone. If CONNECT doesn't happen after
+ * ANSWER seconds, hang up the phone. If everything is
+ * okay, start the connect timeout and slide into state
+ * 2.
+ */
+ (void)strncpy(str, strtok(pp->lastcode, " "), SMAX);
+ if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") ==
+ 0 || strcmp(str, "NO") == 0) {
+ TIMER_DEQUEUE(&up->timer);
+ syslog(LOG_NOTICE,
+ "clock %s ACTS modem status %s",
+ ntoa(&peer->srcadr), pp->lastcode);
+ acts_disc(peer);
+ } else if (strcmp(str, "CONNECT") == 0) {
+ TIMER_DEQUEUE(&up->timer);
+ up->timer.event_time = current_time + CONNECT;
+ TIMER_INSERT(timerqueue, &up->timer);
+ up->msgcnt = 0;
+ up->state++;
+ }
+ return;
+
+ case 2:
+
+ /*
+ * State 2. The call has been answered and we are
+ * waiting for the first ACTS message. If this doesn't
+ * happen within the timecode timeout, hang up the
+ * phone. We probably got a wrong number or ACTS is
+ * down.
+ */
+ TIMER_DEQUEUE(&up->timer);
+ up->timer.event_time = current_time + TIMECODE;
+ TIMER_INSERT(timerqueue, &up->timer);
+ up->state++;
+ }
+
+ /*
+ * Real yucky things here. Ignore everything except timecode
+ * messages, as determined by the message length. We told the
+ * terminal routines to end the line with '*' and the line
+ * discipline to strike a timestamp on that character. However,
+ * when the ACTS echo-delay scheme works, the '*' eventually
+ * becomes a '#'. In this case the message is ended by the <CR>
+ * that comes about 200 ms after the '#' and the '#' cannot be
+ * echoed at the proper time. But, this may not be a lose, since
+ * we already have good data from prior messages and only need
+ * the millisecond advance calculated by ACTS. So, if the
+ * message is long enough and has an on-time character at the
+ * right place, we consider the message (but not neccesarily the
+ * timestmap) to be valid.
+ */
+ if (pp->lencode != LENCODE)
+ return;
+
+ /*
+ * We apparently have a valid timecode message, so dismember it
+ * with sscan(). This routine does a good job in spotting syntax
+ * errors without becoming overly pedantic.
+ *
+ * D L D
+ * MJD YR MO DA H M S ST S UT1 msADV OTM
+ * 47222 88-03-02 21:39:15 83 0 +.3 045.0 UTC(NBS) *
+ */
+ if (sscanf(pp->lastcode,
+ "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %s %c",
+ &mjd, &pp->year, &month, &day, &pp->hour, &pp->minute,
+ &pp->second, &dst, &leap, &dut1, &msADV, utc, &flag) != 13) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Some modems can't be trusted (the Practical Peripherals
+ * 9600SA comes to mind) and, even if they manage to unstick
+ * ACTS, the millisecond advance is wrong, so we use CLK_FLAG2
+ * to disable echoes, if neccessary.
+ */
+ if ((flag == '*' || flag == '#') && !(pp->sloppyclockflag &
+ CLK_FLAG2))
+ (void)write(pp->io.fd, &flag, 1);
+
+ /*
+ * Yes, I know this code incorrectly thinks that 2000 is a leap
+ * year. The ACTS timecode format croaks then anyway. Life is
+ * short. Would only the timecode mavens resist the urge to
+ * express months of the year and days of the month in favor of
+ * days of the year.
+ */
+ if (month < 1 || month > 12 || day < 1) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ if (pp->year % 4) {
+ if (day > day1tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day1tab[i];
+ } else {
+ if (day > day2tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day2tab[i];
+ }
+ pp->day = day;
+ if (leap == 1)
+ pp->leap = LEAP_ADDSECOND;
+ else if (pp->leap == 2)
+ pp->leap = LEAP_DELSECOND;
+ else
+ pp->leap = 0;
+ pp->lasttime = current_time;
+
+ /*
+ * Colossal hack here. We process each sample in a trimmed-mean
+ * filter and determine the reference clock offset and
+ * dispersion. The fudge time1 value is added to each sample as
+ * received. If we collect MSGCNT samples before the '#' on-time
+ * character, we use the results of the filter as is. If the '#'
+ * is found before that, the adjusted msADV is used to correct
+ * the propagation delay.
+ */
+ up->msgcnt++;
+ if (flag == '#') {
+ L_CLR(&tstmp);
+ TVUTOTSF((long)((msADV - up->msADV) * 1000.),
+ tstmp.l_uf);
+ L_ADD(&pp->offset, &tstmp);
+ } else {
+ up->msADV = msADV;
+ if (!refclock_process(pp, up->msgcnt, up->msgcnt -
+ up->msgcnt / 3)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ } else if (up->msgcnt < MSGCNT)
+ return;
+ }
+
+ /*
+ * We have a filtered sample offset ready for peer processing.
+ * We use lastrec 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. Finaly, we unhook the
+ * timeout, arm for the next call, fold the tent and go home.
+ * The little dance with the '%' character is an undocumented
+ * ACTS feature that hangs up the phone real quick without
+ * waiting for carrier loss or long-space disconnect, but we do
+ * these clumsy things anyway.
+ */
+ disp = LFPTOFP(&pp->fudgetime2);
+ record_clock_stats(&peer->srcadr, pp->lastcode);
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion +
+ (u_fp)disp, &pp->lastrec, &pp->lastrec, pp->leap);
+ pp->sloppyclockflag &= ~CLK_FLAG1;
+ up->pollcnt = 0;
+ TIMER_DEQUEUE(&up->timer);
+ (void)write(pp->io.fd, &hangup, 1);
+ up->state = 0;
+ acts_disc(peer);
+}
+
+
+/*
+ * acts_poll - called by the transmit routine
+ */
+static void
+acts_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+
+ /*
+ * If the driver is running, we set the enable flag (fudge
+ * flag1), which causes the driver timeout routine to initiate a
+ * call to ACTS. If not, the enable flag can be set using
+ * xntpdc. If this is the sustem peer, then follow the system
+ * poll interval.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ if (up->run) {
+ pp->sloppyclockflag |= CLK_FLAG1;
+ if (peer == sys_peer)
+ peer->hpoll = sys_poll;
+ else
+ peer->hpoll = peer->minpoll;
+ }
+}
+
+
+/*
+ * acts_timeout - called by the timer interrupt
+ */
+static void
+acts_timeout(peer)
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int dtr = TIOCM_DTR;
+
+ /*
+ * If a timeout occurs in other than state 0, the call has
+ * failed. If in state 0, we just see if there is other work to
+ * do.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ if (up->state) {
+ acts_disc(peer);
+ return;
+ }
+ switch (peer->ttl) {
+
+ /*
+ * In manual mode the ACTS calling program is activated
+ * by the xntpdc program using the enable flag (fudge
+ * flag1), either manually or by a cron job.
+ */
+ case MODE_MANUAL:
+ up->run = 0;
+ break;
+
+ /*
+ * In automatic mode the ACTS calling program runs
+ * continuously at intervals determined by the sys_poll
+ * variable.
+ */
+ case MODE_AUTO:
+ if (!up->run)
+ pp->sloppyclockflag |= CLK_FLAG1;
+ up->run = 1;
+ break;
+
+ /*
+ * In backup mode the ACTS calling program is disabled,
+ * unless no system peer has been selected for MAXOUTAGE
+ * (3600 s). Once enabled, it runs until some other NTP
+ * peer shows up.
+ */
+ case MODE_BACKUP:
+ if (!up->run && sys_peer == 0) {
+ if (current_time - last_time > MAXOUTAGE) {
+ up->run = 1;
+ peer->hpoll = peer->minpoll;
+ syslog(LOG_NOTICE,
+ "clock %s ACTS backup started ",
+ ntoa(&peer->srcadr));
+ }
+ } else if (up->run && sys_peer->refclktype !=
+ REFCLK_NIST_ACTS) {
+ peer->hpoll = peer->minpoll;
+ up->run = 0;
+ syslog(LOG_NOTICE,
+ "clock %s ACTS backup stopped",
+ ntoa(&peer->srcadr));
+ }
+ break;
+
+ default:
+ syslog(LOG_NOTICE,
+ "clock %s ACTS invalid mode", ntoa(&peer->srcadr));
+
+ }
+
+ /*
+ * The fudge flag1 is used as an enable/disable; if set either
+ * by the code or via xntpdc, the ACTS calling program is
+ * started; if reset, the phones stop ringing.
+ */
+ if (!(pp->sloppyclockflag & CLK_FLAG1)) {
+ up->pollcnt = 0;
+ up->timer.event_time = current_time + IDLE;
+ TIMER_INSERT(timerqueue, &up->timer);
+ return;
+ }
+
+ /*
+ * Initiate a call to the ACTS service. If we wind up here in
+ * other than state 0, a successful call could not be completed
+ * within minpoll seconds. We advance to the next modem dial
+ * string. If none are left, we log a notice and clear the
+ * enable flag. For future enhancement: call the site RP and
+ * leave an obscene message in his voicemail.
+ */
+ if (sys_phone[up->pollcnt][0] == '\0') {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ syslog(LOG_NOTICE,
+ "clock %s ACTS calling program terminated",
+ ntoa(&peer->srcadr));
+ pp->sloppyclockflag &= ~CLK_FLAG1;
+#ifdef DEBUG
+ if (debug)
+ printf("acts: calling program terminated\n");
+#endif
+ up->pollcnt = 0;
+ up->timer.event_time = current_time + IDLE;
+ TIMER_INSERT(timerqueue, &up->timer);
+ return;
+ }
+
+ /*
+ * Raise DTR, call ACTS and start the answer timeout. We think
+ * it strange if the OK status has not been received from the
+ * modem, but plow ahead anyway.
+ */
+ if (strcmp(pp->lastcode, "OK") != 0)
+ syslog(LOG_NOTICE, "clock %s ACTS no modem status",
+ ntoa(&peer->srcadr));
+ (void)ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr);
+ (void)acts_write(peer, sys_phone[up->pollcnt]);
+ syslog(LOG_NOTICE, "clock %s ACTS calling %s\n",
+ ntoa(&peer->srcadr), sys_phone[up->pollcnt]);
+ up->state = 1;
+ up->pollcnt++;
+ pp->polls++;
+ up->timer.event_time = current_time + ANSWER;
+ TIMER_INSERT(timerqueue, &up->timer);
+}
+
+
+/*
+ * acts_disc - disconnect the call and wait for the ruckus to cool
+ */
+static void
+acts_disc(peer)
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int dtr = TIOCM_DTR;
+
+ /*
+ * We should never get here other than in state 0, unless a call
+ * has timed out. We drop DTR, which will reliably get the modem
+ * off the air, even while ACTS is hammering away full tilt.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ (void)ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr);
+ if (up->state > 0) {
+ up->state = 0;
+ syslog(LOG_NOTICE, "clock %s ACTS call failed %d",
+ ntoa(&peer->srcadr), up->state);
+#ifdef DEBUG
+ if (debug)
+ printf("acts: call failed %d\n", up->state);
+#endif
+ }
+ up->timer.event_time = current_time + WAIT;
+ TIMER_INSERT(timerqueue, &up->timer);
+}
+
+
+/*
+ * acts_write - write a message to the serial port
+ */
+int
+acts_write(peer, str)
+ struct peer *peer;
+ char *str;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int len;
+ int code;
+ char cr = '\r';
+
+ /*
+ * Not much to do here, other than send the message, handle
+ * debug and report faults.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ len = strlen(str);
+#ifdef DEBUG
+ if (debug)
+ printf("acts: state %d send %d %s\n", up->state, len,
+ str);
+#endif
+ code = write(pp->io.fd, str, len) == len;
+ code |= write(pp->io.fd, &cr, 1) == 1;
+ if (!code)
+ refclock_report(peer, CEVNT_FAULT);
+ return (code);
+}
+
+#endif
diff --git a/usr.sbin/xntpd/doc/ntpq.8 b/usr.sbin/xntpd/doc/ntpq.8
index 1ddb829aba25..b323c73bb8d8 100644
--- a/usr.sbin/xntpd/doc/ntpq.8
+++ b/usr.sbin/xntpd/doc/ntpq.8
@@ -1,5 +1,5 @@
''' $Header
-'''
+'''
.de Sh
.br
.ne 5
@@ -48,7 +48,7 @@ ntpq - standard Network Time Protocol query program
[
.B -inp
] [
-.B -c
+.B -c
.I command
] [
.I host
@@ -57,26 +57,26 @@ ntpq - standard Network Time Protocol query program
]
.SH DESCRIPTION
.I Ntpq
-is used to query NTP servers which implement the recommended NTP
-mode 6 control message format about current state and to request
-changes in that state. The
-program may be run either in interactive mode or controlled using
-command line arguments. Requests to read and write arbitrary
-variables can be assembled, with raw and pretty\-printed output
-options being available.
+is used to query NTP servers which implement the recommended NTP mode 6
+control message format about current state and to request changes in
+that state. The program may be run either in interactive mode or
+controlled using command line arguments. Requests to read and write
+arbitrary variables can be assembled, with raw and pretty\-printed
+output options being available.
.I Ntpq
-can also obtain and print a list of peers in a common format
-by sending multiple queries to the server.
+can also obtain and print a list of peers in a common format by sending
+multiple queries to the server.
.PP
If one or more request options is included on the command line when
.I ntpq
-is executed, each of the requests will be sent to the NTP servers running
-on each of the hosts given as command line arguments, or on
+is executed, each of the requests will be sent to the NTP servers
+running on each of the hosts given as command line arguments, or on
.I localhost
-by default. If no request options are given,
+by default. If no request options are given,
.I ntpq
will attempt to read commands from the standard input and execute these
-on the NTP server running on the first host given on the command line, again
+on the NTP server running on the first host given on the command line,
+again
defaulting to
.I localhost
when no other host is specified.
@@ -86,53 +86,54 @@ will prompt for commands if the standard input is a terminal device.
.I Ntpq
uses NTP mode 6 packets to communicate with the NTP server, and hence
can be used to query any compatable server on the network which permits
-it. Note that since NTP is a UDP protocol this communication will be
+it. Note that since NTP is a UDP protocol this communication will be
somewhat unreliable, especially over large distances in terms of network
topology.
.I Ntpq
makes one attempt to retransmit requests, and will time requests out if
the remote host is not heard from within a suitable time out time.
.PP
-Command line options are described following. Specifying a command
-line option other than
+Command line options are described following. Specifying a command line
+option other than
.B -i
or
.B -n
will cause the specified query (queries) to be sent to the indicated
-host(s) immediately. Otherwise,
+host(s) immediately. Otherwise,
.I ntpq
-will attempt to read interactive format commands from the standard input.
+will attempt to read interactive format commands from the standard
+input.
.Ip -c 8
The following argument is interpreted as an interactive format command
and is added to the list of commands to be executed on the specified
-host(s). Multiple
+host(s). Multiple
.B -c
options may be given.
.Ip -i 8
Force
.I ntpq
-to operate in interactive mode. Prompts will be written to the
-standard output and commands read from the standard input.
+to operate in interactive mode. Prompts will be written to the standard
+output and commands read from the standard input.
.Ip -n 8
Output all host addresses in dotted\-quad numeric format rather than
converting to the canonical host names.
.Ip -p 8
-Print a list of the peers known to the server as well as a summary
-of their state. This is equivalent to the \*(L"peers\*(R" interactive
+Print a list of the peers known to the server as well as a summary of
+their state. This is equivalent to the \*(L"peers\*(R" interactive
command.
.SH INTERNAL COMMANDS
.PP
-Interactive format commands consist of a keyword followed by zero
-to four arguments. Only enough characters of the full keyword to
-uniquely identify the command need be typed. The output of a command
-is normally sent to the standard output, but optionally the output of
-individual commands may be sent to a file by appending a \*(L">\*(R",
-followed by a file name, to the command line.
+Interactive format commands consist of a keyword followed by zero to
+four arguments. Only enough characters of the full keyword to uniquely
+identify the command need be typed. The output of a command is normally
+sent to the standard output, but optionally the output of individual
+commands may be sent to a file by appending a \*(L">\*(R", followed by a
+file name, to the command line.
.PP
A number of interactive format commands are executed entirely within the
.I ntpq
-program itself and do not result in NTP mode 6 requests being sent
-to a server. These are described following.
+program itself and do not result in NTP mode 6 requests being sent to a
+server. These are described following.
.PP
.B ?
[
@@ -143,7 +144,7 @@ A \*(L"?\*(R" by itself will print a list of all the command keywords
known to this incarnation of
.IR ntpq .
A \*(L"?\*(R" followed by a command keyword will print funcation and
-usage information about the command. This command is probably a better
+usage information about the command. This command is probably a better
source of information about
.I ntpq
than this manual page.
@@ -151,8 +152,8 @@ than this manual page.
.B timeout
.I millseconds
.PP
-Specify a time out period for responses to server queries. The default
-is about 5000 milliseconds. Note that since
+Specify a time out period for responses to server queries. The default
+is about 5000 milliseconds. Note that since
.I ntpq
retries each query once after a time out the total waiting time for a
time out will be twice the time out value set.
@@ -161,10 +162,10 @@ time out will be twice the time out value set.
.I milliseconds
.PP
Specify a time interval to be added to timestamps included in requests
-which require authentication. This is used to enable (unreliable) server
+which require authentication. This is used to enable (unreliable) server
reconfiguration over long delay network paths or between machines whose
-clocks are unsynchronized. Actually the server does not now require
-time stamps in authenticated requests, so this command may be obsolete.
+clocks are unsynchronized. Actually the server does not now require time
+stamps in authenticated requests, so this command may be obsolete.
.PP
.B host
.I hostname
@@ -181,30 +182,30 @@ address.
.B verbose
]
.PP
-Poll the current server in client mode. The first argument is the
-number of times to poll (default is 1) while the second argument may
-be given to obtain a more detailed output of the results. This command
-is currently just wishful thinking.
+Poll the current server in client mode. The first argument is the number
+of times to poll (default is 1) while the second argument may be given
+to obtain a more detailed output of the results. This command is
+currently just wishful thinking.
.PP
.B keyid
.I #
.PP
This command allows the specification of a key number to be used to
-authenticate configuration requests. This must correspond to a
-key number the server has been configured to use for this purpose.
+authenticate configuration requests. This must correspond to a key
+number the server has been configured to use for this purpose.
.PP
.B passwd
.PP
This command prompts you to type in a password (which will not be
-echoed) which will be used to authenticate configuration requests. The
-password must correspond to the key configured for use by the NTP
-server for this purpose if such requests are to be successful.
+echoed) which will be used to authenticate configuration requests. The
+password must correspond to the key configured for use by the NTP server
+for this purpose if such requests are to be successful.
.PP
.B "hostnames yes|no"
.PP
If \*(L"yes\*(R" is specified, host names are printed in information
-displays. If \*(L"no\*(R" is given, numeric addresses are printed
-instead. The default is \*(L"yes\*(R" unless modified using the command
+displays. If \*(L"no\*(R" is given, numeric addresses are printed
+instead. The default is \*(L"yes\*(R" unless modified using the command
line
.B -n
switch.
@@ -212,15 +213,15 @@ switch.
.B raw
.PP
Causes all output from query commands is printed as received from the
-remote server. The only formating/intepretation done on the data is
-to transform nonascii data into a printable (but barely understandable)
+remote server. The only formating/intepretation done on the data is to
+transform nonascii data into a printable (but barely understandable)
form.
.PP
.B cooked
.PP
-Causes output from query commands to be \*(L"cooked\*(R". Variables
+Causes output from query commands to be \*(L"cooked\*(R". Variables
which are recognized by the server will have their values reformatted
-for human consumption. Variables which
+for human consumption. Variables which
.I ntpq
thinks should have a decodeable value but didn't are marked with a
trailing \*(L"?\*(R".
@@ -230,23 +231,24 @@ trailing \*(L"?\*(R".
.PP
Sets the NTP version number which
.I ntpq
-claims in packets. Defaults to 3, Note that mode 6 control messages (and modes,
-for that matter) didn't exist in NTP version 1. There appear to be no
-servers left which demand version 1.
+claims in packets. Defaults to 3, Note that mode 6 control messages (and
+modes, for that matter) didn't exist in NTP version 1. There appear to
+be no servers left which demand version 1.
.PP
.B authenticate
.B yes|no
.PP
Normally
.I ntpq
-does not authenticate requests unless they are write requests. The command
+does not authenticate requests unless they are write requests. The
+command
.B authenticate yes
causes
.I ntpq
-to send authentication with all requests it makes. Authenticated requests
-causes some servers to handle requests slightly differently, and can
-occasionally melt the CPU in fuzzballs if you turn authentication on before
-doing a peer display.
+to send authentication with all requests it makes. Authenticated
+requests causes some servers to handle requests slightly differently,
+and can occasionally melt the CPU in fuzzballs if you turn
+authentication on before doing a peer display.
.PP
.B addvars
.IR <variable_name>[=<value>] [,...]
@@ -254,25 +256,24 @@ doing a peer display.
.IR <variable_name> [,...]
.B clearvars
.PP
-The data carried by NTP mode 6 messages consists of a list of items
-of the form
+The data carried by NTP mode 6 messages consists of a list of items of
+the form
.IP "" 8
<variable_name>=<value>
.PP
where the \*(L"=<value>\*(R" is ignored, and can be omitted, in requests
to the server to read variables.
.I Ntpq
-maintains an internal list in which data to be included in control messages
-can be assembled, and sent using
-the
+maintains an internal list in which data to be included in control
+messages can be assembled, and sent using the
.B readlist
and
.B writelist
-commands described below. The
+commands described below. The
.B addvars
command allows variables and their optional values to be added to the
-list. If more than one variable is to be added, the list should be
-comma\-separated and not contain white space. The
+list. If more than one variable is to be added, the list should be
+comma\-separated and not contain white space. The
.B rmvars
command can be used to remove individual variables from the list, while
the
@@ -293,16 +294,15 @@ Exit
Each peer known to an NTP server has a 16 bit integer
.I association
.I identifier
-assigned to it. NTP control messages which carry peer variables
-must identify the peer the values correspond to by including
-its association ID. An association ID of 0 is special, and indicates
-the variables are system variables, whose names are drawn from a
-separate name space.
-.PP
-Control message commands result in one or more NTP mode 6
-messages being sent to the server, and cause the data returned to be
-printed in some format. Most commands currently implemented send a single
-message and expect a single response. The current exceptions are the
+assigned to it. NTP control messages which carry peer variables must
+identify the peer the values correspond to by including its association
+ID. An association ID of 0 is special, and indicates the variables are
+system variables, whose names are drawn from a separate name space.
+.PP
+Control message commands result in one or more NTP mode 6 messages being
+sent to the server, and cause the data returned to be printed in some
+format. Most commands currently implemented send a single message and
+expect a single response. The current exceptions are the
.B peers
command, which will send a preprogrammed series of messages to obtain
the data it needs, and the
@@ -313,57 +313,53 @@ commands, which will iterate over a range of associations.
.PP
.B associations
.PP
-Obtains and prints a list of association identifiers and
-peer statuses for in\-spec
-peers of the server being queried. The list is printed in
-columns. The first of these is an index numbering the associations
-from 1 for internal use, the second the actual association identifier
-returned by the server and the third the status word for the peer. This
+Obtains and prints a list of association identifiers and peer statuses
+for in\-spec peers of the server being queried. The list is printed in
+columns. The first of these is an index numbering the associations from
+1 for internal use, the second the actual association identifier
+returned by the server and the third the status word for the peer. This
is followed by a number of columns containing data decoded from the
-status word. Note
-that the data returned by the \*(L"associations\*(R" command is cached
-internally in
+status word. Note that the data returned by the \*(L"associations\*(R"
+command is cached internally in
.IR ntpq .
The index is then of use when dealing with stupid servers which use
-association identifiers which are hard for humans to type, in that
-for any subsequent commands which require an association identifier
-as an argument, the form
+association identifiers which are hard for humans to type, in that for
+any subsequent commands which require an association identifier as an
+argument, the form
.I &index
may be used as an alternative.
.PP
.B lassocations
.PP
Obtains and prints a list of association identifiers and peer statuses
-for all associations for which the server is maintaining state. This
-command differs from the
-\*(L"associations\*(R"
-command only for servers which retain state for out\-of\-spec client
-associations (i.e. fuzzballs). Such associations are normally omitted
-from the display when the
-\*(L"associations\*(R"
-command is used, but are included in the output of
-\*(L"lassociations\*(R".
+for all associations for which the server is maintaining state. This
+command differs from the \*(L"associations\*(R" command only for servers
+which retain state for out\-of\-spec client associations (i.e.
+fuzzballs). Such associations are normally omitted from the display when
+the \*(L"associations\*(R" command is used, but are included in the
+output of \*(L"lassociations\*(R".
.PP
.B passociations
.PP
-Prints association data concerning in\-spec peers from the internally cached
-list of associations. This command performs
-identically to the \*(L"associations\*(R" except that it displays the
-internally stored data rather than making a new query.
+Prints association data concerning in\-spec peers from the internally
+cached list of associations. This command performs identically to the
+\*(L"associations\*(R" except that it displays the internally stored
+data rather than making a new query.
.PP
.B lpassociations
.PP
Print data for all associations, including out\-of\-spec client
-associations, from the internally cached list of associations. This command
-differs from \*(L"passociations\*(R" only when dealing with fuzzballs.
+associations, from the internally cached list of associations. This
+command differs from \*(L"passociations\*(R" only when dealing with
+fuzzballs.
.PP
.B pstatus
.I assocID
.PP
-Sends a read status request to the server for the given association.
-The names and values of the peer variables returned will be printed. Note
-that the status word from the header is displayed preceding the variables,
-both in hexidecimal and in pidgeon English.
+Sends a read status request to the server for the given association. The
+names and values of the peer variables returned will be printed. Note
+that the status word from the header is displayed preceding the
+variables, both in hexidecimal and in pidgeon English.
.PP
.B readvar
[
@@ -373,13 +369,12 @@ both in hexidecimal and in pidgeon English.
]
.PP
Requests that the values of the specified variables be returned by the
-server by sending a read variables request. If the association ID
-is omitted or is given as zero the variables
-are system variables, otherwise they
-are peer variables and the values returned will be those
-of the corresponding peer. Omitting the variable list will send a
-request with no data which should induce the server to return a
-default display.
+server by sending a read variables request. If the association ID is
+omitted or is given as zero the variables are system variables,
+otherwise they are peer variables and the values returned will be those
+of the corresponding peer. Omitting the variable list will send a
+request with no data which should induce the server to return a default
+display.
.PP
.B rv
[
@@ -405,12 +400,12 @@ request, except the specified variables are written instead of read.
.I assocID
]
.PP
-Requests that the values of the variables in the internal variable
-list be returned by the server. If the association ID is omitted
-or is 0 the variables are assumed to be system variables. Otherwise
-they are treated as peer variables. If the internal variable list
-is empty a request is sent without data, which should induce the remote
-server to return a default display.
+Requests that the values of the variables in the internal variable list
+be returned by the server. If the association ID is omitted or is 0 the
+variables are assumed to be system variables. Otherwise they are treated
+as peer variables. If the internal variable list is empty a request is
+sent without data, which should induce the remote server to return a
+default display.
.PP
.B rl
[
@@ -428,8 +423,7 @@ command.
.PP
Like the
.B readlist
-request, except the internal list variables are written instead of
-read.
+request, except the internal list variables are written instead of read.
.PP
.B mreadvar
.I assocID
@@ -441,7 +435,7 @@ read.
Like the
.B readvar
command except the query is done for each of a range of (nonzero)
-association IDs. This range is determined from the association list
+association IDs. This range is determined from the association list
cached by the most recent
.B associations
command.
@@ -464,7 +458,7 @@ command.
Like the
.B readlist
command except the query is done for each of a range of (nonzero)
-association IDs. This range is determined from the association list
+association IDs. This range is determined from the association list
cached by the most recent
.B associations
command.
@@ -485,15 +479,16 @@ command.
.IR <variable_name>[=<value>] [,...]
]
.PP
-Requests that a list of the server's clock variables be sent. Servers
+Requests that a list of the server's clock variables be sent. Servers
which have a radio clock or other external synchronization will respond
-positively to this. If the association identifier is omitted or zero
-the request is for the variables of the \*(L"system clock\*(R" and will
-generally get a positive response from all servers with a clock. If the
-server treats clocks as pseudo\-peers, and hence can possibly have more than
-one clock connected at once, referencing the appropriate
-peer association ID will show the variables of a particular clock. Omitting
-the variable list will cause the server to return a default variable display.
+positively to this. If the association identifier is omitted or zero the
+request is for the variables of the \*(L"system clock\*(R" and will
+generally get a positive response from all servers with a clock. If the
+server treats clocks as pseudo\-peers, and hence can possibly have more
+than one clock connected at once, referencing the appropriate peer
+association ID will show the variables of a particular clock. Omitting
+the variable list will cause the server to return a default variable
+display.
.PP
.B cv
[
@@ -509,40 +504,42 @@ command.
.PP
.B peers
.PP
-Obtains a list of in\-spec peers of the server, along
-with a summary of each peer's state. Summary information includes the address
-of the remote peer, the reference ID (0.0.0.0 if the refID is unknown),
-the stratum of the remote peer, the polling interval,
-in seconds, the reachability
-register, in octal, and the current estimated delay, offset and dispersion
-of the peer, all in seconds.
+Obtains a list of in\-spec peers of the server, along with a summary of
+each peer's state. Summary information includes the address of the
+remote peer, the reference ID (0.0.0.0 if the refID is unknown), the
+stratum of the remote peer, the type of the peer (local, unicast,
+multicast or broadcast), when the last packet was received, the polling
+interval, in seconds, the reachability register, in octal, and the
+current estimated delay, offset and dispersion of the peer, all in
+seconds.
.PP
The character in the left margin indicates the fate of this peer in the
-clock selection process. The codes mean: <sp> discarded due to high stratum
-and/or failed sanity checks; \*(L"x\*(R" designated falsticker by the
-intersection algorithm; \*(L".\*(R" culled from the end of the candidate
-list; \*(L"-\*(R" discarded by the clustering algorithmi; \*(L"+\*(R"
-included in the final selection set; \*(L"#\*(R" selected for synchronizatio;n
-but distance exceeds maximum; \*(L"*\*(R" selected for synchronization; and
-\*(L"o\*(R" selected for synchronization, pps signal in use.
+clock selection process. The codes mean: <sp> discarded due to high
+stratum and/or failed sanity checks; \*(L"x\*(R" designated falsticker
+by the intersection algorithm; \*(L".\*(R" culled from the end of the
+candidate list; \*(L"-\*(R" discarded by the clustering algorithmi;
+\*(L"+\*(R" included in the final selection set; \*(L"#\*(R" selected
+for synchronizatio;n but distance exceeds maximum; \*(L"*\*(R" selected
+for synchronization; and \*(L"o\*(R" selected for synchronization, pps
+signal in use.
.PP
Note that since the
.B peers
-command depends on the ability to parse the values in the
-responses it gets it may fail to work from time to time with servers
-which poorly control the data formats.
+command depends on the ability to parse the values in the responses it
+gets it may fail to work from time to time with servers which poorly
+control the data formats.
.PP
-The contents of the host field may be one of four forms. It may be a host name,
-an IP address, a reference clock implementation name with its parameter or
-\*(L"REFCLK(<implementation number>, <parameter>)\*(R". On \*(L"hostnames no\*(R"
-only IP\-addresses will be displayed.
+The contents of the host field may be one of four forms. It may be a
+host name, an IP address, a reference clock implementation name with its
+parameter or \*(L"REFCLK(<implementation number>, <parameter>)\*(R". On
+\*(L"hostnames no\*(R" only IP\-addresses will be displayed.
.PP
.B lpeers
.PP
Like
.BR peers ,
except a summary of all associations for which the server is maintaining
-state is printed. This can produce a much longer list of peers from
+state is printed. This can produce a much longer list of peers from
fuzzball servers.
.PP
.B opeers
@@ -561,6 +558,6 @@ messages about invalid associations occuring and terminating the
command.
.PP
The timeout time is a fixed constant, which means you wait a long time
-for time outs since it assumes sort of a worst case. The program
-should improve the time out estimate as it sends queries to a particular
-host, but doesn't.
+for time outs since it assumes sort of a worst case. The program should
+improve the time out estimate as it sends queries to a particular host,
+but doesn't.
diff --git a/usr.sbin/xntpd/doc/xntpd.8 b/usr.sbin/xntpd/doc/xntpd.8
index 84b785bd54f0..77f64f93cb09 100644
--- a/usr.sbin/xntpd/doc/xntpd.8
+++ b/usr.sbin/xntpd/doc/xntpd.8
@@ -1,5 +1,5 @@
''' $Header
-'''
+'''
.de Sh
.br
.ne 5
@@ -46,9 +46,9 @@ xntpd - Network Time Protocol daemon
.SH SYNOPSIS
.B xntpd
[
-.B -ab
+.B -abdm
] [
-.B -c
+.B -c
.I conffile
] [
.B -e
@@ -60,14 +60,11 @@ xntpd - Network Time Protocol daemon
.B -k
.I keyfile
] [
-.B -l
-.I loopfile
-] [
.B -p
.I pidfile
] [
.B -r
-.I broaddelay
+.I broadcastdelay
] [
.B -s
.I statsdir
@@ -82,42 +79,52 @@ xntpd - Network Time Protocol daemon
.I variable
]
.SH DESCRIPTION
-.I Xntpd
-is a daemon which maintains a Unix system's time\-of\-day in agreement
-with Internet standard time servers.
-.I Xntpd
+.I xntpd
+is a daemon which sets and maintains a Unix system time\-of\-day in
+agreement with Internet standard time servers.
+.I xntpd
is a complete implementation of the Network Time Protocol (NTP) version
-3 standard as defined by RFC 1305 and also retains
-compatability with version 1 and 2 servers as defined
-by RFC 1059 and RFC 1119, respectively.
-.I Xntpd
-does all computations in fixed point arithmetic and is entirely free of
-floating point code. The computations done in the protocol and clock
-adjustment code are carried out with high precision and with attention
-to the details which might introduce systematic bias into the integrations,
-to try to maintain an accuracy suitable for synchronizing with even the
+3 standard, as defined by RFC 1305, but also retains compatability with
+version 1 and 2 servers as defined by RFC 1059 and RFC 1119,
+respectively.
+.I xntpd
+does all computations in fixed point arithmetic and requires no floating
+point code. The computations done in the protocol and clock adjustment
+code are carried out with high precision and with attention to the
+details which might introduce systematic bias into the computations, to
+try to maintain an accuracy suitable for synchronizing with even the
most precise external time source.
.PP
Ordinarily,
.I xntpd
-reads its configuration from a file at startup time. The default configuration
-file is
-.I /etc/ntp.conf,
-though this may be overridden from the command line. It is also possible to
-specify a working, though limited,
+reads its configuration from a configuration file at startup time. The
+default configuration file name is
+.IR /etc/ntp.conf,
+although this may be overridden from the command line. It is also
+possible to specify a working, although limited,
.I xntpd
configuration entirely on the command line, obviating the need for a
-configuration file. This may be particularly appropriate when xntpd is
-to be configured as a broadcast client, with all peers being determined
-by listening to broadcasts at run time. Various internal
+configuration file. This may be particularly appropriate when
+.I xntpd
+is to be configured as a broadcast or multicast client, with all peers
+being determined by listening to broadcasts at run time. Various
+internal
.I xntpd
-variables can be displayed, and configuration options altered, while the
+variables can be displayed and configuration options altered while the
daemon is running through use of the
.IR ntpq (8)
and
.IR xntpdc (8)
programs.
.PP
+The daemon can operate in any of several modes, including symmetric
+active/passive, client/server and broadcast/multicast. A
+broadcast/multicast client can automatically discover remote servers,
+compute one-way delay correction factors and comfigure itself
+automatically. This makes it possible to deploy a fleet of workstations
+without specifying a configuration file or configuration details
+specific to its environment.
+.PP
The following command line arguments are understood by
.I xntpd
(see the configuration file description for a more complete functional
@@ -129,42 +136,46 @@ listen for broadcast NTP and sync to this if available
.Ip -c 8
specify an alternate configuration file
.Ip -d 8
-specify debugging options
+specify debugging mode. This flag may occur multiple times, with each
+occurance indicating greater detail of display.
.Ip -e 8
-specify the time (in seconds) it takes to compute the NTP encryption field
-on this computer
-.Ip -f 8
+specify the time (in seconds) it takes to compute the NTP encryption
+field on this computer
+.Ip -f driftfile 8
specify the location of the drift file
.Ip -k 8
-specify the location of the file which contains the NTP authentication keys
+specify the location of the file which contains the NTP authentication
+keys
.Ip -m 8
-listen for multicast NTP and sync to this if available (requires multicast
-kernel)
+listen for multicast messages and synchronize to them if available
+(requires multicast kernel)
.Ip -p 8
specify the name of the file to record the daemon's process id
.Ip -r 8
-specify the default round trip delay (in seconds)
-to be used when synchronizing to broadcasts
+ordinarily, the daemon automatically compensates for the network delay
+between the broadcast/multicast server and the client; if the
+calibration procedure fails, use the specified the default delay (in
+seconds)
.Ip -s 8
-specify a directory to be used for creating statistics files
-.Ip -t 8
+specify the directory to be used for creating statistics files
+.Ip -t trustedkey 8
add a key number to the trusted key list
.Ip -v 8
add a system variable
.Ip -V 8
add a system variable listed by default
-.SH "CONFIGURATION FILE OPTIONS"
-.IR Xntpd 's
-configuration file is relatively free format. Comments, which may be
-freely inserted, begin with a \*(L"#\*(R" character
-and extend to the end of the line. Blank lines are ignored. Configuration
-statements include an initial keyword followed by white space separated
-arguments, some of which may be optional. Configuration statements
-may not be continued over multiple lines. Arguments may be network
-numbers (which must be written in numeric, dotted\-quad form), integers,
-floating point numbers (when specifying times in seconds) and text
-strings. Optional arguments are delimited by \*(L"[]\*(R" in the following
-descriptions, while alternatives are separated by \*(L"|\*(R".
+.SH "CONFIGURATION OPTIONS"
+.I xntpd 's
+configuration file format is similar to other Unix configuration files.
+Comments begin with a \*(L"#\*(R" character and extend to the end of the
+line. Blank lines are ignored. Configuration commands consist of an
+initial keyword followed by a list of arguments, some of which may be
+optional, separated by whitespace. These commands may not be continued
+over multiple lines. Arguments may be host names, host addresses written
+in numeric, dotted\-quad form, integers, floating point numbers (when
+specifying times in seconds) and text strings. Optional arguments are
+delimited by \*(L"[]\*(R" in the following descriptions, while
+alternatives are separated by \*(L"|\*(R".
.PP
.B peer
.I host_address
@@ -199,163 +210,150 @@ descriptions, while alternatives are separated by \*(L"|\*(R".
.B version
.I #
] [
-.B prefer
+.B ttl
+.I #
]
.PP
-These three statements specify various time servers to be used and/or
-time services to be provided. The
+These three commands specify various time servers to be used and/or time
+services to be provided. The
.B peer
-statement specifies that the given host is to be polled in
-\*(L"symmetric active\*(R" mode, i.e. that the host is requested to
-provide time which you might synchronize to and, in addition, indicates
-that you are willing to have to remote host synchronize to your time
-if need be. The
+command specifies that the local server is to operate in \*(L"symmetric
+active\*(R" mode with the remote server
+.I host_address
+named in the command. In this mode the local server can be synchronized
+to the remote server and, in addition, the remote server can be
+synchronized by the local server. This is useful in a network of servers
+where, depending on various failure scenarios, either the local or
+remote server host may be the better source of time. The
.B server
-statement specifies that the given host is to be polled in
-\*(L"client\*(R" mode, i.e. that the host is requested to provide
-time which you might synchronize with but that you are unwilling to have
-the remote host synchronize to your own time. The
+command specifies that the local server is to operate in
+\*(L"client\*(R" mode with the remote server named in the command. In
+this mode the local server can be synchronized to the remote server, but
+the remote server can never be synchronized to the local server. The
.B broadcast
-statement requests your local daemon to transmit broadcast NTP to
-the specified address. The latter is usually the broadcast address
-on [one of] your local network[s] or a multicast address assigned to
-NTP. The Numbers Czar has assigned the address 224.0.1.1 to NTP; this
-is presently the only number that should be used. Note that the use
-of multicast requires a multicast kernel.
+command specifies that the local server is to operate in
+\*(L"broadcast\*(R" mode where the local server sends periodic broadcast
+messages to a client population at the broadcast/multicast address named
+in the command. Ordinarily, this specification applies only to the local
+server operating as a transmitter; for operation as a broadcast client,
+see the
+.B broadcastclient
+or
+.B multicastclient
+commands elsewhere in this document. In this mode the
+.I host_address
+is usually the broadcast address on [one of] the local network[s] or a
+multicast address assigned to NTP. The Numbers Czar has assigned the
+address 224.0.1.1 to NTP; this is presently the only number that should
+be used. Note that the use of multicast features requires a multicast
+kernel, which is not yet ubiquitous in vendor products.
.PP
The
.B key
option, when included, indicates that all packets sent to the address
are to include authentication fields encrypted using the specified key
-number (the range of which is that of an unsigned 32 bit integer). The
-default is to not include an encryption field. The
+number (the range of which is that of an unsigned 32 bit integer). The
+default is to not include an encryption field. The
.B version
option allows one to specify the version number to be used for outgoing
-NTP packets. Versions 1, 2, and 3 are the choices, version 3 is the default.
-The
+NTP packets. Versions 1, 2, and 3 are the choices, version 3 is the
+default. The
.B prefer
-option marks the host as a preferred host. All other things being equal, this
-host will be chosen for synchronization among a set of correctly operating
-hosts.
-.PP
-.B precision
-.I #
+option marks the host as a preferred host. All other things being equal,
+this host will be chosen for synchronization among a set of correctly
+operating hosts. The
+.B ttl
+option is used only with the broadcast mode. It specifies the time-to-
+live (TTL) to use on multicast packets. Selection of the proper value,
+which defaults to 127, is something of a black art and must be
+coordinated with the network admistrator(s).
.PP
-Indicates the precision of local timekeeping. The value is an integer
-which is approximately the base 2 logarithm of the local timekeeping
-precision in seconds. By default this value is set to -6.
+.B broadcastclient
.PP
-The precision declared by an implementation can affect several aspects
-of server operation, and can be used as a tuning parameter for your
-synchronization subnet. It should probably not be changed from the
-default value, however, unless there is a good reason to do so.
+This directs the local server to listen for broadcast messages on the
+local network, in order to discover other servers on the same subnet.
+Upon hearing a broadcast message for the first time, the local server
+measures the nominal network delay using a brief client/server exchange
+with the remote server, then enters the \*(L"broadcastclient\*(R" mode,
+in which it listens for and synchronizes to succeeding broadcast
+messages. Note that, in order to avoid accidental or malicious
+disruption in this mode, both the local and remote servers must operate
+using authentication and the same trusted key and key identifier.
.PP
-.B logfile
-.I filename
+.B multicastclient
+[
+.I IP address ...
+]
.PP
-Gives the file which is to be used instead of syslog output. This
-configuration option is also a compile time option (SYSLOG_FILE).
-So in order to be able to use this xntpd must be compiled with
--DSYSLOG_FILE.
+This command is used in the same way as the
+.IR broadcastclient
+command, but operates using IP multicasting. Support for this function
+requires a multicast kernel and the use of authentication. If one or
+more IP addresses are given, the server joins the respective multicast
+group(s). If none are given, the IP address assigned to NTP (224.0.1.1)
+is assumed.
.PP
.B driftfile
.I filename
.PP
-Specifies the name of the file used to record the \*(L"drift\*(R" (or
-frequency error) value
-.I xntpd
-has computed. If the file exists on startup, it is read and the value
-used to initialize
-.IR xntpd 's
-internal value of the frequency error. The file is then updated once
-every hour by replacing the old file with a new one containing the
-current value of the frequency error. Note that the file is updated
-by first writing the current drift value into a temporary file and
-then using
+This command specifies the name of the file used to record the frequency
+offset of the local clock oscillator. If the file exists, it is read at
+startup in order to set the initial frequency offset and then updated
+once per hour with the current offset computed by the daemon. If the
+file does not exist or this command is not given, the initial frequency
+offset is assumed zero. In this case, it may take some hours for the
+frequency to stabilize and the residual timing errors to subside. The
+file contains a single floating point value equal to the offset in
+parts-per-million (ppm). Note that the file is updated by first writing
+the current drift value into a temporary file and then using
.IR rename (3)
-to replace the old version. This implies that
+to replace the old version. This implies that
.I xntpd
must have write permission for the directory the drift file is located
in, and that file system links, symbolic or otherwise, should probably
be avoided.
.PP
-.B monitor yes|no
-.PP
-Indicates whether the
-.I xntpd
-traffic monitoring function should be enabled or not. When enabled,
-this causes the origin address of each packet received by the server
-to be recorded along with a limited amount of additional information, such
-as the mode of the request and whether it originated from an NTP server port
-or not. Traffic monitoring data may be inspected using the
-.IR xntpdc (8)
-.I monlist
-command. The default is \*(L"no\*(R", i.e. traffic monitoring should not
-be done.
-.PP
-Note that the traffic monitoring facility will increase the CPU used
-by
-.IR xntpd ,
-as well as increasing the daemon's memory utilization by as much as
-8.5 kilobytes. This facility is normally useful for the detection of
-peers with malfunctioning software or which are sending bogus data. It
-is primarily intended for very popular servers which exchange time with
-large numbers of peers, though it may also be useful for access monitoring
-of local servers if you are willing to accept the overhead.
-.PP
-.B broadcastclient
-.PP
-This directs the local server should listen for, and attempt to
-synchonize to, broadcast NTP. Note that authentication is required in
-this mode.
-.PP
-.B multicastclient
+.B enable auth|bclient|pll|monitor|stats
[
-.I IP address ...
+.I ...
]
.PP
-This directs the local server should listen for, and attempt to
-synchonize to, multicast NTP. This function requires a multicast kernel
-and the use of authentication.
-If one or more IP addresses are given, the server joins the respective
-multicast group. If none are given, the default address assigned to
-NTP (224.0.1.1) is assumed.
-.PP
-.B broadcastdelay
-.I seconds
-.PP
-Specifies the default round trip delay to the host whose broadcasts
-are being synchronized to. The value is specified in seconds and is
-typically (for ethernet) a number between 0.007 and 0.015 seconds. This
-initial estimate may be improved by polling each server to determine a
-more accurate value. Defaults to 0.008 seconds.
-.PP
-.B authenticate yes|no
-.PP
-Indicates whether the local server should operate in authenticate mode
-or not. If \*(L"yes\*(R", only peers which include an authentication field
-encrypted with one of our trusted keys (see below) will be considered
-as candidates for synchonizing to. The default is \*(L"no\*(R".
-.PP
-.B authdelay
-.I seconds
+Provides a way to enable various server options. Flags not mentioned are
+unaffected. The \*(L"auth\*(R" flag causes the server to synchronize
+with unconfigured peers only if the peer has been correctly
+authenticated using a trusted key and key identifier. The default for
+this flag is disable (off). The \*(L"bclient\*(R" flag causes the server
+to listen for a message from a broadcast or multicast server, following
+which an association is automatically instantiated for that server. The
+default for this flag is disable (off). The \*(L"pll\*(R" flag enables
+the server to adjust its local clock, with default enable (on). If not
+set, the local clock free-runs at its intrinsic time and frequency
+offset. This flag is useful in case the local clock is controlled by
+some other device or protocol and NTP is used only to provide
+synchronization to other clients. The \*(L"monitor\*(R" flag enables the
+monitoring facility (see elsewhere), with default enable (on). The
+\*(L"stats\*(R" flag enables statistics facility filegen (see
+description elsewhere.), with default enable (on).
+.PP
+.B disable auth|bclient|pll|monitor|stats
+[
+.I ...
+]
.PP
-Indicates the amount of time it takes to encrypt an NTP authentication
-field on the local computer. This value is used to correct transmit
-timestamps when the authentication is used on outgoing packets. The
-value usually lies somewhere in the range 0.0001 seconds to 0.003 seconds,
-though it is very dependent on the CPU speed of the host computer. The
-value is usually computed using the
-.I authspeed
-program included with the distribution.
+Provides a way to disable various server options. Flags not mentioned
+are unaffected. The flags presently available are described under the
+enable command.
+
+.SH "AUTHENTICATION OPTIONS"
.PP
.B keys
.I filename
.PP
-Specifies the name of a file which contains the encryption keys which
-are to be used by
-.IR xntpd .
-The format of this file is described below.
+This command specifies the name of a file which contains the encryption
+keys and key identifiers used by
+.I xntpd
+when operating in authenticated mode. The format of this file is
+described later in this document.
.PP
.B trustedkey
.I #
@@ -363,43 +361,67 @@ The format of this file is described below.
.I "# ..."
]
.PP
-Allows the specification of the encryption key numbers which are trusted
-for the purposes of determining peers suitable for time sychonization,
-when authentication is enabled. Only peers using one of these keys for
-encryption of the authentication field, and whose authenticity can be
-verified by successful decryption, will be considered as synchonization
-candidates. The arguments are 32 bit unsigned integers. Note, however,
-that NTP key 0 is fixed and globally known. If meaningful authentication
-is to be performed the 0 key should not be trusted.
+This command is used to specify the encryption key identifiers which are
+trusted for the purposes of authenticating peers suitable for
+sychonization. The authentication procedures require that both the local
+and remote servers share the same key and key identifier for this
+purpose, although different keys can be used with different servers. The
+arguments are 32 bit unsigned integers. Note, however, that NTP key 0 is
+fixed and globally known. If meaningful authentication is to be
+performed the 0 key should not be trusted.
.PP
.B requestkey
.I #
.PP
-.I Xntpd
-allows run time reconfiguration to be performed using the
+This command specifies the key identifier to use with the
.IR xntpdc (8)
-program. Such requests must be authenticated. The
-.B requestkey
-statement allows the specification of a 32 bit unsigned integer
-key number to be used for authenticating such requests. Note that
-if no
+program, which is useful to diagnose and repair problems that affect
+.IR xntpd (8)
+operation. The operation of the
+.I xntpdc
+program are specific to this particular implementation of xntpd and can
+be expected to work only with this and previous versions of the daemon.
+Requests from a remote xntpdc program which affect the state of the
+local server must be authenticated, which requires bot the remote
+program and local server share a common key and key identifier. The
+argument to this command is a 32 bit unsigned integer. If no
.B requestkey
-statement is included in the configuration file the run time reconfiguration
-facility will be disabled.
+command is included in the configuration file, or if the keys don't
+match, such requests will be ignored.
.PP
.B controlkey
.I #
.PP
-Certain changes can be made to the
+This command specifies the key identifier to use with the
+.IR ntpq (8)
+program, which is useful to diagnose and repair problems that affect
+.IR xntpd (8)
+operation. The operation of the
+.IR ntpq
+program and
.I xntpd
-server via mode 6 control messages, in particular the setting of
-leap second indications in a server with a radio clock.
-The
-.B controlkey
-statement specifies an encription key number to be used for authenticating
-such messages. Omitting this statement will cause control messages
-which would change the state of the server to be ignored.
+conform to those specified in RFC 1305. Requests from a remote
+.I ntpq
+program which affect the state of the local server must be
+authenticated, which requires bot the remote program and local server
+share a common key and key identifier. The argument to this command is a
+32 bit unsigned integer. If no
+.B requestkey
+command is included in the configuration file, or if the keys don't
+match, such requests will be ignored.
+.PP
+.B authdelay
+.I seconds
.PP
+Indicates the amount of time it takes to encrypt an NTP authentication
+field on the local computer. This value is used to correct transmit
+timestamps when the authentication is used on outgoing packets. The
+value usually lies somewhere in the range 0.0001 seconds to 0.003
+seconds, though it is very dependent on the CPU speed of the host
+computer. The value is usually computed using the
+.I authspeed
+program included with the distribution.
+.SH "ACCESS CONTROL OPTIONS"
.B restrict
.I address
[
@@ -411,202 +433,125 @@ which would change the state of the server to be ignored.
.I ...
]
.PP
-.I Xntpd
-implements a general purpose address\-and\-mask based restriction
-list. The list is sorted by address and by mask, and the list is
-searched in this order for matches, with the last match found defining
-the restriction flags associated with the incoming packets. The source
-address of incoming packets is used for the match, with the 32 bit address
-being and'ed with the mask associated with the restriction entry and
-then compared with the entry's address (which has also been and'ed with
-the mask) to look for a match. The \*(L"mask\*(R" argument defaults
+.I xntpd
+implements a general purpose address\-and\-mask based restriction list.
+The list is sorted by address and by mask, and the list is searched in
+this order for matches, with the last match found defining the
+restriction flags associated with the incoming packets. The source
+address of incoming packets is used for the match, with the 32 bit
+address being and'ed with the mask associated with the restriction entry
+and then compared with the entry's address (which has also been and'ed
+with the mask) to look for a match. The \*(L"mask\*(R" argument defaults
to 255.255.255.255, meaning that the \*(L"address\*(R" is treated as the
-address of an individual host. A default entry (address 0.0.0.0, mask
+address of an individual host. A default entry (address 0.0.0.0, mask
0.0.0.0) is always included and, given the sort algorithm, is always the
-first entry in the list. Note that, while \*(L"address\*(R" is normally
-given as a dotted\-quad address, the text string \*(L"default\*(R", with
-no mask option, may be used to indicate the default entry.
-.PP
-In the current implementation flags always restrict access, i.e. an entry
-with no flags indicates that free access to the server is to be given. The
-flags are not orthogonal, in that more restrictive flags will often make
-less restrictive ones redundant. The flags can generally be classed into
-two catagories, those which restrict time service and those which restrict
-informational queries and attempts to do run time reconfiguration of the
-server. One or more of the following flags may be specified:
+first entry in the list. Note that, while \*(L"address\*(R" is normally
+given in dotted\-quad format, the text string \*(L"default\*(R", with no
+mask option, may be used to indicate the default entry.
+.PP
+In the current implementation, flags always restrict access, i.e. an
+entry with no flags indicates that free access to the server is to be
+given. The flags are not orthogonal, in that more restrictive flags will
+often make less restrictive ones redundant. The flags can generally be
+classed into two catagories, those which restrict time service and those
+which restrict informational queries and attempts to do run time
+reconfiguration of the server. One or more of the following flags may be
+specified:
.Ip ignore 10
-Ignore all packets from hosts which match this entry. If this flag
-is specified neither queries nor time server polls will be responded
-to.
+Ignore all packets from hosts which match this entry. If this flag is
+specified neither queries nor time server polls will be responded to.
.Ip noquery 10
-Ignore all NTP mode 6 and 7 packets (i.e. information queries and configuration
-requests) from the source. Time service is not affected.
+Ignore all NTP mode 6 and 7 packets (i.e. information queries and
+configuration requests) from the source. Time service is not affected.
.Ip nomodify 10
-Ignore all NTP mode 6 and 7 packets which attempt to modify the state of the
-server (i.e. run time reconfiguration). Queries which return information
-are permitted.
+Ignore all NTP mode 6 and 7 packets which attempt to modify the state of
+the server (i.e. run time reconfiguration). Queries which return
+information are permitted.
.Ip notrap 10
Decline to provide mode 6 control message trap service to matching
-hosts. The trap service is a subsystem of the mode 6 control message
+hosts. The trap service is a subsystem of the mode 6 control message
protocol which is intended for use by remote event logging programs.
.Ip lowpriotrap 10
-Declare traps set by matching hosts to be low priority. The number
-of traps a server can maintain is limited (the current limit is 3).
-Traps are usually assigned on a first come, first served basis, with
-later trap requestors being denied service. This flag modifies the
-assignment algorithm by allowing low priority traps to be overridden
-by later requests for normal priority traps.
+Declare traps set by matching hosts to be low priority. The number of
+traps a server can maintain is limited (the current limit is 3). Traps
+are usually assigned on a first come, first served basis, with later
+trap requestors being denied service. This flag modifies the assignment
+algorithm by allowing low priority traps to be overridden by later
+requests for normal priority traps.
.Ip noserve 10
-Ignore NTP packets whose mode is other than 6 or 7. In effect, time service is
-denied, though queries may still be permitted.
+Ignore NTP packets whose mode is other than 6 or 7. In effect, time
+service is denied, though queries may still be permitted.
.Ip nopeer 10
-Provide stateless time service to polling hosts, but do not allocate peer
-memory resources to these hosts even if they otherwise might be considered
-useful as future synchronization partners.
+Provide stateless time service to polling hosts, but do not allocate
+peer memory resources to these hosts even if they otherwise might be
+considered useful as future synchronization partners.
.Ip notrust 10
Treat these hosts normally in other respects, but never use them as
synchronization sources.
.Ip limited 10
-These hosts are subject to limitation of number of clients from the
-same net. Net in this context refers to the IP notion of net (class A,
-class B, class C, etc.). Only the first \*(L"client_limit\*(R" hosts
-that have shown up at the server and that have been active during the
-last \*(L"client_limit_period\*(R" seconds are accepted. Requests from
-other clients from the same net are rejected. Only time request
-packets are taken into account. \*(L"Private\*(R", \*(L"control\*(R",
-and \*(L"broadcast\*(R" packets are not subject to client limitation
-and therefore are not contributing to client count. History of clients
-is kept using the monitoring capability of
-.IR xntpd .
-Thus, monitoring is active as long as there is a restriction entry
-with the \*(L"limited\*(R" flag. The default value for
-\*(L"client_limit\*(R" is 3. The default value for
-\*(L"client_limit_period\*(R" is 3600 seconds.
+These hosts are subject to limitation of number of clients from the same
+net. Net in this context refers to the IP notion of net (class A, class
+B, class C, etc.). Only the first \*(L"client_limit\*(R" hosts that have
+shown up at the server and that have been active during the last
+\*(L"client_limit_period\*(R" seconds are accepted. Requests from other
+clients from the same net are rejected. Only time request packets are
+taken into account. \*(L"Private\*(R", \*(L"control\*(R", and
+\*(L"broadcast\*(R" packets are not subject to client limitation and
+therefore are not contributing to client count. History of clients is
+kept using the monitoring capability of
+.I xntpd .
+Thus, monitoring is active as long as there is a restriction entry with
+the \*(L"limited\*(R" flag. The default value for \*(L"client_limit\*(R"
+is 3. The default value for \*(L"client_limit_period\*(R" is 3600
+seconds.
.Ip ntpport 10
This is actually a match algorithm modifier, rather than a restriction
-flag. Its presence causes the restriction entry to be matched only if
-the source port in the packet is the standard NTP UDP port (123). Both
-\*(L"ntpport\*(R" and non\-\*(L"ntpport\*(R" may be specified. The
+flag. Its presence causes the restriction entry to be matched only if
+the source port in the packet is the standard NTP UDP port (123). Both
+\*(L"ntpport\*(R" and non\-\*(L"ntpport\*(R" may be specified. The
\*(L"ntpport\*(R" is considered more specific and is sorted later in the
list.
.PP
-Default restriction list entries, with the flags \*(L"ignore, ntpport\*(R",
-for each of the local host's interface addresses are inserted into the
-table at startup to prevent the server from attempting to synchronize to
-its own time. A default entry is also always present, though if it is
-otherwise unconfigured no flags are associated with the default entry (i.e.
-everything besides your own NTP server is unrestricted).
+Default restriction list entries, with the flags \*(L"ignore,
+ntpport\*(R", for each of the local host's interface addresses are
+inserted into the table at startup to prevent the server from attempting
+to synchronize to its own time. A default entry is also always present,
+though if it is otherwise unconfigured no flags are associated with the
+default entry (i.e. everything besides your own NTP server is
+unrestricted).
.PP
The restriction facility was added to allow the current access policies
-of the time servers running on the NSFnet backbone to be implemented with
+of the time servers running on the NSFnet backbone to be implemented
+with
.I xntpd
-as well. While this facility may be otherwise useful for keeping unwanted or
-broken remote time servers from affecting your own, it should not be
-considered an alternative to the standard NTP authentication facility. Source
-address based restrictions are easily circumvented by a determined cracker.
+as well. While this facility may be otherwise useful for keeping
+unwanted or broken remote time servers from affecting your own, it
+should not be considered an alternative to the standard NTP
+authentication facility. Source address based restrictions are easily
+circumvented by a determined cracker.
.PP
.B clientlimit
.I limit
.PP
-Sets \*(L"client_limit\*(R" to \*(L"limit\*(R", allows configuration
-of client limitation policy. This variable defines the number of
-clients from the same network that are allowed to use the server.
+Sets \*(L"client_limit\*(R" to \*(L"limit\*(R", allows configuration of
+client limitation policy. This variable defines the number of clients
+from the same network that are allowed to use the server.
.PP
.B clientperiod
.I period
.PP
Sets \*(L"client_limit_period\*(R", allows configuration of client
-limitation policy. This variable specifies the number
-of seconds after which a client is considered inactive and thus no
-longer is counted for client limit restriction.
-.PP
-.B trap
-.I host_address
-[
-.B port
-.I port_number
-] [
-.B interface
-.I interface_addess
-]
-.PP
-Configures a trap receiver at the given host address and port number,
-sending messages with the specified local interface address. If the
-port number is unspecified a value of 18447 is used. If the interface
-address is not specified the message is sent with a source address
-which is that of the local interface the message is sent through. Note
-that on a multihomed host the interface used may vary from time to time
-with routing changes.
-.PP
-The trap receiver will generally log event messages and other information
-from the server in a log file. While such monitor programs may also
-request their own trap dynamically, configuring a trap receiver will
-ensure that no messages are lost when the server is started.
-.PP
-.B maxskew
-.I seconds
-.PP
-This command is obsolete and not available in this version of
-.I xntpd.
-.PP
-.B select
-.I algorithm_number
-.PP
-This command is obsolete and not available in this version of
-.I xntpd.
-.PP
-.B setvar
-.I variable
-.I [default]
-.PP
-This command adds an additional system variable. These variables can be
-used to distribute additional information such as the access policy. If
-the variable of the from <name>=<value> is followed by the
-.I default
-keyword the variable will be listed as part of the default system
-variables (ntpq rv command). These additional variables serve informational
-purposes only. They are not related to the protocol other that they can be
-listed. The known protocol variables will always overide any variables defined
-via the
-.I setvar
-mechanism.
-.PP
-There are three special variables that contain the names of all variable of
-the same group. The
-.I sys_var_list
-holds the names of all system variables. The
-.I peer_var_list
-holds the names of all peer variables and the
-.I clock_var_list
-hold the names of the reference clock variables.
-.PP
-.B resolver
-.I /path/xntpres
-.PP
-Normally, names requiring resolution (rather than numeric addresses)
-in the configuration file are resolved by code internal to
-.I xntpd;
-However, in those cases that require it, the code can be installed
-in a standalone program called
-.I xntpres.
-In these cases the full path to the
-.I xntpres
-program is given as the argument the command.
-As
-.I xntpres
-makes use of mode 7 runtime reconfiguration, this facility must also be
-enabled if the procedure is to exceed (see the
-.B requestkey
-and
-.B keys
-statements above).
+limitation policy. This variable specifies the number of seconds after
+which a client is considered inactive and thus no longer is counted for
+client limit restriction.
+.SH "MONITORING OPTIONS"
.PP
.B statsdir
.I /directory path/
.PP
-Indicates the full path of a directory where statistics files should
-be created (see below). This keyword allows the (otherwise constant) filegen
-filename prefix to be modified for file generation sets used for
+Indicates the full path of a directory where statistics files should be
+created (see below). This keyword allows the (otherwise constant)
+filegen filename prefix to be modified for file generation sets used for
handling statistics logs (see
.B filegen
statement below).
@@ -614,41 +559,41 @@ statement below).
.B statistics
.IR name \.\.\.
.PP
-Enables writing of statistics records.
-Currently, three kinds of statistics are supported.
+Enables writing of statistics records. Currently, three kinds of
+statistics are supported.
.Ip loopstats 10
-enables recording of loop filter statistics information.
-Each update of the local clock outputs a line of the
-following form to the file generation set named \*(L"loopstats\*(R":
+enables recording of loop filter statistics information. Each update of
+the local clock outputs a line of the following form to the file
+generation set named \*(L"loopstats\*(R":
.PP
.RS 5
48773 10847.650 0.0001307 17.3478 2
.RE
.RS 10
-The first two fields show the date (Modified Julian Day) and time (seconds
-and fraction past UTC midnight). The next three fields show time offset
-in seconds, frequency offset in parts-per-million and time constant of
-the clock-discipline algorithm at each update of the clock.
+The first two fields show the date (Modified Julian Day) and time
+(seconds and fraction past UTC midnight). The next three fields show
+time offset in seconds, frequency offset in parts-per-million and time
+constant of the clock-discipline algorithm at each update of the clock.
.RE
.Ip peerstats 10
enables recording of peer statistics information. This includes
statistics records of all peers of a NTP server and of the 1-pps signal,
-where present and configured. Each
-valid update appends a line of the following form to the current
-element of a file generation set named \*(L"peerstats\*(R":
+where present and configured. Each valid update appends a line of the
+following form to the current element of a file generation set named
+\*(L"peerstats\*(R":
.PP
.RS 5
48773 10847.650 127.127.4.1 9714 -0.001605 0.00000 0.00142
.RE
.RS 10
-The first two fields show the date (Modified Julian Day) and time (seconds
-and fraction past UTC midnight). The next two fields show the peer
-address in dotted-quad notation and status,
-respectively. The status field is encoded in hex in the format described
-in Appendix A of the NTP specification RFC 1305. The final three fields
-show the offset, delay and dispersion, all in seconds.
+The first two fields show the date (Modified Julian Day) and time
+(seconds and fraction past UTC midnight). The next two fields show the
+peer address in dotted-quad notation and status, respectively. The
+status field is encoded in hex in the format described in Appendix A of
+the NTP specification RFC 1305. The final three fields show the offset,
+delay and dispersion, all in seconds.
.RE
.Ip clockstats 10
enables recording of clock driver statistics information. Each update
@@ -656,23 +601,23 @@ received from a clock driver outputs a line of the following form to the
file generation set named \*(L"clockstats\*(R":
.PP
.RS 5
-49213 525.624 127.127.4.1 93 226 00:08:29.606 D
+49213 525.624 127.127.4.1 93 226 00:08:29.606 D
.RE
.RS 10
-The first two fields show the date (Modified Julian Day) and time (seconds
-and fraction past UTC midnight). The next field shows the clock
+The first two fields show the date (Modified Julian Day) and time
+(seconds and fraction past UTC midnight). The next field shows the clock
address in dotted-quad notation, The final field shows the last timecode
received from the clock in decoded ASCII format, where meaningful. In
some clock drivers a good deal of additional information can be gathered
-and displayed as well. See information specific to each clock
-for further details.
+and displayed as well. See information specific to each clock for
+further details.
.RE
.PP
-Statistic files are managed using file generation sets (see
+Statistic files are managed using file generation sets (see
.B filegen
-below). The information obtained by enabling statistics recording
-allows analysis of temporal properties of a
+below). The information obtained by enabling statistics recording allows
+analysis of temporal properties of a
.I xntpd
server. It is usually only useful to primary servers or maybe main
campus servers.
@@ -700,43 +645,41 @@ Generation file sets provide a means for handling files that are
continously growing during the lifetime of a server. Server statistics
are a typical example for such files. Generation file sets provide
access to a set of files used to store the actual data. At any time at
-most one element of the set is being written to. The
+most one element of the set is being written to. The
.I type
-given specifies when and how data will be directed to a new element
-of the set. This way, information stored in elements of a file set
-that are currently unused are available for administrational
-operations
-without the risc of desturbing the operation of
-.IR xntpd .
+given specifies when and how data will be directed to a new element of
+the set. This way, information stored in elements of a file set that are
+currently unused are available for administrational operations without
+the risc of desturbing the operation of
+.I xntpd .
(Most important: they can be removed to free space for new data
-produced.)
-Filenames of set members are built from three elements.
+produced.) Filenames of set members are built from three elements.
.Ip prefix 10
-This is a constant filename path. It is not subject to modifications
-via the
+This is a constant filename path. It is not subject to modifications via
+the
.B filegen
statement. It is defined by the server, usually specified as a compile
time constant. It may, however, be configurable for individual file
generation sets via other commands. For example, the prefix used with
-"loopstats" and "peerstats" filegens can be configured using the
-.B statsdir
+"loopstats" and "peerstats" filegens can be configured using the
+.B statsdir
statement explained above.
.Ip filename 10
This string is directly concatenated to the
.I prefix
mentioned above (no intervening \*(L'/\*(R' (slash)). This can be
modified using the \*(L"file\*(R" argument to the \*(L"filegen\*(R"
-statement. No \*(L"..\*(R" elements are allowed in this component to
+statement. No \*(L"..\*(R" elements are allowed in this component to
prevent filenames referring to parts outside the filesystem hierarchy
-denoted by \*(L"prefix\*(R".
+denoted by \*(L"prefix\*(R".
.Ip suffix 10
This part is reflects individual elements of a file set. It is generated
-according to the
+according to the
.I type
of a file set as explained below.
.PP
-A file generation set is characterized by its type.
-The following types are supported:
+A file generation set is characterized by its type. The following types
+are supported:
.Ip none 10
The file set is actually a single plain file.
.Ip pid 10
@@ -744,42 +687,41 @@ One element of file set is used per incarnation of a
.I xntpd
server. This type does not perform any changes to file set members
during runtime, however it provides an easy way of seperating files
-belonging to different
+belonging to different
.I xntpd
-server incarnations.
-The set member filename is built by appending a dot (\*(L'.\*(R') to
-concatentated \*(L"prefix\*(R" and \*(L"filename\*(R" strings, and
-appending the decimal representation of the process id of the
+server incarnations. The set member filename is built by appending a dot
+(\*(L'.\*(R') to concatentated \*(L"prefix\*(R" and \*(L"filename\*(R"
+strings, and appending the decimal representation of the process id of
+the
.I xntpd
server process.
.Ip day 10
One file generation set element is created per day. The term
.I day
-is based on
+is based on
.IR UTC .
-A day is defined as the period between 00:00 and 24:00 UTC.
-The file set member suffix consists of a dot \*(L".\*(R"
-and a day specification in the form
+A day is defined as the period between 00:00 and 24:00 UTC. The file set
+member suffix consists of a dot \*(L".\*(R" and a day specification in
+the form
.RI < YYYYMMDD >.
.I YYYY
is a 4 digit year number (e.g. 1992).
.I MM
is a two digit month number.
.I DD
-is a two digit day number.
-Thus, all information written at December 10th, 1992 would end up
-in a file named
+is a two digit day number. Thus, all information written at December
+10th, 1992 would end up in a file named
\*(L"<prefix><filename>.19921210\*(R".
.Ip week 10
Any file set member contains data related to a certain week of a year.
The term
.I week
is definied by computing \*(L"day of year\*(R" modulo 7. Elements of
-such a file generation set are distinguished by appending the
-following suffix to the file set filename base:
-A dot, a four digit year number, the letter \*(L"W\*(R",
-and a two digit week number. For example, information from Jamuary,
-10th 1992 would end up in a file with suffix \*(L".1992W1\*(R".
+such a file generation set are distinguished by appending the following
+suffix to the file set filename base: A dot, a four digit year number,
+the letter \*(L"W\*(R", and a two digit week number. For example,
+information from Jamuary, 10th 1992 would end up in a file with suffix
+\*(L".1992W1\*(R".
.Ip month 10
One generation file set element is generated per month. The file name
suffix consists of a dot, a four digit year number, and a two digit
@@ -789,145 +731,232 @@ One generation file elment is generated per year. The filename suffix
consists of a dot and a 4 digit year number.
.Ip age 10
This type of file generation sets changes to a new element of the file
-set every 24 hours of server operation. The filename suffix consists
-of a dot, the letter \*(L"a\*(R", and an eight digit number. This
-number is taken to be the number of seconds the server is running at
-the start of the corresponding 24 hour period.
+set every 24 hours of server operation. The filename suffix consists of
+a dot, the letter \*(L"a\*(R", and an eight digit number. This number is
+taken to be the number of seconds the server is running at the start of
+the corresponding 24 hour period.
.PP
Information is only written to a file generation set when this set is
-\*(L"enabled\*(R". Output is prevented by specifying
-\*(L"disabled\*(R".
+\*(L"enabled\*(R". Output is prevented by specifying \*(L"disabled\*(R".
.PP
-It is convenient to be able to access the
+It is convenient to be able to access the
.I current
element of a file generation set by a fixed name. This feature is
enabled by specifying \*(L"link\*(R" and disabled using
\*(L"nolink\*(R". If \*(L"link\*(R" is specified, a hard link from the
-current file set element to a file without suffix is created. When
-there is already a file with this name and the number of links of this
-file is one, it is renamed appending a dot, the letter \*(L"C\*(R",
-and the pid of the
+current file set element to a file without suffix is created. When there
+is already a file with this name and the number of links of this file is
+one, it is renamed appending a dot, the letter \*(L"C\*(R", and the pid
+of the
.I xntpd
server process. When the number of links is greater than one, the file
is unlinked. This allows the current file to be accessed by a constant
-name.
+name.
+.SH "MISCELLANEOUS OPTIONS"
+.PP
+.B precision
+.I #
+.PP
+This command specifies the nominal precision of the local clock. The
+value is an integer approximately equal to the base 2 logarithm of the
+local timekeeping precision in seconds. Normally, the daemon determines
+the precision automatically at startup, so this command is necessary
+only in special cases when the precision cannot be determined
+automatically.
+.PP
+.B broadcastdelay
+.I seconds
+.PP
+The broadcast and multicast modes require a special calibration to
+determine the network delay between the local and remote servers.
+Ordinarily, this is done automatically by the initial protocol exchanges
+between the local and remote servers. In some cases, the calibration
+procedure may fail due to network or server access controls, for
+example. This command specifies the default delay to be used under these
+circumstances. Typically (for Ethernet), a number between 0.003 and
+0.007 seconds is appropriate. The default when this command is not used
+is 0.004 seconds.
+.PP
+.B trap
+.I host_address
+[
+.B port
+.I port_number
+] [
+.B interface
+.I interface_addess
+]
+.PP
+This command configures a trap receiver at the given host address and
+port number for sending messages with the specified local interface
+address. If the port number is unspecified a value of 18447 is used. If
+the interface address is not specified the message is sent with a source
+address which is that of the local interface the message is sent
+through. Note that on a multihomed host the interface used may vary from
+time to time with routing changes.
+.PP
+The trap receiver will generally log event messages and other
+information from the server in a log file. While such monitor programs
+may also request their own trap dynamically, configuring a trap receiver
+will ensure that no messages are lost when the server is started.
+.PP
+.B setvar
+.I variable
+.I [default]
+.PP
+This command adds an additional system variable. These variables can be
+used to distribute additional information such as the access policy. If
+the variable of the from <name>=<value> is followed by the
+.I default
+keyword the variable will be listed as part of the default system
+variables (
+.I ntpq rv
+command). These additional variables serve informational purposes only.
+They are not related to the protocol other that they can be listed. The
+known protocol variables will always overide any variables defined via
+the
+.I setvar
+mechanism.
+.PP
+There are three special variables that contain the names of all variable
+of the same group. The
+.I sys_var_list
+holds the names of all system variables. The
+.I peer_var_list
+holds the names of all peer variables and the
+.I clock_var_list
+hold the names of the reference clock variables.
+.PP
+.B monitor yes|no
+.B authenticate yes|no
+.PP
+These commands have been superseded by the
+.B enable
+and
+.B disable
+commands. They are listed here for historical purposes.
.SH "AUTHENTICATION KEY FILE FORMAT"
.PP
-The NTP standard specifies an extension allowing
-verification of the authenticity of received NTP packets, and to provide
-an indication of authenticity in outgoing packets. This is implemented
-in
+The NTP standard specifies an extension allowing verification of the
+authenticity of received NTP packets, and to provide an indication of
+authenticity in outgoing packets. This is implemented in
+.I xntpd
+using the DES or MD5 algorithms to compute a digital signature, or
+message-digest. The specification allows any one of possibly 4 billion
+keys, numbered with 32 bit key identifiers, to be used to authenticate
+an association. The servers involved in an association must agree on the
+key and key identifier used to authenticate their data, though they must
+each learn the key and key identifer independently. In the case of DES,
+the keys are 56 bits long with, depending on type, a parity check on
+each byte. In the case of MD5, the keys are 64 bits (8 bytes).
.I xntpd
-using the DES encryption algorithm. The specification
-allows any one of a possible 4 billion keys, numbered with 32 bit unsigned
-integers, to be used to
-authenticate an association. The servers involved in an association
-must agree on the value of the key used to authenticate their data, though
-they must each learn the key independently. The keys are standard 56 bit
-DES keys.
-.PP
-Addionally, a new experimental authentication algorithm is available which
-uses an MD5 message digest to compute an authenticator. Currently the length
-of the key or password is limited to 8 characters, but this will eventually
-be changed to accomodate an effectively unlimited password phrase.
-.I Xntpd
reads its keys from a file specified using the
.B -k
command line option or the
.B keys
-statement in the configuration file. While key number 0 is fixed by the
+statement in the configuration file. While key number 0 is fixed by the
NTP standard (as 56 zero bits) and may not be changed, one or more of
the keys numbered 1 through 15 may be arbitrarily set in the keys file.
.PP
The key file uses the same comment conventions as the configuration
-file. Key entries use a fixed format of the form
+file. Key entries use a fixed format of the form
.Ip "" 5
-.I "keyno type key"
+.I "keyno type key"
.PP
-where \*(L"keyno\*(R" is a positive integer,
-\*(L"type\*(R" is a single character which defines the format the key
-is given in, and \*(L"key\*(R" is the key itself.
+where \*(L"keyno\*(R" is a positive integer, \*(L"type\*(R" is a single
+character which defines the format the key is given in, and
+\*(L"key\*(R" is the key itself.
.PP
The key may be given in one of three different formats, controlled by
-the \*(L"type\*(R" character. The three key types, and corresponding
+the \*(L"type\*(R" character. The three key types, and corresponding
formats, are listed following.
.Ip "S" 5
The \*(L"key\*(R" is a 64 bit hexadecimal number in the format specified
-in the DES document, that is the high order 7 bits of each octet are used
-to form the 56 bit key while the low order bit of each octet is given a
-value such that odd parity is maintained for the octet. Leading zeroes
-must be specified (i.e. the key must be exactly 16 hex digits long) and
-odd parity must be maintained. Hence a zero key, in standard format,
-would be given as
+in the DES document, that is the high order 7 bits of each octet are
+used to form the 56 bit key while the low order bit of each octet is
+given a value such that odd parity is maintained for the octet. Leading
+zeroes must be specified (i.e. the key must be exactly 16 hex digits
+long) and odd parity must be maintained. Hence a zero key, in standard
+format, would be given as
.I 0101010101010101 .
.Ip "N" 5
The \*(L"key\*(R" is a 64 bit hexadecimal number in the format specified
-in the NTP standard. This is the same as the DES format except the bits
+in the NTP standard. This is the same as the DES format except the bits
in each octet have been rotated one bit right so that the parity bit is
-now the high order bit of the octet. Leading zeroes must be specified
-and odd parity must be maintained. A zero key in NTP format would be specified
-as
+now the high order bit of the octet. Leading zeroes must be specified
+and odd parity must be maintained. A zero key in NTP format would be
+specified as
.I 8080808080808080
.Ip "A" 5
-The \*(L"key\*(R" is a 1\-to\-8 character ASCII string. A key is formed
-from this by using the lower order 7 bits of the ASCII representation
-of each character in the string, with zeroes being added on the right
-when necessary to form a full width 56 bit key, in the same way that
+The \*(L"key\*(R" is a 1\-to\-8 character ASCII string. A key is formed
+from this by using the lower order 7 bits of the ASCII representation of
+each character in the string, with zeroes being added on the right when
+necessary to form a full width 56 bit key, in the same way that
encryption keys are formed from Unix passwords.
.Ip "M" 5
The \*(L"key\*(R" is a 1\-to\-8 character ASCII string, using the MD5
-authentication scheme. Note that both the keys and the authentication
-schemes (DES or MD5) must be identical between a set of peers sharing
+authentication scheme. Note that both the keys and the authentication
+schemes (DES or MD5) must be identical between a set of peers sharing
the same key number.
.PP
One of the keys may be chosen,
by way of the configuration file
.B requestkey
-statement, to authenticate run time configuration
-requests made using the
+statement, to authenticate run time configuration requests made using
+the
.IR xntpdc (8)
-program. The latter program obtains the key from the terminal as
-a password, so it is generally appropriate to specify the key chosen
-to be used for this purpose in ASCII format.
+program. The latter program obtains the key from the terminal as a
+password, so it is generally appropriate to specify the key chosen to be
+used for this purpose in ASCII format.
.SH PRIMARY CLOCK SUPPORT
-.PP
-.I Xntpd
-can be optionally compiled to include support for a number of types
-of reference clocks. A reference clock will generally (though
-not always) be a radio timecode receiver which is synchronized to a
-source of standard time such as the services offered by the NRC in
-Canada and NIST in the U.S. The interface between the computer and
-the timecode receiver is device dependent and will vary, but is
-often a serial port.
+.I xntpd
+can be optionally compiled to include support for a number of types of
+reference clocks. A reference clock will generally (though not always)
+be a radio timecode receiver which is synchronized to a source of
+standard time such as the services offered by the NRC in Canada and NIST
+in the U.S. The interface between the computer and the timecode receiver
+is device dependent and will vary, but is often a serial port.
+.PP
+Support for the various reference clock drivers is conditionally
+compiled using the compiler define codes described elsewhere. An attempt
+to configure a reference clock when specific support is not available or
+the hardware port has not been appropriately configured results in a
+scolding remark to the system log file, but is otherwise non hazardous.
.PP
For the purposes of configuration,
.I xntpd
-treats reference clocks in a manner analogous to normal NTP peers
-as much as possible. Reference clocks are referred to by address,
-much as a normal peer is, though an invalid IP address is used to
-distinguish them from normal peers. Reference clock addresses are
-of the form
+treats reference clocks in a manner analogous to normal NTP peers as
+much as possible. Reference clocks are referred to by address, much as a
+normal peer is, though an invalid IP address is used to distinguish them
+from normal peers. Reference clock addresses are of the form
.I 127.127.t.u
where
.I t
is an integer denoting the clock type and
.I u
-indicates the type\-specific unit number. Reference clocks are normally
-enabled by configuring the clock as a server using a
+indicates the type\-specific unit number. Reference clocks are
+configured using a
.B server
-statement in the configuration file which references the clock's
-address (configuring a reference clock with a
-.B peer
-statement can also be done, though with some clock drivers this may cause
-the clock to be treated somewhat differently and by convention is used
-for debugging purposes). Clock addresses may generally
-be used anywhere else in the configuration file a normal IP address
-can be used, for example in
+statement in the configuration file where the
+.I host_address
+is the clock address. The
+.I key,
+.I version
+and
+.I ttl
+options are not used for reference clock support; however, the
+.I prefer
+option can be useful to persuade the server to cherish a reference clock
+with somewhat more enthusiasm than other reference clocks or peers, if
+this is advisable. Clock addresses may generally be used anywhere in the
+configuration file a normal IP address can be used, for example, in
.B restrict
-statements.
+statements, although such use would normally be considered strange.
.PP
-There is one additional configuration statement which becomes valid
-when reference clock support has been compiled in. Its format is:
+Reference clock support provides the
+.B fudge
+command, which can be used to configure reference clocks in special
+ways. Following is the generic format that applies to this command
.PP
.B fudge
.I 127.127.t.u
@@ -938,10 +967,10 @@ when reference clock support has been compiled in. Its format is:
.B time2
.I secs
] [
-.B value1
+.B stratum
.I int
] [
-.B value2
+.B refid
.I int
] [
.B flag1
@@ -949,502 +978,106 @@ when reference clock support has been compiled in. Its format is:
] [
.B flag2
.I 0|1
+] [
+.B flag3
+.I 0|1
+] [
+.B flag4
+.I 0|1
]
.PP
-There are two times (whose values are specified in fixed point seconds),
-two integral values and two binary flags available for customizing
-the operation of a clock. The interpretation of these values, and
-whether they are used at all, is a function of the needs of the particular
-clock driver.
-.PP
-.I Xntpd
-on Unix machines currently supports several different types of clock hardware
-plus a special pseudo\-clock used for backup or when no other clock
-source is available. In the case of most of the clock drivers, support
-for a 1-pps precision timing signal is available as described in the
-pps.txt file in the doc directory of the xntp3 distribution.
-The clock drivers, and the addresses used to configure
-them, are described following:
-.PP
-.B 127.127.1.u
-\- Local synchronization clock driver
-.PP
-This driver doesn't support an actual clock, but rather allows the
-server to synchronize to its own clock, in essence to free run without
-its stratum increasing to infinity. This can be used to run an
-isolated NTP synchronization network where no standard time source is
-available, by allowing a free running clock to appear as if it has
-external synchronization to other servers. By running the local clock
-at an elevated stratum it can also be used to prevent a server's stratum
-from rising above a fixed value, this allowing a synchronization subnet
-to synchonize to a single local server for periods when connectivity
-to the primary servers is lost.
-.PP
-The unit number of the clock (the least significant octet in the address)
-must lie in the range 0 through 15 inclusive and is used as the stratum
-the local clock will run at. Note that the server, when synchronized
-to the local clock, will advertise a stratum one greater than the clock
-peer's stratum. More than one local clock may be configured (indeed all
-16 units may be active at once), though this hardly seems useful.
-.PP
-The local clock driver uses only the fudge time1 parameter. This parameter
-provides read and write access to the local clock drift compensation
-register. This value, which actually provides a fine resolution speed
-adjustment for the local clock, is settable but will remain unchanged
-from any set value
-when the clock is free running without external synchronization. The
-fudge time1 parameter thus provides a way to manually adjust the speed of the
-clock to maintain reasonable synchronization with, say, a voice
-time announcement. It is actually more useful to manipulate this value
-with the
-.IR xntpdc (8)
-program.
-.PP
-.B 127.127.3.u
-\- Precision Standard Time/Traconex 1010/1020 WWV/H Receiver
-.PP
-This driver can be used with a PST/Traconex Time Source 1010 or 1020 WWV/WWVH
-Synchronized Clock connected via a serial port. Up to
-four units, with unit numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/pst%d (i.e. unit 1, at 127.127.3.1, opens the clock at
-/dev/pst1) and that the clock is configured for 9600-baud operation.
-.PP
-The fudge time1 and time2 parameters are configured directly into the receiver
-as nominal propagation delays when synchronized to WWV and WWVH,
-respectively; the internal DIPswitches ordinarily used for that purpose
-are disabled. The default values are 0.0075 and 0.0265 seconds,
-respectively, which are about right for Toronto. Values for other
-locations can be calculated using the
-.I propdelay
-program in the util directory of the xntp3 distribution or equivalent
-means described in the user's manual.
-.PP
-The fudge value1 parameter can be used to set the stratum at which
-the peer operates. The default is 0, which is correct if you want the
-clock to be considered for synchonization whenever it is operating, though
-higher values may be assigned if you only want the clock to provide backup
-service when all other primary sources have failed. The value2 parameter
-is set to the number of minutes which the daemon will allow the clock to go
-without synchronization before it starts disbelieving it. The default
-is 20, which is suitable if you have good quality backup NTP peers. If
-your network is isolated or your network connections are poor it might
-be advantageous to increase this value substantially.
-.PP
-The fudge flag1 can be used to modifiy the averaging algorithm used
-to smooth the clock indications. Ordinarily, the algorithm picks the
-median of a set of samples, which is appropriate under conditions
-of poor to fair radio propagation conditions. If the clock is located
-relatively close to the WWV or WWVH transmitters, setting this flag
-will cause the algorithm to average the set of samples, which can
-reduce the residual jitter and improve accuracy.
-.PP
-The fudge flag2 can be used to force the driver to send to
-the clock the commands required to reprogram the current WWV and WWVH fudge
-delays into it. This is normally done only when the values are to be changed,
-such as during inital setup and calibration. Setting
-the (otherwise undocumented) fudge flag3 will cause the driver to reset
-the clock. The latter two flags are generally useful primarily for debugging.
-.PP
-127.127.4.u
-\- Spectracom 8170 and Netclock/2 WWVB Synchronized Clocks
-.PP
-This driver can be used with a Spectracom 8170 or Netclock/2 WWVB
-Synchronized Clock connected via a serial port. Up to
-four units, with unit numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/wwvb%d (i.e., unit 1 at 127.127.4.1 opens the clock at
-/dev/wwvb1) and that the clock is configured for 9600-baud operation.
-.PP
-The fudge time1 parameter can be used to compensate for inherent
-latencies in the serial port hardware and operating system.
-The value, which defaults to zero, is in addition to the value
-programmed by the propagation switches on the receiver. The
-fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-.PP
-.B 127.127.5.u
-\- Kinemetrics/TrueTime Timing Receivers
-.PP
-This driver can be used with at least two models of Kinemetrics/TrueTime
-Timing Receivers, the 468-DC MK III GOES Synchronized Clock and GPS-DC
-MK III GPS Synchronized Clock and very likely others in the same model
-family that use the same timecode formats. The clocks are connected
-via a serial port. Up to
-four units, with unit numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/goes%d (i.e., unit 1 at 127.127.5.1 opens the clock at
-/dev/goes1) and that the clock is configured for 9600-baud operation.
-.PP
-The fudge time1 parameter can be used to compensate for inherent
-latencies in the serial port hardware and operating system in the same
-way as described above for the WWVB clock 127.127.4.u.
-The fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-.PP
-.B 127.127.6.0
-\- IRIG-B Audio Decoder
-.PP
-This driver can be used in conjuction with the Inter-Range Instrumentation
-Group standard time-distribution signal IRIG-B. This signal is generated
-by several radio clocks, including those made by Austron, TrueTime, Odetics
-and Spectracom, among others, although it is generally an add-on option.
-The signal is connected via an attenuator box and cable to the audio
-codec input on a Sun SPARCstation and requires a specially modified
-kernel audio driver. Details are in the irig.txt file in the doc
-directory of the xntp3 distribution. As only a single audio codec
-is built into a workstation, the driver assumes the device name is /dev/irig.
-.PP
-Timing jitter using the decoder and a Sun IPC is in the order of a few
-microseconds, although the overal timing accuracy is limited by the
-wander of the CPU oscillator used for timing purposes to a few hundred
-microseconds. These figures are comparable with what can be achieved
-using the 1-pps signal described in the pps.txt file in the doc
-directory of the xntp3 distribution.
-.PP
-.B 127.127.7.u
-\- CHU Modem Decoder
-.PP
-This driver can be used with a shortwave receiver and special modem
-circuitry described in the gadget directory of the xntp3 distribution.
-It requires the chu-clk line discipline or chu_clk STREAMS module
-described in the kernel directory of that distribution. It is connected
-via a serial port operating at 300 baud. Up to
-four units, with unit numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/chu%d (i.e., unit 1 at 127.127.7.1 opens the clock at
-/dev/chu1).
-.PP
-Unlike the NIST time services, whose timecode requires quite specialized
-hardware to interpret, the CHU timecode can be received directly via
-a serial port after demodulation. While there are currently no commercial
-CHU receivers, the hardware required to receive the CHU timecode is fairly
-simple to build. While it is possible to configure several CHU units
-simultaneously this is not recommended as the character interrupts from all
-units will be occuring at the same time and will interfere with each other.
-.PP
-The fudge time1 parameter is used to specify the propagation delay between
-the CHU transmitter at Ottawa, Ontario, and the receiver. The default
-value is 0.0025 seconds, which is about right for Toronto. Values for other
-locations can be calculated using the
-.I propdelay
-program in the util directory of the xntp3 distribution or equivalent
-means.
-The fudge time2
-parameter is used to compensate for inherent latencies in the modem,
-serial port hardware and operating system in the same way as described
-above for the WWVB clock 127.127.4.u. The default value is
-0.0002 seconds, which is about right for typical telephone modem chips.
-The fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-The fudge flag1 can be used to modify the averaging algorithm in the
-same way as described for that clock.
-.PP
-.B 127.127.8.u
-\- Synchronisation to several receivers (DCF77, GPS)
-.PP
-The timecode of
-the receivers will be sampled via a STREAMS module in the kernel (The STREAMS module
-has been designed for use with SUN Systems under SunOS 4.1.x. It can be
-linked directly into the kernel or loaded via the loadable driver mechanism)
-This STREAMS module can be adepted to be able to convert different time code
-formats.
-If the daemon is compiled without the STREAM definition synchronisation
-will work without the Sun streams module, though accuracy is significantly
-degraded.
-.br
-The actual receiver status is mapped into various synchronisation
-states generally used by receivers. The STREAMS module is configured to
-interpret the time codes of DCF U/A 31, PZF535, GPS166, Trimble SV6 GPS, ELV DCF7000,
-Schmid and low cost receivers (see list below).
-.br
-The reference clock support in xntp contains the necessary configuration tables
-for those receivers. In addition to supporting up to 32 different clock types and
-4 devices the generation a a PPS signal is also provided as an configuration
-option. The PPS configuration option uses the receiver generated time stamps
-for feeding the PPS loopfilter control for much finer clock synchronisation.
-.br
-CAUTION: The PPS configuration option is different from the hardware PPS signal,
-which is also supported (see below), as it controls the way xntpd is synchronised
-to the reference clock, while the hardware PPS signal controls the way time
-offsets are determined.
-.br
-The use of the PPS option requires receivers with an accuracy of better than 1ms.
-.PP
-Fudge factors
-.PP
-Only two fudge factors are utilized. The
-.I time1
-fudge factor defines the phase offset of the sychnronisation character to the actual
-time.
-On the availability of PPS information the
-.I time2
-fudge factor defines the skew between the PPS time stamp and the reception
-time stamp of the PPS signal. This parameter is usually 0 as usually
-the PPS signal is believed in time and OS delays should be corrected
-in the machine specific section of the kernel driver.
-.I time2
-needs only be set when the actial PPS signal is delayed for some
-reason.
The
-.I flag0
-enables input filtering. This a median filter with continuous sampling. The
-.I flag1
-selects averaging of the samples remaining after the filtering. Leap second
-handling is controlled with the
-.I flag2.
-When set a leap second will be deleted on receipt of a leap second indication
-from the receiver. Otherwise the leap second will be added (which is the default).
+.I time1
+and
+.B time2
+options are specified in fixed point seconds and used in some clock
+drivers as calibration constants. By convention, and unless indicated
+otherwise,
+.B time1
+is used as a calibration constant to adjust the nominal time offset of a
+particular clock to agree with an external standard, such as a precision
+PPS signal. The specified offset is in addition to the propagation delay
+provided by other means, such as internal DIPswitches. The
+.B stratum
+option is a number in the range zero to 15 and is used to assign a
+nonstandard operating stratum to the clock. The
+.B refid
+option is an ASCII string in the range one to four characters and is
+used to assign a nonstandard reference identifier to the clock. Finally,
+the four binary flags
+.B flag1,
+.B flag2,
+.B flag3
+and
+.B flag4
+are used for customizing the clock driver. The interpretation of these
+values, and whether they are used at all, is a function of the needs of
+the particular clock driver. However, by convention, and unless
+indicated otherwise,
+.B flag3
+is used to attach the ppsclock streams module to the configured driver,
+while
+.B flag4
+is used to enable recording verbose monitoring data to the clockstats
+file configured with the
+.I filegen
+command. Further information on the ppsclock streams module is in the
+README file in the ./kernel directory in the current xntp3 program
+distribution. Further information on this feature is available in the
+./scripts/stats directory in the same distribution.
+.PP
+Ordinarily, the stratum of a reference clock is by default zero. Since
+the
+.I xntpd
+daemon adds one to the stratum of each peer, a primary server ordinarily
+displays stratum one. In order to provide engineered backups, it is
+often useful to specify the reference clock stratum as greater than
+zero. The
+.B stratum
+option is used for this purpose. Also, in cases involving both a
+reference clock and a 1-pps discipline signal, it is useful to specify
+the reference clock identifier as other than the default, depending on
+the driver. The
+.I refid
+option is used for this purpose. Except where noted, these options apply
+to all clock drivers.
.PP
-.I ntpq
-timecode variable
-.PP
-The ntpq read clock variables command list several variables. These
-hold followinf information:
-.I refclock_time
-is the local time with the offset to UTC (format HHMM).
-The currently active receiver flags are listed in
-.I refclock_status.
-Additional feature flags of the receiver are optionally listed in paranthesis.
-The actual time code is listed in
-.I timecode.
-A qualification of the decoded time code format is following in
-.I refclock_format.
-The last piece of information is the overall running time and the accumulated
-times for the clock event states in
-.I refclock_states.
-When PPS information is present additional variable are available.
-.I refclock_ppstime
-lists then the PPS timestamp and
-.I refclock_ppsskew
-lists the difference between RS232 derived timestamp and the PPS timestamp.
-.PP
-Unit encoding
-.PP
-The unit field <u> encodes the device, clock type and the PPS generation option.
-There are 4 possible devices which are encoded in the lower 2 bits of the <u>
-field. The devices are named
-.IR /dev/refclock-0
-through
-.IR /dev/refclock-3 .
-Bits 2 thru 6 encode the clock type. The fudge factors
-of the clock type are take from a table
-.I clockinfo
-in refclock_parse.c. The generation of PPS information for disciplining the
-local NTP clock is encoded in bit 7 of <u>.
-.PP
-Currently nine clock types (devices /dev/refclock-0 - /dev/refclock-3) are supported.
-.Ip 127.127.8.0-3 16
-Meinberg PZF535 receiver (FM demodulation/TCXO / 50us)
-.Ip 127.127.8.4-7 16
-Meinberg PZF535 receiver (FM demodulation/OCXO / 50us)
-.Ip 127.127.8.8-11 16
-Meinberg DCF U/A 31 receiver (AM demodulation / 4ms)
-.Ip 127.127.8.12-15 16
-ELV DCF7000 (sloppy AM demodulation / 50ms)
-.Ip 127.127.8.16-19 16
-Walter Schmid DCF receiver Kit (AM demodulation / 1ms)
-.Ip 127.127.8.20-23 16
-RAW DCF77 100/200ms pulses (Conrad DCF77 receiver module / 5ms)
-.Ip 127.127.8.24-27 16
-RAW DCF77 100/200ms pulses (TimeBrick DCF77 receiver module / 5ms)
-.Ip 127.127.8.28-31 16
-Meinberg GPS166 receiver (GPS / <<1us)
-.Ip 127.127.8.32-35 16
-Trimble SV6 GPS receiver (GPS / <<1us)
-.PP
-The reference clock support carefully monitors the state transitions of
-the receiver. All state changes and exceptional events such as loss of time code
-transmission are logged via the
-.I syslog
-facility.
-Every hour a summary of the accumulated times for the clock states is
-listed via syslog.
-.PP
-PPS support is only available when the receiver is completely
-synchronised. The receiver is believed to deliver correct time for an additional
-period of time after losing sychronisation unless a disruption in time code
-transmission is detected (possible power loss). The trust period is dependent
-on the receiver oscillator and thus a function of clock type. This is one of
-the parameters in the
-.I clockinfo
-field of the reference clock implementation. This parameter cannot be
-configured by xntpdc.
-.PP
-In addition to the PPS loopfilter control a true PPS hardware signal can be applied
-on Sun Sparc stations via the CPU serial ports on the CD pin. This signal is
-automatically detected and will be used for offset calculation. The input signal
-must be the time mark for the following time code. (The edge sensitivity can be
-selected - look into the appropriate kernel/parsestreams.c for details).
-Meinberg receivers can be connected by feeding the PPS pulse of the receiver via
-a 1488 level converter to Pin 8 (CD) of a Sun serial zs\-port.
-.PP
-There exists a special firmware release for the PZF535 Meinberg receivers.
-This release (PZFUERL 4.6 (or higher - The UERL is important)) is absolutely
-recommended for XNTP use, as it provides LEAP warning, time code time zone information
-and alternate antenna indication. Please check with Meinberg for this
-firmware release.
-For the Meinberg GPS166 receiver is also a special firmaware release available
-(Uni-Erlangen). This release must be used for proper operation.
-.PP
-The raw DCF77 pulses can be fed via a level converter directly into Pin 3 (Rx)
-of the Sun. The telegrams will be decoded an used for synchronisation.
-AM DCF77 receivers are running as low as $25. The accuracy is dependent on
-the receiver and is somewhere between 2ms (expensive) to 10ms (cheap).
-Upon bad signal reception of DCF77 sychronisation will cease as no backup
-oscillator is available as usually found in other reference clock receivers.
-So it is important to have a good place for the DCF77 antenna. For transmitter
-shutdowns you are out of luck unless you have other NTP servers with alternate
-time sources available.
-.PP
-127.127.9.u
-\- Magnavox MX4200 Navigation Receiver used as GPS Synchronized Clocks
-.PP
-This driver can be used with a Magnavox MX4200 Navigation Receiver
-adapted to precision timing applications. This requires an interface
-box described in the ppsclock directory of the xntp3 distribution.
-It is connected via a serial port and requires the ppsclock STREAMS
-module described in the same directory. Up to
-four units, with unit numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/gps%d (i.e., unit 1 at 127.127.9.1 opens the clock at
-/dev/gps1) and that the clock is configured for 9600-baud operation.
-.PP
-The fudge time1 parameter can be used to compensate for inherent
-latencies in the serial port hardware and operating system in the
-same way described above for the WWVB clock 127.127.4.u. The
-fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-.PP
-127.127.10.u
-\- Austron 2200A/2201A GPS/LORAN Synchronized Clock and Timing Receiver
-.PP
-This driver can be used with an Austron 2200A/2201A GPS/LORAN Synchronized
-Clock and Timing Receiver connected via a serial port. It supports
-several special features of the clock, including the Input Burffer Module,
-Output Buffer Module, IRIG-B Interface Module and LORAN Assist Module. It
-requires the RS232 Serial Interface module for communication with
-the driver. Up to four units (which hardly seems affordable), with unit
-numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/gps%d (i.e., unit 1 at 127.127.10.1 opens the clock at
-/dev/gps1) and that the clock is configured for 9600-baud operation.
-.PP
-The fudge time1 parameter can be used to compensate for inherent
-latencies in the serial port hardware and operating system in the
-same way described above for the WWVB clock 127.127.4.u. The
-fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-.PP
-This receiver is capable of a comprehensive and large volume of
-statistics and operational data. The specific data-collection
-commands and attributes are embedded in the driver source code;
-however, the collection process can be enabled or disabled
-using the flag4 flag. If set, collection is enabled; if not,
-which is the default, it is disabled. A comprehensive suite of data reduction
-and summary scripts is in the ./scripts/stats directory of the xntp
-distribution.
-.PP
-127.127.11.u
-\- Kinemetrics/TrueTime OMEGA-DC OMEGA Synchronized Clock
-.PP
-This driver can be used with a Kinemetrics/TrueTime OMEGA-DC OMEGA
-Synchronized Clock connected via a serial port. This clock is
-sufficiently different than other Kinemetrics/TrueTime models
-to require a separate driver. Up to
-four units, with unit numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/omega%d (i.e., unit 1 at 127.127.11.1 opens the clock at
-/dev/omega1) and that the clock is configured for 9600-baud operation.
-.PP
-The fudge time1 parameter can be used to compensate for inherent
-latencies in the serial port hardware and operating system in the
-same way described above for the WWVB clock 127.127.4.u. The
-fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-.PP
-127.127.12.0
-\- KSI/Odeteics TPRO IRIG-B Decoder
-.PP
-This driver can be used with a KSI/Odeteics TPRO or TPRO-SAT IRIG-B
-Decoder, which is a module connected directly to the SBus of a
-Sun workstation. The module works with the IRIG-B signal generated
-by several radio clocks, including those made by Austron, TrueTime, Odetics
-and Spectracom, among others, although it is generally an add-on option.
-In the case of the TPRO-SAT, the module is an integral part of a GPS
-receiver, which serves as the primary timing source.
-As only a single module of this type can be
-used on a single workstation, only the unit number 0 is acceptable.
-The driver assumes the device name is /dev/tpro0.
-.PP
-The fudge time1 parameter can be used to compensate for inherent
-latencies in the serial port hardware and operating system in the
-same way described above for the WWVB clock 127.127.4.u. The
-fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-.PP
-127.127.13.u
-\- Leitch CSD 500 Controller with HP 5061A Atomic Clock
-.PP
-This driver can be used with a Leitch CSD 500 Controller
-connected to an HP 5061A Atomic Clock or equivalent primary timing source
-and connected via a serial port. Up to
-four units, with unit numbers in the range 0 through 3, can be
-configured. The driver assumes the serial port device name is
-/dev/leitch%d (i.e., unit 1 at 127.127.13.1 opens the clock at
-/dev/leitch1) and that the clock is configured for 300-baud operation.
-.PP
-The fudge time1 parameter can be used to compensate for inherent
-latencies in the serial port hardware and operating system in the
-same way described above for the WWVB clock 127.127.4.u. The
-fudge value1 parameter can be used to specify the stratum of the clock
-in the same way described above for the WWV/WWVH clock 127.127.3.u.
-.PP
-127.127.14.u
-\- EES M201 MSF receiver
-.PP
-This driver can be used with an EES M201 MSF receiver connected
-to a Sun running SunOS 4.x with the "ppsclock" STREAMS module.
-.PP
-The fudge time1 and time2 parameters can be used to compensate for
-inherent latencies in the serial port hardware and operating system
-respectively in the same way described above for the WWVB clock 127.127.4.u.
-The bottom 4 bits of fudge value1 parameter can be used to specify
-the stratum of the clock in the same way described above for the
-WWV/WWVH clock 127.127.3.u.
-The fudge value2 parameter can be used to specify the debug mask.
-bit 0x1 causes logging of smoothing processing.
-bit 0x4 causes the clock buffer to be dumped.
-If flag1 is set, then the system clock is assumed to be sloppy
-(e.g. Sun4 with 20ms clock), so samples are averaged.
-If flag2 is set, then leaphold is set.
-If flag3 is set, then the sample information is dumped.
-If flag4 is set, then the input data is smoothed, and all data
-points are used.
+.I xntpd
+on Unix machines currently supports several different types of clock
+hardware plus a special pseudo\-clock used for backup or when no other
+clock source is available. In the case of most of the clock drivers,
+support for a 1-pps precision timing signal is available as described in
+the README file in the ./doc directory of the xntp3 progam distribution.
+The clock drivers, and the addresses used to configure them, are
+described in the README.refclocks in the doc directory of the current
+program distribution.
.PP
.SH VARIABLES
-Most variables used by the NTP protocol can be examined with the xntpdc
-(mode 7 messages) and the ntpq (mode 6 messages). Currently very few variables
-can be modified via mode 6 messages. These variables are either created with the
+Most variables used by the NTP protocol can be examined with the
+.I xntpdc
+(mode 7 messages) and the
+.I ntpq
+(mode 6 messages). Currently very few variables can be modified via mode
+6 messages. These variables are either created with the
.I setvar
-directive or the leap warning variables. The leap warning bits that can be
-set in the
+directive or the leap warning variables. The leap warning bits that can
+be set in the
.B leapwarning
variable (up to one month ahead). Both, the
-.B leapwarning and in the
+.B leapwarning and in the
.B leapindication
variable, have a slightly different encoding than the usual
.B leap
bits interpretation:
.P
.Ip 00 8
-The daemon passes the leap bits of its synchronisation source (usual mode of
-operation).
+The daemon passes the leap bits of its synchronisation source (usual
+mode of operation).
.Ip 01/10 8
A leap second is added/deleted (operator forced leap second).
.Ip 11 8
-Leap information from the sychronisation source is ignored (thus LEAP_NOWARNING
-is passed on).
+Leap information from the sychronisation source is ignored (thus
+LEAP_NOWARNING is passed on).
.PP
.SH FILES
.Ip /etc/ntp.conf 20
@@ -1460,20 +1093,13 @@ the conventional name of the key file
.IR ntpdate (8)
.SH HISTORY
.PP
-Written by Dennis Ferguson at the University of Toronto.
-Text amended by David Mills at the University of Delaware.
+Written by Dennis Ferguson at the University of Toronto. Text amended by
+David Mills at the University of Delaware.
.SH BUGS
.PP
-.I Xntpd
-has gotten rather fat. While not huge, it has gotten larger
-than might be desireable for an elevated\-priority daemon running on a
-workstation, particularly since many of the fancy features which
-consume the space were designed more with a busy primary server, rather
-than a high stratum workstation, in mind. This will eventually be corrected
-either by adopting the
-.I ntpd
-daemon as an alternative when it becomes able to match
-.IR xntpd 's
-performance, or if not than by producing a stripped down version of
.I xntpd
-specifically for workstation use.
+has gotten rather fat. While not huge, it has gotten larger than might
+be desireable for an elevated\-priority daemon running on a workstation,
+particularly since many of the fancy features which consume the space
+were designed more with a busy primary server, rather than a high
+stratum workstation, in mind.
diff --git a/usr.sbin/xntpd/doc/xntpdc.8 b/usr.sbin/xntpd/doc/xntpdc.8
index 80979e2675b4..739eeced707e 100644
--- a/usr.sbin/xntpd/doc/xntpdc.8
+++ b/usr.sbin/xntpd/doc/xntpdc.8
@@ -1,5 +1,5 @@
''' $Header
-'''
+'''
.de Sh
.br
.ne 5
@@ -48,7 +48,7 @@ xntpdc - query/control program for the Network Time Protocol daemon
[
.B -ilnps
] [
-.B -c
+.B -c
.I command
] [
.I host
@@ -59,12 +59,12 @@ xntpdc - query/control program for the Network Time Protocol daemon
.I Xntpdc
is used to query the
.IR xntpd (8)
-daemon about its current state and to request changes in that state. The
+daemon about its current state and to request changes in that state. The
program may be run either in interactive mode or controlled using
-command line arguments. Extensive state and statistics information is
+command line arguments. Extensive state and statistics information is
available through the
.I xntpdc
-interface. In addition, nearly all the configuration options which can
+interface. In addition, nearly all the configuration options which can
be specified at start up using
.IR xntpd 's
configuration file may also be specified at run time using
@@ -72,14 +72,14 @@ configuration file may also be specified at run time using
.PP
If one or more request options is included on the command line when
.I xntpdc
-is executed, each of the requests will be sent to the NTP servers running
-on each of the hosts given as command line arguments, or on
+is executed, each of the requests will be sent to the NTP servers
+running on each of the hosts given as command line arguments, or on
.I localhost
-by default. If no request options are given,
+by default. If no request options are given,
.I xntpdc
will attempt to read commands from the standard input and execute these
-on the NTP server running on the first host given on the command line, again
-defaulting to
+on the NTP server running on the first host given on the command line,
+again defaulting to
.I localhost
when no other host is specified.
.I Xntpdc
@@ -88,60 +88,61 @@ will prompt for commands if the standard input is a terminal device.
.I Xntpdc
uses NTP mode 7 packets to communicate with the NTP server, and hence
can be used to query any compatable server on the network which permits
-it. Note that since NTP is a UDP protocol this communication will be
+it. Note that since NTP is a UDP protocol this communication will be
somewhat unreliable, especially over large distances in terms of network
topology.
.I Xntpdc
makes no attempt to retransmit requests, and will time requests out if
the remote host is not heard from within a suitable time out time.
.PP
-Command line options are described following. Specifying a command
-line option other than
+Command line options are described following. Specifying a command line
+option other than
.B -i
or
.B -n
will cause the specified query (queries) to be sent to the indicated
-host(s) immediately. Otherwise,
+host(s) immediately. Otherwise,
.I xntpdc
-will attempt to read interactive format commands from the standard input.
+will attempt to read interactive format commands from the standard
+input.
.Ip -c 8
The following argument is interpreted as an interactive format command
and is added to the list of commands to be executed on the specified
-host(s). Multiple
+host(s). Multiple
.B -c
options may be given.
.Ip -i 8
Force
.I xntpdc
-to operate in interactive mode. Prompts will be written to the
-standard output and commands read from the standard input.
+to operate in interactive mode. Prompts will be written to the standard
+output and commands read from the standard input.
.Ip -l 8
-Obtain a list of peers which are known to the server(s). This switch
-is equivalent to \*(L"-c listpeers\*(R".
+Obtain a list of peers which are known to the server(s). This switch is
+equivalent to \*(L"-c listpeers\*(R".
.Ip -n 8
Output all host addresses in dotted\-quad numeric format rather than
converting to the canonical host names.
.Ip -p 8
-Print a list of the peers known to the server as well as a summary
-of their state. This is equivalent to \*(L"-c peers\*(R".
+Print a list of the peers known to the server as well as a summary of
+their state. This is equivalent to \*(L"-c peers\*(R".
.Ip -s 8
-Print a list of the peers known to the server as well as a summary
-of their state, but in a slightly different format than the
+Print a list of the peers known to the server as well as a summary of
+their state, but in a slightly different format than the
.B -p
-switch. This is equivalent to \*(L"-c dmpeers\*(R".
+switch. This is equivalent to \*(L"-c dmpeers\*(R".
.SH INTERNAL COMMANDS
.PP
-Interactive format commands consist of a keyword followed by zero
-to four arguments. Only enough characters of the full keyword to
-uniquely identify the command need be typed. The output of a command
-is normally sent to the standard output, but optionally the output of
-individual commands may be sent to a file by appending a \*(L">\*(R",
-followed by a file name, to the command line.
+Interactive format commands consist of a keyword followed by zero to
+four arguments. Only enough characters of the full keyword to uniquely
+identify the command need be typed. The output of a command is normally
+sent to the standard output, but optionally the output of individual
+commands may be sent to a file by appending a \*(L">\*(R", followed by a
+file name, to the command line.
.PP
A number of interactive format commands are executed entirely within the
.I xntpdc
-program itself and do not result in NTP mode 7 requests being sent
-to a server. These are described following.
+program itself and do not result in NTP mode 7 requests being sent to a
+server. These are described following.
.PP
.B ?
[
@@ -152,7 +153,7 @@ A \*(L"?\*(R" by itself will print a list of all the command keywords
known to this incarnation of
.IR xntpdc .
A \*(L"?\*(R" followed by a command keyword will print funcation and
-usage information about the command. This command is probably a better
+usage information about the command. This command is probably a better
source of information about
.I xntpdc
than this manual page.
@@ -169,14 +170,14 @@ command.
.B timeout
.I millseconds
.PP
-Specify a time out period for responses to server queries. The default
+Specify a time out period for responses to server queries. The default
is about 8000 milliseconds.
.PP
.B delay
.I milliseconds
.PP
Specify a time interval to be added to timestamps included in requests
-which require authentication. This is used to enable (unreliable) server
+which require authentication. This is used to enable (unreliable) server
reconfiguration over long delay network paths or between machines whose
clocks are unsynchronized.
.PP
@@ -185,40 +186,27 @@ clocks are unsynchronized.
.PP
Set the host to which future queries will be sent.
.I Hostname
-may be either a host name or a numeric
-address.
-.PP
-.B poll
-[
-.I #
-] [
-.B verbose
-]
-.PP
-Poll the current server in client mode. The first argument is the
-number of times to poll (default is 1) while the second argument may
-be given to obtain a more detailed output of the results. This command
-is currently just wishful thinking.
+may be either a host name or a numeric (dotted quad) dmaddress.
.PP
.B keyid
.I #
.PP
This command allows the specification of a key number to be used to
-authenticate configuration requests. This must correspond to the
-key number the server has been configured to use for this purpose.
+authenticate configuration requests. This must correspond to the key
+number the server has been configured to use for this purpose.
.PP
.B passwd
.PP
This command prompts you to type in a password (which will not be
-echoed) which will be used to authenticate configuration requests. The
-password must correspond to the key configured for use by the NTP
-server for this purpose if such requests are to be successful.
+echoed) which will be used to authenticate configuration requests. The
+password must correspond to the key configured for use by the NTP server
+for this purpose if such requests are to be successful.
.PP
.B "hostnames yes|no"
.PP
If \*(L"yes\*(R" is specified, host names are printed in information
-displays. If \*(L"no\*(R" is given, numeric addresses are printed
-instead. The default is \*(L"yes\*(R" unless modified using the command
+displays. If \*(L"no\*(R" is given, numeric addresses are printed
+instead. The default is \*(L"yes\*(R" unless modified using the command
line
.B -n
switch.
@@ -230,51 +218,49 @@ Exit
.SH QUERY COMMANDS
.PP
Query commands result in NTP mode 7 packets containing requests for
-information being sent to the server. These are \*(L"read\-only\*(R"
+information being sent to the server. These are \*(L"read\-only\*(R"
commands in that they make no modification of the server configuration
state.
.PP
.B listpeers
.PP
-Obtains and prints a brief list of the peers for which the
-server is maintaining state. These should include all configured
-peer associations as well as those peers whose stratum is such that
-they are considered by the server to be possible future synchonization
-candidates.
+Obtains and prints a brief list of the peers for which the server is
+maintaining state. These should include all configured peer associations
+as well as those peers whose stratum is such that they are considered by
+the server to be possible future synchonization candidates.
.PP
.B peers
.PP
Obtains a list of peers for which the server is maintaining state, along
-with a summary of that state. Summary information includes the address
-of the remote peer, the local interface address (0.0.0.0 if a local address
-has yet to be determined), the stratum of the remote peer (a stratum of
-16 indicates the remote peer is unsynchronized), the polling interval,
-in seconds, the reachability
-register, in octal, and the current estimated delay, offset and dispersion
-of the peer, all in seconds. In addition, the character in the left
-margin indicates the mode this peer entry is operating in. A
-\*(L"+\*(R" denotes symmetric active, a \*(L"-\*(R" indicates symmetric
-passive, a \*(L"=\*(R" means the remote server is being polled in
-client mode, a \*(L"^\*(R" indicates that the server is broadcasting
-to this address, a \*(L"~\*(R" denotes that the remote peer is sending
-broadcasts and a \*(L"*\*(R" marks the peer the server is currently
-synchonizing to.
-.PP
-The contents of the host field may be one of four forms. It may be a host name,
-an IP address, a reference clock implementation name with its parameter or
-\*(L"REFCLK(<implementation number>, <parameter>)\*(R". On \*(L"hostnames no\*(R"
-only IP\-addresses will be displayed.
+with a summary of that state. Summary information includes the address
+of the remote peer, the local interface address (0.0.0.0 if a local
+address has yet to be determined), the stratum of the remote peer (a
+stratum of 16 indicates the remote peer is unsynchronized), the polling
+interval, in seconds, the reachability register, in octal, and the
+current estimated delay, offset and dispersion of the peer, all in
+seconds. In addition, the character in the left margin indicates the
+mode this peer entry is operating in. A \*(L"+\*(R" denotes symmetric
+active, a \*(L"-\*(R" indicates symmetric passive, a \*(L"=\*(R" means
+the remote server is being polled in client mode, a \*(L"^\*(R"
+indicates that the server is broadcasting to this address, a \*(L"~\*(R"
+denotes that the remote peer is sending broadcasts and a \*(L"*\*(R"
+marks the peer the server is currently synchonizing to.
+.PP
+The contents of the host field may be one of four forms. It may be a
+host name, an IP address, a reference clock implementation name with its
+parameter or \*(L"REFCLK(<implementation number>, <parameter>)\*(R". On
+\*(L"hostnames no\*(R" only IP\-addresses will be displayed.
.PP
.B dmpeers
.PP
-A slightly different peer summary list. Identical to the output of the
+A slightly different peer summary list. Identical to the output of the
.B peers
-command except for the character in the leftmost column. Characters
-only appear beside peers which were included in the final stage of
-the clock selection algorithm. A \*(L".\*(R" indicates that this
-peer was cast off in the falseticker detection, while a \*(L"+\*(R"
-indicates that the peer made it through. A \*(L"*\*(R" denotes the
-peer the server is currently synchronizing with.
+command except for the character in the leftmost column. Characters only
+appear beside peers which were included in the final stage of the clock
+selection algorithm. A \*(L".\*(R" indicates that this peer was cast off
+in the falseticker detection, while a \*(L"+\*(R" indicates that the
+peer made it through. A \*(L"*\*(R" denotes the peer the server is
+currently synchronizing with.
.PP
.B showpeer
.I peer_address
@@ -287,7 +273,7 @@ peer the server is currently synchronizing with.
]
.PP
Shows a detailed display of the current peer variables for one or more
-peers. Most of these values are described in the NTP Version 2
+peers. Most of these values are described in the NTP Version 2
specification.
.PP
.B pstats
@@ -302,72 +288,93 @@ specification.
.PP
Show per\-peer statistic counters associated with the specified peer(s).
.PP
+.B clockinfo
+.I clock_peer_address
+[
+.I addr2
+] [
+.I addr3
+] [
+.I addr4
+]
+.PP
+Obtain and print information concerning a peer clock. The values
+obtained provide information on the setting of fudge factors and other
+clock performance information.
+.PP
+.B kerninfo
+.PP
+Obtain and print kernel phase-lock loop operating parameters. This
+information is available only if the kernel has been specially modified
+for a precision timekeeping function.
+.PP
.B loopinfo
[
.B oneline|multiline
]
.PP
-Print the values of selected loop filter variables. The loop filter is
-the part of NTP which deals with adjusting the local system clock. The
+Print the values of selected loop filter variables. The loop filter is
+the part of NTP which deals with adjusting the local system clock. The
\*(L"offset\*(R" is the last offset given to the loop filter by the
-packet processing code. The \*(L"frequency\*(R" is actually the
-frequency error, or drift, of your system's clock in the units NTP
-uses for internal computations. Dividing this number by 4096 should
-give you the actual drift rate. The \*(L"compliance\*(R" is actually
-a long term average offset and is used by NTP to control the gain of
-the loop filter. The \*(L"timer\*(R" value is the number of seconds
-which have elapsed since a new sample offset was given to the loop
-filter. The \*(L"oneline\*(R" and \*(L"multiline\*(R" options specify
-the format in which this information is to be printed. \*(L"multiline\*(R"
-is the default.
+packet processing code. The \*(L"frequency\*(R" is the frequency error
+of the local clock in parts-per-million (ppm). The \*(L"time_const\*(R"
+controls the "stiffness" of the phase-lock loop and thus the speed at
+which it can adapt to oscillator drift. The \*(L"watchdog timer\*(R"
+value is the number of seconds which have elapsed since the last sample
+offset was given to the loop filter. The \*(L"oneline\*(R" and
+\*(L"multiline\*(R" options specify the format in which this information
+is to be printed, with \*(L"multiline\*(R" as the default.
.PP
.B sysinfo
.PP
Print a variety of system state variables, i.e. state related to the
-local server. Many of these values are described in the NTP Version 2
-specification, RFC 1119.
+local server. All except the last four lines are described in the NTP
+Version 3 specification, RFC 1305. The \*(L"system flags\*(R" show
+various system flags, some of which can be set and cleared by the
+\*(L"enable\*(R" and \*(L"disable\*(R" configuration commands,
+respectively. The \*(L"stability\*(R" is the residual frequency error
+remaining after the system frequency correction is applied and is
+intended for maintenance and debugging. In most architectures, this
+value will initially decrease from as high as 500 ppm to a nominal value
+in the range .01 to 0.1 ppm. If it remains high for some time after
+starting the daemon, something may be wrong with the local clock, or the
+value of the kernel variable \*(L"tick\*(R" may be incorrect. The
+\*(L"broadcastdelay\*(R" shows the default broadcast delay, as set by
+the \*(L"broadcastdelay\*(R" configuration command, while the
+\*(L"authdelay\*(R" shows the default authentication delay, as set by
+the \*(L"authdelay\*(R" configuration command.
.PP
.B sysstats
.PP
-Print a number of stat counters maintained in the protocol module.
+Print statistics counters maintained in the protocol module.
.PP
.B memstats
.PP
-Print a number of counters related to the peer memory allocation
+Print statistics counters related to memory allocation
code.
.PP
.B iostats
.PP
-Print counters maintained in the input\-output module.
+Print statistics counters maintained in the input\-output module.
.PP
.B timerstats
.PP
-Print counters maintained in the timer/event queue support code.
+Print statistics counters maintained in the timer/event queue support
+code.
.PP
.B reslist
.PP
-Obtain and print the server's restriction list. This list is (usually)
+Obtain and print the server's restriction list. This list is (usually)
printed in sorted order and may help to understand how the restrictions
are applied.
.PP
.B monlist
-.PP
-Obtain and print traffic counts collected and maintained by the
-monitor facility.
-.PP
-.B clockinfo
-.I clock_peer_address
[
-.I addr2
-] [
-.I addr3
-] [
-.I addr4
+.I version
]
.PP
-Obtain and print information concerning a peer clock. The values
-obtained provide information on the setting of fudge factors and
-other clock performance information.
+Obtain and print traffic counts collected and maintained by the monitor
+facility. The version number should not normally need to be specified.
.PP
.B clkbug
.I clock_peer_address
@@ -379,51 +386,43 @@ other clock performance information.
.I addr4
]
.PP
-Obtain debugging information for a clock peer. This information is
-provided only by some clock drivers and is mostly undecodable without
-a copy of the driver source in hand.
-.PP
-.B kerninfo
-.PP
-Obtain and print kernel phase-lock loop operating parameters. This
-information is available only if the kernel has been specially modified
-for a precision timekeeping function.
+Obtain debugging information for a reference clock driver. This
+information is provided only by some clock drivers and is mostly
+undecodable without a copy of the driver source in hand.
.SH RUNTIME CONFIGURATION REQUESTS
.PP
All requests which cause state changes in the server are authenticated
by the server using a configured NTP key (the facility can also be
-disabled by
-the server by not configuring a key). The key number and the corresponding
-key must also be made known to
+disabled by the server by not configuring a key). The key number and the
+corresponding key must also be made known to
.IR xtnpdc .
This can be done using the
.B keyid
and
.B passwd
-commands, the latter of which will prompt at the
-terminal for a password to use
-as the encryption key. You will also be prompted automatically for
-both the key number and password the
-first time a command which would result in an authenticated request
-to the server is given. Authentication not only provides verification
-that the requester has permission to make such changes, but also gives
-an extra degree of protection again transmission errors.
-.PP
-Authenticated requests always include a timestamp in the packet data, which
-is included in the computation of the authentication code. This timestamp
-is compared by the server to its receive time stamp. If they differ
-by more than a small amount the request is rejected. This is done for
-two reasons. First, it makes simple replay attacks on the server, by someone
-who might be able to overhear traffic on your LAN, much more difficult.
-Second, it makes it more difficult to request configuration changes
-to your server from topologically remote hosts. While the reconfiguration
-facility will work well with a server on the local host, and may work
-adequately between time\-synchronized hosts on the same LAN, it will
-work very poorly for more distant hosts. As such, if reasonable passwords
-are chosen, care is taken in the distribution and protection of keys and
-appropriate source address restrictions are applied, the
-run time reconfiguration facility should provide an adequate level of
-security.
+commands, the latter of which will prompt at the terminal for a password
+to use as the encryption key. You will also be prompted automatically
+for both the key number and password the first time a command which
+would result in an authenticated request to the server is given.
+Authentication not only provides verification that the requester has
+permission to make such changes, but also gives an extra degree of
+protection again transmission errors.
+.PP
+Authenticated requests always include a timestamp in the packet data,
+which is included in the computation of the authentication code. This
+timestamp is compared by the server to its receive time stamp. If they
+differ by more than a small amount the request is rejected. This is done
+for two reasons. First, it makes simple replay attacks on the server, by
+someone who might be able to overhear traffic on your LAN, much more
+difficult. Second, it makes it more difficult to request configuration
+changes to your server from topologically remote hosts. While the
+reconfiguration facility will work well with a server on the local host,
+and may work adequately between time\-synchronized hosts on the same
+LAN, it will work very poorly for more distant hosts. As such, if
+reasonable passwords are chosen, care is taken in the distribution and
+protection of keys and appropriate source address restrictions are
+applied, the run time reconfiguration facility should provide an
+adequate level of security.
.PP
The following commands all make authenticated requests.
.PP
@@ -434,24 +433,21 @@ The following commands all make authenticated requests.
] [
.I version#
] [
-.B minpoll|prefer
+.B prefer
]
.PP
-Add a configured, symmetric active peer association with a peer at the
-given address. If the optional \*(L"keyid\*(R" is a nonzero integer
-all outgoing packets to the remote server will
-have an authentication field attached encrypted with this key. If the
-value is 0 (or not given) no authentication will be done. The
-\*(L"version#\*(R" can be 1 or 2, and defaults to 2. If \*(L"minpoll\*(R"
-is specified the polling interval for the association will remain
-clamped at the minimum. The latter option is only useful for testing.
-Note that an existing association with the same peer may be deleted
-when this command is executed, or may simply be converted to conform to
-the new configuration, as appropriate. The prefer keyword indicates
-a preferred peer (and thus will be used primarily for clock synchronisation
-if possible). The preferred peer also determines the validity of the PPS
-signal - if the preferred peer is suitable for synchronisation so is the
-PPS signal.
+Add a configured peer association at the given address and operating in
+symmetric active mode. Note that an existing association with the same
+peer may be deleted when this command is executed, or may simply be
+converted to conform to the new configuration, as appropriate. If the
+optional \*(L"keyid\*(R" is a nonzero integer, all outgoing packets to
+the remote server will have an authentication field attached encrypted
+with this key. If the value is 0 (or not given) no authentication will
+be done. The \*(L"version#\*(R" can be 1, 2 or 3 and defaults to 3. The
+\*(L"prefer\*(R" keyword indicates a preferred peer (and thus will be
+used primarily for clock synchronisation if possible). The preferred
+peer also determines the validity of the PPS signal - if the preferred
+peer is suitable for synchronisation so is the PPS signal.
.PP
.B addserver
.I peer_address
@@ -460,13 +456,12 @@ PPS signal.
] [
.I version#
] [
-.B minpoll|prefer
+.B prefer
]
.PP
Identical to the
.B addpeer
-command except that polling is done in client mode rather than
-symmetric active mode.
+command, except that the operating mode is client.
.PP
.B broadcast
.I peer_address
@@ -474,15 +469,15 @@ symmetric active mode.
.I keyid
] [
.I version#
-] [
-.B minpoll
]
.PP
Identical to the
.B addpeer
-command except that packets are instead sent in broadcast mode. The
-\*(L"peer_address\*(R" parameter will generally be a broadcast address
-on one of your local networks.
+command, except that the operating mode is broadcast. In this case a
+valid key identifier and key are required. The \*(L"peer_address\*(R"
+parameter can be the broadcast address of the local network or a
+multicast group address assigned to NTP. If a multicast address, a
+multicast-capable kernel is required.
.PP
.B unconfig
.I peer_address
@@ -495,34 +490,56 @@ on one of your local networks.
]
.PP
This command causes the configured bit to be removed from the specified
-peer(s). In many cases this will cause the peer association to be
-deleted. When appropriate, however, the association may persist in
-an unconfigured mode if the remote peer is willing to continue on in
-this fashion.
+peer(s). In many cases this will cause the peer association to be
+deleted. When appropriate, however, the association may persist in an
+unconfigured mode if the remote peer is willing to continue on in this
+fashion.
+.PP
+.B fudge
+.I peer_address
+[
+.I time1
+] [
+.I time2
+] [
+.I stratum
+] [
+.I refid
+]
.PP
-.B set bclient|mclient|auth
+This command provides a way to set certain data for a reference clock.
+See the source listing for further information.
+.PP
+.B enable auth|bclient|pll|monitor|stats
[
.I ...
]
.PP
-Allows the setting of the broadcast/multicast client and/or authenticate
-system flags. Setting bclient causes the server to listen for broadcast
-NTP to to synchronize to broadcasts when appropriate. Setting mclient
-causes the same thing, but using multicast facilities, when available.
-Setting auth causes the server to only synchronize with peers which
-include an authentication field encrypted with one of the local server's
-trusted keys.
-.PP
-.B clear bclient|auth
+Provides a way to enable various server options. Flags not mentioned are
+unaffected. The \*(L"auth\*(R" flag causes the server to synchronize
+with unconfigured peers only if the peer has been correctly
+authenticated using a trusted key and key identifier. The default for
+this flag is disable (off). The \*(L"bclient\*(R" flag causes the server
+to listen for a message from a broadcast or multicast server, following
+which an association is automatically instantiated for that server. The
+default for this flag is disable (off). The \*(L"pll\*(R" flag enables
+the server to adjust its local clock, with default enable (on). If not
+set, the local clock free-runs at its intrinsic time and frequency
+offset. This flag is useful in case the local clock is controlled by
+some other device or protocol and NTP is used only to provide
+synchronization to other clients. The \*(L"monitor\*(R" flag enables the
+monitoring facility (see elsewhere), with default disable (off). The
+\*(L"stats\*(R" flag enables statistics facility filegen (see
+description elsewhere.), with default enable (on).
+.PP
+.B disable auth|bclient|pll|monitor|stats
[
.I ...
]
.PP
-Allows the broadcast/multicast client and/or authenticate system flags to be
-cleared. Clearing bclient causes incoming broadcast and multicast NTP packets
-to be ignored. Clearing auth allows peers which have not included
-an authentication field, or which have included one but have encrypted
-it with an untrusted key, to be considered synchronization candidates.
+Provides a way to disable various server options. Flags not mentioned
+are unaffected. The flags presently available are described under the
+enable command.
.PP
.B restrict
.I address
@@ -532,63 +549,61 @@ it with an untrusted key, to be considered synchronization candidates.
.I flag
]
.PP
-Causes flag(s) to be added to an existing restrict list entry, or adds
-a new entry to the list with the specified flag(s). The possible choices
+Causes flag(s) to be added to an existing restrict list entry, or adds a
+new entry to the list with the specified flag(s). The possible choices
for the flags arguments are given in the following list:
.Ip ignore 10
-Ignore all packets from hosts which match this entry. If this flag
-is specified neither queries nor time server polls will be responded
-to.
+Ignore all packets from hosts which match this entry. If this flag is
+specified neither queries nor time server polls will be responded to.
.Ip noquery 10
-Ignore all NTP mode 7 packets (i.e. information queries and configuration
-requests) from the source. Time service is not affected.
+Ignore all NTP mode 7 packets (i.e. information queries and
+configuration requests) from the source. Time service is not affected.
.Ip nomodify 10
Ignore all NTP mode 7 packets which attempt to modify the state of the
-server (i.e. run time reconfiguration). Queries which return information
+server (i.e. run time reconfiguration). Queries which return information
are permitted.
.Ip notrap 10
Decline to provide mode 6 control message trap service to matching
-hosts. The trap service is a subsystem of the mode 6 control message
+hosts. The trap service is a subsystem of the mode 6 control message
protocol which is intended for use by remote event logging programs.
.Ip lowpriotrap 10
-Declare traps set by matching hosts to be low priority. The number
-of traps a server can maintain is limited (the current limit is 3).
-Traps are usually assigned on a first come, first served basis, with
-later trap requestors being denied service. This flag modifies the
-assignment algorithm by allowing low priority traps to be overridden
-by later requests for normal priority traps.
+Declare traps set by matching hosts to be low priority. The number of
+traps a server can maintain is limited (the current limit is 3). Traps
+are usually assigned on a first come, first served basis, with later
+trap requestors being denied service. This flag modifies the assignment
+algorithm by allowing low priority traps to be overridden by later
+requests for normal priority traps.
.Ip noserve 10
-Ignore NTP packets whose mode is other than 7. In effect, time service is
-denied, though queries may still be permitted.
+Ignore NTP packets whose mode is other than 7. In effect, time service
+is denied, though queries may still be permitted.
.Ip nopeer 10
-Provide stateless time service to polling hosts, but do not allocate peer
-memory resources to these hosts even if they otherwise might be considered
-useful as future synchronization partners.
+Provide stateless time service to polling hosts, but do not allocate
+peer memory resources to these hosts even if they otherwise might be
+considered useful as future synchronization partners.
.Ip notrust 10
Treat these hosts normally in other respects, but never use them as
synchronization sources.
.Ip limited 10
-These hosts are subject to limitation of number of clients from the
-same net. Net in this context refers to the IP notion of net (class A,
-class B, class C, etc.). Only the first \*(L"client_limit\*(R" hosts
-that have shown up at the server and that have been active during the
-last \*(L"client_limit_period\*(R" seconds are accepted. Requests from
-other clients from the same net are rejected. Only time request
-packets are taken into account. \*(L"Private\*(R", \*(L"control\*(R",
-and \*(L"broadcast\*(R" packets are not subject to client limitation
-and therefore are not contributing to client count. History of clients
-is kept using the monitoring capability of
+These hosts are subject to limitation of number of clients from the same
+net. Net in this context refers to the IP notion of net (class A, class
+B, class C, etc.). Only the first \*(L"client_limit\*(R" hosts that have
+shown up at the server and that have been active during the last
+\*(L"client_limit_period\*(R" seconds are accepted. Requests from other
+clients from the same net are rejected. Only time request packets are
+taken into account. \*(L"Private\*(R", \*(L"control\*(R", and
+\*(L"broadcast\*(R" packets are not subject to client limitation and
+therefore are not contributing to client count. History of clients is
+kept using the monitoring capability of
.IR xntpd.
-Thus, monitoring is active as long as there is a restriction entry
-with the \*(L"limited\*(R" flag. The default value for
-\*(L"client_limit\*(R" is 3. The default value for
-\*(L"client_limit_period\*(R" is 3600 seconds. Currently both
-variables are not runtime configurable.
+Thus, monitoring is active as long as there is a restriction entry with
+the \*(L"limited\*(R" flag. The default value for \*(L"client_limit\*(R"
+is 3. The default value for \*(L"client_limit_period\*(R" is 3600
+seconds. Currently both variables are not runtime configurable.
.Ip ntpport 10
This is actually a match algorithm modifier, rather than a restriction
-flag. Its presence causes the restriction entry to be matched only if
-the source port in the packet is the standard NTP UDP port (123). Both
-\*(L"ntpport\*(R" and non\-\*(L"ntpport\*(R" may be specified. The
+flag. Its presence causes the restriction entry to be matched only if
+the source port in the packet is the standard NTP UDP port (123). Both
+\*(L"ntpport\*(R" and non\-\*(L"ntpport\*(R" may be specified. The
\*(L"ntpport\*(R" is considered more specific and is sorted later in the
list.
.PP
@@ -618,7 +633,7 @@ Delete the matching entry from the restrict list.
.PP
.B "monitor yes|no"
.PP
-Enable or disable the monitoring facility. Note that a
+Enable or disable the monitoring facility. Note that a
.B "monitor no"
command followed by a
.B "monitor yes"
@@ -626,11 +641,11 @@ command is a good way of resetting the packet counts.
.PP
.B readkeys
.PP
-Causes the current set of authentication keys to be purged and a
-new set to be obtained by rereading the keys file (which must have
-been specified in the
+Causes the current set of authentication keys to be purged and a new set
+to be obtained by rereading the keys file (which must have been
+specified in the
.I xntpd
-configuration file). This allows encryption keys to be changed without
+configuration file). This allows encryption keys to be changed without
restarting the server.
.PP
.B trustkey
@@ -643,9 +658,9 @@ restarting the server.
.I keyid
]
.PP
-Adds one or more keys to the trusted key list. When authentication
-is enabled, peers whose time is to be trusted must be authenticated using
-a trusted key.
+Adds one or more keys to the trusted key list. When authentication is
+enabled, peers whose time is to be trusted must be authenticated using a
+trusted key.
.PP
.B untrustkey
.I keyid
@@ -668,8 +683,40 @@ done.
.B setprecision
.I precision_value
.PP
-Sets the precision which the server advertises to the specified value. This
-should be a negative integer in the range -4 through -20.
+Sets the precision which the server advertises to the specified value.
+This should be a negative integer in the range -4 through -20.
+.PP
+.B traps
+.PP
+Display the traps set in the server. See the source listing for further
+information.
+.PP
+.B addtrap
+.I address
+[
+.I port
+] [
+.I interface
+]
+.PP
+Set a trap for asynchronous messages. See the source listing for further
+information.
+.PP
+.B clrtrap
+.I address
+[
+.I port
+] [
+.I interface
+]
+.PP
+Clear a trap for asynchronous messages. See the source listing for
+further information.
+.PP
+.B reset ...
+.PP
+Clear the statistics counters in various modules of the server. See the
+source listing for further information.
.SH SEE ALSO
.PP
.IR xntpd (8)
@@ -679,8 +726,8 @@ Written by Dennis Ferguson at the University of Toronto.
.SH BUGS
.PP
.I Xntpdc
-is a crude hack. Much of the information it shows is deadly boring
-and could only be loved by its implementer. The program was designed
-so that new (and temporary) features were easy to hack in, at great
-expense to the program's ease of use. Despite this, the program
-is occasionally useful.
+is a crude hack. Much of the information it shows is deadly boring and
+could only be loved by its implementer. The program was designed so that
+new (and temporary) features were easy to hack in, at great expense to
+the program's ease of use. Despite this, the program is occasionally
+useful.
diff --git a/usr.sbin/xntpd/include/README b/usr.sbin/xntpd/include/README
index 5127b70a1b3a..73d0620569a2 100644
--- a/usr.sbin/xntpd/include/README
+++ b/usr.sbin/xntpd/include/README
@@ -4,3 +4,18 @@ This directory contains the include files used by most programs in this
distribution. The ./sys directory in this directory contains system
header files used by the clock discipline and STREAMS modules in the
../kernel directory.
+
+Note that multicast support (MCAST define) requires the header file
+/usr/include/netinet/in.h for the particular architecture to be in place.
+This file is constructed during the installation process in older systems;
+it is already in place for those machines that support multicast ex box.
+The file in.h included in this distribution is for Suns; the files for
+other systems can be found in the multicast distribtutions for each
+architecture separately.
+
+If the precision-time kernel (KERNEL_PLL define) is configured, the
+installation process requires the header file /usr/include/sys/timex.h
+for the particular architecture to be in place. The file timex.h included
+in this distribution is for Suns; the files for other systems can be
+found in the kernel distributions available from the manufacturer's
+representatives.
diff --git a/usr.sbin/xntpd/include/in.h b/usr.sbin/xntpd/include/in.h
new file mode 100644
index 000000000000..abd404ceda8d
--- /dev/null
+++ b/usr.sbin/xntpd/include/in.h
@@ -0,0 +1,256 @@
+/* @(#)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
+
+/*
+ * 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/usr.sbin/xntpd/include/l_stdlib.h b/usr.sbin/xntpd/include/l_stdlib.h
index e0b7c474095c..426dc48b2e34 100644
--- a/usr.sbin/xntpd/include/l_stdlib.h
+++ b/usr.sbin/xntpd/include/l_stdlib.h
@@ -80,6 +80,7 @@ extern int link P((const char *, const char *));
extern int fclose P((FILE *));
extern int fflush P((FILE *));
extern int fprintf P((FILE *, char *, ...));
+extern int fscanf P((FILE *, char *, ...));
extern int fputs P((char *, FILE *));
extern int fputc P((char, FILE *));
extern int fread P((char *, int, int, FILE *));
@@ -87,6 +88,7 @@ extern int printf P((char *, ...));
extern int setbuf P((FILE *, char *));
extern int setvbuf P((FILE *, char *, int, int));
extern int scanf P((char *, ...));
+extern int sscanf P((char *, char *, ...));
extern int vsprintf P((char *, char *, ...));
extern int _flsbuf P((int, FILE *));
extern int _filbuf P((FILE *));
@@ -151,7 +153,43 @@ extern int nlist P((char *, struct nlist *));
#endif /* SYS_SUNOS4 */
/*
- * Unprototyped library functions for ULTRIX.
+ * Unprototyped library functions for DEC OSF/1
+ */
+#ifdef SYS_DECOSF1
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_ENDIAN_H_
+extern u_short htons P((u_short));
+extern u_short ntohs P((u_short));
+extern U_LONG htonl P((U_LONG));
+extern U_LONG ntohl P((U_LONG));
+#endif /* _MACHINE_ENDIAN_H_ */
+
+/*
+extern char * getpass P((char *));
+*/
+extern char * mktemp P((char *));
+#ifndef SYS_IX86OSF1
+extern int ioctl P((int, u_long, char *));
+extern void bzero P((char *, int));
+#endif
+
+#ifdef SOCK_DGRAM
+extern int bind P((int, const struct sockaddr *, int));
+extern int connect P((int, const struct sockaddr *, int));
+extern int socket P((int, int, int));
+extern int sendto P((int, const void *, int, int, const struct sockaddr *, int));
+extern int setsockopt P((int, int, int, const void *, int));
+extern int recvfrom P((int, void *, int, int, struct sockaddr *, int *));
+#endif /* SOCK_STREAM */
+
+#ifdef _ntp_select_h
+extern int select P((int, fd_set *, fd_set *, fd_set *, struct timeval *));
+#endif
+
+#endif /* DECOSF1 */
+
+/*
+ * Unprototyped library functions for Ultrix
*/
#ifdef SYS_ULTRIX
extern int close P((int));
@@ -162,7 +200,6 @@ extern char *mktemp P((char *));
extern int unlink P((const char *));
extern int link P((const char *, const char *));
-#if defined(LOG_DEBUG)
extern void closelog P((void));
extern void syslog P((int, char *, ...));
#ifndef LOG_DAEMON
@@ -170,7 +207,6 @@ extern void openlog P((char *, int));
#else
extern void openlog P((char *, int, int));
#endif
-#endif
extern int setpriority P((int ,int ,int ));
@@ -184,7 +220,9 @@ extern int recvfrom P((int, char *, int, int, struct sockaddr *, int *));
#endif /* SOCK_STREAM */
#ifdef _TIME_H_
-extern int adjtime P((struct timeval *, struct timeval *));
+extern int gettimeofday P((struct timeval *, struct timezone *));
+extern int settimeofday P((struct timeval *, struct timezone *));
+extern int adjtime P((struct timeval *, struct timeval *));
extern int select P((int, fd_set *, fd_set *, fd_set *, struct timeval *));
extern int setitimer P((int , struct itimerval *, struct itimerval *));
#endif /* _TIME_H_ */
@@ -193,6 +231,12 @@ extern int setitimer P((int , struct itimerval *, struct itimerval *));
extern int nlist P((char *, struct nlist *));
#endif
+#ifndef bzero /* XXX macro prototyping clash */
+extern void bzero P((char *, int));
+extern int bcmp P((char *, char *, int));
+extern void bcopy P((char *, char *, int));
+#endif
+
#ifndef NTP_POSIX_SOURCE
extern int atoi P((char *));
extern void bzero P((char *, int));
@@ -204,15 +248,17 @@ extern int getdtablesize P((void));
extern int ran P((void));
extern int rand P((void));
extern void srand P((unsigned int));
-#if defined(_STDIO_H_)
-extern int setlinebuf P((FILE *));
-#endif
#ifdef _TIME_H_
extern int gettimeofday P((struct timeval *, struct timezone *));
+extern int settimeofday P((struct timeval *, struct timezone *));
+#endif
#endif
+
+#ifdef _RESOURCE_H_
+extern int getrusage P((int, struct rusage *));
#endif
-#endif /* SYS_ULTIRX */
+#endif /* SYS_ULTRIX */
#if defined(__convex__)
extern char * getpass P((char *));
@@ -230,5 +276,9 @@ extern char * getpass P((char *));
extern char * getpass P((char *));
#endif /* SYS_DOMAINOS */
+#ifdef SYS_BSD
+#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
+#endif
+
#endif /* l_stdlib_h */
diff --git a/usr.sbin/xntpd/include/md5.h b/usr.sbin/xntpd/include/md5.h
index c13f63905ebc..82b43e1b5da7 100644
--- a/usr.sbin/xntpd/include/md5.h
+++ b/usr.sbin/xntpd/include/md5.h
@@ -1,4 +1,4 @@
-/* md5.h,v 3.1 1993/07/06 01:06:44 jbj Exp
+/*
***********************************************************************
** md5.h -- header file for implementation of MD5 **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
diff --git a/usr.sbin/xntpd/include/mx4200.h b/usr.sbin/xntpd/include/mx4200.h
index 5a9e49651ca4..13058deb1e5e 100644
--- a/usr.sbin/xntpd/include/mx4200.h
+++ b/usr.sbin/xntpd/include/mx4200.h
@@ -1,5 +1,3 @@
-/* @(#) mx4200.h,v 3.1 1993/07/06 01:06:46 jbj Exp */
-
/* records transmitted from extern CDU to MX 4200 */
#define PMVXG_S_INITMODEA 0 /* initialization/mode part A */
diff --git a/usr.sbin/xntpd/include/ntp.h b/usr.sbin/xntpd/include/ntp.h
index 01bfa16a7ad8..733f2e72893f 100644
--- a/usr.sbin/xntpd/include/ntp.h
+++ b/usr.sbin/xntpd/include/ntp.h
@@ -1,4 +1,4 @@
-/* ntp.h,v 3.1 1993/07/06 01:06:47 jbj Exp
+/*
* ntp.h - NTP definitions for the masses
*/
@@ -32,18 +32,20 @@ typedef signed char s_char;
#define NTP_MAXSKEW 1 /* 1 sec, skew after NTP_MAXAGE w/o updates */
#define NTP_SKEWINC 49170 /* skew increment for clock updates (l_f) */
#define NTP_SKEWFACTOR 16 /* approximation of factor for peer calcs */
-#define NTP_MAXDISTANCE (1*FP_SECOND) /* max. rootdelay for synchr. */
-#define NTP_MINDPOLL 6 /* default min poll (64 sec) */
-#define NTP_MINPOLL 4 /* absolute min poll (16 sec) */
-#define NTP_MAXPOLL 10 /* actually 1<<10, or 1024 sec */
+#define NTP_MAXDISTANCE (1 * FP_SECOND) /* max. rootdelay for synchr. */
+#define NTP_MINDPOLL 6 /* log2 default min poll interval (64 s) */
+#define NTP_MAXDPOLL 10 /* log2 default max poll interval (~17 m) */
+#define NTP_MINPOLL 4 /* log2 min poll interval (16 s) */
+#define NTP_MAXPOLL 14 /* log2 max poll interval (~4.5 h) */
#define NTP_MINCLOCK 3 /* minimum for outlyer detection */
#define NTP_MAXCLOCK 10 /* maximum select list size */
-#define NTP_MINDISPERSE 0x28f /* 0.01 sec in fp format */
-#define NTP_MAXDISPERSE (16*FP_SECOND) /* maximum dispersion (fp 16) */
-#define NTP_DISPFACTOR 20 /* MAXDISPERSE as a shift */
+#define NTP_MINDISPERSE (FP_SECOND / 100) /* min dispersion (u_fp 10 ms) */
+#define NTP_MAXDISPERSE (FP_SECOND * 16) /* max dispersion (u_fp 16 s) */
+#define NTP_DISPFACTOR 20 /* MAXDISPERSE as a shift (u_fp 16 s) */
#define NTP_WINDOW 8 /* reachability register size */
#define NTP_SHIFT 8 /* 8 suitable for crystal time base */
#define NTP_MAXKEY 65535 /* maximum authentication key number */
+#define NTP_MAXD 3 /* log2 estimated error averaging factor */
/*
* Loop filter parameters. See section 5.1 of the specification.
@@ -62,27 +64,23 @@ typedef signed char s_char;
#define CLOCK_DSCALE 20 /* skew reg. scale: unit is 2**-20 ~= 1 ppm */
#define CLOCK_FREQ 16 /* log2 frequency weight (65536) */
#define CLOCK_PHASE 6 /* log2 phase weight (64) */
-#define CLOCK_WEIGHTTC 5 /* log2 time constant weight (32) */
-#define CLOCK_HOLDTC 128 /* time constant hold (sec) */
+#define CLOCK_LIMIT 30 /* time constant adjust threshold */
+#define CLOCK_G 2 /* log2 frequency averaging factor */
+#define CLOCK_MAXSEC 800 /* max update interval for pll */
-#define CLOCK_MAX_F 0x20c49ba6 /* 128 ms, in time stamp format */
-#define CLOCK_MAX_I 0x0 /* both fractional and integral parts */
+#define CLOCK_MAX_FP 0x000020c5 /* max clock offset (s_fp 128 ms) */
+#define CLOCK_MAX_F 0x20c49ba6 /* max clock offset (l_fp 128 ms) */
+#define CLOCK_MAX_I 0x00000000 /* both fractional and integral parts */
#define CLOCK_WAYTOOBIG 1000 /* if clock 1000 sec off, forget it */
/*
- * Unspecified default. sys.precision defaults to -6 unless otherwise
- * adjusted.
- */
-#define DEFAULT_SYS_PRECISION (-6)
-
-/*
* Event timers are actually implemented as a sorted queue of expiry
* times. The queue is slotted, with each slot holding timers which
* expire in a 2**(NTP_MINPOLL-1) (8) second period. The timers in
* each slot are sorted by increasing expiry time. The number of
- * slots is 2**(NTP_MAXPOLL-(NTP_MINPOLL-1)), or 128, to cover a time
- * period of 2**NTP_MAXPOLL (1024) seconds into the future before
+ * slots is 2**(NTP_MAXPOLL-(NTP_MINPOLL-1)), or 512, to cover a time
+ * period of 2**NTP_MAXPOLL (16384) seconds into the future before
* wrapping.
*/
#define EVENT_TIMEOUT CLOCK_ADJ
@@ -92,7 +90,7 @@ struct event {
struct event *prev; /* previous in chain */
struct peer *peer; /* peer this counter belongs to */
void (*event_handler)(); /* routine to call to handle event */
- U_LONG event_time; /* expiry time of counter */
+ u_long event_time; /* expiry time of counter */
};
#define TIMER_SLOTTIME (1<<(NTP_MINPOLL-1))
@@ -162,9 +160,10 @@ struct interface {
struct sockaddr_in mask; /* interface mask */
char name[8]; /* name of interface */
int flags; /* interface flags */
- LONG received; /* number of incoming packets */
- LONG sent; /* number of outgoing packets */
- LONG notsent; /* number of send failures */
+ int last_ttl; /* last TTL specified */
+ long received; /* number of incoming packets */
+ long sent; /* number of outgoing packets */
+ long notsent; /* number of send failures */
};
/*
@@ -200,6 +199,7 @@ struct peer {
struct peer *ass_next; /* link pointer in associd hash */
struct sockaddr_in srcadr; /* address of remote host */
struct interface *dstadr; /* pointer to address on local host */
+ struct refclockproc *procptr; /* pointer to reference clock sutuff */
u_char leap; /* leap indicator */
u_char hmode; /* association mode with this peer */
u_char pmode; /* peer's association mode */
@@ -211,6 +211,7 @@ struct peer {
u_char maxpoll; /* max local host poll interval */
u_char version; /* version number */
u_char flags; /* peer flags */
+ u_char cast_flags; /* flags MDF_?CAST */
u_char flash; /* peer flashers (for maint) */
u_char refclktype; /* reference clock type */
u_char refclkunit; /* reference clock unit number */
@@ -242,33 +243,30 @@ struct peer {
u_char filter_order[NTP_SHIFT]; /* we keep the filter sorted here */
#define end_clear_to_zero filter_order[0]
u_fp filter_error[NTP_SHIFT]; /* error part of shift register */
- LONG update; /* base sys_clock for skew calc.s */
+ long update; /* base sys_clock for skew calc.s */
s_fp delay; /* filter estimated delay */
u_fp dispersion; /* filter estimated dispersion */
l_fp offset; /* filter estimated clock offset */
s_fp soffset; /* fp version of above */
s_fp synch; /* synch distance from above */
u_fp selectdisp; /* select dispersion */
- U_LONG estbdelay; /* broadcast delay, as a ts fraction */
+ s_fp estbdelay; /* broadcast offset */
/*
* statistic counters
*/
- U_LONG timereset; /* time stat counters were reset */
- U_LONG sent; /* number of updates sent */
- U_LONG received; /* number of frames received */
- U_LONG timereceived; /* last time a frame received */
- U_LONG timereachable; /* last reachable/unreachable event */
- U_LONG processed; /* processed by the protocol */
- U_LONG badauth; /* bad credentials detected */
- U_LONG bogusorg; /* rejected due to bogus origin */
- U_LONG bogusrec; /* rejected due to bogus receive */
- U_LONG bogusdelay; /* rejected due to bogus delay */
- U_LONG disttoolarge; /* rejected due to large distance */
- U_LONG oldpkt; /* rejected as duplicate packet */
- U_LONG seldisptoolarge; /* too much dispersion for selection */
- U_LONG selbroken; /* broken NTP detected in selection */
- U_LONG seltooold; /* too LONG since sync in selection */
+ u_long timereset; /* time stat counters were reset */
+ u_long sent; /* number of updates sent */
+ u_long received; /* number of frames received */
+ u_long timereceived; /* last time a frame received */
+ u_long timereachable; /* last reachable/unreachable event */
+ u_long processed; /* processed by the protocol */
+ u_long badauth; /* bad credentials detected */
+ u_long bogusorg; /* rejected due to bogus origin */
+ u_long oldpkt; /* rejected as duplicate packet */
+ u_long seldisptoolarge; /* too much dispersion for selection */
+ u_long selbroken; /* broken NTP detected in selection */
+ u_long seltooold; /* too long since sync in selection */
u_char candidate; /* position after candidate selection */
u_char select; /* position at end of falseticker sel */
u_char was_sane; /* set to 1 if it passed sanity check */
@@ -298,7 +296,7 @@ struct peer {
#define MODE_PRIVATE 7 /* implementation defined function */
#define MODE_BCLIENT 8 /* a pseudo mode, used internally */
-
+#define MODE_MCLIENT 9 /* multicast mode, used internally */
/*
* Values for peer.stratum, sys_stratum
@@ -315,8 +313,8 @@ struct peer {
*/
#define FLAG_CONFIG 0x1 /* association was configured */
#define FLAG_AUTHENABLE 0x2 /* this guy needs authentication */
-#define FLAG_UNUSED 0x4 /* (not used) */
-#define FLAG_DEFBDELAY 0x8 /* using default bdelay */
+#define FLAG_MCAST1 0x4 /* multicast client/server mode */
+#define FLAG_MCAST2 0x8 /* multicast client mode */
#define FLAG_AUTHENTIC 0x10 /* last message was authentic */
#define FLAG_REFCLOCK 0x20 /* this is actually a reference clock */
#define FLAG_SYSPEER 0x40 /* this is one of the selected peers */
@@ -334,13 +332,13 @@ struct peer {
/*
* Reference clock identifiers (for pps signal)
*/
-#define PPSREFID "PPS " /* used when pps controls stratum > 1 */
+#define PPSREFID (U_LONG)"PPS " /* used when pps controls stratum > 1 */
/*
* Reference clock types. Added as necessary.
*/
#define REFCLK_NONE 0 /* unknown or missing */
-#define REFCLK_LOCALCLOCK 1 /* external (e.g., ACTS) */
+#define REFCLK_LOCALCLOCK 1 /* external (e.g., lockclock) */
#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 */
@@ -353,8 +351,16 @@ struct peer {
#define REFCLK_OMEGA_TRUETIME 11 /* TrueTime OM-DC OMEGA */
#define REFCLK_IRIG_TPRO 12 /* KSI/Odetics TPRO-S IRIG */
#define REFCLK_ATOM_LEITCH 13 /* Leitch CSD 5300 Master Clock */
-#define REFCLK_MSF_EES 14 /* MSF EES M201, UK */
-#define REFCLK_GPSTM_TRUETIME 15 /* TrueTime GPS/TM-TMD */
+#define REFCLK_MSF_EES 14 /* EES M201 MSF Receiver */
+#define REFCLK_GPSTM_TRUETIME 15 /* TrueTime GPS/TM-TMD Receiver */
+#define REFCLK_IRIG_BANCOMM 16 /* Bancomm GPS/IRIG Interface */
+#define REFCLK_GPS_DATUM 17 /* Datum Programmable Time System */
+#define REFCLK_NIST_ACTS 18 /* NIST Auto Computer Time Service */
+#define REFCLK_WWV_HEATH 19 /* Heath GC1000 WWV/WWVH Receiver */
+#define REFCLK_GPS_NMEA 20 /* NMEA based GPS clock */
+#define REFCLK_GPS_MOTO 21 /* Motorola GPS clock */
+#define REFCLK_ATOM_PPS 22 /* 1-PPS Clock Discipline */
+#define REFCLK_MAX 24 /* maximum index (room to expand) */
/*
* We tell reference clocks from real peers by giving the reference
@@ -474,6 +480,7 @@ struct recvbuf {
#define recv_srcclock X_from_where.X_recv_srcclock
struct sockaddr_in srcadr; /* where packet came from */
struct interface *dstadr; /* interface datagram arrived thru */
+ int fd; /* fd on which it was received */
l_fp recv_time; /* time of arrival */
void (*receiver)(); /* routine to receive buffer */
int recv_length; /* number of octets received */
@@ -576,6 +583,10 @@ struct recvbuf {
#define PROTO_AUTHDELAY 5
#define PROTO_MULTICAST_ADD 6
#define PROTO_MULTICAST_DEL 7
+#define PROTO_PLL 8
+#define PROTO_PPS 9
+#define PROTO_MONITOR 10
+#define PROTO_FILEGEN 11
/*
* Configuration items for the loop filter
@@ -596,29 +607,38 @@ struct recvbuf {
/*
* Default parameters. We use these in the absense of something better.
*/
-#define DEFPRECISION (-5) /* conservatively low */
-#define DEFBROADDELAY (0x020c49ba) /* 8 ms. This is round trip delay */
+#define DEFPRECISION (-7) /* default precision (~10 ms) */
+#define DEFBROADDELAY 0x00000100 /* default broadcast offset */
+ /* (~4 ms as s_fp) */
+#define DEFAUTHDELAY 0x00080000 /* default authentcation delay */
+ /* (~100 us as l_fp.u_f) */
#define INADDR_NTP 0xe0000101 /* NTP multicast address 224.0.1.1 */
/*
* Structure used optionally for monitoring when this is turned on.
*/
struct mon_data {
struct mon_data *hash_next; /* next structure in hash list */
- 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 */
+ 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 */
U_LONG rmtadr; /* address of remote host */
+ struct interface *interface; /* interface on which this arrived */
u_short rmtport; /* remote port last came from */
u_char mode; /* mode of incoming packet */
u_char version; /* version of incoming packet */
+ u_char cast_flags; /* flags MDF_?CAST */
};
+#define MDF_UCAST 1 /* unicast packet */
+#define MDF_MCAST 2 /* multicast packet */
+#define MDF_BCAST 4 /* broadcast packet */
+#define MDF_LCAST 8 /* local packet */
+
/*
* Values used with mon_enabled to indicate reason for enabling monitoring
*/
@@ -632,7 +652,7 @@ struct restrictlist {
struct restrictlist *next; /* link to next entry */
U_LONG addr; /* host address (host byte order) */
U_LONG mask; /* mask for address (host byte order) */
- U_LONG count; /* number of packets matched */
+ u_long count; /* number of packets matched */
u_short flags; /* accesslist flags */
u_short mflags; /* match flags */
};
diff --git a/usr.sbin/xntpd/include/ntp_calendar.h b/usr.sbin/xntpd/include/ntp_calendar.h
index fc12f0b2945c..461aee4ce9af 100644
--- a/usr.sbin/xntpd/include/ntp_calendar.h
+++ b/usr.sbin/xntpd/include/ntp_calendar.h
@@ -1,4 +1,4 @@
-/* ntp_calendar.h,v 3.1 1993/07/06 01:06:48 jbj Exp
+/*
* ntp_calendar.h - definitions for the calendar time-of-day routine
*/
@@ -66,8 +66,8 @@ struct calendar {
* STARTCYCLE22 seconds after the start of cycle 0.
*/
#define CYCLE22 (22)
-#define STARTCYCLE22 (U_LONG)(0xa586b500) /* 2777068800 */
-#define MAR1988 (U_LONG)(STARTCYCLE22 + (U_LONG)MAR1900)
+#define STARTCYCLE22 (u_long)(0xa586b500) /* 2777068800 */
+#define MAR1988 (u_long)(STARTCYCLE22 + (u_long)MAR1900)
/*
* The length of January + February in leap and non-leap years.
@@ -75,6 +75,6 @@ struct calendar {
#define JANFEBNOLEAP ((JAN+FEB) * SECSPERDAY)
#define JANFEBLEAP ((JAN+FEBLEAP) * SECSPERDAY)
-extern void caljulian P((U_LONG, struct calendar *));
-extern U_LONG caltontp P((const struct calendar *));
+extern void caljulian P((u_long, struct calendar *));
+extern u_long caltontp P((const struct calendar *));
diff --git a/usr.sbin/xntpd/include/ntp_control.h b/usr.sbin/xntpd/include/ntp_control.h
index 1e193835660d..1124bb0cbbba 100644
--- a/usr.sbin/xntpd/include/ntp_control.h
+++ b/usr.sbin/xntpd/include/ntp_control.h
@@ -1,4 +1,4 @@
-/* ntp_control.h,v 3.1 1993/07/06 01:06:50 jbj Exp
+/*
* ntp_control.h - definitions related to NTP mode 6 control messages
*/
@@ -236,10 +236,10 @@ struct ntp_control {
struct ctl_trap {
struct sockaddr_in tr_addr; /* address of trap recipient */
struct interface *tr_localaddr; /* interface to send this through */
- U_LONG tr_settime; /* time trap was set */
- U_LONG tr_count; /* async messages sent to this guy */
- U_LONG tr_origtime; /* time trap was originally set */
- U_LONG tr_resets; /* count of resets for this trap */
+ u_long tr_settime; /* time trap was set */
+ u_long tr_count; /* async messages sent to this guy */
+ u_long tr_origtime; /* time trap was originally set */
+ u_long tr_resets; /* count of resets for this trap */
u_short tr_sequence; /* trap sequence id */
u_char tr_flags; /* trap flags */
u_char tr_version; /* version number of trapper */
diff --git a/usr.sbin/xntpd/include/ntp_datum.h b/usr.sbin/xntpd/include/ntp_datum.h
new file mode 100644
index 000000000000..2aa2cb742d01
--- /dev/null
+++ b/usr.sbin/xntpd/include/ntp_datum.h
@@ -0,0 +1,30 @@
+struct btfp_time /* Structure for reading 5 time words */
+ /* in one ioctl(2) operation. */
+{
+ unsigned short btfp_time[5]; /* Time words 0,1,2,3, and 4. (16bit)*/
+};
+
+/***** Simple ioctl commands *****/
+
+#define RUNLOCK _IO('X',19) /* Release Capture Lockout */
+#define RCR0 _IOR('X',22,unsigned int) /* Read control register */
+#define WCR0 _IOW('X',23,unsigned int) /* Write control register */
+
+/***** Compound ioctl commands *****/
+
+/* Read all 5 time words in one call. */
+#define READTIME _IOR('X',32,struct btfp_time)
+#define VMEFD "/dev/btfp0"
+
+ struct vmedate { /* structure returned by get_vmetime.c */
+ unsigned short year;
+ unsigned short doy;
+ unsigned short hr;
+ unsigned short mn;
+ unsigned short sec;
+ unsigned long frac;
+ unsigned short status;
+ };
+
+#define PRIO 120 /* set the realtime priority */
+#define NREGS 7 /* number of registers we will use */
diff --git a/usr.sbin/xntpd/include/ntp_filegen.h b/usr.sbin/xntpd/include/ntp_filegen.h
index 7281d597aaeb..9e75bc63fc97 100644
--- a/usr.sbin/xntpd/include/ntp_filegen.h
+++ b/usr.sbin/xntpd/include/ntp_filegen.h
@@ -1,5 +1,5 @@
/*
- * ntp_filegen.h,v 3.7 1994/01/25 19:04:16 kardel Exp
+ * ntp_filegen.h,v 3.8 1994/05/30 09:48:53 kardel Exp
*
* definitions for NTP file generations support
*
@@ -40,12 +40,12 @@ typedef struct FILEGEN
char *prefix; /* filename prefix and basename to be used*/
char *basename; /* for constructing filename of generation file */
/* WARNING: must be malloced !!! will be fed to free()*/
- U_LONG id; /* id of current generation */
+ u_long id; /* id of current generation */
u_char type; /* type of file generation */
u_char flag; /* flags modifying processing of file generation */
} FILEGEN;
-extern void filegen_setup P((FILEGEN *, U_LONG));
+extern void filegen_setup P((FILEGEN *, u_long));
extern void filegen_config P((FILEGEN *, char *, u_int, u_int));
extern FILEGEN *filegen_get P((char *));
extern void filegen_register P((char *, FILEGEN *));
diff --git a/usr.sbin/xntpd/include/ntp_fp.h b/usr.sbin/xntpd/include/ntp_fp.h
index 327306054b44..ec657f7fb451 100644
--- a/usr.sbin/xntpd/include/ntp_fp.h
+++ b/usr.sbin/xntpd/include/ntp_fp.h
@@ -1,4 +1,4 @@
-/* ntp_fp.h,v 3.1 1993/07/06 01:06:54 jbj Exp
+/*
* ntp_fp.h - definitions for NTP fixed point arithmetic
*/
@@ -10,7 +10,7 @@
/*
* NTP uses two fixed point formats. The first (l_fp) is the "long" format
- * and is 64 bits LONG with the decimal between bits 31 and 32. This
+ * and is 64 bits long with the decimal between bits 31 and 32. This
* is used for time stamps in the NTP packet header (in network byte
* order) and for internal computations of offsets (in local host byte
* order). We use the same structure for both signed and unsigned values,
@@ -103,13 +103,13 @@ typedef U_LONG u_fp;
* Conversions between the two fixed point types
*/
#define MFPTOFP(x_i, x_f) (((x_i)<<16) | (((x_f)>>16)&0xffff))
-#define LFPTOFP(v) MFPTOFP((v)->l_ui, (v)->l_uf)
+#define LFPTOFP(v) MFPTOFP((v)->l_i, (v)->l_f)
#define UFPTOLFP(x, v) ((v)->l_ui = (u_fp)(x)>>16, (v)->l_uf = (x)<<16)
#define FPTOLFP(x, v) (UFPTOLFP((x), (v)), (x) < 0 ? (v)->l_ui -= 0x10000 : 0)
/*
- * Primitive operations on LONG fixed point values. If these are
+ * Primitive operations on long fixed point values. If these are
* reminiscent of assembler op codes it's only because some may
* be replaced by inline assembler for particular machines someday.
* These are the (kind of inefficient) run-anywhere versions.
@@ -263,7 +263,7 @@ typedef U_LONG u_fp;
((a_i) == (b_i) && (a_f) == (b_f))
/*
- * Operations on the LONG fp format
+ * Operations on the long fp format
*/
#define L_ADD(r, a) M_ADD((r)->l_ui, (r)->l_uf, (a)->l_ui, (a)->l_uf)
#define L_SUB(r, a) M_SUB((r)->l_ui, (r)->l_uf, (a)->l_ui, (a)->l_uf)
@@ -277,6 +277,7 @@ typedef U_LONG u_fp;
#define L_CLR(v) ((v)->l_ui = (v)->l_uf = 0)
#define L_ISNEG(v) (((v)->l_ui & 0x80000000) != 0)
+#define L_ISZERO(v) ((v)->l_ui == 0 && (v)->l_uf == 0)
#define L_ISHIS(a, b) ((a)->l_ui > (b)->l_ui || \
((a)->l_ui == (b)->l_ui && (a)->l_uf >= (b)->l_uf))
#define L_ISGEQ(a, b) ((a)->l_i > (b)->l_i || \
@@ -284,7 +285,7 @@ typedef U_LONG u_fp;
#define L_ISEQU(a, b) M_ISEQU((a)->l_ui, (a)->l_uf, (b)->l_ui, (b)->l_uf)
extern char * dofptoa P((u_fp, int, int, int));
-extern char * dolfptoa P((U_LONG, U_LONG, int, int, int));
+extern char * dolfptoa P((u_long, u_long, int, int, int));
extern int atolfp P((const char *, l_fp *));
extern int buftvtots P((const char *, l_fp *));
diff --git a/usr.sbin/xntpd/include/ntp_if.h b/usr.sbin/xntpd/include/ntp_if.h
index 45a70c51bcd5..bc842fbcc644 100644
--- a/usr.sbin/xntpd/include/ntp_if.h
+++ b/usr.sbin/xntpd/include/ntp_if.h
@@ -12,7 +12,7 @@
#include <time.h>
#endif
-#if defined(SOLARIS)&&!defined(bsd)
+#if (defined(SOLARIS) && !defined(bsd)) || defined(SYS_SUNOS4)
#include <sys/sockio.h>
#endif
diff --git a/usr.sbin/xntpd/include/ntp_machine.h b/usr.sbin/xntpd/include/ntp_machine.h
index abc0acb0c61a..91c18dc306f5 100644
--- a/usr.sbin/xntpd/include/ntp_machine.h
+++ b/usr.sbin/xntpd/include/ntp_machine.h
@@ -1,4 +1,4 @@
-/* ntp_machine.h,v 3.1 1993/07/06 01:06:49 jbj Exp
+/*
* Collect all machine dependent idiosyncrasies in one place.
*/
@@ -180,6 +180,7 @@ in this file.
#define RETSIGTYPE void
#define NTP_SYSCALL_GET 132
#define NTP_SYSCALL_ADJ 147
+#define HAVE_MODEM_CONTROL
#ifndef STR_SYSTEM
#define STR_SYSTEM "UNIX/SunOS 4.x"
#endif
@@ -218,6 +219,7 @@ in this file.
#define HAVE_ATT_SETPGRP
#define HAVE_ATT_NICE
#define UDP_WILDCARD_DELIVERY
+#define HAVE_MODEM_CONTROL
#ifndef STR_SYSTEM
#define STR_SYSTEM "UNIX/Solaris 2.x"
#endif
@@ -276,6 +278,7 @@ in this file.
#define HAVE_BSD_NICE
#define RETSIGTYPE void
#define NTP_SYSCALLS_STD
+#define HAVE_MODEM_CONTROL
#ifndef STR_SYSTEM
#define STR_SYSTEM "UNIX/Ultrix"
#endif
@@ -364,6 +367,19 @@ in this file.
#endif
/*
+ * 4.4 bsd
+ */
+#if defined(SYS_44BSD)
+#define HAVE_SIGNALED_IO
+#define HAVE_LIBKVM
+#define NTP_POSIX_SOURCE
+#define HAVE_BSD_NICE
+#ifndef STR_SYSTEM
+#define STR_SYSTEM "UNIX/4.4BSD"
+#endif
+#endif
+
+/*
* Linux
*/
#if defined(SYS_LINUX)
@@ -391,7 +407,7 @@ in this file.
#define NTP_POSIX_SOURCE
#define HAVE_BSD_NICE
#ifndef STR_SYSTEM
-#define STR_SYSTEM "UNIX/*BSD"
+#define STR_SYSTEM "UNIX/\052BSD"
#endif
#endif
@@ -404,12 +420,42 @@ in this file.
#define NTP_POSIX_SOURCE
#define NTP_SYSCALLS_STD
#define HAVE_BSD_NICE
+#define HAVE_MODEM_CONTROL
#ifndef STR_SYSTEM
#define STR_SYSTEM "UNIX/DECOSF1"
#endif
#endif
/*
+ * Intel x86 OSF/1
+ */
+#if defined(SYS_IX86OSF1)
+#define HAVE_SIGNALED_IO
+#define HAVE_READKMEM
+#define NTP_POSIX_SOURCE
+#define NTP_SYSCALLS_STD
+#define HAVE_BSD_NICE
+#define HAVE_MODEM_CONTROL
+#define SYS_DECOSF1
+#ifndef STR_SYSTEM
+#define STR_SYSTEM "UNIX/IX86OSF1"
+#endif
+#endif
+
+/*
+ * ISI
+ */
+#if defined(SYS_BSD)
+#define NO_SIGNED_CHAR_DECL
+#define HAVE_BSD_NICE
+#define HAVE_BSD_TTYS
+#define HAVE_READKMEM
+#define HAVE_SIGNALED_IO
+#define NEED_VSPRINTF
+#undef NTP_POSIX_SOURCE
+#endif
+
+/*
* I386
* XXX - what OS?
*/
diff --git a/usr.sbin/xntpd/include/ntp_refclock.h b/usr.sbin/xntpd/include/ntp_refclock.h
index cc026f5c742f..fcc120001acf 100644
--- a/usr.sbin/xntpd/include/ntp_refclock.h
+++ b/usr.sbin/xntpd/include/ntp_refclock.h
@@ -4,40 +4,48 @@
#include "ntp_types.h"
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(CLK)
+#include <sys/clkdefs.h>
+#endif /* CLK */
+#endif /* STREAM */
+
#if !defined(SYSV_TTYS) && !defined(STREAM) & !defined(BSD_TTYS)
#define BSD_TTYS
#endif /* SYSV_TTYS STREAM BSD_TTYS */
/*
* Macros to determine the clock type and unit numbers from a
- * 127.127.t.u address.
+ * 127.127.t.u address
*/
#define REFCLOCKTYPE(srcadr) ((SRCADR(srcadr) >> 8) & 0xff)
#define REFCLOCKUNIT(srcadr) (SRCADR(srcadr) & 0xff)
/*
- * list of reference clock names
- * see lib/clocktypes.c (must also agree with xntpd/refclock_conf.c)
+ * List of reference clock names and descriptions. These must agree with
+ * lib/clocktypes.c and xntpd/refclock_conf.c.
*/
struct clktype {
int code; /* driver "major" number */
- char *clocktype; /* LONG description */
+ char *clocktype; /* long description */
char *abbrev; /* short description */
};
/*
- * Definitions for default values
- */
-#define noentry 0 /* flag for null routine */
-
-/*
- * Definitions for flags
- */
-#define NOFLAGS 0
-#define REF_FLAG_BCLIENT 0x1 /* clock prefers to run as a bclient */
-
-/*
- * Flag values
+ * Configuration flag values
*/
#define CLK_HAVETIME1 0x1
#define CLK_HAVETIME2 0x2
@@ -58,25 +66,25 @@ struct clktype {
* Structure for returning clock status
*/
struct refclockstat {
- u_char type;
- u_char flags;
- u_char haveflags;
- u_short lencode; /* ahem, we do have some longer "time-codes" */
- char *lastcode;
- U_LONG polls;
- U_LONG noresponse;
- U_LONG badformat;
- U_LONG baddata;
- U_LONG timereset;
- char *clockdesc; /* description of clock, in ASCII */
- l_fp fudgetime1;
- l_fp fudgetime2;
- LONG fudgeval1;
- LONG fudgeval2;
- u_char currentstatus;
- u_char lastevent;
- u_char unused;
- struct ctl_var *kv_list; /* additional variables */
+ u_char type; /* clock type */
+ u_char flags; /* clock flags */
+ u_char haveflags; /* bit array of valid flags */
+ u_char lencode; /* length of last timecode */
+ char *lastcode; /* last timecode received */
+ U_LONG polls; /* transmit polls */
+ U_LONG noresponse; /* no response to poll */
+ U_LONG badformat; /* bad format timecode received */
+ U_LONG baddata; /* invalid data timecode received */
+ U_LONG timereset; /* driver resets */
+ char *clockdesc; /* ASCII description */
+ l_fp fudgetime1; /* configure fudge time1 */
+ l_fp fudgetime2; /* configure fudge time2 */
+ LONG fudgeval1; /* configure fudge value1 */
+ LONG fudgeval2; /* configure fudge value2 */
+ u_char currentstatus; /* clock status */
+ u_char lastevent; /* last exception event */
+ u_char unused; /* spare */
+ struct ctl_var *kv_list; /* additional variables */
};
/*
@@ -84,59 +92,133 @@ struct refclockstat {
* the reference clock drivers and the I/O module.
*/
struct refclockio {
- struct refclockio *next;
- void (*clock_recv)();
- caddr_t srcclock; /* pointer to clock structure */
- int datalen;
- int fd;
- U_LONG recvcount;
+ struct refclockio *next; /* link to next structure */
+ void (*clock_recv)();/* completion routine */
+ caddr_t srcclock; /* pointer to clock structure */
+ int datalen; /* lenth of data */
+ int fd; /* file descriptor */
+ u_long recvcount; /* count of receive completions */
};
+/*
+ * Structure for returning debugging info
+ */
+#define NCLKBUGVALUES 16
+#define NCLKBUGTIMES 32
+
+struct refclockbug {
+ u_char nvalues; /* values following */
+ u_char ntimes; /* times following */
+ u_short svalues; /* values format sign array */
+ U_LONG stimes; /* times format sign array */
+ U_LONG values[NCLKBUGVALUES]; /* real values */
+ l_fp times[NCLKBUGTIMES]; /* real times */
+};
/*
- * Sizes of things we return for debugging
+ * Structure interface between the reference clock support
+ * ntp_refclock.c and the driver utility routines
*/
-#define NCLKBUGVALUES 16
-#define NCLKBUGTIMES 32
+#define MAXSTAGE 64 /* max stages in shift register */
+#define BMAX 128 /* max timecode length */
+#define GMT 0 /* I hope nobody sees this */
+#define MAXDIAL 20 /* max length of modem dial strings */
/*
- * Structure for returning debugging info
+ * Line discipline flags. These require line discipline or streams
+ * modules to be installed/loaded in the kernel. If specified, but not
+ * installed, the code runs as if unspecified.
*/
-struct refclockbug {
- u_char nvalues;
- u_char ntimes;
- u_short svalues;
- U_LONG stimes;
- U_LONG values[NCLKBUGVALUES];
- l_fp times[NCLKBUGTIMES];
+#define LDISC_STD 0x0 /* standard */
+#define LDISC_CLK 0x1 /* tty_clk \n intercept */
+#define LDISC_CLKPPS 0x2 /* tty_clk \377 intercept */
+#define LDISC_ACTS 0x4 /* tty_clk #* intercept */
+#define LDISC_CHU 0x8 /* tty_chu */
+#define LDISC_PPS 0x10 /* ppsclock */
+
+struct refclockproc {
+ struct refclockio io; /* I/O handler structure */
+ caddr_t unitptr; /* pointer to unit structure */
+ u_long lasttime; /* last clock update time */
+ u_char leap; /* leap/synchronization code */
+ u_char currentstatus; /* clock status */
+ u_char lastevent; /* last exception event */
+ u_char type; /* clock type */
+ char *clockdesc; /* clock description */
+ char lastcode[BMAX]; /* last timecode received */
+ u_char lencode; /* length of last timecode */
+
+ u_int year; /* year of eternity */
+ u_int day; /* day of year */
+ u_int hour; /* hour of day */
+ u_int minute; /* minute of hour */
+ u_int second; /* second of minute */
+ u_int msec; /* millisecond of second */
+ u_long usec; /* microsecond of second (alt) */
+ u_int nstages; /* median filter stages */
+ u_long yearstart; /* beginning of year */
+ u_long coderecv; /* sample counter */
+ l_fp lastref; /* last reference timestamp */
+ l_fp lastrec; /* last local timestamp */
+ l_fp offset; /* median offset */
+ u_fp dispersion; /* sample dispersion */
+ l_fp filter[MAXSTAGE]; /* median filter */
+
+ /*
+ * Configuration data
+ */
+ l_fp fudgetime1; /* fudge time1 */
+ l_fp fudgetime2; /* fudge time2 */
+ u_long refid; /* reference identifier */
+ u_long sloppyclockflag; /* fudge flags */
+
+ /*
+ * Status tallies
+ */
+ u_long timestarted; /* time we started this */
+ u_long polls; /* polls sent */
+ u_long noreply; /* no replies to polls */
+ u_long badformat; /* bad format reply */
+ u_long baddata; /* bad data reply */
};
/*
- * Struct refclock provides the interface between the reference
- * clock support and particular clock drivers. There are entries
- * to open and close a unit, optional values to specify the
- * timer interval for calls to the transmit procedure and to
- * specify a polling routine to be called when the transmit
- * procedure executes. There is an entry which is called when
- * the transmit routine is about to shift zeroes into the
- * filter register, and entries for stuffing fudge factors into
- * the driver and getting statistics from it.
+ * Structure interface between the reference clock support
+ * ntp_refclock.c and particular clock drivers. This must agree with the
+ * structure defined in the driver.
*/
+#define noentry 0 /* flag for null routine */
+#define NOFLAGS 0 /* flag for null flags */
+
struct refclock {
- int (*clock_start) P((u_int, struct peer *)); /* start a clock unit */
- void (*clock_shutdown) P((int)); /* shut a clock down */
- void (*clock_poll) P((int, struct peer *)); /* called from the xmit routine */
- void (*clock_control) P((u_int, struct refclockstat *, struct refclockstat *)); /* set fudge values, return stats */
- void (*clock_init) P((void)); /* initialize driver data at startup */
- void (*clock_buginfo) P((int, struct refclockbug *)); /* get clock dependent bug info */
- U_LONG clock_flags; /* flag values */
+ int (*clock_start) P((int, struct peer *));
+ void (*clock_shutdown) P((int, struct peer *));
+ void (*clock_poll) P((int, struct peer *));
+ void (*clock_control) P((int, struct refclockstat *,
+ struct refclockstat *));
+ void (*clock_init) P((void));
+ void (*clock_buginfo) P((int, struct refclockbug *));
+ u_long clock_flags;
};
+/*
+ * Function prototypes
+ */
extern int io_addclock_simple P((struct refclockio *));
extern int io_addclock P((struct refclockio *));
extern void io_closeclock P((struct refclockio *));
-#ifdef REFCLOCK
-extern void refclock_buginfo P((struct sockaddr_in *, struct refclockbug *));
-extern void refclock_control P((struct sockaddr_in *, struct refclockstat *, struct refclockstat *));
-#endif /* REFCLOCK */
+#ifdef REFCLOCK
+extern void refclock_buginfo P((struct sockaddr_in *,
+ struct refclockbug *));
+extern void refclock_control P((struct sockaddr_in *,
+ struct refclockstat *,
+ struct refclockstat *));
+extern int refclock_open P((char *, int, int));
+extern void refclock_transmit P((struct peer *));
+extern int refclock_ioctl P((int, int));
+extern int refclock_process P((struct refclockproc *, int, int));
+extern void refclock_report P((struct peer *, u_char));
+extern int refclock_gtlin P((struct recvbuf *, char *, int,
+ l_fp *));
+#endif /* REFCLOCK */
diff --git a/usr.sbin/xntpd/include/ntp_request.h b/usr.sbin/xntpd/include/ntp_request.h
index b1a947291316..698e20a99555 100644
--- a/usr.sbin/xntpd/include/ntp_request.h
+++ b/usr.sbin/xntpd/include/ntp_request.h
@@ -1,4 +1,4 @@
-/* ntp_request.h,v 3.1 1993/07/06 01:06:57 jbj Exp
+/*
* ntp_request.h - definitions for the xntpd remote query facility
*/
@@ -207,7 +207,6 @@ struct resp_pkt {
* the receive time stamp by no more than 10 seconds.
*/
#define INFO_TS_MAXSKEW_UI 10
-#define INFO_TS_MAXSKEW_UF 0
/*
* Universal request codes go here. There aren't any.
@@ -257,23 +256,33 @@ struct resp_pkt {
#define REQ_GET_KERNEL 38 /* get kernel pll/pps information */
#define REQ_GET_CLKBUGINFO 39 /* get clock debugging info */
#define REQ_SET_PRECISION 41 /* set clock precision */
-
+#define REQ_MON_GETLIST_1 42 /* return data collected by monitor v1*/
/*
- * Flags in the information returns
+ * Flags in the peer information returns
*/
#define INFO_FLAG_CONFIG 0x1
#define INFO_FLAG_SYSPEER 0x2
-#define INFO_FLAG_MINPOLL 0x4
+#define INFO_FLAG_UNUSED 0x4
#define INFO_FLAG_REFCLOCK 0x8
-#define INFO_FLAG_MCLIENT 0x8 /* danger */
-#define INFO_FLAG_BCLIENT 0x10
-#define INFO_FLAG_PREFER 0x10 /* danger */
+#define INFO_FLAG_PREFER 0x10
#define INFO_FLAG_AUTHENABLE 0x20
#define INFO_FLAG_SEL_CANDIDATE 0x40
#define INFO_FLAG_SHORTLIST 0x80
/*
+ * Flags in the system information returns
+ */
+#define INFO_FLAG_BCLIENT 0x1
+#define INFO_FLAG_AUTHENTICATE 0x2
+#define INFO_FLAG_PLL 0x4
+#define INFO_FLAG_PPS 0x8 /* unused */
+#define INFO_FLAG_PLL_SYNC 0x10
+#define INFO_FLAG_PPS_SYNC 0x20
+#define INFO_FLAG_MONITOR 0x40
+#define INFO_FLAG_FILEGEN 0x80
+
+/*
* Peer list structure. Used to return raw lists of peers. It goes
* without saying that everything returned is in network byte order.
*/
@@ -352,7 +361,7 @@ struct info_peer {
LONG unused5;
LONG unused6;
LONG unused7;
- U_LONG estbdelay; /* broadcast delay */
+ s_fp estbdelay; /* broadcast offset */
};
@@ -369,21 +378,21 @@ struct info_peer_stats {
U_LONG timetosend; /* time until a packet sent */
U_LONG timereachable; /* time peer has been reachable */
U_LONG sent; /* number sent */
- U_LONG received; /* number received */
+ U_LONG unused1; /* (unused) */
U_LONG processed; /* number processed */
- U_LONG badlength; /* rejected due to bad length */
- U_LONG badauth; /* rejected due to bad auth */
- U_LONG bogusorg; /* funny org time stamps */
- U_LONG oldpkt; /* duplicate packets */
- U_LONG baddelay; /* dropped due to bad delays */
- U_LONG seldelay; /* not selected due to delay */
- U_LONG seldisp; /* not selected due to dispersion */
- U_LONG selbroken; /* not selected because of brokenness */
- U_LONG selold; /* not selected because too old */
- u_char candidate; /* order after falseticker candidate select */
- u_char falseticker; /* order after resort for falseticker */
- u_char select; /* order after select */
- u_char select_total; /* number who made it to selection */
+ U_LONG unused2; /* (unused) */
+ U_LONG badauth; /* bad authentication */
+ U_LONG bogusorg; /* bogus origin */
+ U_LONG oldpkt; /* duplicate */
+ U_LONG unused3; /* (unused) */
+ U_LONG unused4; /* (unused) */
+ U_LONG seldisp; /* bad dispersion */
+ U_LONG selbroken; /* bad reference time */
+ U_LONG unused5; /* (unused) */
+ u_char candidate; /* select order */
+ u_char unused6; /* (unused) */
+ u_char unused7; /* (unused) */
+ u_char unused8; /* (unused) */
};
@@ -417,9 +426,10 @@ struct info_sys {
u_char unused1; /* unused */
u_char unused2; /* unused */
u_char unused3; /* unused */
- l_fp bdelay; /* default broadcast delay */
+ s_fp bdelay; /* default broadcast offset */
+ s_fp frequency; /* frequency residual (scaled ppm) */
l_fp authdelay; /* default authentication delay */
- u_fp maxskew; /* (obsolete) */
+ u_fp stability; /* clock stability (scaled ppm) */
};
@@ -518,8 +528,7 @@ struct conf_peer {
};
#define CONF_FLAG_AUTHENABLE 0x1
-#define CONF_FLAG_MINPOLL 0x2
-#define CONF_FLAG_PREFER 0x4
+#define CONF_FLAG_PREFER 0x2
/*
* Structure for passing peer deletion information. Currently
@@ -530,7 +539,6 @@ struct conf_unpeer {
U_LONG peeraddr; /* address of peer */
};
-
/*
* Structure for carrying system flags.
*/
@@ -543,7 +551,10 @@ struct conf_sys_flags {
*/
#define SYS_FLAG_BCLIENT 0x1
#define SYS_FLAG_AUTHENTICATE 0x2
-#define SYS_FLAG_MCLIENT 0x4
+#define SYS_FLAG_PLL 0x4
+#define SYS_FLAG_PPS 0x8
+#define SYS_FLAG_MONITOR 0x10
+#define SYS_FLAG_FILEGEN 0x20
/*
* Structure used for returning restrict entries
@@ -571,6 +582,23 @@ struct conf_restrict {
/*
* Structure used for returning monitor data
*/
+struct info_monitor_1 {
+ 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_LONG daddr; /* destination host address */
+ U_LONG flags; /* flags about destination */
+ 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 returning monitor data
+ */
struct info_monitor {
U_LONG lasttime; /* last packet from this host */
U_LONG firsttime; /* first time we received a packet */
@@ -626,7 +654,7 @@ struct info_auth {
U_LONG keynotfound; /* requested key unknown */
U_LONG encryptions; /* number of encryptions */
U_LONG decryptions; /* number of decryptions */
- U_LONG decryptok; /* number of successful decryptions */
+ U_LONG unused; /* (unused) */
U_LONG keyuncached; /* calls to encrypt/decrypt with uncached key */
};
diff --git a/usr.sbin/xntpd/include/ntp_stdlib.h b/usr.sbin/xntpd/include/ntp_stdlib.h
index f68c768d82d3..646ce602e92b 100644
--- a/usr.sbin/xntpd/include/ntp_stdlib.h
+++ b/usr.sbin/xntpd/include/ntp_stdlib.h
@@ -1,4 +1,4 @@
-/* ntp_stdlib.h,v 3.1 1993/07/06 01:06:58 jbj Exp
+/*
* ntp_stdlib.h - Prototypes for XNTP lib.
*/
#include <sys/types.h>
@@ -24,28 +24,28 @@ extern void msyslog P((int, char *, ...));
extern void msyslog P(());
#endif
-extern void auth_des P((U_LONG *, u_char *));
+extern void auth_des P((u_long *, u_char *));
extern void auth_delkeys P((void));
-extern int auth_havekey P((U_LONG));
-extern int auth_parity P((U_LONG *));
-extern void auth_setkey P((U_LONG, U_LONG *));
-extern void auth_subkeys P((U_LONG *, u_char *, u_char *));
-extern int authistrusted P((U_LONG));
-extern int authusekey P((U_LONG, int, const char *));
+extern int auth_havekey P((u_long));
+extern int auth_parity P((u_long *));
+extern void auth_setkey P((u_long, u_long *));
+extern void auth_subkeys P((u_long *, u_char *, u_char *));
+extern int authistrusted P((u_long));
+extern int authusekey P((u_long, int, const char *));
extern void auth_delkeys P((void));
-extern void auth1crypt P((U_LONG, U_LONG *, int));
-extern int auth2crypt P((U_LONG, U_LONG *, int));
-extern int authdecrypt P((U_LONG, U_LONG *, int));
-extern int authencrypt P((U_LONG, U_LONG *, int));
-extern int authhavekey P((U_LONG));
+extern void auth1crypt P((u_long, U_LONG *, int));
+extern int auth2crypt P((u_long, U_LONG *, int));
+extern int authdecrypt P((u_long, U_LONG *, int));
+extern int authencrypt P((u_long, U_LONG *, int));
+extern int authhavekey P((u_long));
extern int authreadkeys P((const char *));
-extern void authtrust P((U_LONG, int));
-extern void calleapwhen P((U_LONG, U_LONG *, U_LONG *));
-extern U_LONG calyearstart P((U_LONG));
+extern void authtrust P((u_long, int));
+extern void calleapwhen P((u_long, u_long *, u_long *));
+extern u_long calyearstart P((u_long));
extern const char *clockname P((int));
-extern int clocktime P((int, int, int, int, int, U_LONG, U_LONG *, U_LONG *));
+extern int clocktime P((int, int, int, int, int, u_long, u_long *, U_LONG *));
extern char * emalloc P((u_int));
extern int ntp_getopt P((int, char **, char *));
extern void init_auth P((void));
@@ -53,41 +53,41 @@ extern void init_lib P((void));
extern void init_random P((void));
#ifdef DES
-extern void DESauth1crypt P((U_LONG, U_LONG *, int));
-extern int DESauth2crypt P((U_LONG, U_LONG *, int));
-extern int DESauthdecrypt P((U_LONG, const U_LONG *, int));
-extern int DESauthencrypt P((U_LONG, U_LONG *, int));
-extern void DESauth_setkey P((U_LONG, const U_LONG *));
+extern void DESauth1crypt P((u_long, U_LONG *, int));
+extern int DESauth2crypt P((u_long, U_LONG *, int));
+extern int DESauthdecrypt P((u_long, const U_LONG *, int));
+extern int DESauthencrypt P((u_long, U_LONG *, int));
+extern void DESauth_setkey P((u_long, const U_LONG *));
extern void DESauth_subkeys P((const U_LONG *, u_char *, u_char *));
extern void DESauth_des P((U_LONG *, u_char *));
extern int DESauth_parity P((U_LONG *));
#endif /* DES */
#ifdef MD5
-extern void MD5auth1crypt P((U_LONG, U_LONG *, int));
-extern int MD5auth2crypt P((U_LONG, U_LONG *, int));
-extern int MD5authdecrypt P((U_LONG, const U_LONG *, int));
-extern int MD5authencrypt P((U_LONG, U_LONG *, int));
-extern void MD5auth_setkey P((U_LONG, const U_LONG *));
+extern void MD5auth1crypt P((u_long, U_LONG *, int));
+extern int MD5auth2crypt P((u_long, U_LONG *, int));
+extern int MD5authdecrypt P((u_long, const U_LONG *, int));
+extern int MD5authencrypt P((u_long, U_LONG *, int));
+extern void MD5auth_setkey P((u_long, const U_LONG *));
#endif /* MD5 */
-extern int atoint P((const char *, LONG *));
-extern int atouint P((const char *, U_LONG *));
-extern int hextoint P((const char *, U_LONG *));
-extern char * humandate P((U_LONG));
-extern char * inttoa P((LONG));
-extern char * mfptoa P((U_LONG, U_LONG, int));
-extern char * mfptoms P((U_LONG, U_LONG, int));
+extern int atoint P((const char *, long *));
+extern int atouint P((const char *, u_long *));
+extern int hextoint P((const char *, u_long *));
+extern char * humandate P((u_long));
+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 *));
-extern U_LONG ranp2 P((int));
-extern char * refnumtoa P((U_LONG));
-extern int tsftomsu P((U_LONG, int));
-extern char * uinttoa P((U_LONG));
+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 *));
+extern u_long ranp2 P((int));
+extern char * refnumtoa P((u_long));
+extern int tsftomsu P((u_long, int));
+extern char * uinttoa P((u_long));
-extern int decodenetnum P((const char *, U_LONG *));
+extern int decodenetnum P((const char *, u_long *));
extern RETSIGTYPE signal_no_reset P((int, RETSIGTYPE (*func)()));
diff --git a/usr.sbin/xntpd/include/ntp_syslog.h b/usr.sbin/xntpd/include/ntp_syslog.h
index 0d5dff8cc45a..38b847bb82ca 100644
--- a/usr.sbin/xntpd/include/ntp_syslog.h
+++ b/usr.sbin/xntpd/include/ntp_syslog.h
@@ -1,4 +1,4 @@
-/* ntp_syslog.h,v 3.1 1993/07/06 01:06:59 jbj Exp
+/*
* A hack for platforms which require specially built syslog facilities
*/
#ifdef GIZMO
diff --git a/usr.sbin/xntpd/include/ntp_types.h b/usr.sbin/xntpd/include/ntp_types.h
index 7a2a3474bdf3..ac3d76cbc911 100644
--- a/usr.sbin/xntpd/include/ntp_types.h
+++ b/usr.sbin/xntpd/include/ntp_types.h
@@ -1,4 +1,4 @@
-/* ntp_types.h,v 3.1 1993/07/06 01:07:00 jbj Exp
+/*
* ntp_types.h - defines how LONG and U_LONG are treated. For 64 bit systems
* like the DEC Alpha, they has to be defined as int and u_int. for 32 bit
* systems, define them as long and u_long
diff --git a/usr.sbin/xntpd/include/ntp_unixtime.h b/usr.sbin/xntpd/include/ntp_unixtime.h
index c1ab573f4d4c..8007a06640c9 100644
--- a/usr.sbin/xntpd/include/ntp_unixtime.h
+++ b/usr.sbin/xntpd/include/ntp_unixtime.h
@@ -1,4 +1,4 @@
-/* ntp_unixtime.h,v 3.1 1993/07/06 01:07:02 jbj Exp
+/*
* ntp_unixtime.h - contains constants and macros for converting between
* NTP time stamps (l_fp) and Unix times (struct timeval)
*/
@@ -34,9 +34,9 @@
* Convert usec to a time stamp fraction. If you use this the program
* must include the following declarations:
*/
-extern U_LONG ustotslo[];
-extern U_LONG ustotsmid[];
-extern U_LONG ustotshi[];
+extern u_long ustotslo[];
+extern u_long ustotsmid[];
+extern u_long ustotshi[];
#define TVUTOTSF(tvu, tsf) \
(tsf) = ustotslo[(tvu) & 0xff] \
@@ -48,14 +48,14 @@ extern U_LONG ustotshi[];
*/
#define TVTOTS(tv, ts) \
do { \
- (ts)->l_ui = (unsigned LONG)(tv)->tv_sec; \
+ (ts)->l_ui = (u_long)(tv)->tv_sec; \
TVUTOTSF((tv)->tv_usec, (ts)->l_uf); \
} while(0)
#define sTVTOTS(tv, ts) \
do { \
int isneg = 0; \
- LONG usec; \
+ long usec; \
(ts)->l_ui = (tv)->tv_sec; \
usec = (tv)->tv_usec; \
if (((tv)->tv_sec < 0) || ((tv)->tv_usec < 0)) { \
@@ -81,9 +81,9 @@ extern U_LONG ustotshi[];
* Convert a time stamp fraction to microseconds. The time stamp
* fraction is assumed to be unsigned. To use this in a program, declare:
*/
-extern LONG tstouslo[];
-extern LONG tstousmid[];
-extern LONG tstoushi[];
+extern long tstouslo[];
+extern long tstousmid[];
+extern long tstoushi[];
#define TSFTOTVU(tsf, tvu) \
(tvu) = (tstoushi[((tsf) >> 24) & 0xff] \
@@ -109,8 +109,8 @@ extern LONG tstoushi[];
* here, but it is convenient since the guys who use the definition will
* often be including this file anyway.
*/
-extern U_LONG msutotsflo[];
-extern U_LONG msutotsfhi[];
+extern u_long msutotsflo[];
+extern u_long msutotsfhi[];
#define MSUTOTSF(msu, tsf) \
(tsf) = msutotsfhi[((msu) >> 5) & 0x1f] + msutotsflo[(msu) & 0x1f]
diff --git a/usr.sbin/xntpd/include/ntpd.h b/usr.sbin/xntpd/include/ntpd.h
index 037e8cb366f4..53e3a913f2d6 100644
--- a/usr.sbin/xntpd/include/ntpd.h
+++ b/usr.sbin/xntpd/include/ntpd.h
@@ -63,10 +63,10 @@ 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 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));
+extern void sendpkt P((struct sockaddr_in *, struct interface *, int, struct pkt *, int));
#ifdef HAVE_SIGNALED_IO
extern void wait_for_signal P((void));
extern void unblock_io_and_alarm P((void));
@@ -88,6 +88,7 @@ extern int leap_actual P((int));
/* ntp_loopfilter.c */
extern void init_loopfilter P((void));
extern int local_clock P((l_fp *, struct peer *));
+extern void adj_frequency P((s_fp));
extern void adj_host_clock P((void));
extern void loop_config P((int, l_fp *, int));
#if defined(PPS) || defined(PPSPPS) || defined(PPSCD)
@@ -103,12 +104,12 @@ extern void monitor P((struct recvbuf *));
/* ntp_peer.c */
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 *findpeer P((struct sockaddr_in *, struct interface *, int));
extern struct peer *findpeerbyassoc P((int));
-extern struct peer *newpeer P((struct sockaddr_in *, struct interface *, int, 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, int, int, U_LONG));
+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 *));
@@ -134,7 +135,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, U_LONG));
+extern void proto_config P((int, u_long));
extern void proto_clr_stats P((void));
#ifdef REFCLOCK
@@ -168,7 +169,7 @@ extern void init_util P((void));
extern void hourly_stats P((void));
extern void stats_config P((int, char *));
extern void record_peer_stats P((struct sockaddr_in *, int, l_fp *, s_fp, u_fp));
-extern void record_loop_stats P((l_fp *, s_fp *, int));
+extern void record_loop_stats P((l_fp *, s_fp, int));
extern void record_clock_stats P((struct sockaddr_in *, char *));
extern void getauthkeys P((char *));
extern void rereadkeys P((void));
diff --git a/usr.sbin/xntpd/include/parse.h b/usr.sbin/xntpd/include/parse.h
index 6ce3f192754a..49ed4e55b82c 100644
--- a/usr.sbin/xntpd/include/parse.h
+++ b/usr.sbin/xntpd/include/parse.h
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/include/parse.h,v 3.17 1994/03/03 09:27:20 kardel Exp
+ * /src/NTP/REPOSITORY/v3/include/parse.h,v 3.21 1994/05/30 20:58:34 kardel Exp
*
- * parse.h,v 3.17 1994/03/03 09:27:20 kardel Exp
+ * parse.h,v 3.21 1994/05/30 20:58:34 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.17 1994/03/03 09:27:20 kardel Exp";
+ static char parsehrcsid[]="parse.h,v 3.21 1994/05/30 20:58:34 kardel Exp";
#endif
#include "ntp_types.h"
@@ -50,7 +50,6 @@ extern int splhigh();
#define FREE(_X_, _Y_) kmem_free((caddr_t)_X_, _Y_)
#endif
#else
-/* extern char *malloc(); XXX defined elsewhere */
#define MALLOC(_X_) malloc(_X_)
#define FREE(_X_, _Y_) free(_X_)
#endif
@@ -74,6 +73,13 @@ extern int debug;
#endif /* DEBUG */
#endif /* PARSESTREAM */
+#if defined(timercmp) && defined(__GNUC__)
+#undef timercmp
+#define timercmp(tvp, uvp, cmp) \
+ ((tvp)->tv_sec cmp (uvp)->tv_sec || \
+ ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec))
+#endif
+
#ifndef TIMES10
#define TIMES10(_X_) (((_X_) << 3) + ((_X_) << 1))
#endif
@@ -149,6 +155,7 @@ extern int debug;
#define PARSE_STAT_FILTER 0x01 /* filter incoming data */
#define PARSE_STAT_AVG 0x02 /* 1:median average / 0: median point */
#define PARSE_LEAP_DELETE 0x04 /* delete leap */
+#define PARSE_STATISTICS 0x08 /* enable statistics */
#define PARSE_FIXED_FMT 0x10 /* fixed format */
#define PARSE_PPSCLOCK 0x20 /* try to get PPS time stamp via ppsclock ioctl */
@@ -163,13 +170,13 @@ typedef union timestamp
*/
struct parsetime
{
- unsigned LONG parse_status; /* data status - CVT_OK, CVT_NONE, CVT_FAIL ... */
+ u_long parse_status; /* data status - CVT_OK, CVT_NONE, CVT_FAIL ... */
timestamp_t parse_time; /* PARSE timestamp */
timestamp_t parse_stime; /* telegram sample timestamp */
timestamp_t parse_ptime; /* PPS time stamp */
- LONG parse_usecerror; /* sampled/filtered usec error */
- LONG parse_usecdisp; /* sampled usecdispersion */
- unsigned LONG parse_state; /* current receiver state */
+ long parse_usecerror; /* sampled/filtered usec error */
+ long parse_usecdisp; /* sampled usecdispersion */
+ u_long parse_state; /* current receiver state */
unsigned short parse_format; /* format code */
};
@@ -212,13 +219,13 @@ union parsectl
{
struct parsestatus
{
- unsigned LONG flags; /* new/old flags */
+ u_long flags; /* new/old flags */
} parsestatus;
struct parsegettc
{
- unsigned LONG parse_state; /* last state */
- unsigned LONG parse_badformat; /* number of bad packets since last query */
+ u_long parse_state; /* last state */
+ u_long parse_badformat; /* number of bad packets since last query */
unsigned short parse_format;/* last decoded format */
unsigned short parse_count; /* count of valid time code bytes */
char parse_buffer[PARSE_TCMAX+1]; /* timecode buffer */
@@ -233,7 +240,7 @@ union parsectl
struct parsesetcs
{
- unsigned LONG parse_cs; /* character size (needed for stripping) */
+ u_long parse_cs; /* character size (needed for stripping) */
} parsesetcs;
};
@@ -269,21 +276,27 @@ struct parse /* parse module local data */
timestamp_t parse_lastchar; /* time stamp of last received character */
/*
+ * private data - fixed format only
+ */
+ unsigned short parse_plen; /* length of private data */
+ void *parse_pdata; /* private data pointer */
+
+ /*
* time code input buffer (from RS232 or PPS)
*/
unsigned short parse_index; /* current buffer index */
char *parse_data; /* data buffer */
unsigned short parse_dsize; /* size of data buffer */
unsigned short parse_lformat; /* last format used */
- unsigned LONG parse_lstate; /* last state code */
+ u_long parse_lstate; /* last state code */
char *parse_ldata; /* last data buffer */
unsigned short parse_ldsize; /* last data buffer length */
- unsigned LONG parse_badformat; /* number of unparsable pakets */
+ u_long parse_badformat; /* number of unparsable pakets */
/*
* time stamp filtering
*/
- LONG parse_delta[PARSE_DELTA]; /* delta buffer */
+ long parse_delta[PARSE_DELTA]; /* delta buffer */
int parse_dindex;
parsetime_t parse_dtime; /* external data prototype */
@@ -293,16 +306,16 @@ typedef struct parse parse_t;
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 */
+ long day;
+ long month;
+ long year;
+ long hour;
+ long minute;
+ long second;
+ long usecond;
+ long utcoffset; /* in seconds */
time_t utctime; /* the actual time - alternative to date/time */
- LONG flags; /* current clock status */
+ long flags; /* current clock status */
};
typedef struct clocktime clocktime_t;
@@ -335,20 +348,23 @@ typedef struct clocktime clocktime_t;
#define CVT_NONE 0x00000001 /* format not applicable */
#define CVT_FAIL 0x00000002 /* conversion failed - error code returned */
#define CVT_OK 0x00000004 /* conversion succeeded */
+#define CVT_SKIP 0x00000008 /* conversion succeeded */
#define CVT_BADFMT 0x00000010 /* general format error - (unparsable) */
#define CVT_BADDATE 0x00000020 /* date field incorrect */
#define CVT_BADTIME 0x00000040 /* time field incorrect */
struct clockformat
{
- unsigned LONG (*convert)(); /* conversion routine */
+ u_long (*input)(); /* special input protocol - implies fixed format */
+ u_long (*convert)(); /* conversion routine */
void (*syncevt)(); /* routine for handling RS232 sync events (time stamps) */
- unsigned LONG (*syncpps)(); /* PPS input routine */
- unsigned LONG (*synth)(); /* time code synthesizer */
+ u_long (*syncpps)(); /* PPS input routine */
+ u_long (*synth)(); /* time code synthesizer */
void *data; /* local parameters */
char *name; /* clock format name */
unsigned short length; /* maximum length of data packet */
- unsigned LONG flags; /* valid start symbols etc. */
+ u_long flags; /* valid start symbols etc. */
+ unsigned short plen; /* length of private data - implies fixed format */
struct timeval timeout; /* buffer restart after timeout (us) */
unsigned char startsym; /* start symbol */
unsigned char endsym; /* end symbol */
@@ -360,32 +376,44 @@ typedef struct clockformat clockformat_t;
/*
* parse interface
*/
-extern int parse_ioinit(/* parse_t *parseio */);
-extern void parse_ioend(/* parse_t *parseio */);
-extern int parse_ioread(/* parse_t *parseio, char ch, timestamp_t *ctime */);
-extern int parse_iopps(/* parse_t *parseio, int status, struct timeval *ptime, parsetime_t *dtime */);
-extern void parse_iodone(/* parse_t *parseio */);
-
-extern int parse_getstat(/* parsectl_t *dct, parse_t *parse */);
-extern int parse_setstat(/* parsectl_t *dct, parse_t *parse */);
-extern int parse_timecode(/* parsectl_t *dct, parse_t *parse */);
-extern int parse_getfmt(/* parsectl_t *dct, parse_t *parse */);
-extern int parse_setfmt(/* parsectl_t *dct, parse_t *parse */);
-extern int parse_setcs(/* parsectl_t *dct, parse_t *parse */);
+extern int parse_ioinit P((parse_t *));
+extern void parse_ioend P((parse_t *));
+extern int parse_ioread P((parse_t *, unsigned char, timestamp_t *));
+extern int parse_iopps P((parse_t *, int, timestamp_t *));
+extern void parse_iodone P((parse_t *));
+
+extern int parse_getstat P((parsectl_t *, parse_t *));
+extern int parse_setstat P((parsectl_t *, parse_t *));
+extern int parse_timecode P((parsectl_t *, parse_t *));
+extern int parse_getfmt P((parsectl_t *, parse_t *));
+extern int parse_setfmt P((parsectl_t *, parse_t *));
+extern int parse_setcs P((parsectl_t *, parse_t *));
extern int Strok P((char *, char *));
-extern int Stoi P((char *, LONG *, int));
+extern int Stoi P((char *, long *, int));
-extern time_t parse_to_unixtime P((clocktime_t *, unsigned LONG *));
-extern unsigned LONG updatetimeinfo P((parse_t *, time_t, unsigned LONG, unsigned LONG));
-extern void syn_simple P((parse_t *, timestamp_t *, struct format *, unsigned LONG));
-extern unsigned LONG pps_simple P((parse_t *, int status, timestamp_t *));
+extern time_t parse_to_unixtime P((clocktime_t *, u_long *));
+extern u_long updatetimeinfo P((parse_t *, time_t, u_long, u_long));
+extern void syn_simple P((parse_t *, timestamp_t *, struct format *, u_long));
+extern u_long pps_simple P((parse_t *, int, timestamp_t *));
#endif
/*
* History:
*
* parse.h,v
+ * Revision 3.21 1994/05/30 20:58:34 kardel
+ * fix prototypes
+ *
+ * Revision 3.20 1994/05/30 10:19:44 kardel
+ * LONG cleanup
+ *
+ * Revision 3.19 1994/05/15 11:30:33 kardel
+ * documented flag4 as statistics enable flag
+ *
+ * Revision 3.18 1994/05/12 12:40:34 kardel
+ * shut up gcc about broken Sun/BSD code
+ *
* Revision 3.17 1994/03/03 09:27:20 kardel
* rcs ids fixed
*
diff --git a/usr.sbin/xntpd/include/parse_conf.h b/usr.sbin/xntpd/include/parse_conf.h
index 13cec551db34..47f8c0c4fbd7 100644
--- a/usr.sbin/xntpd/include/parse_conf.h
+++ b/usr.sbin/xntpd/include/parse_conf.h
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/include/parse_conf.h,v 3.5 1994/01/25 19:04:23 kardel Exp
+ * /src/NTP/REPOSITORY/v3/include/parse_conf.h,v 3.6 1994/05/30 10:19:49 kardel Exp
*
- * parse_conf.h,v 3.5 1994/01/25 19:04:23 kardel Exp
+ * parse_conf.h,v 3.6 1994/05/30 10:19:49 kardel Exp
*
* Copyright (c) 1993,1994
* Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
@@ -15,7 +15,7 @@
#ifndef __PARSE_CONF_H__
#define __PARSE_CONF_H__
#if !(defined(lint) || defined(__GNUC__))
- static char dcfhrcsid[]="parse_conf.h,v 3.5 1994/01/25 19:04:23 kardel Exp FAU";
+ static char dcfhrcsid[]="parse_conf.h,v 3.6 1994/05/30 10:19:49 kardel Exp FAU";
#endif
/*
@@ -49,6 +49,6 @@ struct format
char length; /* length of field */
} field_offsets[O_COUNT];
char *fixed_string; /* string with must be chars (blanks = wildcards) */
- unsigned LONG flags;
+ u_long flags;
};
#endif
diff --git a/usr.sbin/xntpd/include/sys/bsd_audioirig.h b/usr.sbin/xntpd/include/sys/bsd_audioirig.h
index 1daeec700b42..6a23260b8147 100644
--- a/usr.sbin/xntpd/include/sys/bsd_audioirig.h
+++ b/usr.sbin/xntpd/include/sys/bsd_audioirig.h
@@ -13,14 +13,14 @@
/*
* irig ioctls
*/
-#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__)
-#define AUDIO_IRIG_OPEN _IO(A, 50)
-#define AUDIO_IRIG_CLOSE _IO(A, 51)
-#define AUDIO_IRIG_SETFORMAT _IOWR(A, 52, int)
-#else
+#if defined(__STDC__) || !(defined(ibm032) && !defined(__GNUC))
#define AUDIO_IRIG_OPEN _IO('A', 50)
#define AUDIO_IRIG_CLOSE _IO('A', 51)
#define AUDIO_IRIG_SETFORMAT _IOWR('A', 52, int)
+#else
+#define AUDIO_IRIG_OPEN _IO(A, 50)
+#define AUDIO_IRIG_CLOSE _IO(A, 51)
+#define AUDIO_IRIG_SETFORMAT _IOWR(A, 52, int)
#endif
/*
diff --git a/usr.sbin/xntpd/include/sys/chudefs.h b/usr.sbin/xntpd/include/sys/chudefs.h
index 50f82527f468..f5549f58b828 100644
--- a/usr.sbin/xntpd/include/sys/chudefs.h
+++ b/usr.sbin/xntpd/include/sys/chudefs.h
@@ -1,4 +1,4 @@
-/* chudefs.h,v 3.1 1993/07/06 01:07:11 jbj Exp
+/*
* Definitions for the CHU line discipline v2.0
*/
diff --git a/usr.sbin/xntpd/include/sys/clkdefs.h b/usr.sbin/xntpd/include/sys/clkdefs.h
index b2596e110514..afbc77a8f1ac 100644
--- a/usr.sbin/xntpd/include/sys/clkdefs.h
+++ b/usr.sbin/xntpd/include/sys/clkdefs.h
@@ -1,8 +1,12 @@
-/* clkdefs.h,v 3.1 1993/07/06 01:07:12 jbj Exp
+/*
* Defines for the "clk" timestamping STREAMS module
*/
+#if defined(sun)
#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
/*
* First, we need to define the maximum size of the set of
@@ -10,6 +14,9 @@
*/
#define CLK_MAXSTRSIZE 32
+struct clk_tstamp_charset { /* XXX to use _IOW not _IOWN */
+ char val[CLK_MAXSTRSIZE];
+};
/*
* ioctl(fd, CLK_SETSTR, (char*)c );
@@ -23,9 +30,9 @@
* change this file.
*/
-#if __STDC__
-#define CLK_SETSTR _IOWN('K',01,CLK_MAXSTRSIZE)
+#if defined(__STDC__) /* XXX avoid __STDC__=0 on SOLARIS */
+#define CLK_SETSTR _IOW('K', 01, struct clk_tstamp_charset)
#else
-#define CLK_SETSTR _IOWN(K,01,CLK_MAXSTRSIZE)
+#define CLK_SETSTR _IOW(K, 01, struct clk_tstamp_charset)
#endif
diff --git a/usr.sbin/xntpd/include/sys/parsestreams.h b/usr.sbin/xntpd/include/sys/parsestreams.h
index d07e75cbf26f..7c054afbace6 100644
--- a/usr.sbin/xntpd/include/sys/parsestreams.h
+++ b/usr.sbin/xntpd/include/sys/parsestreams.h
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/include/sys/parsestreams.h,v 3.11 1994/01/25 19:04:30 kardel Exp
+ * /src/NTP/REPOSITORY/v3/include/sys/parsestreams.h,v 3.12 1994/06/01 08:21:08 kardel Exp
*
- * parsestreams.h,v 3.11 1994/01/25 19:04:30 kardel Exp
+ * parsestreams.h,v 3.12 1994/06/01 08:21:08 kardel Exp
*
* Copyright (c) 1989,1990,1991,1992,1993,1994
* Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
@@ -13,7 +13,7 @@
*/
#if !(defined(lint) || defined(__GNUC__))
- static char parse77hrcsid[]="parsestreams.h,v 3.11 1994/01/25 19:04:30 kardel Exp";
+ static char parse77hrcsid[]="parsestreams.h,v 3.12 1994/06/01 08:21:08 kardel Exp";
#endif
#undef PARSEKERNEL
@@ -42,7 +42,7 @@ typedef struct parsestream parsestream_t;
/*--------------- debugging support ---------------------------------*/
-#ifdef DEBUG_DCF
+#ifdef DEBUG_PARSE
extern int parsedebug;
diff --git a/usr.sbin/xntpd/include/sys/ppsclock.h b/usr.sbin/xntpd/include/sys/ppsclock.h
index 952a57bff1e1..edf28aa2e1e8 100644
--- a/usr.sbin/xntpd/include/sys/ppsclock.h
+++ b/usr.sbin/xntpd/include/sys/ppsclock.h
@@ -1,4 +1,3 @@
-/* ppsclock.h,v 3.1 1993/07/06 01:07:14 jbj Exp */
/*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66.
diff --git a/usr.sbin/xntpd/include/sys/timex.h b/usr.sbin/xntpd/include/sys/timex.h
new file mode 100644
index 000000000000..bc2d6349f46b
--- /dev/null
+++ b/usr.sbin/xntpd/include/sys/timex.h
@@ -0,0 +1,290 @@
+/******************************************************************************
+ * *
+ * 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 *
+ * that the above copyright notice appears in all copies and that both the *
+ * copyright notice and this permission notice appear in supporting *
+ * documentation, and that the name University of Delaware not be used in *
+ * advertising or publicity pertaining to distribution of the software *
+ * without specific, written prior permission. The University of Delaware *
+ * makes no representations about the suitability this software for any *
+ * purpose. It is provided "as is" without express or implied warranty. *
+ * *
+ ******************************************************************************/
+
+/*
+ * 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.
+ *
+ * 17 Sep 93 David L. Mills
+ * Created file
+ */
+/*
+ * This header file defines the Network Time Protocol (NTP) interfaces
+ * for user and daemon application programs. These are implemented using
+ * private syscalls and data structures and require specific kernel
+ * support.
+ *
+ * NAME
+ * ntp_gettime - NTP user application interface
+ *
+ * SYNOPSIS
+ * #include <sys/timex.h>
+ *
+ * int syscall(SYS_ntp_gettime, tptr)
+ *
+ * int SYS_ntp_gettime defined in syscall.h header file
+ * struct ntptimeval *tptr pointer to ntptimeval structure
+ *
+ * NAME
+ * ntp_adjtime - NTP daemon application interface
+ *
+ * SYNOPSIS
+ * #include <sys/timex.h>
+ *
+ * int syscall(SYS_ntp_adjtime, mode, tptr)
+ *
+ * int SYS_ntp_adjtime defined in syscall.h header file
+ * struct timex *tptr pointer to timex structure
+ *
+ */
+#ifndef _SYS_TIMEX_H_
+#define _SYS_TIMEX_H_ 1
+
+#ifndef MSDOS /* Microsoft specific */
+#include <sys/syscall.h>
+#endif /* MSDOS */
+
+/*
+ * 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.
+ */
+#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) */
+
+/*
+ * 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 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 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 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 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 following defines and structures define the user interface for
+ * the ntp_gettime() and ntp_adjtime() system calls.
+ *
+ * Control mode codes (timex.modes)
+ */
+#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 */
+
+/*
+ * Status codes (timex.status)
+ */
+#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 states (time_state)
+ */
+#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_WAIT 4 /* leap second has occured */
+#define TIME_ERROR 5 /* clock not synchronized */
+
+/*
+ * 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 (ro) */
+ long maxerror; /* maximum error (us) (ro) */
+ long esterror; /* estimated error (us) (ro) */
+};
+
+/*
+ * NTP daemon interface - (ntp_adjtime()) used to discipline CPU clock
+ * oscillator
+ */
+struct timex {
+ 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) */
+
+};
+#ifdef __FreeBSD__
+
+#ifndef KERNEL
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int ntp_gettime __P((struct ntptimeval *));
+extern int ntp_adjtime __P((struct timex *));
+__END_DECLS
+
+#endif /* not KERNEL */
+
+#endif /* __FreeBSD__ */
+#endif /* _SYS_TIMEX_H_ */
diff --git a/usr.sbin/xntpd/include/sys/tpro.h b/usr.sbin/xntpd/include/sys/tpro.h
index 1cdaf9c8e610..f276f81bead0 100644
--- a/usr.sbin/xntpd/include/sys/tpro.h
+++ b/usr.sbin/xntpd/include/sys/tpro.h
@@ -1,4 +1,4 @@
-/* tpro.h,v 3.1 1993/07/06 01:07:07 jbj Exp
+/*
* Structure for the KSI/Odetics TPRO-S data returned in reponse to a
* read() call. Note that these are driver-specific and not dependent on
* 32/64-bit architecture.
diff --git a/usr.sbin/xntpd/kernel/Makefile.tmpl b/usr.sbin/xntpd/kernel/Makefile.tmpl
index c40f810d5e65..8b40f4a92e05 100644
--- a/usr.sbin/xntpd/kernel/Makefile.tmpl
+++ b/usr.sbin/xntpd/kernel/Makefile.tmpl
@@ -13,9 +13,10 @@ CLOCKDEFS=
DEFS=
DEFS_OPT=
DEFS_LOCAL=
-#
+CLK_VDOBJS=clkinit.o tty_clk_STREAMS.o
+CHU_VDOBJS=chuinit.o tty_chu_STREAMS.o
INCL=-I../include
-CFLAGS= $(COPTS) $(DEFS) $(DEFS_LOCAL) $(INCL)
+CFLAGS= $(COPTS) $(DEFS) $(DEFS_LOCAL) $(INCL) -DKERNEL
CC= $(COMPILER)
#
@@ -30,6 +31,26 @@ all:
print "### The parse refclock implementation has their own support in"; \
print "### parse/*."; } }'
+loadable: clk.o chu.o
+
+clk.o: ${CLK_VDOBJS}
+ ld -r ${OBJS} -o clk.o
+
+clk.h:
+ echo "#define NCLK 2" > clk.h
+
+tty_clk_STREAMS.o: clk.h tty_clk_STREAMS.c
+ cc ${CFLAGS} tty_clk_STREAMS.c -c tty_clk_STREAMS.o
+
+chu.o: ${CHU_VDOBJS}
+ ld -r ${OBJS} -o chu.o
+
+chu.h:
+ echo "#define NCHU 2" > chu.h
+
+tty_chu_STREAMS.o: chu.h tty_chu_STREAMS.c
+ cc ${CFLAGS} tty_chu_STREAMS.c -c tty_chu_STREAMS.o
+
clean:
-@rm -f *~ *.o *.out *.ln make.log Makefile.bak \
lintlib.errs lint.errs
diff --git a/usr.sbin/xntpd/kernel/chuinit.c b/usr.sbin/xntpd/kernel/chuinit.c
new file mode 100644
index 000000000000..5fd96fdfee0b
--- /dev/null
+++ b/usr.sbin/xntpd/kernel/chuinit.c
@@ -0,0 +1,76 @@
+/*
+** dynamically loadable chu driver
+**
+** $Header: /usr/src/etc/xntp3.3ww/kernel/RCS/chuinit.c,v 1.1 1994/06/15 22:14:38 rob Exp $
+**
+** william robertson <rob@agate.berkeley.edu>
+*/
+
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/stream.h>
+#include <sys/syslog.h>
+
+#include <sun/openprom.h>
+#include <sun/vddrv.h>
+
+extern int findmod(); /* os/str_io.c */
+
+extern struct streamtab chuinfo;
+
+struct vdldrv vd = {
+ VDMAGIC_USER,
+ "chu"
+ };
+
+
+int
+xxxinit(function_code, vdp, vdi, vds)
+unsigned int function_code;
+struct vddrv *vdp;
+addr_t vdi;
+struct vdstat *vds;
+{
+ register int i = 0;
+ register int j;
+
+ switch (function_code) {
+ case VDLOAD:
+
+ if (findmod("chu") >= 0) {
+ log(LOG_ERR, "chu stream module already loaded\n");
+ return (EADDRINUSE);
+ }
+
+ i = findmod("\0");
+
+ if (i == -1 || fmodsw[i].f_name[0] != '\0')
+ return(-1);
+
+ for (j = 0; vd.Drv_name[j] != '\0'; j++) /* XXX check bounds */
+ fmodsw[i].f_name[j] = vd.Drv_name[j];
+
+ fmodsw[i].f_name[j] = '\0';
+ fmodsw[i].f_str = &chuinfo;
+
+ vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+
+ return(0);
+
+ case VDUNLOAD:
+ if ((i = findmod(vd.Drv_name)) == -1)
+ return(-1);
+
+ fmodsw[i].f_name[0] = '\0';
+ fmodsw[i].f_str = 0;
+
+ return(0);
+
+ case VDSTAT:
+ return(0);
+
+ default:
+ return(EIO);
+ }
+}
diff --git a/usr.sbin/xntpd/kernel/clkinit.c b/usr.sbin/xntpd/kernel/clkinit.c
new file mode 100644
index 000000000000..e15b114cf00f
--- /dev/null
+++ b/usr.sbin/xntpd/kernel/clkinit.c
@@ -0,0 +1,76 @@
+/*
+** dynamically loadable clk driver
+**
+** $Header: /usr/src/etc/xntp3.3ww/kernel/RCS/clkinit.c,v 1.1 1994/06/15 22:14:38 rob Exp $
+**
+** william robertson <rob@agate.berkeley.edu>
+*/
+
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/stream.h>
+#include <sys/syslog.h>
+
+#include <sun/openprom.h>
+#include <sun/vddrv.h>
+
+extern int findmod(); /* os/str_io.c */
+
+extern struct streamtab clkinfo;
+
+struct vdldrv vd = {
+ VDMAGIC_USER,
+ "clk"
+ };
+
+
+int
+xxxinit(function_code, vdp, vdi, vds)
+unsigned int function_code;
+struct vddrv *vdp;
+addr_t vdi;
+struct vdstat *vds;
+{
+ register int i = 0;
+ register int j;
+
+ switch (function_code) {
+ case VDLOAD:
+
+ if (findmod("clk") >= 0) {
+ log(LOG_ERR, "clk stream module already loaded\n");
+ return (EADDRINUSE);
+ }
+
+ i = findmod("\0");
+
+ if (i == -1 || fmodsw[i].f_name[0] != '\0')
+ return(-1);
+
+ for (j = 0; vd.Drv_name[j] != '\0'; j++) /* XXX check bounds */
+ fmodsw[i].f_name[j] = vd.Drv_name[j];
+
+ fmodsw[i].f_name[j] = '\0';
+ fmodsw[i].f_str = &clkinfo;
+
+ vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+
+ return(0);
+
+ case VDUNLOAD:
+ if ((i = findmod(vd.Drv_name)) == -1)
+ return(-1);
+
+ fmodsw[i].f_name[0] = '\0';
+ fmodsw[i].f_str = 0;
+
+ return(0);
+
+ case VDSTAT:
+ return(0);
+
+ default:
+ return(EIO);
+ }
+}
diff --git a/usr.sbin/xntpd/kernel/tty_clk.c b/usr.sbin/xntpd/kernel/tty_clk.c
index d1b4bbef64b4..072061039bf3 100644
--- a/usr.sbin/xntpd/kernel/tty_clk.c
+++ b/usr.sbin/xntpd/kernel/tty_clk.c
@@ -191,6 +191,19 @@ clkinput(c, tp)
if (putc(c, &clk->clkbuf) == -1)
goto flushout;
+#ifdef CLKLDISC
+ /*
+ * STREAMS people started writing timestamps this way.
+ * It's not my fault, I am just going along with the flow...
+ */
+ for (i = 0; i < sizeof(struct timeval); i++)
+ if (putc(*( ((char*)&tv) + i ), &clk->clkbuf) == -1)
+ goto flushout;
+#else
+ /*
+ * This is a machine independant way of puting longs into
+ * the datastream. It has fallen into disuse...
+ */
s = tv.tv_sec;
for (i = 0; i < sizeof(long); i++) {
if (putc((s >> 24) & 0xff, &clk->clkbuf) == -1)
@@ -204,6 +217,7 @@ clkinput(c, tp)
goto flushout;
s <<= 8;
}
+#endif
/*
* If the length of the rawq exceeds our sanity limit, dump
diff --git a/usr.sbin/xntpd/kernel/tty_clk_STREAMS.c b/usr.sbin/xntpd/kernel/tty_clk_STREAMS.c
index a69a7573be45..13b0a25f1d89 100644
--- a/usr.sbin/xntpd/kernel/tty_clk_STREAMS.c
+++ b/usr.sbin/xntpd/kernel/tty_clk_STREAMS.c
@@ -38,6 +38,7 @@
#include <sys/kernel.h>
#include <sys/user.h>
#include <sys/errno.h>
+#include <sys/syslog.h>
#include <sys/clkdefs.h>
diff --git a/usr.sbin/xntpd/lib/Makefile.tmpl b/usr.sbin/xntpd/lib/Makefile.tmpl
index 997aa8cbe04b..1a8d020bd886 100644
--- a/usr.sbin/xntpd/lib/Makefile.tmpl
+++ b/usr.sbin/xntpd/lib/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:07:38 jbj Exp
+# Makefile.tmpl
#
LIBNAME= libntp
#
diff --git a/usr.sbin/xntpd/lib/a_md512crypt.c b/usr.sbin/xntpd/lib/a_md512crypt.c
index 6033dedcff44..e3705c0483ea 100644
--- a/usr.sbin/xntpd/lib/a_md512crypt.c
+++ b/usr.sbin/xntpd/lib/a_md512crypt.c
@@ -1,4 +1,4 @@
-/* authmd512crypt.c,v 3.1 1993/07/06 01:07:52 jbj Exp
+/*
* md5crypt - MD5 based authentication routines
*/
@@ -7,7 +7,7 @@
#include "md5.h"
#include "ntp_stdlib.h"
-extern U_LONG cache_keyid;
+extern u_long cache_keyid;
extern char *cache_key;
extern int cache_keylen;
@@ -17,7 +17,6 @@ extern int cache_keylen;
extern U_LONG authencryptions;
extern U_LONG authdecryptions;
extern U_LONG authkeyuncached;
-extern U_LONG authdecryptok;
extern U_LONG authnokey;
/*
@@ -41,7 +40,7 @@ static MD5_CTX ctx;
void
MD5auth1crypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* length of all encrypted data */
{
@@ -67,7 +66,7 @@ MD5auth1crypt(keyno, pkt, length)
*/
int
MD5auth2crypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* total length of encrypted area */
{
diff --git a/usr.sbin/xntpd/lib/a_md5decrypt.c b/usr.sbin/xntpd/lib/a_md5decrypt.c
index dc7acf6e44bb..bde17c0dbfc9 100644
--- a/usr.sbin/xntpd/lib/a_md5decrypt.c
+++ b/usr.sbin/xntpd/lib/a_md5decrypt.c
@@ -1,4 +1,4 @@
-/* authmd5decrypt.c,v 3.1 1993/07/06 01:07:53 jbj Exp
+/*
* md5crypt - MD5 based authentication routines
*/
@@ -7,7 +7,7 @@
#include "md5.h"
#include "ntp_stdlib.h"
-extern U_LONG cache_keyid;
+extern u_long cache_keyid;
extern char *cache_key;
extern int cache_keylen;
@@ -17,7 +17,6 @@ extern int cache_keylen;
extern U_LONG authencryptions;
extern U_LONG authdecryptions;
extern U_LONG authkeyuncached;
-extern U_LONG authdecryptok;
extern U_LONG authnokey;
/*
@@ -35,7 +34,7 @@ extern U_LONG authnokey;
int
MD5authdecrypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
const U_LONG *pkt;
int length; /* length of variable data in octets */
{
diff --git a/usr.sbin/xntpd/lib/a_md5encrypt.c b/usr.sbin/xntpd/lib/a_md5encrypt.c
index 2ae625810339..0d816dc20976 100644
--- a/usr.sbin/xntpd/lib/a_md5encrypt.c
+++ b/usr.sbin/xntpd/lib/a_md5encrypt.c
@@ -1,4 +1,4 @@
-/* authmd5encrypt.c,v 3.1 1993/07/06 01:07:54 jbj Exp
+/*
* md5crypt - MD5 based authentication routines
*/
@@ -7,7 +7,7 @@
#include "md5.h"
#include "ntp_stdlib.h"
-extern U_LONG cache_keyid;
+extern u_long cache_keyid;
extern char *cache_key;
extern int cache_keylen;
@@ -17,7 +17,6 @@ extern int cache_keylen;
extern U_LONG authencryptions;
extern U_LONG authdecryptions;
extern U_LONG authkeyuncached;
-extern U_LONG authdecryptok;
extern U_LONG authnokey;
/*
@@ -36,7 +35,7 @@ extern U_LONG authnokey;
int
MD5authencrypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* length of encrypted portion of packet */
{
diff --git a/usr.sbin/xntpd/lib/atoint.c b/usr.sbin/xntpd/lib/atoint.c
index 0e8ea8f6fc18..33b5c5d5bc31 100644
--- a/usr.sbin/xntpd/lib/atoint.c
+++ b/usr.sbin/xntpd/lib/atoint.c
@@ -1,4 +1,4 @@
-/* atoint.c,v 3.1 1993/07/06 01:07:39 jbj Exp
+/*
* atoint - convert an ascii string to a signed long, with error checking
*/
#include <sys/types.h>
@@ -9,9 +9,9 @@
int
atoint(str, ival)
const char *str;
- LONG *ival;
+ long *ival;
{
- register U_LONG u;
+ register long u;
register const char *cp;
register int isneg;
register int oflow_digit;
@@ -41,8 +41,8 @@ atoint(str, ival)
}
if (isneg)
- *ival = -((LONG)u);
+ *ival = -u;
else
- *ival = (LONG)u;
+ *ival = u;
return 1;
}
diff --git a/usr.sbin/xntpd/lib/atolfp.c b/usr.sbin/xntpd/lib/atolfp.c
index 9e2d88301471..649303e3caa6 100644
--- a/usr.sbin/xntpd/lib/atolfp.c
+++ b/usr.sbin/xntpd/lib/atolfp.c
@@ -1,4 +1,4 @@
-/* atolfp.c,v 3.1 1993/07/06 01:07:40 jbj Exp
+/*
* atolfp - convert an ascii string to an l_fp number
*/
#include <stdio.h>
@@ -10,7 +10,7 @@
/*
* Powers of 10
*/
-static U_LONG ten_to_the_n[10] = {
+static u_long ten_to_the_n[10] = {
0,
10,
100,
@@ -30,8 +30,8 @@ atolfp(str, lfp)
l_fp *lfp;
{
register const char *cp;
- register U_LONG dec_i;
- register U_LONG dec_f;
+ register u_long dec_i;
+ register u_long dec_f;
char *ind;
int ndec;
int isneg;
@@ -87,9 +87,9 @@ atolfp(str, lfp)
}
if (ndec > 0) {
- register U_LONG tmp;
- register U_LONG bit;
- register U_LONG ten_fact;
+ register u_long tmp;
+ register u_long bit;
+ register u_long ten_fact;
ten_fact = ten_to_the_n[ndec];
diff --git a/usr.sbin/xntpd/lib/atouint.c b/usr.sbin/xntpd/lib/atouint.c
index b27653f60a21..d826bb4f4d9a 100644
--- a/usr.sbin/xntpd/lib/atouint.c
+++ b/usr.sbin/xntpd/lib/atouint.c
@@ -1,4 +1,4 @@
-/* atouint.c,v 3.1 1993/07/06 01:07:42 jbj Exp
+/*
* atouint - convert an ascii string to an unsigned long, with error checking
*/
#include <sys/types.h>
@@ -9,9 +9,9 @@
int
atouint(str, uval)
const char *str;
- U_LONG *uval;
+ u_long *uval;
{
- register U_LONG u;
+ register u_long u;
register const char *cp;
cp = str;
diff --git a/usr.sbin/xntpd/lib/auth12crypt.c b/usr.sbin/xntpd/lib/auth12crypt.c
index a5d988972757..0e69dbea2b07 100644
--- a/usr.sbin/xntpd/lib/auth12crypt.c
+++ b/usr.sbin/xntpd/lib/auth12crypt.c
@@ -1,4 +1,4 @@
-/* auth12crypt.c,v 3.1 1993/07/06 01:07:43 jbj Exp
+/*
* auth12crypt.c - routines to support two stage NTP encryption
*/
#include "ntp_stdlib.h"
@@ -21,7 +21,7 @@
/*
* Imported from the key data base module
*/
-extern U_LONG cache_keyid; /* cached key ID */
+extern u_long cache_keyid; /* cached key ID */
extern u_char DEScache_ekeys[]; /* cached decryption keys */
extern u_char DESzeroekeys[]; /* zero key decryption keys */
@@ -38,7 +38,7 @@ extern U_LONG authnokey;
*/
void
DESauth1crypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* length of all encrypted data */
{
@@ -91,7 +91,7 @@ DESauth1crypt(keyno, pkt, length)
*/
int
DESauth2crypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* total length of encrypted area */
{
diff --git a/usr.sbin/xntpd/lib/authdecrypt.c b/usr.sbin/xntpd/lib/authdecrypt.c
index 7ff1129a479e..7462941bf662 100644
--- a/usr.sbin/xntpd/lib/authdecrypt.c
+++ b/usr.sbin/xntpd/lib/authdecrypt.c
@@ -1,4 +1,4 @@
-/* authdecrypt.c,v 3.1 1993/07/06 01:07:44 jbj Exp
+/*
* authdecrypt - routine to decrypt a packet to see if this guy knows our key.
*/
#include "ntp_stdlib.h"
@@ -19,7 +19,7 @@
/*
* Imported from the key data base module
*/
-extern U_LONG cache_keyid; /* cached key ID */
+extern u_long cache_keyid; /* cached key ID */
extern u_char DEScache_dkeys[]; /* cached decryption keys */
extern u_char DESzerodkeys[]; /* zero key decryption keys */
@@ -28,11 +28,10 @@ extern u_char DESzerodkeys[]; /* zero key decryption keys */
*/
extern U_LONG authdecryptions;
extern U_LONG authkeyuncached;
-extern U_LONG authdecryptok;
int
DESauthdecrypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
const U_LONG *pkt;
int length; /* length of variable data in octets */
{
@@ -77,9 +76,7 @@ DESauthdecrypt(keyno, pkt, length)
/*
* Success if the encryption data is zero
*/
- if ((work[0] == 0) && (work[1] == 0)) {
- authdecryptok++;
+ if ((work[0] == 0) && (work[1] == 0))
return 1;
- }
return 0;
}
diff --git a/usr.sbin/xntpd/lib/authdes.c b/usr.sbin/xntpd/lib/authdes.c
index 9f64c403c84c..dd122decf6b6 100644
--- a/usr.sbin/xntpd/lib/authdes.c
+++ b/usr.sbin/xntpd/lib/authdes.c
@@ -1,4 +1,4 @@
-/* authdes.c,v 3.1 1993/07/06 01:07:45 jbj Exp
+/*
* authdes.c - an implementation of the DES cipher algorithm for NTP
*/
#include "ntp_stdlib.h"
diff --git a/usr.sbin/xntpd/lib/authdes.c.export b/usr.sbin/xntpd/lib/authdes.c.export
index a63c6d3839c5..cb311f922034 100644
--- a/usr.sbin/xntpd/lib/authdes.c.export
+++ b/usr.sbin/xntpd/lib/authdes.c.export
@@ -1,4 +1,4 @@
-/* authdes.c.export,v 3.1 1993/07/06 01:07:48 jbj Exp
+/*
* authdes.c - dummy encryption routines for destinations outside the USA.
*
* Sorry, folks; I hate this, too. Send me your e-mail address in an
diff --git a/usr.sbin/xntpd/lib/authencrypt.c b/usr.sbin/xntpd/lib/authencrypt.c
index 66b5281b7ae5..eb203e426f64 100644
--- a/usr.sbin/xntpd/lib/authencrypt.c
+++ b/usr.sbin/xntpd/lib/authencrypt.c
@@ -1,4 +1,4 @@
-/* authencrypt.c,v 3.1 1993/07/06 01:07:50 jbj Exp
+/*
* authencrypt - compute and encrypt the mac field in an NTP packet
*/
#include "ntp_stdlib.h"
@@ -19,7 +19,7 @@
/*
* Imported from the key data base module
*/
-extern U_LONG cache_keyid; /* cached key ID */
+extern u_long cache_keyid; /* cached key ID */
extern u_char DEScache_ekeys[]; /* cached decryption keys */
extern u_char DESzeroekeys[]; /* zero key decryption keys */
@@ -32,7 +32,7 @@ extern U_LONG authnokey;
int
DESauthencrypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* length of encrypted portion of packet */
{
diff --git a/usr.sbin/xntpd/lib/authkeys.c b/usr.sbin/xntpd/lib/authkeys.c
index 743af83ba6e1..8e590ceb0945 100644
--- a/usr.sbin/xntpd/lib/authkeys.c
+++ b/usr.sbin/xntpd/lib/authkeys.c
@@ -1,4 +1,4 @@
-/* authkeys.c,v 3.1 1993/07/06 01:07:51 jbj Exp
+/*
* authkeys.c - routines to manage the storage of authentication keys
*/
#include <stdio.h>
@@ -21,7 +21,7 @@ struct savekey {
char MD5_key[32];
#endif
} k;
- U_LONG keyid;
+ u_long keyid;
u_short flags;
#ifdef MD5
int keylen;
@@ -57,7 +57,6 @@ U_LONG authkeyuncached;
U_LONG authnokey; /* calls to encrypt with no key */
U_LONG authencryptions;
U_LONG authdecryptions;
-U_LONG authdecryptok;
/*
* Storage for free key structures. We malloc() such things but
@@ -90,7 +89,7 @@ u_char DEScache_dkeys[KEY_SCHED_SIZE];
/*
* The key cache. We cache the last key we looked at here.
*/
-U_LONG cache_keyid;
+u_long cache_keyid;
u_short cache_flags;
#ifdef MD5
@@ -114,7 +113,7 @@ init_auth()
authnumfreekeys = authkeynotfound = authkeylookups = 0;
authnumkeys = authuncached = authkeyuncached = authnokey = 0;
- authencryptions = authdecryptions = authdecryptok = 0;
+ authencryptions = authdecryptions = 0;
#ifdef DES
/*
@@ -133,7 +132,7 @@ init_auth()
*/
struct savekey *
auth_findkey(keyno)
- U_LONG keyno;
+ u_long keyno;
{
register struct savekey *sk;
@@ -152,7 +151,7 @@ auth_findkey(keyno)
*/
int
auth_havekey(keyno)
- U_LONG keyno;
+ u_long keyno;
{
register struct savekey *sk;
@@ -182,7 +181,7 @@ auth_havekey(keyno)
*/
int
authhavekey(keyno)
- U_LONG keyno;
+ u_long keyno;
{
register struct savekey *sk;
@@ -249,7 +248,7 @@ auth_moremem()
*/
void
authtrust(keyno, trust)
- U_LONG keyno;
+ u_long keyno;
int trust;
{
register struct savekey *sk;
@@ -316,7 +315,7 @@ authtrust(keyno, trust)
*/
int
authistrusted(keyno)
- U_LONG keyno;
+ u_long keyno;
{
register struct savekey *sk;
@@ -345,7 +344,7 @@ authistrusted(keyno)
*/
void
DESauth_setkey(keyno, key)
- U_LONG keyno;
+ u_long keyno;
const U_LONG *key;
{
register struct savekey *sk;
@@ -393,7 +392,7 @@ DESauth_setkey(keyno, key)
#ifdef MD5
void
MD5auth_setkey(keyno, key)
- U_LONG keyno;
+ u_long keyno;
const U_LONG *key;
{
register struct savekey *sk;
@@ -487,7 +486,7 @@ auth_delkeys()
*/
void
auth1crypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* length of all encrypted data */
{
@@ -520,7 +519,7 @@ auth1crypt(keyno, pkt, length)
*/
int
auth2crypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* total length of encrypted area */
{
@@ -547,7 +546,7 @@ auth2crypt(keyno, pkt, length)
int
authencrypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* length of encrypted portion of packet */
{
@@ -576,7 +575,7 @@ authencrypt(keyno, pkt, length)
int
authdecrypt(keyno, pkt, length)
- U_LONG keyno;
+ u_long keyno;
U_LONG *pkt;
int length; /* length of variable data in octets */
{
diff --git a/usr.sbin/xntpd/lib/authparity.c b/usr.sbin/xntpd/lib/authparity.c
index 33562cb4b12a..a5b59e3eddb7 100644
--- a/usr.sbin/xntpd/lib/authparity.c
+++ b/usr.sbin/xntpd/lib/authparity.c
@@ -1,4 +1,4 @@
-/* authparity.c,v 3.1 1993/07/06 01:07:55 jbj Exp
+/*
* auth_parity - set parity on a key/check for odd parity
*/
#include "ntp_stdlib.h"
diff --git a/usr.sbin/xntpd/lib/authreadkeys.c b/usr.sbin/xntpd/lib/authreadkeys.c
index 5800186dc812..8d2697fa2bab 100644
--- a/usr.sbin/xntpd/lib/authreadkeys.c
+++ b/usr.sbin/xntpd/lib/authreadkeys.c
@@ -1,4 +1,4 @@
-/* authreadkeys.c,v 3.1 1993/07/06 01:07:57 jbj Exp
+/*
* authreadkeys.c - routines to support the reading of the key file
*/
#include <stdio.h>
@@ -80,7 +80,7 @@ authreadkeys(file)
FILE *fp;
char *line;
char *token;
- U_LONG keyno;
+ u_long keyno;
int keytype;
char buf[512]; /* lots of room for line? */
extern FILE * fopen P((const char *filename, const char *type));
@@ -111,7 +111,7 @@ extern int fclose P((FILE *stream));
/*
* First is key number. See if it is okay.
*/
- keyno = (U_LONG)atoi(token);
+ keyno = atoi(token);
if (keyno == 0) {
syslog(LOG_ERR,
"cannot change keyid 0, key entry `%s' ignored",
@@ -125,7 +125,7 @@ extern int fclose P((FILE *stream));
token = nexttok(&line);
if (token == 0) {
syslog(LOG_ERR,
- "no key type for key number %d, entry ignored",
+ "no key type for key number %ld, entry ignored",
keyno);
continue;
}
@@ -150,7 +150,7 @@ extern int fclose P((FILE *stream));
#endif
default:
syslog(LOG_ERR,
- "invalid key type for key number %d, entry ignored",
+ "invalid key type for key number %ld, entry ignored",
keyno);
continue;
}
@@ -161,7 +161,7 @@ extern int fclose P((FILE *stream));
token = nexttok(&line);
if (token == 0) {
syslog(LOG_ERR,
- "no key for number %d entry, entry ignored",
+ "no key for number %ld entry, entry ignored",
keyno);
} else {
switch(keytype) {
@@ -171,7 +171,7 @@ extern int fclose P((FILE *stream));
case KEY_TYPE_ASCII:
if (!authusekey(keyno, keytype, token))
syslog(LOG_ERR,
- "format/parity error for DES key %d, not used",
+ "format/parity error for DES key %ld, not used",
keyno);
break;
#endif
@@ -179,7 +179,7 @@ extern int fclose P((FILE *stream));
case KEY_TYPE_MD5:
if (!authusekey(keyno, keytype, token))
syslog(LOG_ERR,
- "format/parity error for MD5 key %d, not used",
+ "format/parity error for MD5 key %ld, not used",
keyno);
break;
#endif
diff --git a/usr.sbin/xntpd/lib/authusekey.c b/usr.sbin/xntpd/lib/authusekey.c
index c268c4d2455c..20d7f3c3f447 100644
--- a/usr.sbin/xntpd/lib/authusekey.c
+++ b/usr.sbin/xntpd/lib/authusekey.c
@@ -1,4 +1,4 @@
-/* authusekey.c,v 3.1 1993/07/06 01:07:58 jbj Exp
+/*
* authusekey - decode a key from ascii and use it
*/
#include <stdio.h>
@@ -30,7 +30,7 @@
int
authusekey(keyno, keytype, str)
- U_LONG keyno;
+ u_long keyno;
int keytype;
const char *str;
{
diff --git a/usr.sbin/xntpd/lib/buftvtots.c b/usr.sbin/xntpd/lib/buftvtots.c
index d9b484db2df0..7e1ec63a12f1 100644
--- a/usr.sbin/xntpd/lib/buftvtots.c
+++ b/usr.sbin/xntpd/lib/buftvtots.c
@@ -1,4 +1,4 @@
-/* buftvtots.c,v 3.1 1993/07/06 01:07:59 jbj Exp
+/*
* buftvtots - pull a Unix-format (struct timeval) time stamp out of
* an octet stream and convert it to a l_fp time stamp.
* This is useful when using the clock line discipline.
@@ -12,50 +12,50 @@ buftvtots(bufp, ts)
l_fp *ts;
{
register const u_char *bp;
- register U_LONG sec;
- register U_LONG usec;
+ register u_long sec;
+ register u_long usec;
#ifdef XNTP_BIG_ENDIAN
bp = (u_char *)bufp;
- sec = (U_LONG)*bp++ & 0xff;
+ sec = (u_long)*bp++ & 0xff;
sec <<= 8;
- sec += (U_LONG)*bp++ & 0xff;
+ sec += (u_long)*bp++ & 0xff;
sec <<= 8;
- sec += (U_LONG)*bp++ & 0xff;
+ sec += (u_long)*bp++ & 0xff;
sec <<= 8;
- sec += (U_LONG)*bp++ & 0xff;
+ sec += (u_long)*bp++ & 0xff;
- usec = (U_LONG)*bp++ & 0xff;
+ usec = (u_long)*bp++ & 0xff;
usec <<= 8;
- usec += (U_LONG)*bp++ & 0xff;
+ usec += (u_long)*bp++ & 0xff;
usec <<= 8;
- usec += (U_LONG)*bp++ & 0xff;
+ usec += (u_long)*bp++ & 0xff;
usec <<= 8;
- usec += (U_LONG)*bp & 0xff;
+ usec += (u_long)*bp & 0xff;
#else
bp = (u_char *)bufp + 7;
- usec = (U_LONG)*bp-- & 0xff;
+ usec = (u_long)*bp-- & 0xff;
usec <<= 8;
- usec += (U_LONG)*bp-- & 0xff;
+ usec += (u_long)*bp-- & 0xff;
usec <<= 8;
- usec += (U_LONG)*bp-- & 0xff;
+ usec += (u_long)*bp-- & 0xff;
usec <<= 8;
- usec += (U_LONG)*bp-- & 0xff;
+ usec += (u_long)*bp-- & 0xff;
- sec = (U_LONG)*bp-- & 0xff;
+ sec = (u_long)*bp-- & 0xff;
sec <<= 8;
- sec += (U_LONG)*bp-- & 0xff;
+ sec += (u_long)*bp-- & 0xff;
sec <<= 8;
- sec += (U_LONG)*bp-- & 0xff;
+ sec += (u_long)*bp-- & 0xff;
sec <<= 8;
- sec += (U_LONG)*bp & 0xff;
+ sec += (u_long)*bp & 0xff;
#endif
if (usec > 999999)
return 0;
- ts->l_ui = sec + (U_LONG)JAN_1970;
+ ts->l_ui = sec + (u_long)JAN_1970;
TVUTOTSF(usec, ts->l_uf);
return 1;
}
diff --git a/usr.sbin/xntpd/lib/caljulian.c b/usr.sbin/xntpd/lib/caljulian.c
index 92d6d742a63a..070fa0d6f34e 100644
--- a/usr.sbin/xntpd/lib/caljulian.c
+++ b/usr.sbin/xntpd/lib/caljulian.c
@@ -1,4 +1,4 @@
-/* caljulian.c,v 3.1 1993/07/06 01:08:00 jbj Exp
+/*
* caljulian - determine the Julian date from an NTP time.
*/
#include <sys/types.h>
@@ -37,11 +37,11 @@ static u_short caldaytab[YEARSPERCYCLE] = {
void
caljulian(ntptime, jt)
- U_LONG ntptime;
+ u_long ntptime;
register struct calendar *jt;
{
register int i;
- register U_LONG nt;
+ register u_long nt;
register u_short snt;
register int cyear;
diff --git a/usr.sbin/xntpd/lib/calleapwhen.c b/usr.sbin/xntpd/lib/calleapwhen.c
index 379643f09566..83613efc15ff 100644
--- a/usr.sbin/xntpd/lib/calleapwhen.c
+++ b/usr.sbin/xntpd/lib/calleapwhen.c
@@ -1,4 +1,4 @@
-/* calleapwhen.c,v 3.1 1993/07/06 01:08:02 jbj Exp
+/*
* calleapwhen - determine the number of seconds to the next possible
* leap occurance and the last one.
*/
@@ -11,7 +11,7 @@
/*
* calleaptab - leaps occur at the end of December and June
*/
-LONG calleaptab[10] = {
+long calleaptab[10] = {
-(JAN+FEBLEAP)*SECSPERDAY, /* leap previous to cycle */
(MAR+APR+MAY+JUN)*SECSPERDAY, /* end of June */
(MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC)*SECSPERDAY, /* end of Dec */
@@ -27,11 +27,11 @@ LONG calleaptab[10] = {
void
calleapwhen(ntpdate, leaplast, leapnext)
- U_LONG ntpdate;
- U_LONG *leaplast;
- U_LONG *leapnext;
+ u_long ntpdate;
+ u_long *leaplast;
+ u_long *leapnext;
{
- register U_LONG dateincycle;
+ register u_long dateincycle;
register int i;
/*
@@ -50,12 +50,12 @@ calleapwhen(ntpdate, leaplast, leapnext)
* Find where we are with respect to the leap events.
*/
for (i = 1; i < 9; i++)
- if (dateincycle < (U_LONG)calleaptab[i])
+ if (dateincycle < (u_long)calleaptab[i])
break;
/*
* i points at the next leap. Compute the last and the next.
*/
- *leaplast = (U_LONG)((LONG)dateincycle - calleaptab[i-1]);
- *leapnext = (U_LONG)(calleaptab[i] - (LONG)dateincycle);
+ *leaplast = (u_long)((long)dateincycle - calleaptab[i-1]);
+ *leapnext = (u_long)(calleaptab[i] - (long)dateincycle);
}
diff --git a/usr.sbin/xntpd/lib/caltontp.c b/usr.sbin/xntpd/lib/caltontp.c
index f5da0ab761e8..a0c8f610c7de 100644
--- a/usr.sbin/xntpd/lib/caltontp.c
+++ b/usr.sbin/xntpd/lib/caltontp.c
@@ -1,4 +1,4 @@
-/* caltontp.c,v 3.1 1993/07/06 01:08:04 jbj Exp
+/*
* caltontp - convert a julian date to an NTP time
*/
#include <sys/types.h>
@@ -25,13 +25,13 @@ static u_short calmonthtab[12] = {
(MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC+JAN), /* February */
};
-U_LONG
+u_long
caltontp(jt)
register const struct calendar *jt;
{
register int cyear;
register int resyear;
- register U_LONG nt;
+ register u_long nt;
register int yearday;
/*
@@ -77,14 +77,14 @@ caltontp(jt)
}
}
- nt = TIMESDPERC((U_LONG)cyear);
+ nt = TIMESDPERC((u_long)cyear);
while (resyear-- > 0)
nt += DAYSPERYEAR;
- nt += (U_LONG) (yearday - 1);
+ nt += (u_long) (yearday - 1);
- nt = TIMES24(nt) + (U_LONG)jt->hour;
- nt = TIMES60(nt) + (U_LONG)jt->minute;
- nt = TIMES60(nt) + (U_LONG)jt->second;
+ nt = TIMES24(nt) + (u_long)jt->hour;
+ nt = TIMES60(nt) + (u_long)jt->minute;
+ nt = TIMES60(nt) + (u_long)jt->second;
return nt + MAR1900;
}
diff --git a/usr.sbin/xntpd/lib/calyearstart.c b/usr.sbin/xntpd/lib/calyearstart.c
index 1bb3321f7252..015ed933b7fa 100644
--- a/usr.sbin/xntpd/lib/calyearstart.c
+++ b/usr.sbin/xntpd/lib/calyearstart.c
@@ -1,4 +1,4 @@
-/* calyearstart.c,v 3.1 1993/07/06 01:08:06 jbj Exp
+/*
* calyearstart - determine the NTP time at midnight of January 1 in
* the year of the given date.
*/
@@ -11,19 +11,19 @@
/*
* calyeartab - year start offsets from the beginning of a cycle
*/
-U_LONG calyeartab[YEARSPERCYCLE] = {
+u_long calyeartab[YEARSPERCYCLE] = {
(SECSPERLEAPYEAR-JANFEBLEAP),
(SECSPERLEAPYEAR-JANFEBLEAP) + SECSPERYEAR,
(SECSPERLEAPYEAR-JANFEBLEAP) + 2*SECSPERYEAR,
(SECSPERLEAPYEAR-JANFEBLEAP) + 3*SECSPERYEAR
};
-U_LONG
+u_long
calyearstart(dateinyear)
- register U_LONG dateinyear;
+ register u_long dateinyear;
{
- register U_LONG cyclestart;
- register U_LONG nextyear, lastyear;
+ register u_long cyclestart;
+ register u_long nextyear, lastyear;
register int i;
/*
diff --git a/usr.sbin/xntpd/lib/clocktime.c b/usr.sbin/xntpd/lib/clocktime.c
index 36b967e9a16c..0217f2b5c4a6 100644
--- a/usr.sbin/xntpd/lib/clocktime.c
+++ b/usr.sbin/xntpd/lib/clocktime.c
@@ -1,4 +1,4 @@
-/* clocktime.c,v 3.1 1993/07/06 01:08:07 jbj Exp
+/*
* clocktime - compute the NTP date from a day of year, hour, minute
* and second.
*/
@@ -34,21 +34,21 @@ clocktime(yday, hour, minute, second, tzoff, rec_ui, yearstart, ts_ui)
int minute;
int second;
int tzoff;
- U_LONG rec_ui;
- U_LONG *yearstart;
+ u_long rec_ui;
+ u_long *yearstart;
U_LONG *ts_ui;
{
- register LONG tmp;
- register U_LONG date;
- register U_LONG yst;
+ register long tmp;
+ register u_long date;
+ register u_long yst;
/*
* Compute the offset into the year in seconds. Note that
* this could come out to be a negative number.
*/
- tmp = (LONG)(MULBY24((yday-1)) + hour + tzoff);
- tmp = MULBY60(tmp) + (LONG)minute;
- tmp = MULBY60(tmp) + (LONG)second;
+ tmp = (long)(MULBY24((yday-1)) + hour + tzoff);
+ tmp = MULBY60(tmp) + (long)minute;
+ tmp = MULBY60(tmp) + (long)second;
/*
* Initialize yearstart, if necessary.
@@ -66,7 +66,7 @@ clocktime(yday, hour, minute, second, tzoff, rec_ui, yearstart, ts_ui)
* Use the current year start for the first check, this should
* work most of the time.
*/
- date = (U_LONG)(tmp + (LONG)yst);
+ date = (u_long)(tmp + (long)yst);
if (date < (rec_ui + CLOSETIME) &&
date > (rec_ui - CLOSETIME)) {
*ts_ui = date;
@@ -79,7 +79,7 @@ clocktime(yday, hour, minute, second, tzoff, rec_ui, yearstart, ts_ui)
*/
yst = calyearstart(rec_ui);
if (yst != *yearstart) {
- date = (U_LONG)((LONG)yst + tmp);
+ date = (u_long)((long)yst + tmp);
*ts_ui = date;
if (date < (rec_ui + CLOSETIME) &&
date > (rec_ui - CLOSETIME)) {
@@ -98,7 +98,7 @@ clocktime(yday, hour, minute, second, tzoff, rec_ui, yearstart, ts_ui)
if ((rec_ui - yst) < TWODAYS) {
yst = calyearstart(yst - TWODAYS);
if (yst != *yearstart) {
- date = (U_LONG)(tmp + (LONG)yst);
+ date = (u_long)(tmp + (long)yst);
if (date < (rec_ui + CLOSETIME) &&
date > (rec_ui - CLOSETIME)) {
*yearstart = yst;
@@ -115,7 +115,7 @@ clocktime(yday, hour, minute, second, tzoff, rec_ui, yearstart, ts_ui)
*/
yst = calyearstart(rec_ui + TWODAYS);
if (yst != *yearstart) {
- date = (U_LONG)((LONG)yst + tmp);
+ date = (u_long)((long)yst + tmp);
if (date < (rec_ui + CLOSETIME) &&
date > (rec_ui - CLOSETIME)) {
*yearstart = yst;
diff --git a/usr.sbin/xntpd/lib/clocktypes.c b/usr.sbin/xntpd/lib/clocktypes.c
index 816ef0708b3e..38b8cd28a6b2 100644
--- a/usr.sbin/xntpd/lib/clocktypes.c
+++ b/usr.sbin/xntpd/lib/clocktypes.c
@@ -1,4 +1,4 @@
-/* clocktypes.c,v 3.1 1993/07/06 01:08:09 jbj Exp
+/*
* Data for pretty printing clock types
*/
#include <stdio.h>
@@ -9,38 +9,64 @@
#include "ntp_refclock.h"
struct clktype clktypes[] = {
- { REFCLK_NONE, "unspecified type (0)", "UNKNOWN" },
- { REFCLK_LOCALCLOCK, "local clock synchronization (1)", "LOCAL" },
- { 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" },
- { REFCLK_IRIG_AUDIO, "IRIG audio decoder (6)", "IRIG_AUDIO" },
- { REFCLK_CHU, "Direct synced to CHU (7)", "CHU" },
- { REFCLK_PARSE, "Generic reference clock driver (8)", "GENERIC" },
- { REFCLK_GPS_MX4200, "Magnavox MX4200 GPS clock (9)", "GPS_MX4200" },
- { REFCLK_GPS_AS2201, "Austron 2201A GPS clock (10)", "GPS_AS2201" },
- { REFCLK_OMEGA_TRUETIME, "TrueTime OMEGA clock (11)", "OMEGA_TRUE" },
- { REFCLK_IRIG_TPRO, "Odetics/KSI TPRO IRIG decoder (12)", "IRIG_TPRO" },
- { REFCLK_ATOM_LEITCH, "Leitch CSD 5300 controller (13)", "ATOM_LEITCH" },
- { REFCLK_MSF_EES, "MSF EES M201, UK (14)", "MSF_EES" },
- { REFCLK_GPSTM_TRUETIME, "TrueTime GPS/TM-TMD clock (15)", "GPS_TRUE" },
+ { REFCLK_NONE, "unspecified type (0)",
+ "UNKNOWN" },
+ { REFCLK_LOCALCLOCK, "Undisciplined local clock (1)",
+ "LOCAL" },
+ { REFCLK_GPS_TRAK, "TRAK 8810 GPS Receiver (2)",
+ "GPS_TRAK" },
+ { REFCLK_WWV_PST, "PSTI/Traconex WWV/WWVH Receiver (3)",
+ "WWV_PST" },
+ { REFCLK_WWVB_SPECTRACOM, "Spectracom WWVB Receiver (4)",
+ "WWVB_SPEC" },
+ { REFCLK_GOES_TRUETIME, "TrueTime GPS/GOES Receivers (5)",
+ "GPS_GOES_TRUE" },
+ { REFCLK_IRIG_AUDIO, "IRIG Audio Decoder (6)",
+ "IRIG_AUDIO" },
+ { REFCLK_CHU, "Scratchbuilt CHU Receiver (7)",
+ "CHU" },
+ { REFCLK_PARSE, "Generic reference clock driver (8)",
+ "GENERIC" },
+ { REFCLK_GPS_MX4200, "Magnavox MX4200 GPS Receiver (9)",
+ "GPS_MX4200" },
+ { REFCLK_GPS_AS2201, "Austron 2201A GPS Receiver (10)",
+ "GPS_AS2201" },
+ { REFCLK_OMEGA_TRUETIME, "TrueTime OM-DC OMEGA Receiver (11)",
+ "OMEGA_TRUE" },
+ { REFCLK_IRIG_TPRO, "KSI/Odetics TPRO/S IRIG Interface (12)",
+ "IRIG_TPRO" },
+ { REFCLK_ATOM_LEITCH, "Leitch CSD 5300 Master Clock Controller (13)",
+ "ATOM_LEITCH" },
+ { REFCLK_MSF_EES, "EES M201 MSF Receiver (14)",
+ "MSF_EES" },
+ { REFCLK_GPSTM_TRUETIME, "TrueTime GPS/TM-TMD Receiver (15)",
+ "GPS_TRUE" },
+ { REFCLK_IRIG_BANCOMM, "Bancomm GPS/IRIG Receiver (16)",
+ "GPS_BANC" },
+ { REFCLK_GPS_DATUM, "Datum Precision Time System (17)",
+ "GPS_DATUM" },
+ { REFCLK_NIST_ACTS, "NIST Automated Computer Time Service (18)",
+ "NIST_ACTS" },
+ { REFCLK_WWV_HEATH, "Heath WWV/WWVH Receiver (19)",
+ "WWV_HEATH" },
+ { REFCLK_GPS_NMEA, "Generic NMEA GPS Receiver (20)",
+ "GPS_NMEA" },
+ { REFCLK_GPS_MOTO, "Motorola Six Gun GPS Receiver (21)",
+ "GPS_MOTO" },
+ { REFCLK_ATOM_PPS, "PPS Clock Discipline (22)",
+ "ATOM_PPS" },
{ -1, "", "" }
};
const char *
clockname(num)
- int num;
+ int num;
{
- register struct clktype *clk;
+ register struct clktype *clk;
- for (clk = clktypes; clk->code != -1; clk++)
- {
- if (num == clk->code)
- {
- return clk->abbrev;
+ for (clk = clktypes; clk->code != -1; clk++) {
+ if (num == clk->code)
+ return (clk->abbrev);
}
- }
-
- return NULL;
+ return (NULL);
}
diff --git a/usr.sbin/xntpd/lib/decodenetnum.c b/usr.sbin/xntpd/lib/decodenetnum.c
index 32320a24b881..65e77619c33d 100644
--- a/usr.sbin/xntpd/lib/decodenetnum.c
+++ b/usr.sbin/xntpd/lib/decodenetnum.c
@@ -1,4 +1,4 @@
-/* decodenetnum.c,v 3.1 1993/07/06 01:08:11 jbj Exp
+/*
* decodenetnum - return a net number (this is crude, but careful)
*/
#include <sys/types.h>
@@ -11,7 +11,7 @@
int
decodenetnum(num, netnum)
const char *num;
- U_LONG *netnum;
+ u_long *netnum;
{
register const char *cp;
register char *bp;
diff --git a/usr.sbin/xntpd/lib/dofptoa.c b/usr.sbin/xntpd/lib/dofptoa.c
index a496df85dd5b..31673fbbbc59 100644
--- a/usr.sbin/xntpd/lib/dofptoa.c
+++ b/usr.sbin/xntpd/lib/dofptoa.c
@@ -1,4 +1,4 @@
-/* dofptoa.c,v 3.1 1993/07/06 01:08:12 jbj Exp
+/*
* dofptoa - do the grunge work to convert an fp number to ascii
*/
#include <stdio.h>
@@ -16,7 +16,7 @@ dofptoa(fpv, neg, ndec, msec)
int msec;
{
register u_char *cp, *cpend;
- register U_LONG val;
+ register u_long val;
register short dec;
u_char cbuf[12];
u_char *cpdec;
diff --git a/usr.sbin/xntpd/lib/dolfptoa.c b/usr.sbin/xntpd/lib/dolfptoa.c
index ff37c9f1e1e6..a79d8c669577 100644
--- a/usr.sbin/xntpd/lib/dolfptoa.c
+++ b/usr.sbin/xntpd/lib/dolfptoa.c
@@ -1,4 +1,4 @@
-/* dolfptoa.c,v 3.1 1993/07/06 01:08:14 jbj Exp
+/*
* dolfptoa - do the grunge work of converting an l_fp number to decimal
*/
#include <stdio.h>
@@ -10,14 +10,14 @@
char *
dolfptoa(fpi, fpv, neg, ndec, msec)
- U_LONG fpi;
- U_LONG fpv;
+ u_long fpi;
+ u_long fpv;
int neg;
int ndec;
int msec;
{
register u_char *cp, *cpend;
- register U_LONG work_i;
+ register u_long lwork;
register int dec;
u_char cbuf[24];
u_char *cpdec;
@@ -39,22 +39,22 @@ dolfptoa(fpi, fpv, neg, ndec, msec)
* compiles fairly well for a 68000.
*/
cp = cpend = &cbuf[10];
- work_i = fpi;
- if (work_i & 0xffff0000) {
- register U_LONG lten = 10;
- register U_LONG ltmp;
+ lwork = fpi;
+ if (lwork & 0xffff0000) {
+ register u_long lten = 10;
+ register u_long ltmp;
do {
- ltmp = work_i;
- work_i /= lten;
- ltmp -= (work_i<<3) + (work_i<<1);
+ ltmp = lwork;
+ lwork /= lten;
+ ltmp -= (lwork << 3) + (lwork << 1);
*--cp = (u_char)ltmp;
- } while (work_i & 0xffff0000);
+ } while (lwork & 0xffff0000);
}
- if (work_i != 0) {
+ if (lwork != 0) {
register u_short sten = 10;
register u_short stmp;
- register u_short swork = (u_short)work_i;
+ register u_short swork = (u_short)lwork;
do {
stmp = swork;
@@ -86,12 +86,12 @@ dolfptoa(fpi, fpv, neg, ndec, msec)
* If there's a fraction to deal with, do so.
*/
if (fpv != 0) {
- register U_LONG work_f;
+ l_fp work;
- work_f = fpv;
+ work.l_ui = 0;
+ work.l_uf = fpv;
while (dec > 0) {
- register U_LONG tmp_i;
- register U_LONG tmp_f;
+ l_fp ftmp;
dec--;
/*
@@ -100,22 +100,21 @@ dolfptoa(fpi, fpv, neg, ndec, msec)
* a junk of BCD into the units part.
* record that and iterate.
*/
- work_i = 0;
- M_LSHIFT(work_i, work_f);
- tmp_i = work_i;
- tmp_f = work_f;
- M_LSHIFT(work_i, work_f);
- M_LSHIFT(work_i, work_f);
- M_ADD(work_i, work_f, tmp_i, tmp_f);
- *cpend++ = (u_char)work_i;
- if (work_f == 0)
+ work.l_ui = 0;
+ L_LSHIFT(&work);
+ ftmp = work;
+ L_LSHIFT(&work);
+ L_LSHIFT(&work);
+ L_ADD(&work, &ftmp);
+ *cpend++ = (u_char)work.l_ui;
+ if (work.l_uf == 0)
break;
}
/*
* Rounding is rotten
*/
- if (work_f & 0x80000000) {
+ if (work.l_uf & 0x80000000) {
register u_char *tp = cpend;
*(--tp) += 1;
diff --git a/usr.sbin/xntpd/lib/emalloc.c b/usr.sbin/xntpd/lib/emalloc.c
index d2a8e789f012..61d4cb6a9786 100644
--- a/usr.sbin/xntpd/lib/emalloc.c
+++ b/usr.sbin/xntpd/lib/emalloc.c
@@ -1,4 +1,4 @@
-/* emalloc.c,v 3.1 1993/07/06 01:08:15 jbj Exp
+/*
* emalloc - return new memory obtained from the system. Belch if none.
*/
#include "ntp_types.h"
@@ -8,7 +8,7 @@
char *
emalloc(size)
- unsigned int size;
+ u_int size;
{
char *mem;
diff --git a/usr.sbin/xntpd/lib/fptoa.c b/usr.sbin/xntpd/lib/fptoa.c
index d245e9fa6917..b0d7a1484ebb 100644
--- a/usr.sbin/xntpd/lib/fptoa.c
+++ b/usr.sbin/xntpd/lib/fptoa.c
@@ -1,4 +1,4 @@
-/* fptoa.c,v 3.1 1993/07/06 01:08:16 jbj Exp
+/*
* fptoa - return an asciized representation of an s_fp number
*/
#include "ntp_fp.h"
diff --git a/usr.sbin/xntpd/lib/fptoms.c b/usr.sbin/xntpd/lib/fptoms.c
index fb850c5362c2..f8ae6ba64e33 100644
--- a/usr.sbin/xntpd/lib/fptoms.c
+++ b/usr.sbin/xntpd/lib/fptoms.c
@@ -1,4 +1,4 @@
-/* fptoms.c,v 3.1 1993/07/06 01:08:17 jbj Exp
+/*
* fptoms - return an asciized s_fp number in milliseconds
*/
#include "ntp_fp.h"
diff --git a/usr.sbin/xntpd/lib/getopt.c b/usr.sbin/xntpd/lib/getopt.c
index 5519235180fa..8505d808d430 100644
--- a/usr.sbin/xntpd/lib/getopt.c
+++ b/usr.sbin/xntpd/lib/getopt.c
@@ -1,4 +1,4 @@
-/* getopt.c,v 3.1 1993/07/06 01:08:18 jbj Exp
+/*
* getopt - get option letter from argv
*
* This is a version of the public domain getopt() implementation by
diff --git a/usr.sbin/xntpd/lib/gettstamp.c b/usr.sbin/xntpd/lib/gettstamp.c
index 19bcb0c638ff..53b124a80ee1 100644
--- a/usr.sbin/xntpd/lib/gettstamp.c
+++ b/usr.sbin/xntpd/lib/gettstamp.c
@@ -1,4 +1,4 @@
-/* gettstamp.c,v 3.1 1993/07/06 01:08:20 jbj Exp
+/*
* gettstamp - return the system time in timestamp format
*/
#include <stdio.h>
diff --git a/usr.sbin/xntpd/lib/hextoint.c b/usr.sbin/xntpd/lib/hextoint.c
index 90329c4136f4..23f8c08464f8 100644
--- a/usr.sbin/xntpd/lib/hextoint.c
+++ b/usr.sbin/xntpd/lib/hextoint.c
@@ -1,4 +1,4 @@
-/* hextoint.c,v 3.1 1993/07/06 01:08:21 jbj Exp
+/*
* hextoint - convert an ascii string in hex to an unsigned
* long, with error checking
*/
@@ -9,9 +9,9 @@
int
hextoint(str, ival)
const char *str;
- U_LONG *ival;
+ u_long *ival;
{
- register U_LONG u;
+ register u_long u;
register const char *cp;
cp = str;
diff --git a/usr.sbin/xntpd/lib/hextolfp.c b/usr.sbin/xntpd/lib/hextolfp.c
index 6473c7c3dbca..d9291cc994a4 100644
--- a/usr.sbin/xntpd/lib/hextolfp.c
+++ b/usr.sbin/xntpd/lib/hextolfp.c
@@ -1,4 +1,4 @@
-/* hextolfp.c,v 3.1 1993/07/06 01:08:22 jbj Exp
+/*
* hextolfp - convert an ascii hex string to an l_fp number
*/
#include <stdio.h>
@@ -15,8 +15,8 @@ hextolfp(str, lfp)
{
register const char *cp;
register const char *cpstart;
- register U_LONG dec_i;
- register U_LONG dec_f;
+ register u_long dec_i;
+ register u_long dec_f;
char *ind = NULL;
static char *digits = "0123456789abcdefABCDEF";
diff --git a/usr.sbin/xntpd/lib/humandate.c b/usr.sbin/xntpd/lib/humandate.c
index 464ed6ba4de4..8ea936fa1e46 100644
--- a/usr.sbin/xntpd/lib/humandate.c
+++ b/usr.sbin/xntpd/lib/humandate.c
@@ -1,4 +1,4 @@
-/* humandate.c,v 3.1 1993/07/06 01:08:24 jbj Exp
+/*
* humandate - convert an NTP (or the current) time to something readable
*/
#include <stdio.h>
@@ -22,16 +22,16 @@ static char *days[] = {
char *
humandate(ntptime)
- U_LONG ntptime;
+ u_long ntptime;
{
char *bp;
struct tm *tm;
- U_LONG sec;
+ time_t sec;
LIB_GETBUF(bp);
sec = ntptime - JAN_1970;
- tm = localtime((LONG *)&sec);
+ tm = localtime(&sec);
(void) sprintf(bp, "%s, %s %2d %4d %2d:%02d:%02d",
days[tm->tm_wday], months[tm->tm_mon], tm->tm_mday,
diff --git a/usr.sbin/xntpd/lib/inttoa.c b/usr.sbin/xntpd/lib/inttoa.c
index 25ce26cb8144..ff886f592a84 100644
--- a/usr.sbin/xntpd/lib/inttoa.c
+++ b/usr.sbin/xntpd/lib/inttoa.c
@@ -1,4 +1,4 @@
-/* inttoa.c,v 3.1 1993/07/06 01:08:25 jbj Exp
+/*
* inttoa - return an asciized signed integer
*/
#include <stdio.h>
@@ -8,12 +8,12 @@
char *
inttoa(ival)
- LONG ival;
+ long ival;
{
register char *buf;
LIB_GETBUF(buf);
- (void) sprintf(buf, "%ld", ival);
+ (void) sprintf(buf, "%ld", (long)ival);
return buf;
}
diff --git a/usr.sbin/xntpd/lib/lib_strbuf.c b/usr.sbin/xntpd/lib/lib_strbuf.c
index 15661ab980ad..47df66decd21 100644
--- a/usr.sbin/xntpd/lib/lib_strbuf.c
+++ b/usr.sbin/xntpd/lib/lib_strbuf.c
@@ -1,4 +1,4 @@
-/* lib_strbuf.c,v 3.1 1993/07/06 01:08:27 jbj Exp
+/*
* lib_strbuf - library string storage
*/
diff --git a/usr.sbin/xntpd/lib/lib_strbuf.h b/usr.sbin/xntpd/lib/lib_strbuf.h
index 20720fd5892b..699b9787323b 100644
--- a/usr.sbin/xntpd/lib/lib_strbuf.h
+++ b/usr.sbin/xntpd/lib/lib_strbuf.h
@@ -1,4 +1,4 @@
-/* lib_strbuf.h,v 3.1 1993/07/06 01:08:28 jbj Exp
+/*
* lib_strbuf.h - definitions for routines which use the common string buffers
*/
diff --git a/usr.sbin/xntpd/lib/machines.c b/usr.sbin/xntpd/lib/machines.c
index 5e0169441fec..1d1cbc92faa4 100644
--- a/usr.sbin/xntpd/lib/machines.c
+++ b/usr.sbin/xntpd/lib/machines.c
@@ -41,3 +41,21 @@ ntp_memset(a, x, c)
*a++ = x;
}
#endif /*POSIX*/
+
+#if defined(USE_CLOCK_SETTIME)
+
+#include <time.h>
+
+int
+settimeofday(tvp)
+ struct timeval *tvp;
+{
+ struct timespec ts;
+
+ /* Convert timeval to timespec */
+ ts.tv_sec = tvp->tv_sec;
+ ts.tv_nsec = 1000 * tvp->tv_usec;
+
+ return clock_settime(CLOCK_REALTIME, &ts);
+}
+#endif /* USE_CLOCK_SETTIME */
diff --git a/usr.sbin/xntpd/lib/md5.c b/usr.sbin/xntpd/lib/md5.c
index 77644cb32aa6..2c373cf0d128 100644
--- a/usr.sbin/xntpd/lib/md5.c
+++ b/usr.sbin/xntpd/lib/md5.c
@@ -1,4 +1,4 @@
-/* md5.c,v 3.1 1993/07/06 01:08:29 jbj Exp
+/*
***********************************************************************
** md5.c -- the source code for MD5 routines **
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
diff --git a/usr.sbin/xntpd/lib/mfptoa.c b/usr.sbin/xntpd/lib/mfptoa.c
index 4e513d24f8b0..7de3b6e13e1a 100644
--- a/usr.sbin/xntpd/lib/mfptoa.c
+++ b/usr.sbin/xntpd/lib/mfptoa.c
@@ -1,13 +1,13 @@
-/* mfptoa.c,v 3.1 1993/07/06 01:08:30 jbj Exp
- * mfptoa - Return an asciized representation of a signed LONG fp number
+/*
+ * mfptoa - Return an asciized representation of a signed long fp number
*/
#include "ntp_fp.h"
#include "ntp_stdlib.h"
char *
mfptoa(fpi, fpf, ndec)
- U_LONG fpi;
- U_LONG fpf;
+ u_long fpi;
+ u_long fpf;
int ndec;
{
int isneg;
diff --git a/usr.sbin/xntpd/lib/mfptoms.c b/usr.sbin/xntpd/lib/mfptoms.c
index f686d413edba..01a6f09c2e1b 100644
--- a/usr.sbin/xntpd/lib/mfptoms.c
+++ b/usr.sbin/xntpd/lib/mfptoms.c
@@ -1,13 +1,13 @@
-/* mfptoms.c,v 3.1 1993/07/06 01:08:31 jbj Exp
- * mfptoms - Return an asciized signed LONG fp number in milliseconds
+/*
+ * mfptoms - Return an asciized signed long fp number in milliseconds
*/
#include "ntp_fp.h"
#include "ntp_stdlib.h"
char *
mfptoms(fpi, fpf, ndec)
- U_LONG fpi;
- U_LONG fpf;
+ u_long fpi;
+ u_long fpf;
int ndec;
{
int isneg;
diff --git a/usr.sbin/xntpd/lib/modetoa.c b/usr.sbin/xntpd/lib/modetoa.c
index 483327186a11..e8292b3fb548 100644
--- a/usr.sbin/xntpd/lib/modetoa.c
+++ b/usr.sbin/xntpd/lib/modetoa.c
@@ -1,4 +1,4 @@
-/* modetoa.c,v 3.1 1993/07/06 01:08:33 jbj Exp
+/*
* modetoa - return an asciized mode
*/
#include <stdio.h>
diff --git a/usr.sbin/xntpd/lib/mstolfp.c b/usr.sbin/xntpd/lib/mstolfp.c
index 8a642cf0a55b..f9c21b7e3da4 100644
--- a/usr.sbin/xntpd/lib/mstolfp.c
+++ b/usr.sbin/xntpd/lib/mstolfp.c
@@ -1,4 +1,4 @@
-/* mstolfp.c,v 3.1 1993/07/06 01:08:34 jbj Exp
+/*
* mstolfp - convert an ascii string in milliseconds to an l_fp number
*/
#include <stdio.h>
diff --git a/usr.sbin/xntpd/lib/msutotsf.c b/usr.sbin/xntpd/lib/msutotsf.c
index 412cfbd1ed96..eb3babe9cd1a 100644
--- a/usr.sbin/xntpd/lib/msutotsf.c
+++ b/usr.sbin/xntpd/lib/msutotsf.c
@@ -1,4 +1,4 @@
-/* msutotsf.c,v 3.1 1993/07/06 01:08:35 jbj Exp
+/*
* msutotsf - tables for converting from a subsecond millisecond value
* to a time stamp fraction.
*/
@@ -12,7 +12,7 @@
* truncated). The error in the result will thus be +-1 low order
* bit in the time stamp fraction.
*/
-U_LONG msutotsflo[32] = {
+u_long msutotsflo[32] = {
0x00000000, 0x00418937, 0x0083126f, 0x00c49ba6,
0x010624dd, 0x0147ae14, 0x0189374c, 0x01cac083,
0x020c49ba, 0x024dd2f2, 0x028f5c29, 0x02d0e560,
@@ -23,7 +23,7 @@ U_LONG msutotsflo[32] = {
0x072b020c, 0x076c8b44, 0x07ae147b, 0x07ef9db2
};
-U_LONG msutotsfhi[32] = {
+u_long msutotsfhi[32] = {
0x00000000, 0x083126e9, 0x10624dd3, 0x189374bc,
0x20c49ba6, 0x28f5c28f, 0x3126e979, 0x39581062,
0x4189374c, 0x49ba5e35, 0x51eb851f, 0x5a1cac08,
diff --git a/usr.sbin/xntpd/lib/msyslog.c b/usr.sbin/xntpd/lib/msyslog.c
index a6186b72ef34..b1c8e0df5960 100644
--- a/usr.sbin/xntpd/lib/msyslog.c
+++ b/usr.sbin/xntpd/lib/msyslog.c
@@ -1,4 +1,4 @@
-/* msyslog.c,v 3.1 1993/07/06 01:08:36 jbj Exp
+/*
* msyslog - either send a message to the terminal or print it on
* the standard output.
*
diff --git a/usr.sbin/xntpd/lib/netof.c b/usr.sbin/xntpd/lib/netof.c
index 286a5846eb40..def3013dd425 100644
--- a/usr.sbin/xntpd/lib/netof.c
+++ b/usr.sbin/xntpd/lib/netof.c
@@ -7,19 +7,18 @@
#include "ntp_fp.h"
#include "ntp_stdlib.h"
-U_LONG
+u_long
netof(num)
- U_LONG num;
+ u_long num;
{
- register U_LONG netnum;
+ 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 */
+ else /* treat all other like class A */
netnum &= IN_CLASSA_NET;
return netnum;
}
diff --git a/usr.sbin/xntpd/lib/numtoa.c b/usr.sbin/xntpd/lib/numtoa.c
index c36885d19e68..ef291c8d6bcd 100644
--- a/usr.sbin/xntpd/lib/numtoa.c
+++ b/usr.sbin/xntpd/lib/numtoa.c
@@ -1,4 +1,4 @@
-/* numtoa.c,v 3.1 1993/07/06 01:08:38 jbj Exp
+/*
* numtoa - return asciized network numbers store in local array space
*/
#include <stdio.h>
@@ -9,16 +9,14 @@
char *
numtoa(num)
- U_LONG num;
+ u_long num;
{
- register U_LONG netnum;
+ register u_long netnum;
register char *buf;
netnum = ntohl(num);
LIB_GETBUF(buf);
-
- (void) sprintf(buf, "%d.%d.%d.%d", (netnum>>24)&0xff,
- (netnum>>16)&0xff, (netnum>>8)&0xff, netnum&0xff);
-
+ (void) sprintf(buf, "%lu.%lu.%lu.%lu", (netnum >> 24) & 0xff,
+ (netnum >> 16) & 0xff, (netnum >> 8) & 0xff, netnum & 0xff);
return buf;
}
diff --git a/usr.sbin/xntpd/lib/numtohost.c b/usr.sbin/xntpd/lib/numtohost.c
index 2f07c2c4dac5..844bbceb63b4 100644
--- a/usr.sbin/xntpd/lib/numtohost.c
+++ b/usr.sbin/xntpd/lib/numtohost.c
@@ -13,7 +13,7 @@
char *
numtohost(netnum)
- U_LONG netnum;
+ u_long netnum;
{
char *bp;
struct hostent *hp;
diff --git a/usr.sbin/xntpd/lib/octtoint.c b/usr.sbin/xntpd/lib/octtoint.c
index 1f25b1d57693..7598d723bd35 100644
--- a/usr.sbin/xntpd/lib/octtoint.c
+++ b/usr.sbin/xntpd/lib/octtoint.c
@@ -1,4 +1,4 @@
-/* octtoint.c,v 3.1 1993/07/06 01:08:41 jbj Exp
+/*
* octtoint - convert an ascii string in octal to an unsigned
* long, with error checking
*/
@@ -10,9 +10,9 @@
int
octtoint(str, ival)
const char *str;
- U_LONG *ival;
+ u_long *ival;
{
- register U_LONG u;
+ register u_long u;
register const char *cp;
cp = str;
diff --git a/usr.sbin/xntpd/lib/prettydate.c b/usr.sbin/xntpd/lib/prettydate.c
index ad679bd872ce..747e31018e7d 100644
--- a/usr.sbin/xntpd/lib/prettydate.c
+++ b/usr.sbin/xntpd/lib/prettydate.c
@@ -1,4 +1,4 @@
-/* prettydate.c,v 3.1 1993/07/06 01:08:42 jbj Exp
+/*
* prettydate - convert a time stamp to something readable
*/
#include <stdio.h>
@@ -18,8 +18,8 @@ prettydate(ts)
{
char *bp;
struct tm *tm;
- U_LONG sec;
- U_LONG msec;
+ time_t sec;
+ u_long msec;
static char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
@@ -31,14 +31,14 @@ prettydate(ts)
LIB_GETBUF(bp);
sec = ts->l_ui - JAN_1970;
- msec = ts->l_uf / 4294967; /* fract / (2**32/1000) */
+ msec = ts->l_uf / 4294967; /* fract / (2 ** 32 / 1000) */
- tm = localtime((LONG *)&sec);
+ tm = localtime(&sec);
- (void) sprintf(bp, "%08x.%08x %s, %s %2d %4d %2d:%02d:%02d.%03d",
- ts->l_ui, ts->l_uf, days[tm->tm_wday], months[tm->tm_mon],
- tm->tm_mday, 1900+tm->tm_year, tm->tm_hour, tm->tm_min,
- tm->tm_sec, msec);
+ (void) sprintf(bp, "%08lx.%08lx %s, %s %2d %4d %2d:%02d:%02d.%03lu",
+ (u_long)ts->l_ui, (u_long)ts->l_uf, days[tm->tm_wday],
+ months[tm->tm_mon], tm->tm_mday, 1900 + tm->tm_year,
+ tm->tm_hour,tm->tm_min, tm->tm_sec, msec);
return bp;
}
diff --git a/usr.sbin/xntpd/lib/ranny.c b/usr.sbin/xntpd/lib/ranny.c
index 2a47e03f59ac..3fe7b221c3b8 100644
--- a/usr.sbin/xntpd/lib/ranny.c
+++ b/usr.sbin/xntpd/lib/ranny.c
@@ -1,4 +1,4 @@
-/* ranny.c,v 3.1 1993/07/06 01:08:43 jbj Exp
+/*
* Random number generator is:
*
* Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
@@ -20,9 +20,9 @@ extern time_t time P((time_t *loc));
* 55 random numbers, not all even. Note we don't initialize ran_y
* directly since I have had thoughts of putting this in an EPROM
*/
-static U_LONG ran_y[55];
+static time_t ran_y[55];
-static U_LONG init_ran_y[55] = {
+static time_t init_ran_y[55] = {
1860909544, 231033423, 437666411, 1349655137, 2014584962,
504613712, 656256107, 1246027206, 573713775, 643466871,
540235388, 1630565153, 443649364, 729302839, 1933991552,
@@ -41,38 +41,22 @@ static int ran_k;
/*
- * ranp2 - return a random integer in the range 0 .. (1<<m)-1
+ * ranp2 - return a random integer in the range 0 .. (1 << m) - 1
*/
-U_LONG
+u_long
ranp2(m)
int m;
{
- U_LONG r;
-
- ran_y[ran_k] += ran_y[ran_j]; /* overflow does a mod */
- r = ran_y[ran_k];
- if (ran_k-- == 0) ran_k = 54;
- if (ran_j-- == 0) ran_j = 54;
- return (r & ((1<<m)-1));
-}
-
-#ifdef notdef
-/*
- * ranny - return a random integer in the range 0 .. m-1
- */
-U_LONG
-ranny(m)
- u_int m;
-{
- unsigned LONG r;
+ time_t r;
ran_y[ran_k] += ran_y[ran_j]; /* overflow does a mod */
r = ran_y[ran_k];
- if (ran_k-- == 0) ran_k = 54;
- if (ran_j-- == 0) ran_j = 54;
- return (r % m);
+ if (ran_k-- == 0)
+ ran_k = 54;
+ if (ran_j-- == 0)
+ ran_j = 54;
+ return (u_long)(r & ((1 << m ) - 1));
}
-#endif /* notdef */
/*
* init_random - do initialization of random number routine
@@ -90,7 +74,7 @@ init_random()
* Randomize the seed array some more. The time of day
* should be initialized by now.
*/
- now = (time_t)(time((time_t *)0))|01;
+ now = time((time_t *)0) | 01;
for (i = 0; i < 55; ++i)
ran_y[i] = now * init_ran_y[i]; /* overflow does a mod */
diff --git a/usr.sbin/xntpd/lib/refnumtoa.c b/usr.sbin/xntpd/lib/refnumtoa.c
index 31175d9f877b..b46fdd8cb350 100644
--- a/usr.sbin/xntpd/lib/refnumtoa.c
+++ b/usr.sbin/xntpd/lib/refnumtoa.c
@@ -1,4 +1,4 @@
-/* refnumtoa.c,v 3.1 1993/07/06 01:08:44 jbj Exp
+/*
* refnumtoa - return asciized refclock addresses stored in local array space
*/
#include <stdio.h>
@@ -9,9 +9,9 @@
char *
refnumtoa(num)
- U_LONG num;
+ u_long num;
{
- register U_LONG netnum;
+ register u_long netnum;
register char *buf;
register const char *rclock;
@@ -19,16 +19,12 @@ refnumtoa(num)
LIB_GETBUF(buf);
- rclock = clockname((int)((netnum>>8)&0xff));
+ rclock = clockname((int)((netnum >> 8) & 0xff));
if (rclock != NULL)
- {
- (void) sprintf(buf, "%s(%d)", clockname((int)((netnum>>8)&0xff)), netnum&0xff);
- }
+ (void)sprintf(buf, "%s(%lu)", rclock, netnum & 0xff);
else
- {
- (void) sprintf(buf, "REFCLK(%d,%d)", (netnum>>8)&0xff, netnum&0xff);
- }
-
+ (void)sprintf(buf, "REFCLK(%lu,%lu)",
+ (netnum >> 8) & 0xff, netnum&0xff);
return buf;
}
diff --git a/usr.sbin/xntpd/lib/systime.c b/usr.sbin/xntpd/lib/systime.c
index 1d6c59a5d969..4464e8dae3f4 100644
--- a/usr.sbin/xntpd/lib/systime.c
+++ b/usr.sbin/xntpd/lib/systime.c
@@ -1,15 +1,16 @@
-/* systime.c,v 3.1 1993/07/06 01:08:46 jbj Exp
+/*
* systime -- routines to fiddle a UNIX clock.
*/
+#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
-#if defined(SYS_HPUX) || defined(sgi) || defined(SYS_BSDI)
+#if defined(SYS_HPUX) || defined(sgi) || defined(SYS_BSDI) || defined(SYS_44BSD)
#include <sys/param.h>
#include <utmp.h>
#endif
#ifdef SYS_LINUX
-#include <sys/timex.h>
+#include "sys/timex.h"
#endif
#include "ntp_fp.h"
@@ -47,12 +48,12 @@ extern int debug;
* We also remember the clock precision we computed from the kernel in
* case someone asks us.
*/
- LONG sys_clock;
+ long sys_clock;
- LONG adj_precision; /* adj precision in usec (tickadj) */
- LONG tvu_maxslew; /* maximum adjust doable in 1<<CLOCK_ADJ sec (usec) */
+ 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 */
+ u_long tsf_maxslew; /* same as above, as long format */
l_fp sys_clock_offset; /* correction for current system time */
@@ -83,7 +84,7 @@ get_systime(ts)
TVTOTS(&tv, ts);
L_ADD(ts, &sys_clock_offset);
if (ts->l_uf & TS_ROUNDBIT)
- L_ADDUF(ts, (unsigned LONG) TS_ROUNDBIT);
+ L_ADDUF(ts, TS_ROUNDBIT);
#endif /* !defined(SLEWALWAYS) */
ts->l_ui += JAN_1970;
ts->l_uf &= TS_MASK;
@@ -101,8 +102,8 @@ step_systime(ts)
{
#ifdef SLEWALWAYS
#ifdef STEP_SLEW
- register U_LONG tmp_ui;
- register U_LONG tmp_uf;
+ register u_long tmp_ui;
+ register u_long tmp_uf;
int isneg;
int n;
@@ -148,13 +149,13 @@ int
adj_systime(ts)
l_fp *ts;
{
- register unsigned LONG offset_i, offset_f;
- register LONG temp;
- register unsigned LONG residual;
+ register u_long offset_i, offset_f;
+ register long temp;
+ register u_long residual;
register int isneg = 0;
struct timeval adjtv, oadjtv;
l_fp oadjts;
- LONG adj = ts->l_f;
+ long adj = ts->l_f;
int rval;
adjtv.tv_sec = adjtv.tv_usec = 0;
@@ -199,8 +200,7 @@ adj_systime(ts)
#ifdef DEBUG
if (debug > 4)
- syslog(LOG_DEBUG,
- "maximum slew: %s%s, remainder = %s\n",
+ printf("systime: maximum slew: %s%s, remainder = %s\n",
isneg?"-":"", umfptoa(0, tsf_maxslew, 9),
mfptoa(offset_i, offset_f, 9));
#endif
@@ -232,8 +232,8 @@ adj_systime(ts)
}
#ifdef DEBUG
if (debug > 4)
- syslog(LOG_DEBUG,
- "slew adjtv = %s, adjts = %s, sys_clock_offset = %s\n",
+ printf(
+ "systime: adjtv = %s, adjts = %s, sys_clock_offset = %s\n",
tvtoa(&adjtv), umfptoa(0, residual, 9),
mfptoa(offset_i, offset_f, 9));
#endif
diff --git a/usr.sbin/xntpd/lib/tsftomsu.c b/usr.sbin/xntpd/lib/tsftomsu.c
index b9161141d359..9904b4f5de17 100644
--- a/usr.sbin/xntpd/lib/tsftomsu.c
+++ b/usr.sbin/xntpd/lib/tsftomsu.c
@@ -1,4 +1,4 @@
-/* tsftomsu.c,v 3.1 1993/07/06 01:08:47 jbj Exp
+/*
* tsftomsu - convert from a time stamp fraction to milliseconds
*/
#include "ntp_fp.h"
@@ -6,11 +6,11 @@
int
tsftomsu(tsf, round)
- U_LONG tsf;
+ u_long tsf;
int round;
{
- register U_LONG val_ui, val_uf;
- register U_LONG tmp_ui, tmp_uf;
+ register long val_ui, val_uf;
+ register long tmp_ui, tmp_uf;
register int i;
/*
diff --git a/usr.sbin/xntpd/lib/tstotv.c b/usr.sbin/xntpd/lib/tstotv.c
index c9b0d1c036ad..be4bdd44155d 100644
--- a/usr.sbin/xntpd/lib/tstotv.c
+++ b/usr.sbin/xntpd/lib/tstotv.c
@@ -1,4 +1,4 @@
-/* tstotv.c,v 3.1 1993/07/06 01:08:49 jbj Exp
+/*
* tstotv - tables for converting from NTP time stamps to struct timeval
*/
@@ -13,7 +13,7 @@
* These tables are rounded.
*/
-LONG tstoushi[256] = {
+long tstoushi[256] = {
0x000000, 0x007a12, 0x00f424, 0x016e36,
0x01e848, 0x02625a, 0x02dc6c, 0x03567e,
0x03d090, 0x044aa2, 0x04c4b4, 0x053ec6,
@@ -80,7 +80,7 @@ LONG tstoushi[256] = {
0x7829b8, 0x78a3ca, 0x791ddc, 0x7997ee
};
-LONG tstousmid[256] = {
+long tstousmid[256] = {
0x0000, 0x007a, 0x00f4, 0x016e, 0x01e8, 0x0262, 0x02dc, 0x0356,
0x03d1, 0x044b, 0x04c5, 0x053f, 0x05b9, 0x0633, 0x06ad, 0x0727,
0x07a1, 0x081b, 0x0895, 0x090f, 0x0989, 0x0a03, 0x0a7e, 0x0af8,
@@ -115,7 +115,7 @@ LONG tstousmid[256] = {
0x7641, 0x76bc, 0x7736, 0x77b0, 0x782a, 0x78a4, 0x791e, 0x7998
};
-LONG tstouslo[128] = {
+long tstouslo[128] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
diff --git a/usr.sbin/xntpd/lib/tvtoa.c b/usr.sbin/xntpd/lib/tvtoa.c
index 778caa1cee26..dd9ee7eec5ac 100644
--- a/usr.sbin/xntpd/lib/tvtoa.c
+++ b/usr.sbin/xntpd/lib/tvtoa.c
@@ -1,4 +1,4 @@
-/* tvtoa.c,v 3.1 1993/07/06 01:08:50 jbj Exp
+/*
* tvtoa - return an asciized representation of a struct timeval
*/
#include <stdio.h>
@@ -12,8 +12,8 @@ tvtoa(tv)
struct timeval *tv;
{
register char *buf;
- register U_LONG sec;
- register U_LONG usec;
+ register u_long sec;
+ register u_long usec;
register int isneg;
if (tv->tv_sec < 0 || tv->tv_usec < 0) {
diff --git a/usr.sbin/xntpd/lib/tvtots.c b/usr.sbin/xntpd/lib/tvtots.c
index befc48055933..0bd2b6911472 100644
--- a/usr.sbin/xntpd/lib/tvtots.c
+++ b/usr.sbin/xntpd/lib/tvtots.c
@@ -1,4 +1,4 @@
-/* tvtots.c,v 3.1 1993/07/06 01:08:51 jbj Exp
+/*
* tvtots - tables for converting from Unix struct timeval's to
* NTP time stamp format.
*/
@@ -17,7 +17,7 @@
* +- 1.5 low order bits.
*/
-U_LONG ustotslo[256] = {
+u_long ustotslo[256] = {
0x00000000, 0x000010c7, 0x0000218e, 0x00003255,
0x0000431c, 0x000053e3, 0x000064aa, 0x00007571,
0x00008638, 0x000096ff, 0x0000a7c6, 0x0000b88d,
@@ -84,7 +84,7 @@ U_LONG ustotslo[256] = {
0x001083dc, 0x001094a3, 0x0010a56a, 0x0010b631,
};
-U_LONG ustotsmid[256] = {
+u_long ustotsmid[256] = {
0x00000000, 0x0010c6f8, 0x00218def, 0x003254e7,
0x00431bde, 0x0053e2d6, 0x0064a9ce, 0x007570c5,
0x008637bd, 0x0096feb4, 0x00a7c5ac, 0x00b88ca4,
@@ -151,7 +151,7 @@ U_LONG ustotsmid[256] = {
0x1083dbbc, 0x1094a2b4, 0x10a569ab, 0x10b630a3,
};
-U_LONG ustotshi[16] = {
+u_long ustotshi[16] = {
0x00000000, 0x10c6f79a, 0x218def35, 0x3254e6cf,
0x431bde6a, 0x53e2d604, 0x64a9cd9f, 0x7570c539,
0x8637bcd3, 0x96feb46e, 0xa7c5ac08, 0xb88ca3a3,
diff --git a/usr.sbin/xntpd/lib/uglydate.c b/usr.sbin/xntpd/lib/uglydate.c
index 308c70336232..25a8e56fa911 100644
--- a/usr.sbin/xntpd/lib/uglydate.c
+++ b/usr.sbin/xntpd/lib/uglydate.c
@@ -1,4 +1,4 @@
-/* uglydate.c,v 3.1 1993/07/06 01:08:53 jbj Exp
+/*
* uglydate - convert a time stamp to something barely readable
* The string returned is 37 characters long.
*/
@@ -19,17 +19,15 @@ uglydate(ts)
char *bp;
char *timep;
struct tm *tm;
- U_LONG sec;
- U_LONG msec;
+ time_t sec;
+ long msec;
int year;
timep = ulfptoa(ts, 6); /* returns max 17 characters */
-
LIB_GETBUF(bp);
-
sec = ts->l_ui - JAN_1970;
msec = ts->l_uf / 4294967; /* fract / (2**32/1000) */
- tm = gmtime((LONG *)&sec);
+ tm = gmtime(&sec);
if (ts->l_ui == 0) {
/*
* Probably not a real good thing to do. Oh, well.
@@ -44,10 +42,8 @@ uglydate(ts)
while (year >= 100)
year -= 100;
}
-
- (void) sprintf(bp, "%17s %02d:%03d:%02d:%02d:%02d.%03d",
+ (void) sprintf(bp, "%17s %02d:%03d:%02d:%02d:%02d.%03ld",
timep, year, tm->tm_yday, tm->tm_hour, tm->tm_min,
tm->tm_sec, msec);
-
return bp;
}
diff --git a/usr.sbin/xntpd/lib/uinttoa.c b/usr.sbin/xntpd/lib/uinttoa.c
index ce29390342b0..7c406dd5902e 100644
--- a/usr.sbin/xntpd/lib/uinttoa.c
+++ b/usr.sbin/xntpd/lib/uinttoa.c
@@ -1,4 +1,4 @@
-/* uinttoa.c,v 3.1 1993/07/06 01:08:54 jbj Exp
+/*
* uinttoa - return an asciized unsigned integer
*/
#include <stdio.h>
@@ -8,12 +8,12 @@
char *
uinttoa(uval)
- U_LONG uval;
+ u_long uval;
{
register char *buf;
LIB_GETBUF(buf);
- (void) sprintf(buf, "%lu", uval);
+ (void) sprintf(buf, "%lu", (u_long)uval);
return buf;
}
diff --git a/usr.sbin/xntpd/lib/utvtoa.c b/usr.sbin/xntpd/lib/utvtoa.c
index b573f187a38f..48310a837135 100644
--- a/usr.sbin/xntpd/lib/utvtoa.c
+++ b/usr.sbin/xntpd/lib/utvtoa.c
@@ -1,4 +1,4 @@
-/* utvtoa.c,v 3.1 1993/07/06 01:08:55 jbj Exp
+/*
* utvtoa - return an asciized representation of an unsigned struct timeval
*/
#include <stdio.h>
@@ -15,7 +15,7 @@ utvtoa(tv)
LIB_GETBUF(buf);
- (void) sprintf(buf, "%lu.%06lu", (U_LONG)tv->tv_sec,
- (U_LONG)tv->tv_usec);
+ (void) sprintf(buf, "%lu.%06lu", (u_long)tv->tv_sec,
+ (u_long)tv->tv_usec);
return buf;
}
diff --git a/usr.sbin/xntpd/ntpdate/Makefile.tmpl b/usr.sbin/xntpd/ntpdate/Makefile.tmpl
index 170625f0e35b..34f8f666c4a4 100644
--- a/usr.sbin/xntpd/ntpdate/Makefile.tmpl
+++ b/usr.sbin/xntpd/ntpdate/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:09:20 jbj Exp
+# Makefile.tmpl
#
PROGRAM= ntpdate
#
diff --git a/usr.sbin/xntpd/ntpdate/ntpdate.c b/usr.sbin/xntpd/ntpdate/ntpdate.c
index b5ad05dc9baa..20fa604f00eb 100644
--- a/usr.sbin/xntpd/ntpdate/ntpdate.c
+++ b/usr.sbin/xntpd/ntpdate/ntpdate.c
@@ -1,4 +1,4 @@
-/* ntpdate.c,v 3.1 1993/07/06 01:09:22 jbj Exp
+/*
* ntpdate - set the time of day by polling one or more NTP servers
*/
#include <stdio.h>
@@ -92,19 +92,19 @@ char *progname;
* Systemwide parameters and flags
*/
int sys_samples = DEFSAMPLES; /* number of samples/server */
-U_LONG sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */
+u_long sys_timeout = DEFTIMEOUT; /* timeout time, in TIMER_HZ units */
struct server **sys_servers; /* the server list */
int sys_numservers = 0; /* number of servers to poll */
int sys_maxservers = 0; /* max number of servers to deal with */
int sys_authenticate = 0; /* true when authenticating */
-U_LONG sys_authkey = 0; /* set to authentication key in use */
-U_LONG sys_authdelay = 0; /* authentication delay */
+u_long sys_authkey = 0; /* set to authentication key in use */
+u_long sys_authdelay = 0; /* authentication delay */
int sys_version = NTP_VERSION; /* version to poll with */
/*
* The current internal time
*/
-U_LONG current_time = 0;
+u_long current_time = 0;
/*
* Counter for keeping track of completed servers
@@ -149,7 +149,7 @@ static void input_handler P((void));
static int l_adj_systime P((l_fp *));
static int l_step_systime P((l_fp *));
-static int getnetnum P((char *, U_LONG *));
+static int getnetnum P((char *, u_long *));
static void printserver P((struct server *, FILE *));
/*
@@ -183,7 +183,7 @@ main(argc, argv)
case 'a':
c = atoi(ntp_optarg);
sys_authenticate = 1;
- sys_authkey = (U_LONG)c;
+ sys_authkey = c;
break;
case 'b':
always_step++;
@@ -313,7 +313,7 @@ main(argc, argv)
if (!authhavekey(sys_authkey)) {
char buf[10];
- (void) sprintf(buf, "%u", sys_authkey);
+ (void) sprintf(buf, "%lu", (unsigned long)sys_authkey);
syslog(LOG_ERR, "authentication key %s unknown", buf);
exit(1);
}
@@ -418,7 +418,7 @@ transmit(server)
* Last message to this server timed out. Shift
* zeros into the filter.
*/
- ts.l_ui = ts.l_uf = 0;
+ L_CLR(&ts);
server_data(server, 0, &ts, 0);
}
@@ -444,9 +444,9 @@ transmit(server)
xpkt.rootdelay = htonl(NTPDATE_DISTANCE);
xpkt.rootdispersion = htonl(NTPDATE_DISP);
xpkt.refid = htonl(NTPDATE_REFID);
- xpkt.reftime.l_ui = xpkt.reftime.l_uf = 0;
- xpkt.org.l_ui = xpkt.org.l_uf = 0;
- xpkt.rec.l_ui = xpkt.rec.l_uf = 0;
+ L_CLR(&xpkt.reftime);
+ L_CLR(&xpkt.org);
+ L_CLR(&xpkt.rec);
/*
* Determine whether to authenticate or not. If so,
@@ -494,8 +494,7 @@ receive(rbufp)
register struct pkt *rpkt;
register struct server *server;
register s_fp di;
- register U_LONG t10_ui, t10_uf;
- register U_LONG t23_ui, t23_uf;
+ l_fp t10, t23;
l_fp org;
l_fp rec;
l_fp ci;
@@ -564,9 +563,9 @@ receive(rbufp)
is_authentic = 0;
if (debug > 3)
- printf("receive: rpkt keyid=%d sys_authkey=%d decrypt=%d\n",
- ntohl(rpkt->keyid), sys_authkey,
- authdecrypt(sys_authkey, (U_LONG *)rpkt,
+ printf("receive: rpkt keyid=%ld sys_authkey=%ld decrypt=%ld\n",
+ (long int)ntohl(rpkt->keyid), (long int)sys_authkey,
+ (long int)authdecrypt(sys_authkey, (U_LONG *)rpkt,
LEN_PKT_NOMAC));
if (has_mac && ntohl(rpkt->keyid) == sys_authkey &&
@@ -597,7 +596,7 @@ receive(rbufp)
* Make sure the server is at least somewhat sane. If not, try
* again.
*/
- if ((rec.l_ui == 0 && rec.l_uf == 0) || !L_ISHIS(&server->org, &rec)) {
+ if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
transmit(server);
return;
}
@@ -609,36 +608,32 @@ receive(rbufp)
* d = (t2 - t3) - (t1 - t0)
* c = ((t2 - t3) + (t1 - t0)) / 2
*/
- t10_ui = server->org.l_ui; /* pkt.xmt == t1 */
- t10_uf = server->org.l_uf;
- M_SUB(t10_ui, t10_uf, rbufp->recv_time.l_ui,
- rbufp->recv_time.l_uf); /* recv_time == t0*/
+ t10 = server->org; /* pkt.xmt == t1 */
+ L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/
- t23_ui = rec.l_ui; /* pkt.rec == t2 */
- t23_uf = rec.l_uf;
- M_SUB(t23_ui, t23_uf, org.l_ui, org.l_uf); /* pkt->org == t3 */
+ t23 = rec; /* pkt.rec == t2 */
+ L_SUB(&t23, &org); /* pkt->org == t3 */
/* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */
- ci.l_ui = t10_ui;
- ci.l_uf = t10_uf;
- M_ADD(ci.l_ui, ci.l_uf, t23_ui, t23_uf);
- M_RSHIFT(ci.l_i, ci.l_uf);
+ ci = t10;
+ L_ADD(&ci, &t23);
+ L_RSHIFT(&ci);
/*
* 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);
+ L_SUB(&t23, &t10);
+ di = LFPTOFP(&t23);
if (debug > 3)
- printf("offset: %s, delay %s\n", lfptoa(&ci, 9), fptoa(di, 4));
+ printf("offset: %s, delay %s\n", lfptoa(&ci, 6), fptoa(di, 5));
di += (FP_SECOND >> (-(int)NTPDATE_PRECISION))
+ (FP_SECOND >> (-(int)server->precision)) + NTP_MAXSKW;
if (di <= 0) { /* value still too raunchy to use? */
- ci.l_ui = ci.l_uf = 0;
+ L_CLR(&ci);
di = 0;
} else {
di = max(di, NTP_MINDIST);
@@ -668,7 +663,7 @@ server_data(server, d, c, e)
if (i < NTP_SHIFT) {
server->filter_delay[i] = d;
server->filter_offset[i] = *c;
- server->filter_soffset[i] = MFPTOFP(c->l_ui, c->l_uf);
+ server->filter_soffset[i] = LFPTOFP(c);
server->filter_error[i] = e;
server->filter_nextpt = i + 1;
}
@@ -714,7 +709,7 @@ clock_filter(server)
*/
if (server->filter_delay[ord[0]] == 0) {
server->delay = 0;
- server->offset.l_ui = server->offset.l_uf = 0;
+ L_CLR(&server->offset);
server->soffset = 0;
server->dispersion = PEER_MAXDISP;
} else {
@@ -786,12 +781,12 @@ clock_select()
}
if (server->leap == LEAP_NOTINSYNC)
continue; /* he's in trouble */
- if (server->org.l_ui < server->reftime.l_ui) {
+ if (!L_ISHIS(&server->org, &server->reftime)) {
continue; /* very broken host */
}
if ((server->org.l_ui - server->reftime.l_ui)
>= NTP_MAXAGE) {
- continue; /* too LONG without sync */
+ continue; /* too long without sync */
}
if (server->trust != 0) {
continue;
@@ -984,13 +979,13 @@ clock_adjust()
if (simple_query || l_step_systime(&server->offset)) {
syslog(LOG_NOTICE, "step time server %s offset %s",
ntoa(&server->srcadr),
- lfptoa(&server->offset, 7));
+ lfptoa(&server->offset, 6));
}
} else {
if (simple_query || l_adj_systime(&server->offset)) {
syslog(LOG_NOTICE, "adjust time server %s offset %s",
ntoa(&server->srcadr),
- lfptoa(&server->offset, 7));
+ lfptoa(&server->offset, 6));
}
}
return(0);
@@ -1007,7 +1002,7 @@ addserver(serv)
char *serv;
{
register struct server *server;
- U_LONG netnum;
+ u_long netnum;
static int toomany = 0;
if (sys_numservers >= sys_maxservers) {
@@ -1037,7 +1032,7 @@ addserver(serv)
server->srcadr.sin_port = htons(NTP_PORT);
sys_servers[sys_numservers++] = server;
- server->event_time = (U_LONG)sys_numservers;
+ server->event_time = sys_numservers;
}
@@ -1049,7 +1044,7 @@ findserver(addr)
struct sockaddr_in *addr;
{
register int i;
- register U_LONG netnum;
+ register u_long netnum;
if (htons(addr->sin_port) != NTP_PORT)
return 0;
@@ -1191,7 +1186,7 @@ init_io()
memset((char *)&addr, 0, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons(NTP_PORT);
- addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
if (errno == EADDRINUSE)
syslog(LOG_ERR,
@@ -1366,7 +1361,7 @@ input_handler()
/*
- * adj_systime - do a big LONG slew of the system time
+ * adj_systime - do a big long slew of the system time
*/
static int
l_adj_systime(ts)
@@ -1425,8 +1420,7 @@ l_step_systime(ts)
{
#ifdef SLEWALWAYS
#ifdef STEP_SLEW
- register U_LONG tmp_ui;
- register U_LONG tmp_uf;
+ l_fp ftmp;
int isneg;
int n;
@@ -1434,17 +1428,17 @@ l_step_systime(ts)
/*
* Take the absolute value of the offset
*/
- tmp_ui = ts->l_ui;
- tmp_uf = ts->l_uf;
- if (M_ISNEG(tmp_ui, tmp_uf)) {
- M_NEG(tmp_ui, tmp_uf);
+ ftmp = ts;
+ if (L_ISNEG(&ftmp)) {
+ L_NEG(&tmp);
isneg = 1;
} else
isneg = 0;
if (tmp_ui >= 3) { /* Step it and slew - we might win */
n = step_systime_real(ts);
- if (!n) return n;
+ if (!n)
+ return n;
if (isneg)
ts->l_ui = ~0;
else
@@ -1456,7 +1450,8 @@ l_step_systime(ts)
* line.
*/
#endif
- if (debug) return 1;
+ if (debug)
+ return 1;
#ifdef FORCE_NTPDATE_STEP
return step_systime_real(ts);
#else
@@ -1464,7 +1459,8 @@ l_step_systime(ts)
return 1;
#endif
#else /* SLEWALWAYS */
- if (debug) return 1;
+ if (debug)
+ return 1;
return step_systime_real(ts);
#endif /* SLEWALWAYS */
}
@@ -1475,7 +1471,7 @@ l_step_systime(ts)
static int
getnetnum(host, num)
char *host;
- U_LONG *num;
+ u_long *num;
{
struct hostent *hp;
@@ -1504,7 +1500,7 @@ printserver(pp, fp)
if (!debug) {
(void) fprintf(fp, "server %s, stratum %d, offset %s, delay %s\n",
ntoa(&pp->srcadr), pp->stratum,
- lfptoa(&pp->offset, 7), ufptoa(pp->delay, 4));
+ lfptoa(&pp->offset, 6), fptoa(pp->delay, 5));
return;
}
@@ -1526,8 +1522,8 @@ printserver(pp, fp)
}
(void) fprintf(fp,
"refid [%s], delay %s, dispersion %s\n",
- str, fptoa(pp->delay, 4),
- ufptoa(pp->dispersion, 4));
+ str, fptoa(pp->delay, 5),
+ ufptoa(pp->dispersion, 5));
(void) fprintf(fp, "transmitted %d, in filter %d\n",
pp->xmtcnt, pp->filter_nextpt);
@@ -1541,7 +1537,7 @@ printserver(pp, fp)
(void) fprintf(fp, "filter delay: ");
for (i = 0; i < NTP_SHIFT; i++) {
- (void) fprintf(fp, " %-8.8s", ufptoa(pp->filter_delay[i],4));
+ (void) fprintf(fp, " %-8.8s", fptoa(pp->filter_delay[i], 5));
if (i == (NTP_SHIFT>>1)-1)
(void) fprintf(fp, "\n ");
}
@@ -1549,17 +1545,17 @@ printserver(pp, fp)
(void) fprintf(fp, "filter offset:");
for (i = 0; i < PEER_SHIFT; i++) {
- (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 5));
+ (void) fprintf(fp, " %-8.8s", lfptoa(&pp->filter_offset[i], 6));
if (i == (PEER_SHIFT>>1)-1)
(void) fprintf(fp, "\n ");
}
(void) fprintf(fp, "\n");
(void) fprintf(fp, "delay %s, dispersion %s\n",
- ufptoa(pp->delay, 4), ufptoa(pp->dispersion, 4));
+ fptoa(pp->delay, 5), ufptoa(pp->dispersion, 5));
(void) fprintf(fp, "offset %s\n\n",
- lfptoa(&pp->offset, 7));
+ lfptoa(&pp->offset, 6));
}
#if defined(NEED_VSPRINTF)
diff --git a/usr.sbin/xntpd/ntpdate/ntpdate.h b/usr.sbin/xntpd/ntpdate/ntpdate.h
index f6d3ebf877f3..cfbe90a92334 100644
--- a/usr.sbin/xntpd/ntpdate/ntpdate.h
+++ b/usr.sbin/xntpd/ntpdate/ntpdate.h
@@ -1,4 +1,4 @@
-/* ntpdate.h,v 3.1 1993/07/06 01:09:23 jbj Exp
+/*
* ntpdate.h - declarations for the ntpdate program
*/
@@ -21,7 +21,7 @@ struct server {
u_fp rootdispersion; /* peer clock dispersion */
U_LONG refid; /* peer reference ID */
l_fp reftime; /* time of peer's last update */
- U_LONG event_time; /* time for next timeout */
+ u_long event_time; /* time for next timeout */
u_short xmtcnt; /* number of packets transmitted */
u_short filter_nextpt; /* index into filter shift register */
s_fp filter_delay[NTP_SHIFT]; /* delay part of shift register */
@@ -50,7 +50,7 @@ struct server {
#define TIMER_HZ (5) /* 5 per second */
/*
- * ntpdate will make a LONG adjustment using adjtime() if the times
+ * ntpdate will make a long adjustment using adjtime() if the times
* are close, or step the time if the times are farther apart. The
* following defines what is "close".
*/
@@ -87,4 +87,3 @@ struct server {
*/
#define DEFTIMEOUT 5 /* 5 timer increments */
#define DEFSAMPLES 4 /* get 4 samples per server */
-#define DEFPRECISION (-5) /* the precision we claim */
diff --git a/usr.sbin/xntpd/ntpq/Makefile.tmpl b/usr.sbin/xntpd/ntpq/Makefile.tmpl
index e80286123cf0..76a09ad6b7e1 100644
--- a/usr.sbin/xntpd/ntpq/Makefile.tmpl
+++ b/usr.sbin/xntpd/ntpq/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:09:28 jbj Exp
+# Makefile.tmpl
#
PROGRAM= ntpq
#
diff --git a/usr.sbin/xntpd/ntpq/ntpq.c b/usr.sbin/xntpd/ntpq/ntpq.c
index 73c2a351aa70..441b283bad6d 100644
--- a/usr.sbin/xntpd/ntpq/ntpq.c
+++ b/usr.sbin/xntpd/ntpq/ntpq.c
@@ -1,4 +1,4 @@
-/* ntpq.c,v 3.1 1993/07/06 01:09:29 jbj Exp
+/*
* ntpq - query an NTP server using mode 6 commands
*/
#include <stdio.h>
@@ -27,7 +27,7 @@ char *prompt = "ntpq> "; /* prompt to ask him about */
/*
* Keyid used for authenticated requests. Obtained on the fly.
*/
-U_LONG info_auth_keyid = -1;
+u_long info_auth_keyid = -1;
/*
* Type of key md5 or des
@@ -88,7 +88,7 @@ struct ctl_var sys_var[] = {
{ CS_LEAP, LP, "leap" }, /* 1 */
{ CS_STRATUM, UI, "stratum" }, /* 2 */
{ CS_PRECISION, IN, "precision" }, /* 3 */
- { CS_ROOTDELAY, FU, "rootdelay" }, /* 4 */
+ { CS_ROOTDELAY, FS, "rootdelay" }, /* 4 */
{ CS_ROOTDISPERSION, FU, "rootdispersion" }, /* 5 */
{ CS_REFID, RF, "refid" }, /* 6 */
{ CS_REFTIME, TS, "reftime" }, /* 7 */
@@ -96,7 +96,7 @@ struct ctl_var sys_var[] = {
{ CS_PEERID, UI, "peer" }, /* 9 */
{ CS_OFFSET, FL, "phase" }, /* 10 */
{ CS_DRIFT, FS, "freq" }, /* 11 */
- { CS_COMPLIANCE, UI, "compliance" }, /* 12 */
+ { CS_COMPLIANCE, FU, "error" }, /* 12 */
{ CS_CLOCK, TS, "clock" }, /* 13 */
{ CS_LEAPIND, LP, "leapindicator" }, /* 14 */
{ CS_LEAPWARNING, LP, "leapwarning" }, /* 15 */
@@ -149,7 +149,7 @@ struct ctl_var peer_var[] = {
{ CP_FLASH, TST, "flash"}, /* 34 */
{ CP_DISP, AR, "disp" }, /* 35 */
/*
- * These are duplicate entires so that we can
+ * These are duplicate entries so that we can
* process deviant version of the xntp protocal.
*/
{ CP_SRCADR, HA, "peeraddr" }, /* 4 */
@@ -173,8 +173,8 @@ struct ctl_var clock_var[] = {
{ CC_BADDATA, UI, "baddata" }, /* 6 */
{ CC_FUDGETIME1, FL, "fudgetime1" }, /* 7 */
{ CC_FUDGETIME2, FL, "fudgetime2" }, /* 8 */
- { CC_FUDGEVAL1, IN, "fudgeval1" }, /* 9 */
- { CC_FUDGEVAL2, IN, "fudgeval2" }, /* 10 */
+ { CC_FUDGEVAL1, UI, "stratum" }, /* 9 */
+ { CC_FUDGEVAL2, RF, "refid" }, /* 10 */
{ CC_FLAGS, UI, "flags" }, /* 11 */
{ CC_DEVICE, ST, "device" }, /* 12 */
{ 0, EOV, "" }
@@ -308,11 +308,6 @@ static void tokenize P((char *, char **, int *));
static int findcmd P((char *, struct xcmd *, struct xcmd *, struct xcmd **));
static int getarg P((char *, int, arg_v *));
static int rtdatetolfp P((char *, l_fp *));
-
-#ifdef UNUSED
-static int decodereach P((char *, U_LONG *));
-#endif /* UNUSED */
-
static int decodearr P((char *, int *, l_fp *));
static char * getcode P((int, struct codestring *));
static void help P((struct parse *, FILE *));
@@ -339,7 +334,7 @@ static void authenticate P((struct parse *, FILE *));
static void ntpversion P((struct parse *, FILE *));
static void warning P((char *, char *, char *));
static void error P((char *, char *, char *));
-static U_LONG getkeyid P((char *));
+static u_long getkeyid P((char *));
static void atoascii P((int, char *, char *));
static void makeascii P((int, char *, FILE *));
static char * getevents P((int));
@@ -424,7 +419,7 @@ struct xcmd builtins[] = {
#define DEFSTIMEOUT (2) /* 2 second time out after first */
#define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */
#define DEFHOST "localhost" /* default host name */
-#define LENHOSTNAME 256 /* host name is 256 characters LONG */
+#define LENHOSTNAME 256 /* host name is 256 characters long */
#define MAXCMDS 100 /* maximum commands on cmd line */
#define MAXHOSTS 100 /* maximum hosts on cmd line */
#define MAXLINE 512 /* maximum line length */
@@ -454,12 +449,12 @@ struct servent *server_entry = NULL; /* server entry for ntp */
u_short sequence;
/*
- * Holds data returned from queries. Declare buffer LONG to be sure of
+ * Holds data returned from queries. Declare buffer long to be sure of
* alignment.
*/
#define MAXFRAGS 24 /* maximum number of fragments */
#define DATASIZE (MAXFRAGS*480) /* maximum amount of data */
-LONG pktdata[DATASIZE/sizeof(LONG)];
+long pktdata[DATASIZE/sizeof(long)];
/*
* Holds association data for use with the &n operator.
@@ -597,7 +592,7 @@ static int
openhost(hname)
char *hname;
{
- U_LONG netnum;
+ u_long netnum;
char temphost[LENHOSTNAME];
if (server_entry == NULL) {
@@ -712,9 +707,9 @@ getresponse(opcode, associd, rstatus, rsize, rdata, timeo)
/*
* This is pretty tricky. We may get between 1 and MAXFRAG packets
* back in response to the request. We peel the data out of
- * each packet and collect it in one LONG block. When the last
+ * each packet and collect it in one long block. When the last
* packet in the sequence is received we'll know how much data we
- * should have had. Note we use one LONG time out, should reconsider.
+ * should have had. Note we use one long time out, should reconsider.
*/
*rsize = 0;
if (rstatus)
@@ -879,8 +874,8 @@ again:
if (debug >= 3) {
int shouldbesize;
- U_LONG key;
- U_LONG *lpkt;
+ u_long key;
+ u_long *lpkt;
int maclen;
/*
@@ -898,15 +893,15 @@ again:
printf(
"Packet shows signs of authentication (total %d, data %d, mac %d)\n",
n, shouldbesize, maclen);
- lpkt = (U_LONG *)&rpkt;
+ lpkt = (u_long *)&rpkt;
printf("%08lx %08lx %08lx %08lx %08lx %08lx\n",
- ntohl(lpkt[(n - maclen)/sizeof(U_LONG) - 3]),
- ntohl(lpkt[(n - maclen)/sizeof(U_LONG) - 2]),
- ntohl(lpkt[(n - maclen)/sizeof(U_LONG) - 1]),
- ntohl(lpkt[(n - maclen)/sizeof(U_LONG)]),
- ntohl(lpkt[(n - maclen)/sizeof(U_LONG) + 1]),
- ntohl(lpkt[(n - maclen)/sizeof(U_LONG) + 2]));
- key = ntohl(lpkt[(n - maclen) / sizeof(U_LONG)]);
+ (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) - 3]),
+ (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) - 2]),
+ (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) - 1]),
+ (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long)]),
+ (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) + 1]),
+ (u_long)ntohl(lpkt[(n - maclen)/sizeof(u_long) + 2]));
+ key = ntohl(lpkt[(n - maclen) / sizeof(u_long)]);
printf("Authenticated with keyid %lu\n", key);
if (key != 0 && key != info_auth_keyid) {
printf("We don't know that key\n");
@@ -1067,7 +1062,7 @@ sendrequest(opcode, associd, auth, qsize, qdata)
if (qsize > 0) {
memmove((char *)qpkt.data, qdata, qsize);
pktsize = qsize + CTL_HEADER_LEN;
- while (pktsize & (sizeof(U_LONG)-1)) {
+ while (pktsize & (sizeof(u_long) - 1)) {
qpkt.data[qsize++] = 0;
pktsize++;
}
@@ -1118,7 +1113,7 @@ sendrequest(opcode, associd, auth, qsize, qdata)
* cp currently points. Cp should be aligned
* properly. Then do the encryptions.
*/
- *(U_LONG *)(&qpkt.data[qsize]) = htonl(info_auth_keyid);
+ *(u_long *)(&qpkt.data[qsize]) = htonl(info_auth_keyid);
maclen = authencrypt(info_auth_keyid, (U_LONG *)&qpkt,
pktsize);
return sendpkt((char *)&qpkt, pktsize + maclen);
@@ -1542,21 +1537,22 @@ getarg(str, code, argp)
int
getnetnum(host, num, fullhost)
char *host;
- U_LONG *num;
+ u_long *num;
char *fullhost;
{
struct hostent *hp;
if (decodenetnum(host, num)) {
if (fullhost != 0) {
- (void) sprintf(fullhost,
- "%d.%d.%d.%d", ((htonl(*num)>>24)&0xff),
- ((htonl(*num)>>16)&0xff), ((htonl(*num)>>8)&0xff),
- (htonl(*num)&0xff));
+ (void) sprintf(fullhost, "%lu.%lu.%lu.%lu",
+ (u_long)((htonl(*num) >> 24) & 0xff),
+ (u_long)((htonl(*num) >> 16) & 0xff),
+ (u_long)((htonl(*num) >> 8) & 0xff),
+ (u_long)(htonl(*num) & 0xff));
}
return 1;
} else if ((hp = gethostbyname(host)) != 0) {
- memmove((char *)num, hp->h_addr, sizeof(U_LONG));
+ memmove((char *)num, hp->h_addr, sizeof(u_long));
if (fullhost != 0)
(void) strcpy(fullhost, hp->h_name);
return 1;
@@ -1573,7 +1569,7 @@ getnetnum(host, num, fullhost)
*/
char *
nntohost(netnum)
- U_LONG netnum;
+ u_long netnum;
{
if (!showhostnames)
return numtoa(netnum);
@@ -1613,7 +1609,7 @@ rtdatetolfp(str, lfp)
/*
* Catch special case
*/
- lfp->l_ui = lfp->l_uf = 0;
+ L_CLR(lfp);
return 1;
}
return 0;
@@ -1654,7 +1650,7 @@ rtdatetolfp(str, lfp)
* Catch special case. If cal.year == 0 this is a zero timestamp.
*/
if (cal.year == 0) {
- lfp->l_ui = lfp->l_uf = 0;
+ L_CLR(lfp);
return 1;
}
@@ -1748,49 +1744,18 @@ decodetime(str, lfp)
}
-#ifdef UNUSED
-/*
- * decodereach - decode a (possibly octal or hex, damn fuzzballs) reachability
- */
-static int
-decodereach(str, uval)
- char *str;
- U_LONG *uval;
-{
- U_LONG u;
-
- if (*str == '0') {
- /*
- * Could be octal or hex
- */
- if (*(str+1) == 'x' || *(str+1) == 'X')
- return hextoint(str+2, uval);
- return octtoint(str, uval);
- }
-
- if (!atouint(str, &u))
- return 0;
-
- if (u > 255)
- return octtoint(str, uval);
- *uval = u;
- return 1;
-}
-#endif /* UNUSED */
-
-
/*
* decodeint - decode an integer
*/
int
decodeint(str, val)
char *str;
- LONG *val;
+ long *val;
{
if (*str == '0') {
if (*(str+1) == 'x' || *(str+1) == 'X')
- return hextoint(str+2, (U_LONG *)val);
- return octtoint(str, (U_LONG *)val);
+ return hextoint(str+2, (u_long *)&val);
+ return octtoint(str, (u_long *)&val);
}
return atoint(str, val);
}
@@ -1802,7 +1767,7 @@ decodeint(str, val)
int
decodeuint(str, val)
char *str;
- U_LONG *val;
+ u_long *val;
{
if (*str == '0') {
if (*(str+1) == 'x' || *(str+1) == 'X')
@@ -2017,18 +1982,18 @@ delay(pcmd, fp)
FILE *fp;
{
int isneg;
- U_LONG val;
+ u_long val;
if (pcmd->nargs == 0) {
val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
- (void) fprintf(fp, "delay %d ms\n", val);
+ (void) fprintf(fp, "delay %lu ms\n", val);
} else {
if (pcmd->argval[0].ival < 0) {
isneg = 1;
- val = (U_LONG)(-pcmd->argval[0].ival);
+ val = (u_long)(-pcmd->argval[0].ival);
} else {
isneg = 0;
- val = (U_LONG)pcmd->argval[0].ival;
+ val = (u_long)pcmd->argval[0].ival;
}
delay_time.l_ui = val / 1000;
@@ -2092,7 +2057,7 @@ keyid(pcmd, fp)
if (info_auth_keyid == -1)
(void) fprintf(fp, "no keyid defined\n");
else
- (void) fprintf(fp, "keyid is %u\n", info_auth_keyid);
+ (void) fprintf(fp, "keyid is %lu\n", info_auth_keyid);
} else {
info_auth_keyid = pcmd->argval[0].uval;
}
@@ -2344,7 +2309,7 @@ error(fmt, st1, st2)
/*
* getkeyid - prompt the user for a keyid to use
*/
-static U_LONG
+static u_long
getkeyid(prompt)
char *prompt;
{
@@ -2368,7 +2333,7 @@ char *prompt;
if (strcmp(pbuf, "0") == 0)
return 0;
- return (U_LONG) atoi(pbuf);
+ return (u_long) atoi(pbuf);
}
@@ -2515,7 +2480,9 @@ statustoa(type, st)
case TYPE_SYS:
(void)strcpy(cb, getcode(CTL_SYS_LI(st), leap_codes));
(void)strcat(cb, ", ");
- (void)strcat(cb, getcode(CTL_SYS_SOURCE(st), sync_codes));
+ (void)strcat(cb, getcode(CTL_SYS_SOURCE(st) & ~CTL_SST_TS_PPS, sync_codes));
+ if (CTL_SYS_SOURCE(st) & CTL_SST_TS_PPS)
+ (void)strcat(cb, "/PPS");
(void)strcat(cb, ", ");
(void)strcat(cb, getevents(CTL_SYS_NEVNT(st)));
(void)strcat(cb, ", ");
@@ -2853,7 +2820,7 @@ outputarr(fp, name, narr, lfp)
static char *
tstflags(val)
- U_LONG val;
+ u_long val;
{
register char *cb, *s;
register int i;
@@ -2865,7 +2832,7 @@ tstflags(val)
if (++nextcb >= NUMCB)
nextcb = 0;
- sprintf(cb, "0x%x", val);
+ sprintf(cb, "0x%lx", val);
cb += strlen(cb);
if (val <= ((1<<8)-1)) {
if (!val) {
@@ -2909,8 +2876,9 @@ cookedprint(datatype, length, data, status, fp)
int fmt;
struct ctl_var *varlist;
l_fp lfp;
- LONG ival;
- U_LONG uval;
+ long ival;
+ u_long hval;
+ u_long uval;
l_fp lfparr[8];
int narr;
@@ -2986,12 +2954,12 @@ cookedprint(datatype, length, data, status, fp)
case HA:
case NA:
- if (!decodenetnum(value, &uval))
+ if (!decodenetnum(value, &hval))
output_raw = '?';
else if (fmt == HA)
- output(fp, name, nntohost(uval));
+ output(fp, name, nntohost(hval));
else
- output(fp, name, numtoa(uval));
+ output(fp, name, numtoa(hval));
break;
case ST:
@@ -2999,8 +2967,8 @@ cookedprint(datatype, length, data, status, fp)
break;
case RF:
- if (decodenetnum(value, &uval))
- output(fp, name, nntohost(uval));
+ if (decodenetnum(value, &hval))
+ output(fp, name, nntohost(hval));
else if ((int)strlen(value) <= 4)
output(fp, name, value);
else
@@ -3028,7 +2996,7 @@ cookedprint(datatype, length, data, status, fp)
else {
char b[10];
- (void) sprintf(b, "%03o", uval);
+ (void) sprintf(b, "%03lo", uval);
output(fp, name, b);
}
break;
diff --git a/usr.sbin/xntpd/ntpq/ntpq.h b/usr.sbin/xntpd/ntpq/ntpq.h
index edfc9b599028..c233b240ec5f 100644
--- a/usr.sbin/xntpd/ntpq/ntpq.h
+++ b/usr.sbin/xntpd/ntpq/ntpq.h
@@ -1,4 +1,4 @@
-/* ntpq.h,v 3.1 1993/07/06 01:09:30 jbj Exp
+/*
* ntpq.h - definitions of interest to ntpq
*/
#include "ntp_fp.h"
@@ -28,9 +28,9 @@
*/
typedef union {
char *string;
- LONG ival;
- U_LONG uval;
- U_LONG netnum;
+ long ival;
+ u_long uval;
+ u_long netnum;
} arg_v;
/*
@@ -84,14 +84,14 @@ struct ctl_var {
};
extern void asciize P((int, char *, FILE *));
-extern int getnetnum P((char *, U_LONG *, char *));
+extern int getnetnum P((char *, u_long *, char *));
extern void sortassoc P((void));
extern int doquery P((int, int, int, int, char *, u_short *, int *, char **));
-extern char * nntohost P((U_LONG));
+extern char * nntohost P((u_long));
extern int decodets P((char *, l_fp *));
-extern int decodeuint P((char *, U_LONG *));
+extern int decodeuint P((char *, u_long *));
extern int nextvar P((int *, char **, char **, char **));
extern int decodetime P((char *, l_fp *));
extern void printvars P((int, char *, int, int, FILE *));
-extern int decodeint P((char *, LONG *));
+extern int decodeint P((char *, long *));
extern int findvar P((char *, struct ctl_var *));
diff --git a/usr.sbin/xntpd/ntpq/ntpq_ops.c b/usr.sbin/xntpd/ntpq/ntpq_ops.c
index 395a9ecfd914..8bab73df576f 100644
--- a/usr.sbin/xntpd/ntpq/ntpq_ops.c
+++ b/usr.sbin/xntpd/ntpq/ntpq_ops.c
@@ -1,4 +1,4 @@
-/* ntpq_ops.c,v 3.1 1993/07/06 01:09:32 jbj Exp
+/*
* ntpdc_ops.c - subroutines which are called to perform operations by xntpdc
*/
#include <stdio.h>
@@ -18,7 +18,7 @@ int maxhostlen;
/*
* Declarations for command handlers in here
*/
-static int checkassocid P((U_LONG));
+static int checkassocid P((u_long));
static char * strsave P((char *));
static struct varlist *findlistvar P((struct varlist *, char *));
static void doaddvlist P((struct varlist *, char *));
@@ -38,7 +38,7 @@ static void readvar P((struct parse *, FILE *));
static void writevar P((struct parse *, FILE *));
static void clocklist P((struct parse *, FILE *));
static void clockvar P((struct parse *, FILE *));
-static int findassidrange P((U_LONG, U_LONG, int *, int *));
+static int findassidrange P((u_long, u_long, int *, int *));
static void mreadlist P((struct parse *, FILE *));
static void mreadvar P((struct parse *, FILE *));
static int dogetassoc P((FILE *));
@@ -159,7 +159,7 @@ struct xcmd opcmds[] = {
* Variable list data space
*/
#define MAXLIST 64 /* maximum number of variables in list */
-#define LENHOSTNAME 256 /* host name is 256 characters LONG */
+#define LENHOSTNAME 256 /* host name is 256 characters long */
/*
* Old CTL_PST defines for version 2.
*/
@@ -205,7 +205,7 @@ extern u_char pktversion;
*/
static int
checkassocid(value)
- U_LONG value;
+ u_long value;
{
if (value == 0 || value >= 65536) {
(void) fprintf(stderr, "***Invalid association ID specified\n");
@@ -706,8 +706,8 @@ clockvar(pcmd, fp)
*/
static int
findassidrange(assid1, assid2, from, to)
- U_LONG assid1;
- U_LONG assid2;
+ u_long assid1;
+ u_long assid2;
int *from;
int *to;
{
@@ -716,13 +716,13 @@ findassidrange(assid1, assid2, from, to)
if (assid1 == 0 || assid1 > 65535) {
(void) fprintf(stderr,
- "***Invalid association ID %lu specified\n", assid1);
+ "***Invalid association ID %lu specified\n", (u_long)assid1);
return 0;
}
if (assid2 == 0 || assid2 > 65535) {
(void) fprintf(stderr,
- "***Invalid association ID %lu specified\n", assid2);
+ "***Invalid association ID %lu specified\n", (u_long)assid2);
return 0;
}
@@ -743,7 +743,7 @@ findassidrange(assid1, assid2, from, to)
if (f == -1 || t == -1) {
(void) fprintf(stderr,
"***Association ID %lu not found in list\n",
- (f == -1) ? assid1 : assid2);
+ (f == -1) ? (u_long)assid1 : (u_long)assid2);
return 0;
}
@@ -876,7 +876,7 @@ printassoc(showall, fp)
int i;
u_char statval;
int event;
- U_LONG event_count;
+ u_long event_count;
char *conf;
char *reach;
char *auth;
@@ -1028,7 +1028,7 @@ associations(pcmd, fp)
/*
- * lassociations - get, record and print a LONG list of associations
+ * lassociations - get, record and print a long list of associations
*/
/*ARGSUSED*/
static void
@@ -1055,7 +1055,7 @@ passociations(pcmd, fp)
/*
- * lpassociations - print the LONG association list
+ * lpassociations - print the long association list
*/
/*ARGSUSED*/
static void
@@ -1146,7 +1146,7 @@ fixup(width, str)
/*
- * when - print how LONG its been since his last packet arrived
+ * when - print how long its been since his last packet arrived
*/
static char *
when(ts, rec, reftime)
@@ -1154,7 +1154,7 @@ when(ts, rec, reftime)
l_fp *rec;
l_fp *reftime;
{
- LONG diff;
+ long diff;
l_fp *lasttime;
static char buf[20];
@@ -1165,7 +1165,7 @@ when(ts, rec, reftime)
else
return "-";
- diff = (LONG)(ts->l_ui - lasttime->l_ui);
+ diff = (long)(ts->l_ui - lasttime->l_ui);
if (diff <= 0) {
/*
* Time warp?
@@ -1174,24 +1174,24 @@ when(ts, rec, reftime)
}
if (diff <= 2048) {
- (void) sprintf(buf, "%d", diff);
+ (void) sprintf(buf, "%ld", (long int)diff);
return buf;
}
diff = (diff + 29) / 60;
if (diff <= 300) {
- (void) sprintf(buf, "%dm", diff);
+ (void) sprintf(buf, "%ldm", (long int)diff);
return buf;
}
diff = (diff + 29) / 60;
if (diff <= 96) {
- (void) sprintf(buf, "%dh", diff);
+ (void) sprintf(buf, "%ldh", (long int)diff);
return buf;
}
diff = (diff + 11) / 24;
- (void) sprintf(buf, "%dd", diff);
+ (void) sprintf(buf, "%ldd", (long int)diff);
return buf;
}
@@ -1264,14 +1264,14 @@ doprintpeers(pvl, associd, rstatus, datalen, data, fp)
int i;
int c;
- U_LONG srcadr;
- U_LONG dstadr;
- U_LONG srcport;
+ u_long srcadr;
+ u_long dstadr;
+ u_long srcport;
char *dstadr_refid = "0.0.0.0";
- U_LONG stratum;
- LONG ppoll;
- LONG hpoll;
- U_LONG reach;
+ u_long stratum;
+ long ppoll;
+ long hpoll;
+ u_long reach;
l_fp estdelay;
l_fp estoffset;
l_fp estdisp;
@@ -1279,7 +1279,8 @@ doprintpeers(pvl, associd, rstatus, datalen, data, fp)
l_fp reftime;
l_fp ts;
u_char havevar[MAXHAVE];
- U_LONG poll;
+ u_long poll;
+ char type = '?';
char refid_string[10];
extern struct ctl_var peer_var[];
@@ -1287,6 +1288,7 @@ doprintpeers(pvl, associd, rstatus, datalen, data, fp)
gettstamp(&ts);
while (nextvar(&datalen, &data, &name, &value)) {
+ u_long dummy;
i = findvar(name, peer_var);
if (i == 0)
continue; /* don't know this one */
@@ -1296,6 +1298,14 @@ doprintpeers(pvl, associd, rstatus, datalen, data, fp)
havevar[HAVE_SRCADR] = 1;
break;
case CP_DSTADR:
+ if (decodenetnum(value, &dummy)) {
+ dummy = ntohl(dummy);
+ type = ((dummy&0xf0000000)==0xe0000000) ? 'm' :
+ ((dummy&0x000000ff)==0x000000ff) ? 'b' :
+ ((dummy&0xffffffff)==0x7f000001) ? 'l' :
+ ((dummy&0xffffffe0)==0x00000000) ? '-' :
+ 'u';
+ }
if (pvl == opeervarlist) {
if (decodenetnum(value, &dstadr)) {
havevar[HAVE_DSTADR] = 1;
@@ -1370,7 +1380,7 @@ doprintpeers(pvl, associd, rstatus, datalen, data, fp)
case CP_REFTIME:
havevar[HAVE_REFTIME] = 1;
if (!decodets(value, &reftime))
- reftime.l_ui = reftime.l_uf = 0;
+ L_CLR(&reftime);
break;
default:
break;
@@ -1408,11 +1418,10 @@ doprintpeers(pvl, associd, rstatus, datalen, data, fp)
if (numhosts > 1)
(void) fprintf(fp, "%-*s ", maxhostlen, currenthost);
(void) fprintf(fp,
- "%c%-15.15s %-15.15s %2d %4.4s %4d %3o %7.7s %7.7s %7.7s\n",
- c, nntohost(srcadr), dstadr_refid, stratum,
- when(&ts, &rec, &reftime),
- poll, reach, fixup(7, lfptoms(&estdelay, 2)),
- fixup(7, lfptoms(&estoffset, 2)),
+ "%c%-15.15s %-15.15s %2ld %c %4.4s %4ld %3lo %7.7s %8.7s %7.7s\n",
+ c, nntohost(srcadr), dstadr_refid, stratum, type,
+ when(&ts, &rec, &reftime), poll, reach,
+ fixup(7, lfptoms(&estdelay, 2)), fixup(8, lfptoms(&estoffset, 3)),
fixup(7, lfptoms(&estdisp, 2)));
return 1;
}
@@ -1484,7 +1493,7 @@ dopeers(showall, fp)
{
register int i;
char fullname[LENHOSTNAME];
- U_LONG netnum;
+ u_long netnum;
if (!dogetassoc(fp))
@@ -1498,12 +1507,12 @@ dopeers(showall, fp)
if (numhosts > 1)
(void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "host");
(void) fprintf(fp,
-" remote refid st when poll reach delay offset disp\n");
+" remote refid st t when poll reach delay offset disp\n");
if (numhosts > 1)
for (i = 0; i <= maxhostlen; ++i)
(void) fprintf(fp, "=");
(void) fprintf(fp,
-"===========================================================================\n");
+"==============================================================================\n");
for (i = 0; i < numassoc; i++) {
if (!showall &&
@@ -1558,9 +1567,9 @@ doopeers(showall, fp)
return;
(void) fprintf(fp,
-" remote local st when poll reach delay offset disp\n");
+" remote local st t when poll reach delay offset disp\n");
(void) fprintf(fp,
-"=========================================================================\n");
+"===========================================================================\n");
for (i = 0; i < numassoc; i++) {
if (!showall &&
diff --git a/usr.sbin/xntpd/ntptrace/Makefile.tmpl b/usr.sbin/xntpd/ntptrace/Makefile.tmpl
index c98482da06ec..ca321f13931d 100644
--- a/usr.sbin/xntpd/ntptrace/Makefile.tmpl
+++ b/usr.sbin/xntpd/ntptrace/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:09:37 jbj Exp
+# Makefile.tmpl
#
PROGRAM= ntptrace
#
diff --git a/usr.sbin/xntpd/ntptrace/ntptrace.c b/usr.sbin/xntpd/ntptrace/ntptrace.c
index 6454ec1df1f4..b4c5c57138af 100644
--- a/usr.sbin/xntpd/ntptrace/ntptrace.c
+++ b/usr.sbin/xntpd/ntptrace/ntptrace.c
@@ -1,4 +1,4 @@
-/* ntptrace.c,v 3.1 1993/07/06 01:09:38 jbj Exp
+/*
* ntptrace - show the chain from an NTP host leading back to
* its source of time
*
@@ -56,7 +56,7 @@ char *progname;
* Systemwide parameters and flags
*/
int sys_retries = 5; /* # of retry attempts per server */
-U_LONG sys_timeout = 2; /* timeout time, in seconds */
+int sys_timeout = 2; /* timeout time, in seconds */
struct server **sys_servers; /* the server list */
int sys_numservers = 0; /* number of servers to poll */
int sys_maxservers = NTP_MAXSTRATUM+1; /* max number of servers to deal with */
@@ -68,7 +68,7 @@ int sys_version = NTP_OLDVERSION; /* version to poll with */
struct recvbuf *freelist; /* free buffers */
struct recvbuf *fulllist; /* buffers with data */
-int full_recvbufs; /* number of full ones */
+int full_recvbufs; /* number of full ones */
int free_recvbufs;
/*
@@ -94,8 +94,8 @@ static struct server *addservbyname P((char *));
static void setup_io P((void));
static void freerecvbuf P((struct recvbuf *));
static void sendpkt P((struct sockaddr_in *, struct pkt *, int));
-static int getipaddr P((char *, U_LONG *));
-static int decodeipaddr P((char *, U_LONG *));
+static int getipaddr P((char *, long *));
+static int decodeipaddr P((char *, long *));
static void printserver P((struct server *, FILE *));
static void printrefid P((FILE *, struct server *));
@@ -253,9 +253,9 @@ register struct server *server;
xpkt.rootdelay = htonl(NTPTRACE_DISTANCE);
xpkt.rootdispersion = htonl(NTPTRACE_DISP);
xpkt.refid = htonl(NTPTRACE_REFID);
- xpkt.reftime.l_ui = xpkt.reftime.l_uf = 0;
- xpkt.org.l_ui = xpkt.org.l_uf = 0;
- xpkt.rec.l_ui = xpkt.rec.l_uf = 0;
+ L_CLR(&xpkt.reftime);
+ L_CLR(&xpkt.org);
+ L_CLR(&xpkt.rec);
/*
* just timestamp packet and send it away.
@@ -351,8 +351,7 @@ ReceiveBuf(server, rbufp)
{
register struct pkt *rpkt;
register s_fp di;
- register U_LONG t10_ui, t10_uf;
- register U_LONG t23_ui, t23_uf;
+ l_fp t10, t23;
l_fp org;
l_fp rec;
l_fp ci;
@@ -431,7 +430,7 @@ ReceiveBuf(server, rbufp)
* Make sure the server is at least somewhat sane. If not, try
* again.
*/
- if ((rec.l_ui == 0 && rec.l_uf == 0) || !L_ISHIS(&server->org, &rec)) {
+ if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
return(0);
}
@@ -442,27 +441,23 @@ ReceiveBuf(server, rbufp)
* d = (t2 - t3) - (t1 - t0)
* c = ((t2 - t3) + (t1 - t0)) / 2
*/
- t10_ui = server->org.l_ui; /* pkt.xmt == t1 */
- t10_uf = server->org.l_uf;
- M_SUB(t10_ui, t10_uf, rbufp->recv_time.l_ui,
- rbufp->recv_time.l_uf); /* recv_time == t0*/
+ t10 = server->org; /* pkt.xmt == t1 */
+ L_SUB(&t10, &rbufp->recv_time); /* recv_time == t0*/
- t23_ui = rec.l_ui; /* pkt.rec == t2 */
- t23_uf = rec.l_uf;
- M_SUB(t23_ui, t23_uf, org.l_ui, org.l_uf); /* pkt->org == t3 */
+ t23 = rec; /* pkt.rec == t2 */
+ L_SUB(&t23, &org); /* pkt->org == t3 */
/* now have (t2 - t3) and (t0 - t1). Calculate (ci) and (di) */
- ci.l_ui = t10_ui;
- ci.l_uf = t10_uf;
- M_ADD(ci.l_ui, ci.l_uf, t23_ui, t23_uf);
- M_RSHIFT(ci.l_i, ci.l_uf);
+ ci = t10;
+ L_ADD(&ci, &t23);
+ L_RSHIFT(&ci);
/*
* 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);
+ L_SUB(&t23, &t10);
+ di = LFPTOFP(&t23);
server->offset = ci;
server->delay = di;
@@ -520,7 +515,7 @@ static struct server *
addservbyname(serv)
char *serv;
{
- U_LONG ipaddr;
+ long ipaddr;
struct in_addr ia;
if (!getipaddr(serv, &ipaddr)) {
@@ -609,14 +604,14 @@ sendpkt(dest, pkt, len)
static int
getipaddr(host, num)
char *host;
- U_LONG *num;
+ long *num;
{
struct hostent *hp;
if (decodeipaddr(host, num)) {
return 1;
} else if ((hp = gethostbyname(host)) != 0) {
- memmove((char *)num, hp->h_addr, sizeof(U_LONG));
+ memmove((char *)num, hp->h_addr, sizeof(long));
return 1;
}
return 0;
@@ -628,7 +623,7 @@ getipaddr(host, num)
static int
decodeipaddr(num, ipaddr)
char *num;
- U_LONG *ipaddr;
+ long *ipaddr;
{
register char *cp;
register char *bp;
@@ -682,8 +677,8 @@ printserver(pp, fp)
if (!verbose) {
(void) fprintf(fp, "stratum %d, offset %s, synch distance %s",
pp->stratum,
- lfptoa(&pp->offset, 7),
- ufptoa(synchdist, 7));
+ lfptoa(&pp->offset, 6),
+ ufptoa(synchdist, 5));
if (pp->stratum == 1) {
(void) fprintf(fp, ", refid ");
printrefid(fp, pp);
@@ -705,14 +700,14 @@ printserver(pp, fp)
(void) fprintf(fp,
" delay %s, dispersion %s ",
- fptoa(pp->delay, 7),
- ufptoa(pp->dispersion, 4));
+ fptoa(pp->delay, 5),
+ ufptoa(pp->dispersion, 5));
(void) fprintf(fp, "offset %s\n",
- lfptoa(&pp->offset, 7));
+ lfptoa(&pp->offset, 6));
(void) fprintf(fp, "rootdelay %s, rootdispersion %s",
- fptoa(pp->rootdelay, 7), ufptoa(pp->rootdispersion, 4));
+ fptoa(pp->rootdelay, 5), ufptoa(pp->rootdispersion, 5));
(void) fprintf(fp, ", synch dist %s\n",
- ufptoa(synchdist, 7));
+ ufptoa(synchdist, 5));
(void) fprintf(fp, "reference time: %s\n",
prettydate(&pp->reftime));
diff --git a/usr.sbin/xntpd/ntptrace/ntptrace.h b/usr.sbin/xntpd/ntptrace/ntptrace.h
index 3367c226a89d..65b72fb71c66 100644
--- a/usr.sbin/xntpd/ntptrace/ntptrace.h
+++ b/usr.sbin/xntpd/ntptrace/ntptrace.h
@@ -1,4 +1,4 @@
-/* ntptrace.h,v 3.1 1993/07/06 01:09:39 jbj Exp
+/*
* ntptrace.h - declarations for the ntptrace program
*/
diff --git a/usr.sbin/xntpd/parse/Makefile.kernel b/usr.sbin/xntpd/parse/Makefile.kernel
index aceb0a5bb639..4cd0acede737 100644
--- a/usr.sbin/xntpd/parse/Makefile.kernel
+++ b/usr.sbin/xntpd/parse/Makefile.kernel
@@ -2,7 +2,7 @@
# very simple makefile (SunOS!)
#
# Possible defines:
-# DEBUG_DCF: include debug code (STREAMS mechanism and parsing)
+# DEBUG_PARSE: include debug code (STREAMS mechanism and parsing)
# DEBUG_CD: include signal propagation to sun4c LED (sun4c only)
#
# Possible defines (parsestreams variants only):
@@ -30,19 +30,19 @@ parse: parsesolaris.c libparse_kernel.a ../lib/libntp.a
ld -r -o parse parsesolaris.o libparse_kernel.a ../lib/libntp.a
@echo "--- Install 'parse' in /kernel/strmod for automatic loading"
-mparsestreams.o: mparsestreams.o.$(KARCH)
- @echo "--- You may load mparsestreams.o.$(KARCH) via 'modload mparsestreams.o.$(KARCH)' into the kernel"
+mparsestreams.o: mparsestreams.$(KARCH).o
+ @echo "--- You may load mparsestreams.$(KARCH).o via 'modload mparsestreams.$(KARCH).o' into the kernel"
-mparsestreams.o.$(KARCH): parsestreams.c microtime.o ../lib/libntp.a libparse_kernel.a ../include/parse.h ../include/sys/parsestreams.h
+mparsestreams.$(KARCH).o: parsestreams.c microtime.o ../lib/libntp.a libparse_kernel.a ../include/parse.h ../include/sys/parsestreams.h
cc -c -DMICROTIME $(DEFS) -I../include parsestreams.c
ld -r -o $@ parsestreams.o ../lib/libntp.a libparse_kernel.a \
microtime.o
rm -f parsestreams.o
-parsestreams.o: parsestreams.o.$(KARCH)
- @echo "--- You may load parsestreams.o.$(KARCH) via 'modload parsestreams.o' (put in e.g. /sys/<karch>/OBJ) into the kernel"
+parsestreams.o: parsestreams.$(KARCH).o
+ @echo "--- You may load parsestreams.$(KARCH).o via 'modload parsestreams.o' (put in e.g. /sys/<karch>/OBJ) into the kernel"
-parsestreams.o.$(KARCH): parsestreams.c ../lib/libntp.a libparse_kernel.a ../include/parse.h ../include/sys/parsestreams.h
+parsestreams.$(KARCH).o: parsestreams.c ../lib/libntp.a libparse_kernel.a ../include/parse.h ../include/sys/parsestreams.h
cc -c $(DEFS) -I../include parsestreams.c
ld -r -o $@ parsestreams.o ../lib/libntp.a libparse_kernel.a
rm -f parsestreams.o
diff --git a/usr.sbin/xntpd/parse/Makefile.tmpl b/usr.sbin/xntpd/parse/Makefile.tmpl
index 29a3029eb147..781fed69e5d1 100644
--- a/usr.sbin/xntpd/parse/Makefile.tmpl
+++ b/usr.sbin/xntpd/parse/Makefile.tmpl
@@ -22,10 +22,10 @@ CFLAGS= $(COPTS) $(DEFS) $(DEFS_LOCAL) $(INCL)
CC= $(COMPILER)
#
SOURCE= parse.c parse_conf.c clk_meinberg.c clk_schmid.c clk_rawdcf.c \
- clk_dcf7000.c clk_trimble.c
+ clk_dcf7000.c clk_trimtaip.c clk_trimtsip.c
OBJS= parse.o parse_conf.o clk_meinberg.o clk_schmid.o clk_rawdcf.o \
- clk_dcf7000.o clk_trimble.o
+ clk_dcf7000.o clk_trimtaip.o clk_trimtsip.o
all:
@echo $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) | \
diff --git a/usr.sbin/xntpd/parse/README.new_clocks b/usr.sbin/xntpd/parse/README.new_clocks
index 8fdd7cbd4250..5b2d29e67816 100644
--- a/usr.sbin/xntpd/parse/README.new_clocks
+++ b/usr.sbin/xntpd/parse/README.new_clocks
@@ -15,16 +15,16 @@ Make a conversion module (parse/clk_*.c)
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 */
+ 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 */
+ long flags; /* current clock status */
};
Conversion is usually simple and straight forward. For the flags following
@@ -87,14 +87,14 @@ Make a conversion module (parse/clk_*.c)
struct clockformat
{
- unsigned LONG (*convert)();
+ u_long (*convert)();
/* conversion routine - your routine - cvt_<yourclock> */
void (*syncevt)();
/* routine for handling RS232 sync events (time stamps) - usually sync_simple */
- unsigned LONG (*syncpps)();
+ u_long (*syncpps)();
/* PPS input routine - usually pps_simple */
- unsigned LONG (*synth)();
- /* time code synthesizer - usually not used - (LONG (*)())0 */
+ u_long (*synth)();
+ /* time code synthesizer - usually not used - (long (*)())0 */
void *data;
/* local parameters - any parameters/data/configuration info your conversion
routine might need */
@@ -102,7 +102,7 @@ struct clockformat
/* clock format name - Name of the time code */
unsigned short length;
/* maximum length of data packet for your clock format */
- unsigned LONG flags;
+ u_long flags;
/* information for the parser what to look for */
struct timeval timeout;
/* buffer restart after timeout (us) - some clocks preceede new data by
@@ -148,7 +148,7 @@ xntpd/refclock_parse.c
(see all the other clocks for example)
struct clockinfo
{
- U_LONG cl_flags; /* operation flags (io modes) */
+ 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)
@@ -166,10 +166,10 @@ xntpd/refclock_parse.c
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
+ 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
+ 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") */
@@ -181,14 +181,14 @@ xntpd/refclock_parse.c
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
+ 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 */
+ 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>,...
diff --git a/usr.sbin/xntpd/parse/clk_dcf7000.c b/usr.sbin/xntpd/parse/clk_dcf7000.c
index 8b55e2f23280..208e52932ae0 100644
--- a/usr.sbin/xntpd/parse/clk_dcf7000.c
+++ b/usr.sbin/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.11 1994/02/02 17:45:14 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_dcf7000.c,v 3.12 1994/05/30 10:19:57 kardel Exp
*
- * clk_dcf7000.c,v 3.11 1994/02/02 17:45:14 kardel Exp
+ * clk_dcf7000.c,v 3.12 1994/05/30 10:19:57 kardel Exp
*
* ELV DCF7000 module
*
@@ -35,18 +35,20 @@ static struct format dcf7000_fmt =
0
};
-static unsigned LONG cvt_dcf7000();
+static u_long cvt_dcf7000();
clockformat_t clock_dcf7000 =
{
+ (unsigned LONG (*)())0, /* no input handling */
cvt_dcf7000, /* ELV DCF77 conversion */
syn_simple, /* easy time stamps */
- (unsigned LONG (*)())0, /* no direct PPS monitoring */
- (unsigned LONG (*)())0, /* no time code synthesizer monitoring */
+ (u_long (*)())0, /* no direct PPS monitoring */
+ (u_long (*)())0, /* no time code synthesizer monitoring */
(void *)&dcf7000_fmt, /* conversion configuration */
"ELV DCF7000", /* ELV clock */
24, /* string buffer */
F_END|SYNC_END, /* END packet delimiter / synchronisation */
+ 0, /* no private data (complete pakets) */
{ 0, 0},
'\0',
'\r',
@@ -58,7 +60,7 @@ clockformat_t clock_dcf7000 =
*
* convert dcf7000 type format
*/
-static unsigned LONG
+static u_long
cvt_dcf7000(buffer, size, format, clock)
register char *buffer;
register int size;
@@ -89,7 +91,7 @@ cvt_dcf7000(buffer, size, format, clock)
else
{
char *f = &buffer[format->field_offsets[O_FLAGS].offset];
- LONG flags;
+ long flags;
clock->flags = 0;
clock->usecond = 0;
@@ -121,6 +123,9 @@ cvt_dcf7000(buffer, size, format, clock)
* History:
*
* clk_dcf7000.c,v
+ * Revision 3.12 1994/05/30 10:19:57 kardel
+ * LONG cleanup
+ *
* Revision 3.11 1994/02/02 17:45:14 kardel
* rcs ids fixed
*
diff --git a/usr.sbin/xntpd/parse/clk_meinberg.c b/usr.sbin/xntpd/parse/clk_meinberg.c
index 69f88b90d30e..6e3b22453bc9 100644
--- a/usr.sbin/xntpd/parse/clk_meinberg.c
+++ b/usr.sbin/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.14 1994/02/20 13:04:37 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_meinberg.c,v 3.15 1994/05/30 10:19:59 kardel Exp
*
- * clk_meinberg.c,v 3.14 1994/02/20 13:04:37 kardel Exp
+ * clk_meinberg.c,v 3.15 1994/05/30 10:19:59 kardel Exp
*
* Meinberg clock support
*
@@ -136,48 +136,54 @@ static struct format meinberg_fmt[] =
}
};
-static unsigned LONG cvt_meinberg();
-static unsigned LONG cvt_mgps();
+static u_long cvt_meinberg();
+static u_long cvt_mgps();
clockformat_t clock_meinberg[] =
{
{
+ (unsigned LONG (*)())0, /* no input handling */
cvt_meinberg, /* Meinberg conversion */
syn_simple, /* easy time stamps for RS232 (fallback) */
pps_simple, /* easy PPS monitoring */
- (unsigned LONG (*)())0, /* no time code synthesizer monitoring */
+ (u_long (*)())0, /* no time code synthesizer monitoring */
(void *)&meinberg_fmt[0], /* conversion configuration */
"Meinberg Standard", /* Meinberg simple format - beware */
32, /* string buffer */
F_START|F_END|SYNC_START|SYNC_ONE, /* paket START/END delimiter, START synchronisation, PPS ONE sampling */
+ 0, /* no private data (complete pakets) */
{ 0, 0},
'\2',
'\3',
'\0'
},
{
+ (unsigned LONG (*)())0, /* no input handling */
cvt_meinberg, /* Meinberg conversion */
syn_simple, /* easy time stamps for RS232 (fallback) */
pps_simple, /* easy PPS monitoring */
- (unsigned LONG (*)())0, /* no time code synthesizer monitoring */
+ (u_long (*)())0, /* no time code synthesizer monitoring */
(void *)&meinberg_fmt[1], /* conversion configuration */
"Meinberg Extended", /* Meinberg enhanced format */
32, /* string buffer */
F_START|F_END|SYNC_START|SYNC_ONE, /* paket START/END delimiter, START synchronisation, PPS ONE sampling */
+ 0, /* no private data (complete pakets) */
{ 0, 0},
'\2',
'\3',
'\0'
},
{
+ (unsigned LONG (*)())0, /* no input handling */
cvt_mgps, /* Meinberg GPS166 conversion */
syn_simple, /* easy time stamps for RS232 (fallback) */
pps_simple, /* easy PPS monitoring */
- (unsigned LONG (*)())0, /* no time code synthesizer monitoring */
+ (u_long (*)())0, /* no time code synthesizer monitoring */
(void *)&meinberg_fmt[2], /* conversion configuration */
"Meinberg GPS Extended", /* Meinberg FAU GPS format */
70, /* string buffer */
F_START|F_END|SYNC_START|SYNC_ONE, /* paket START/END delimiter, START synchronisation, PPS ONE sampling */
+ 0, /* no private data (complete pakets) */
{ 0, 0},
'\2',
'\3',
@@ -190,7 +196,7 @@ clockformat_t clock_meinberg[] =
*
* convert simple type format
*/
-static unsigned LONG
+static u_long
cvt_meinberg(buffer, size, format, clock)
register char *buffer;
register int size;
@@ -305,7 +311,7 @@ cvt_meinberg(buffer, size, format, clock)
*
* convert Meinberg GPS format
*/
-static unsigned LONG
+static u_long
cvt_mgps(buffer, size, format, clock)
register char *buffer;
register int size;
@@ -335,7 +341,7 @@ cvt_mgps(buffer, size, format, clock)
}
else
{
- LONG h;
+ long h;
char *f = &buffer[format->field_offsets[O_FLAGS].offset];
clock->flags = PARSEB_S_LEAP|PARSEB_S_POSITION;
@@ -422,6 +428,9 @@ cvt_mgps(buffer, size, format, clock)
* History:
*
* clk_meinberg.c,v
+ * Revision 3.15 1994/05/30 10:19:59 kardel
+ * LONG cleanup
+ *
* Revision 3.14 1994/02/20 13:04:37 kardel
* parse add/delete second support
*
diff --git a/usr.sbin/xntpd/parse/clk_rawdcf.c b/usr.sbin/xntpd/parse/clk_rawdcf.c
index 6b02031b6394..296af9e22b02 100644
--- a/usr.sbin/xntpd/parse/clk_rawdcf.c
+++ b/usr.sbin/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.13 1994/03/10 19:00:43 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_rawdcf.c,v 3.16 1994/05/31 20:02:40 kardel Exp
*
- * clk_rawdcf.c,v 3.13 1994/03/10 19:00:43 kardel Exp
+ * clk_rawdcf.c,v 3.16 1994/05/31 20:02:40 kardel Exp
*
* Raw DCF77 pulse clock support
*
@@ -79,12 +79,13 @@
* 59 - usually missing (minute indication), except for leap insertion
*/
-static unsigned LONG cvt_rawdcf();
-static unsigned LONG pps_rawdcf();
-static unsigned LONG snt_rawdcf();
+static u_long cvt_rawdcf();
+static u_long pps_rawdcf();
+static u_long snt_rawdcf();
clockformat_t clock_rawdcf =
{
+ (unsigned LONG (*)())0, /* no input handling */
cvt_rawdcf, /* raw dcf input conversion */
(void (*)())0, /* no character bound synchronisation */
pps_rawdcf, /* examining PPS information */
@@ -94,6 +95,7 @@ clockformat_t clock_rawdcf =
61, /* bit buffer */
SYNC_ONE|SYNC_ZERO|SYNC_TIMEOUT|SYNC_SYNTHESIZE|CVT_FIXEDONLY,
/* catch all transitions, buffer restart on timeout, fixed configuration only */
+ 0, /* no private data (currently in input buffer) */
{ 1, 500000}, /* restart after 1.5 seconds */
'\0',
'\0',
@@ -155,12 +157,12 @@ static struct partab
#define DCF_Z_MET 0x2
#define DCF_Z_MED 0x1
-static unsigned LONG ext_bf(buf, idx, zero)
+static u_long ext_bf(buf, idx, zero)
register char *buf;
register int idx;
register char *zero;
{
- register unsigned LONG sum = 0;
+ register u_long sum = 0;
register int i, first;
first = rawdcfcode[idx].offset;
@@ -189,7 +191,7 @@ static unsigned pcheck(buf, idx, zero)
return psum;
}
-static unsigned LONG convert_rawdcf(buffer, size, dcfparam, clock)
+static u_long convert_rawdcf(buffer, size, dcfparam, clock)
register unsigned char *buffer;
register int size;
register struct dcfparam *dcfparam;
@@ -284,9 +286,9 @@ static unsigned LONG convert_rawdcf(buffer, size, dcfparam, clock)
if (ext_bf(buffer, DCF_R, dcfparam->zerobits))
clock->flags |= PARSEB_ALTERNATE;
- parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%x\n",
- clock->hour, clock->minute, clock->day, clock->month, clock->year,
- clock->flags));
+ parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%lx\n",
+ (int)clock->hour, (int)clock->minute, (int)clock->day, (int)clock->month,(int) clock->year,
+ (u_long)clock->flags));
return CVT_OK;
}
else
@@ -307,7 +309,7 @@ static unsigned LONG convert_rawdcf(buffer, size, dcfparam, clock)
* raw dcf input routine - needs to fix up 50 baud
* characters for 1/0 decision
*/
-static unsigned LONG cvt_rawdcf(buffer, size, param, clock)
+static u_long cvt_rawdcf(buffer, size, param, clock)
register unsigned char *buffer;
register int size;
register void *param;
@@ -465,12 +467,12 @@ static unsigned LONG cvt_rawdcf(buffer, size, param, clock)
* also ones and zeros (which is easy)
*/
/*ARGSUSED*/
-static unsigned LONG pps_rawdcf(parseio, status, ptime)
+static u_long pps_rawdcf(parseio, status, ptime)
register parse_t *parseio;
register int status;
register timestamp_t *ptime;
{
- if (!status)
+ if (status)
{
parseio->parse_dtime.parse_ptime = *ptime;
parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
@@ -480,12 +482,12 @@ static unsigned LONG pps_rawdcf(parseio, status, ptime)
}
/*ARGSUSED*/
-static unsigned LONG snt_rawdcf(parseio, ptime)
+static u_long snt_rawdcf(parseio, ptime)
register parse_t *parseio;
register timestamp_t *ptime;
{
clocktime_t clock;
- unsigned LONG cvtrtc;
+ u_long cvtrtc;
time_t t;
/*
@@ -529,7 +531,16 @@ static unsigned LONG snt_rawdcf(parseio, ptime)
/*
* History:
*
- * clk_rawdcf.c,v
+ * clk_rawdcf.c,v $
+ * Revision 3.16 1994/05/31 20:02:40 kardel
+ * sync on ONE transition
+ *
+ * Revision 3.15 1994/05/30 10:20:01 kardel
+ * LONG cleanup
+ *
+ * Revision 3.14 1994/05/12 12:49:09 kardel
+ * printf fmt/arg cleanup
+ *
* Revision 3.13 1994/03/10 19:00:43 kardel
* clear utctime field to avoid confusion on synthesize time stamps
*
diff --git a/usr.sbin/xntpd/parse/clk_schmid.c b/usr.sbin/xntpd/parse/clk_schmid.c
index 8129474782bb..d15ba908da55 100644
--- a/usr.sbin/xntpd/parse/clk_schmid.c
+++ b/usr.sbin/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.13 1994/02/20 13:04:41 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/clk_schmid.c,v 3.16 1994/05/30 10:20:03 kardel Exp
*
- * clk_schmid.c,v 3.13 1994/02/20 13:04:41 kardel Exp
+ * clk_schmid.c,v 3.16 1994/05/30 10:20:03 kardel Exp
*
* Schmid clock support
*
@@ -58,18 +58,20 @@
#define WS_MEST 0x04
#define WS_LEAP 0x10
-static unsigned LONG cvt_schmid();
+static u_long cvt_schmid();
clockformat_t clock_schmid =
{
+ (unsigned LONG (*)())0, /* no input handling */
cvt_schmid, /* Schmid conversion */
syn_simple, /* easy time stamps */
- (unsigned LONG (*)())0, /* not direct PPS monitoring */
- (unsigned LONG (*)())0, /* no time code synthesizer monitoring */
+ (u_long (*)())0, /* not direct PPS monitoring */
+ (u_long (*)())0, /* no time code synthesizer monitoring */
(void *)0, /* conversion configuration */
"Schmid", /* Schmid receiver */
12, /* binary data buffer */
F_END|SYNC_START, /* END packet delimiter / synchronisation */
+ 0, /* no private data (complete messages) */
{ 0, 0},
'\0',
(unsigned char)'\375',
@@ -77,21 +79,20 @@ clockformat_t clock_schmid =
};
-static unsigned LONG
+static u_long
cvt_schmid(buffer, size, format, clock)
- register char *buffer;
+ register unsigned char *buffer;
register int size;
register struct format *format;
register clocktime_t *clock;
{
- if ((size != 11) || (buffer[10] != '\375'))
+ if ((size != 11) || (buffer[10] != (unsigned char)'\375'))
{
return CVT_NONE;
}
else
{
- if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] > 9 /* Time */
- || buffer[0] < 0 || buffer[1] < 0 || buffer[2] < 0 || buffer[3] < 0)
+ if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] > 9) /* Time */
{
return CVT_FAIL|CVT_BADTIME;
}
@@ -168,6 +169,15 @@ cvt_schmid(buffer, size, format, clock)
* History:
*
* clk_schmid.c,v
+ * Revision 3.16 1994/05/30 10:20:03 kardel
+ * LONG cleanup
+ *
+ * Revision 3.15 1994/05/12 12:34:48 kardel
+ * data type cleanup
+ *
+ * Revision 3.14 1994/04/12 14:56:31 kardel
+ * fix declaration
+ *
* Revision 3.13 1994/02/20 13:04:41 kardel
* parse add/delete second support
*
diff --git a/usr.sbin/xntpd/parse/clk_trimtaip.c b/usr.sbin/xntpd/parse/clk_trimtaip.c
new file mode 100644
index 000000000000..87538f1eb8a1
--- /dev/null
+++ b/usr.sbin/xntpd/parse/clk_trimtaip.c
@@ -0,0 +1,140 @@
+#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS)) && defined(CLOCK_TRIMTAIP)
+/*
+ * $Header: /src/NTP/REPOSITORY/v3/parse/clk_trimble.c,v 3.9 1994/02/02 17:45:27 kardel Exp $
+ *
+ * Trimble SV6 clock support
+ */
+
+#include "sys/types.h"
+#include "sys/time.h"
+#include "sys/errno.h"
+#include "ntp_fp.h"
+#include "ntp_unixtime.h"
+#include "ntp_calendar.h"
+
+#include "parse.h"
+
+/* 0000000000111111111122222222223333333 / char
+ * 0123456789012345678901234567890123456 \ posn
+ * >RTMhhmmssdddDDMMYYYYoodnnvrrrrr;*xx< Actual
+ * ----33445566600112222BB7__-_____--99- Parse
+ * >RTM 1 ;* <", Check
+ */
+
+#define hexval(x) (('0' <= (x) && (x) <= '9') ? (x) - '0' : \
+ ('a' <= (x) && (x) <= 'f') ? (x) - 'a' + 10 : \
+ ('A' <= (x) && (x) <= 'F') ? (x) - 'A' + 10 : \
+ -1)
+#define O_USEC O_WDAY
+#define O_GPSFIX O_FLAGS
+#define O_CHKSUM O_UTCHOFFSET
+static struct format trimsv6_fmt =
+{ { { 13, 2 }, {15, 2}, { 17, 4}, /* Day, Month, Year */
+ { 4, 2 }, { 6, 2}, { 8, 2}, /* Hour, Minute, Second */
+ { 10, 3 }, {23, 1}, { 0, 0}, /* uSec, FIXes (WeekDAY, FLAGS, ZONE) */
+ { 34, 2 }, { 0, 0}, { 21, 2}, /* cksum, -, utcS (UTC[HMS]OFFSET) */
+ },
+ ">RTM 1 ;* <",
+ 0
+};
+
+static unsigned LONG cvt_trimtaip();
+
+clockformat_t clock_trimtaip =
+{
+ (unsigned LONG (*)())0, /* no input handling */
+ cvt_trimtaip, /* Trimble conversion */
+ syn_simple, /* easy time stamps for RS232 (fallback) */
+ pps_simple, /* easy PPS monitoring */
+ (unsigned LONG (*)())0, /* no time code synthesizer monitoring */
+ (void *)&trimsv6_fmt, /* conversion configuration */
+ "Trimble SV6/TAIP",
+ 37, /* string buffer */
+ F_START|F_END|SYNC_START|SYNC_ONE, /* paket START/END delimiter, START synchronisation, PPS ONE sampling */
+ 0, /* no private data */
+ { 0, 0},
+ '>',
+ '<',
+ '\0'
+};
+
+static unsigned LONG
+cvt_trimtaip(buffer, size, format, clock)
+ register char *buffer;
+ register int size;
+ register struct format *format;
+ register clocktime_t *clock;
+{
+ LONG gpsfix;
+ u_char calc_csum = 0;
+ long recv_csum;
+ int i;
+
+ if (!Strok(buffer, format->fixed_string)) return CVT_NONE;
+#define OFFS(x) format->field_offsets[(x)].offset
+#define STOI(x, y) \
+ Stoi(&buffer[OFFS(x)], y, \
+ format->field_offsets[(x)].length)
+ if ( STOI(O_DAY, &clock->day) ||
+ STOI(O_MONTH, &clock->month) ||
+ STOI(O_YEAR, &clock->year) ||
+ STOI(O_HOUR, &clock->hour) ||
+ STOI(O_MIN, &clock->minute) ||
+ STOI(O_SEC, &clock->second) ||
+ STOI(O_USEC, &clock->usecond)||
+ STOI(O_GPSFIX, &gpsfix)
+ ) return CVT_FAIL|CVT_BADFMT;
+
+ clock->usecond *= 1000;
+ /* Check that the checksum is right */
+ for (i=OFFS(O_CHKSUM)-1; i >= 0; i--) calc_csum ^= buffer[i];
+ recv_csum = (hexval(buffer[OFFS(O_CHKSUM)]) << 4) |
+ hexval(buffer[OFFS(O_CHKSUM)+1]);
+ if (recv_csum < 0) return CVT_FAIL|CVT_BADTIME;
+ if (((u_char) recv_csum) != calc_csum) return CVT_FAIL|CVT_BADTIME;
+
+ clock->utcoffset = 0;
+
+ /* What should flags be set to ? */
+ clock->flags = PARSEB_UTC;
+
+ /* if the current GPS fix is 9 (unknown), reject */
+ if (0 > gpsfix || gpsfix > 9) clock->flags |= PARSEB_POWERUP;
+
+ return CVT_OK;
+}
+#endif /* defined(PARSE) && defined(CLOCK_TRIMTAIP) */
+
+/*
+ * History:
+ *
+ * $Log: 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
+ *
+ * Revision 3.6 1993/10/30 09:44:45 kardel
+ * conditional compilation flag cleanup
+ *
+ * Revision 3.5 1993/10/09 15:01:35 kardel
+ * file structure unified
+ *
+ * revision 3.4
+ * date: 1993/10/08 14:44:51; author: kardel;
+ * trimble - initial working version
+ *
+ * revision 3.3
+ * date: 1993/10/03 19:10:50; author: kardel;
+ * restructured I/O handling
+ *
+ * revision 3.2
+ * date: 1993/09/27 21:07:17; author: kardel;
+ * Trimble alpha integration
+ *
+ * revision 3.1
+ * date: 1993/09/26 23:40:29; author: kardel;
+ * new parse driver logic
+ *
+ */
diff --git a/usr.sbin/xntpd/parse/clk_trimtsip.c b/usr.sbin/xntpd/parse/clk_trimtsip.c
new file mode 100644
index 000000000000..f622beac08db
--- /dev/null
+++ b/usr.sbin/xntpd/parse/clk_trimtsip.c
@@ -0,0 +1,471 @@
+#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS)) && defined(CLOCK_TRIMTSIP)
+/*
+ * $Header: /src/NTP/REPOSITORY/v3/parse/clk_trimble.c,v 3.9 1994/02/02 17:45:27 kardel Exp $
+ *
+ * Trimble TSIP support - CURRENTLY VERY MUCH UNDER CONSTRUCTION
+ */
+
+#include "sys/types.h"
+#include "sys/time.h"
+#include "sys/errno.h"
+
+#include "ntp_syslog.h"
+#include "ntp_types.h"
+#include "ntp_fp.h"
+#include "ntp_unixtime.h"
+#include "ntp_calendar.h"
+
+#include "parse.h"
+
+/*
+ * Trimble TSIP parser
+ *
+ * The receiver uses a serial message protocol called Trimble Standard
+ * Interface Protocol (it can support others but this driver only supports
+ * TSIP). Messages in this protocol have the following form:
+ *
+ * <DLE><id> ... <data> ... <DLE><ETX>
+ *
+ * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled
+ * on transmission and compressed back to one on reception. Otherwise
+ * the values of data bytes can be anything. The serial interface is RS-422
+ * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits
+ * in total!), and 1 stop bit. The protocol supports byte, integer, single,
+ * and double datatypes. Integers are two bytes, sent most significant first.
+ * Singles are IEEE754 single precision floating point numbers (4 byte) sent
+ * sign & exponent first. Doubles are IEEE754 double precision floating point
+ * numbers (8 byte) sent sign & exponent first.
+ * The receiver supports a large set of messages, only a small subset of
+ * which are used here. From driver to receiver the following are used:
+ *
+ * ID Description
+ *
+ * 21 Request current time
+ * 22 Mode Select
+ * 2C Set/Request operating parameters
+ * 2F Request UTC info
+ * 35 Set/Request I/O options
+ *
+ * From receiver to driver the following are recognised:
+ *
+ * ID Description
+ *
+ * 41 GPS Time
+ * 44 Satellite selection, PDOP, mode
+ * 46 Receiver health
+ * 4B Machine code/status
+ * 4C Report operating parameters (debug only)
+ * 4F UTC correction data (used to get leap second warnings)
+ * 55 I/O options (debug only)
+ *
+ * All others are accepted but ignored.
+ *
+ */
+
+extern int debug;
+
+struct trimble
+{
+ u_char t_in_pkt; /* first DLE received */
+ u_char t_dle; /* subsequent DLE received */
+ u_char t_status; /* last status */
+ u_char t_error; /* last error */
+ u_short t_week; /* GPS week */
+ u_short t_weekleap; /* GPS week of next/last week */
+ u_short t_dayleap; /* day in week */
+ u_short t_gpsutc; /* GPS - UTC offset */
+ u_short t_gpsutcleap; /* offset at next/last leap */
+ u_char t_operable; /* receiver feels OK */
+ u_char t_leap; /* possible leap warning */
+};
+
+static unsigned LONG inp_tsip();
+static unsigned LONG cvt_trimtsip();
+
+struct clockformat clock_trimtsip =
+{
+ inp_tsip, /* Trimble TSIP input handler */
+ cvt_trimtsip, /* Trimble TSIP conversion */
+ syn_simple, /* easy time stamps for RS232 (fallback) */
+ pps_simple, /* easy PPS monitoring */
+ (unsigned LONG (*)())0, /* no time code synthesizer monitoring */
+ (void *)0, /* no configuration data */
+ "Trimble SV6/TSIP",
+ 128, /* input buffer */
+ CVT_FIXEDONLY, /* we do our own input handling */
+ sizeof(struct trimble), /* no private data */
+ { 0, 0},
+ '\0',
+ '\0',
+ '\0'
+};
+
+#define ADDSECOND 0x01
+#define DELSECOND 0x02
+
+#define DLE 0x10
+#define ETX 0x03
+
+static unsigned LONG inp_tsip(parseio, ch, ctime)
+ register parse_t *parseio;
+ register unsigned char ch;
+ register timestamp_t *ctime;
+{
+ register struct trimble *t = (struct trimble *)parseio->parse_pdata;
+
+ if (!t)
+ return 0; /* local data not allocated - sigh! */
+
+ if (!t->t_in_pkt && ch != DLE) {
+ /* wait for start of packet */
+#ifdef DEBUG
+ if (debug > 2)
+ printf("sv6+ discarding %2.2x\n", ch);
+#endif
+ return 0;
+ }
+
+ switch (ch) {
+ case DLE:
+ if (!t->t_in_pkt) {
+ t->t_dle = 0;
+ t->t_in_pkt = 1;
+ parseio->parse_index = 0;
+ parseio->parse_data[parseio->parse_index++] = ch;
+ parseio->parse_dtime.parse_stime = *ctime; /* pick up time stamp at packet start */
+ } else if (t->t_dle) {
+ /* Double DLE -> insert a DLE */
+ t->t_dle = 0;
+ parseio->parse_data[parseio->parse_index++] = DLE;
+ } else
+ t->t_dle = 1;
+ break;
+ case ETX:
+ if (t->t_dle) {
+ /* DLE,ETX -> end of packet */
+ parseio->parse_data[parseio->parse_index++] = DLE;
+ parseio->parse_data[parseio->parse_index++] = ch;
+ parseio->parse_data[parseio->parse_index] = '\0';
+ parseio->parse_ldsize = parseio->parse_index+1;
+ bcopy(parseio->parse_data, parseio->parse_ldata, parseio->parse_ldsize);
+ t->t_in_pkt = t->t_dle = 0;
+ return 1;
+ }
+ /* fall into ... */
+ default:
+ t->t_dle = 0;
+ parseio->parse_data[parseio->parse_index++] = ch;
+ }
+
+ return (parseio->parse_index == parseio->parse_dsize-1); /* buffer full - attempt to parse (likely to fail) */
+}
+
+#define GPSORIGIN 2524953600 /* NTP origin - GPS origin in seconds */
+#define SECSPERWEEK 604800 /* seconds per week - GPS tells us about weeks */
+#define L_UF_SCALE 4294967296.0 /* scale a float fraction to l_uf units */
+
+/*
+ * mapping union for ints, floats, doubles for both input & output to the
+ * receiver
+ *
+ * CAVEAT: must disappear - non portable
+ */
+
+union {
+ u_char bd[8];
+ int iv;
+ float fv;
+ double dv;
+} uval;
+
+static float getflt P((u_char *));
+static double getdbl P((u_char *));
+static int getint P((u_char *));
+
+/*
+ * cvt_trimtsip
+ *
+ * convert TSIP type format
+ */
+static unsigned LONG
+cvt_trimtsip(buffer, size, format, clock, t)
+ register char *buffer;
+ register int size;
+ register struct format *format;
+ register clocktime_t *clock;
+ register struct trimble *t;
+{
+#define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */
+ register u_char cmd;
+
+ if (!t) {
+#ifdef DEBUG
+ if (debug) printf("sv6+ BAD call (t=0)\n");
+#endif
+ return CVT_NONE; /* local data not allocated - sigh! */
+ }
+
+ if ((size < 4) ||
+ (buffer[0] != DLE) ||
+ (buffer[size-1] != ETX) ||
+ (buffer[size-2] != DLE))
+ {
+#ifdef DEBUG
+ if (debug > 2) {
+ int i;
+
+ printf("sv6+ BAD packet, size %d:\n ", size);
+ for (i = 0; i < size; i++) {
+ printf ("%2.2x, ", buffer[i]&0xff);
+ if (i%16 == 15) printf("\n\t");
+ }
+ printf("\n");
+ }
+#endif
+ return CVT_NONE;
+ }
+ else
+ {
+ cmd = buffer[1];
+
+#ifdef DEBUG
+ if (debug > 1)
+ switch(cmd)
+ {
+ case 0x41:
+ printf("sv6+ gps time: %f, %d, %f\n",
+ getflt(&mb(0)), getint(&mb(4)), getflt(&mb(6)));
+ break;
+
+ case 0x44:
+ printf("sv6+ sats: %2x, %2d %2d %2d %2d, %.2f\n",
+ mb(0), mb(1), mb(2), mb(3), mb(4), getflt(&mb(5)));
+ break;
+
+ case 0x45:
+ printf("sv6+ software: %d.%d (19%d/%d/%d)\n",
+ mb(0)&0xff, mb(1)&0xff, mb(4)&0xff, mb(2)&0xff, mb(3)&0xff);
+ break;
+
+ case 0x46:
+ printf("sv6+ health: %2x %2x\n",
+ mb(0), mb(1));
+ break;
+
+ case 0x48:
+ printf("sv6+ gps message: '%.22s'\n", &mb(0));
+ break;
+
+ case 0x4b:
+ printf("sv6+ status: %2d %2x\n",
+ mb(0), mb(1));
+ break;
+
+ case 0x4c:
+ printf("sv6+ op params: %2x %.1f %.1f %.1f %.1f\n",
+ mb(0), getflt(&mb(1)), getflt(&mb(5)),
+ getflt(&mb(9)), getflt(&mb(13)));
+ break;
+
+ case 0x4f:
+ printf("sv6+ utc data: %.3e %.3e %d %d %d %d %d\n",
+ getdbl(&mb(0)), getflt(&mb(8)), getint(&mb(18)),
+ getint(&mb(12)), getint(&mb(20)), getint(&mb(22)), getint(&mb(24)));
+ break;
+
+ case 0x54:
+ /*printf("sv6+ bias and rate: %.1fm %.2fm/s at %.1fs\n",
+ getflt(&mb(0)), getflt(&mb(4)), getflt(&mb(8))); ignore it*/
+ break;
+
+ case 0x55:
+ printf("sv6+ io opts: %2x %2x %2x %2x\n",
+ mb(0), mb(1), mb(2), mb(3));
+ break;
+
+ case 0x8f:
+ {
+#define RTOD (180.0 / 3.1415926535898)
+ double lat = getdbl(&mb(2));
+ double lng = getdbl(&mb(10));
+ printf("sv6+ last fix: %2.2x %d lat %f %c, long %f %c, alt %.2fm\n",
+ mb(1)&0xff, mb(40)&0xff,
+ ((lat < 0) ? (-lat) : (lat))*RTOD, (lat < 0 ? 'S' : 'N'),
+ ((lng < 0) ? (-lng) : (lng))*RTOD, (lng < 0 ? 'W' : 'E'),
+ getdbl(&mb(18)));
+ }
+ break;
+
+ case 0x40:
+ case 0x5b:
+ case 0x6d:
+ /* Ignore */
+ break;
+
+ default:
+ printf("sv6+ cmd ignored: %2x, length: %d\n",
+ cmd, size);
+ break;
+ }
+#endif /* DEBUG */
+
+ switch(cmd)
+ {
+ case 0x41:
+ { /* GPS time */
+ float secs = getflt(&mb(0));
+ int week = getint(&mb(4));
+ int secint;
+ float secfrac;
+ l_fp gpstime, off;
+
+ if (secs <= 0)
+ {
+#ifdef DEBUG
+ if (debug)
+ printf("sv6+ seconds <= 0 (%e), setting POWERUP\n");
+#endif
+ clock->flags = PARSEB_POWERUP;
+ return CVT_OK;
+ }
+
+ /* time OK */
+ secint = secs; /* integer part, hopefully */
+ secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
+ secint -= getflt(&mb(6)); /* UTC offset */
+ gpstime.l_ui = week*SECSPERWEEK + secint + GPSORIGIN; /* convert to NTP time */
+ gpstime.l_uf = secfrac*L_UF_SCALE;
+
+ clock->utctime = gpstime.l_ui - JAN_1970;
+ TSFTOTVU(gpstime.l_uf, clock->usecond);
+
+ if (t->t_leap == ADDSECOND)
+ clock->flags |= PARSEB_LEAPADD;
+
+ if (t->t_leap == DELSECOND)
+ clock->flags |= PARSEB_LEAPDEL;
+
+ if (t->t_operable)
+ clock->flags &= ~(PARSEB_NOSYNC|PARSEB_POWERUP);
+ else
+ clock->flags |= PARSEB_NOSYNC;
+ return CVT_OK;
+
+ } /* case 0x41 */
+ break;
+
+ case 0x46:
+ {
+ /* sv6+ health */
+ u_char status = t->t_status = mb(0);
+ u_char error = t->t_error = mb(1);
+
+ if (status == 0 || status == 9 || status == 10 || status == 11)
+ {
+ if (!t->t_operable)
+ syslog(LOG_ERR, "Trimble clock synced");
+ t->t_operable = 1;
+ }
+ else
+ {
+ if (t->t_operable)
+ syslog(LOG_ERR, "Trimble clock unsynced");
+ t->t_operable = 0;
+ }
+ }
+ break;
+
+ case 0x4f:
+ {
+ /* UTC correction data - derive a leap warning */
+ int tls = t->t_gpsutc = getint(&mb(12)); /* current leap correction (GPS-UTC) */
+ int wnlsf = t->t_weekleap = getint(&mb(20)); /* week no of leap correction */
+ int dn = t->t_dayleap = getint(&mb(22)); /* day in week of leap correction */
+ int tlsf = t->t_gpsutcleap = getint(&mb(24)); /* new leap correction */
+ U_LONG now, leaptime;
+
+ t->t_week = getint(&mb(18)); /* current week no */
+
+ /* this stuff hasn't been tested yet... */
+ now = clock->utctime + JAN_1970; /* now in GPS seconds */
+ leaptime = (wnlsf*7 + dn)*86400; /* time of leap in GPS seconds */
+ if ((leaptime > now) && ((leaptime-now) < 86400*28))
+ {
+ /* generate a leap warning */
+ if (tlsf > tls)
+ t->t_leap = ADDSECOND;
+ else
+ t->t_leap = DELSECOND;
+ }
+ else
+ {
+ t->t_leap = 0;
+ }
+ }
+ break;
+
+ default:
+ /* it's validly formed, but we don't care about it! */
+ break;
+ }
+ }
+ return CVT_SKIP;
+}
+
+/*
+ * getflt, getdbl, getint convert fields in the incoming data into the
+ * appropriate type of item
+ *
+ * CAVEAT: these routines are currently definitely byte order dependent
+ * and assume Representation(float) == IEEE754
+ * These functions MUST be converted to portable versions (especially
+ * converting the float representation into ntp_fp formats in order
+ * to avoid floating point operations at all!
+ */
+
+static float
+getflt(bp)
+ u_char *bp;
+{
+ uval.bd[0] = *bp++;
+ uval.bd[1] = *bp++;
+ uval.bd[2] = *bp++;
+ uval.bd[3] = *bp;
+ return uval.fv;
+}
+
+static double
+getdbl(bp)
+ u_char *bp;
+{
+ uval.bd[0] = *bp++;
+ uval.bd[1] = *bp++;
+ uval.bd[2] = *bp++;
+ uval.bd[3] = *bp++;
+ uval.bd[4] = *bp++;
+ uval.bd[5] = *bp++;
+ uval.bd[6] = *bp++;
+ uval.bd[7] = *bp;
+ return uval.dv;
+}
+
+static int
+getint(bp)
+ u_char *bp;
+{
+ uval.bd[2] = *bp++;
+ uval.bd[3] = *bp;
+ if (uval.bd[2] & 0x80) /* sign-extend */
+ uval.bd[0] = uval.bd[1] = 0xff;
+ else
+ uval.bd[0] = uval.bd[1] = 0;
+ return uval.iv;
+}
+
+#endif /* defined(PARSE) && defined(CLOCK_TRIMTSIP) */
+
+/*
+ * History:
+ *
+ * $Log: clk_trimble.c,v $
+ */
diff --git a/usr.sbin/xntpd/parse/parse.c b/usr.sbin/xntpd/parse/parse.c
index 84bfa39d1293..16c7813acedc 100644
--- a/usr.sbin/xntpd/parse/parse.c
+++ b/usr.sbin/xntpd/parse/parse.c
@@ -1,8 +1,8 @@
#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS))
/*
- * /src/NTP/REPOSITORY/v3/parse/parse.c,v 3.23 1994/03/25 13:09:02 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/parse.c,v 3.27 1994/06/01 08:18:33 kardel Exp
*
- * parse.c,v 3.23 1994/03/25 13:09:02 kardel Exp
+ * parse.c,v 3.27 1994/06/01 08:18:33 kardel Exp
*
* Parser module for reference clock
*
@@ -64,7 +64,7 @@ static char rcsid[] = "parse.c,v 3.19 1994/01/25 19:05:20 kardel Exp";
extern clockformat_t *clockformats[];
extern unsigned short nformats;
-static unsigned LONG timepacket();
+static u_long timepacket();
/*
* strings support usually not in kernel - duplicated, but what the heck
@@ -120,9 +120,9 @@ timedout(parseio, ctime)
delta.tv_usec += 1000000;
}
#else
- extern LONG tstouslo[];
- extern LONG tstousmid[];
- extern LONG tstoushi[];
+ extern long tstouslo[];
+ extern long tstousmid[];
+ extern long tstoushi[];
l_fp delt;
@@ -145,6 +145,8 @@ timedout(parseio, ctime)
/*
* setup_bitmaps
+ * WARNING: NOT TO BE CALLED CONCURRENTLY WITH
+ * parse_ioread, parse_ioend, parse_ioinit
*/
static int
setup_bitmaps(parseio, low, high)
@@ -155,7 +157,7 @@ setup_bitmaps(parseio, low, high)
register unsigned short i;
register int f = 0;
register clockformat_t *fmt;
- register unsigned index, mask;
+ register unsigned short index, mask, plen;
if ((low >= high) ||
(high > nformats))
@@ -167,6 +169,9 @@ setup_bitmaps(parseio, low, high)
bzero(parseio->parse_startsym, sizeof (parseio->parse_startsym));
bzero(parseio->parse_endsym, sizeof (parseio->parse_endsym));
bzero(parseio->parse_syncsym, sizeof (parseio->parse_syncsym));
+
+ plen = 0;
+
parseio->parse_syncflags = 0;
parseio->parse_timeout.tv_sec = 0;
parseio->parse_timeout.tv_usec = 0;
@@ -179,13 +184,16 @@ setup_bitmaps(parseio, low, high)
fmt = clockformats[i];
if (!(parseio->parse_flags & PARSE_FIXED_FMT) &&
- (fmt->flags & CVT_FIXEDONLY))
+ (fmt->flags & CVT_FIXEDONLY)) {
+ if (parseio->parse_dsize < fmt->length)
+ parseio->parse_dsize = fmt->length;
continue;
+ }
if (fmt->flags & F_START)
{
- index = fmt->startsym / 8;
- mask = 1 << (fmt->startsym % 8);
+ index = fmt->startsym >> 3;
+ mask = 1 << (fmt->startsym & 0x7);
if (parseio->parse_endsym[index] & mask)
{
@@ -205,8 +213,8 @@ setup_bitmaps(parseio, low, high)
if (fmt->flags & F_END)
{
- index = fmt->endsym / 8;
- mask = 1 << (fmt->endsym % 8);
+ index = fmt->endsym >> 3;
+ mask = 1 << (fmt->endsym & 0x7);
if (parseio->parse_startsym[index] & mask)
{
@@ -226,12 +234,12 @@ setup_bitmaps(parseio, low, high)
if (fmt->flags & SYNC_CHAR)
{
- parseio->parse_syncsym[fmt->syncsym / 8] |= (1 << (fmt->syncsym % 8));
+ parseio->parse_syncsym[fmt->syncsym >> 3] |= (1 << (fmt->syncsym & 0x7));
}
parseio->parse_syncflags |= fmt->flags & (SYNC_START|SYNC_END|SYNC_CHAR|SYNC_ONE|SYNC_ZERO|SYNC_TIMEOUT|SYNC_SYNTHESIZE);
- if ((fmt->flags & SYNC_TIMEOUT) &&
+ if (((fmt->flags & (SYNC_TIMEOUT|CVT_FIXEDONLY)) == (SYNC_TIMEOUT|CVT_FIXEDONLY)) &&
((parseio->parse_timeout.tv_sec || parseio->parse_timeout.tv_usec) ? timercmp(&parseio->parse_timeout, &fmt->timeout, >) : 1))
{
parseio->parse_timeout = fmt->timeout;
@@ -241,6 +249,13 @@ setup_bitmaps(parseio, low, high)
parseio->parse_dsize = fmt->length;
}
+ if (parseio->parse_pdata)
+ {
+ FREE(parseio->parse_pdata, parseio->parse_plen);
+ parseio->parse_plen = 0;
+ parseio->parse_pdata = (void *)0;
+ }
+
if (!f && ((int)(high - low) > 1))
{
/*
@@ -254,6 +269,27 @@ setup_bitmaps(parseio, low, high)
return 0;
}
+ if ((high - low == 1) && (clockformats[low]->flags & CVT_FIXEDONLY) &&
+ (clockformats[low]->plen))
+ {
+ parseio->parse_plen = clockformats[low]->plen;
+ parseio->parse_pdata = (void *)MALLOC(parseio->parse_plen);
+
+ if (!parseio->parse_pdata)
+ {
+ /*
+ * no memory
+ */
+#ifdef PARSEKERNEL
+ printf("parse: setup_bitmaps: failed: no memory for private data\n");
+#else
+ syslog(LOG_ERR, "parse: setup_bitmaps: failed: no memory for private data\n");
+#endif
+ return 0;
+ }
+ bzero((char *)parseio->parse_pdata, parseio->parse_plen);
+ }
+
return 1;
}
@@ -264,6 +300,9 @@ parse_ioinit(parseio)
{
parseprintf(DD_PARSE, ("parse_iostart\n"));
+ parseio->parse_plen = 0;
+ parseio->parse_pdata = (void *)0;
+
if (!setup_bitmaps(parseio, 0, nformats))
return 0;
@@ -294,6 +333,10 @@ parse_ioend(parseio)
register parse_t *parseio;
{
parseprintf(DD_PARSE, ("parse_ioend\n"));
+
+ if (parseio->parse_pdata)
+ FREE(parseio->parse_pdata, parseio->parse_plen);
+
if (parseio->parse_data)
FREE(parseio->parse_data, parseio->parse_dsize * 2 + 2);
}
@@ -309,24 +352,6 @@ parse_ioread(parseio, ch, ctime)
register unsigned short low, high;
register unsigned index, mask;
- parseprintf(DD_PARSE, ("parse_ioread(0x%x, char=0x%x, ..., ...)\n", (unsigned int)parseio, ch & 0xFF));
-
- if (parseio->parse_flags & PARSE_FIXED_FMT)
- {
- if (!clockformats[parseio->parse_lformat]->convert)
- {
- parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n"));
- return CVT_NONE;
- }
- low = parseio->parse_lformat;
- high = low + 1;
- }
- else
- {
- low = 0;
- high = nformats;
- }
-
/*
* within STREAMS CSx (x < 8) chars still have the upper bits set
* so we normalize the characters by masking unecessary bits off.
@@ -349,114 +374,146 @@ parse_ioread(parseio, ch, ctime)
break;
}
- index = ch / 8;
- mask = 1 << (ch % 8);
+ parseprintf(DD_PARSE, ("parse_ioread(0x%x, char=0x%x, ..., ...)\n", (unsigned int)parseio, ch & 0xFF));
- if ((parseio->parse_syncflags & SYNC_CHAR) &&
- (parseio->parse_syncsym[index] & mask))
+ if (parseio->parse_flags & PARSE_FIXED_FMT)
{
- register clockformat_t *fmt;
- register unsigned short i;
- /*
- * got a sync event - call sync routine
- */
-
- for (i = low; i < high; i++)
+ if (!clockformats[parseio->parse_lformat]->convert)
{
- fmt = clockformats[i];
+ parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n"));
+ return CVT_NONE;
+ }
- if ((fmt->flags & SYNC_CHAR) &&
- (fmt->syncsym == ch))
- {
- parseprintf(DD_PARSE, ("parse_ioread: SYNC_CHAR event\n"));
- if (fmt->syncevt)
- fmt->syncevt(parseio, ctime, fmt->data, SYNC_CHAR);
- }
+ if (clockformats[parseio->parse_lformat]->input)
+ {
+ if (clockformats[parseio->parse_lformat]->input(parseio, ch, ctime))
+ updated = timepacket(parseio); /* got a datagram - process */
+
+ low = high = 0; /* all done - just post processing */
}
- }
-
- if ((((parseio->parse_syncflags & SYNC_START) &&
- (parseio->parse_startsym[index] & mask)) ||
- (parseio->parse_index == 0)) ||
- ((parseio->parse_syncflags & SYNC_TIMEOUT) &&
- timedout(parseio, ctime)))
- {
- register unsigned short i;
- /*
- * packet start - re-fill buffer
- */
- if (parseio->parse_index)
+ else
{
- /*
- * filled buffer - thus not end character found
- * do processing now
- */
- parseio->parse_data[parseio->parse_index] = '\0';
-
- updated = timepacket(parseio);
- bcopy(parseio->parse_data, parseio->parse_ldata, parseio->parse_index+1);
- parseio->parse_ldsize = parseio->parse_index+1;
- if (parseio->parse_syncflags & SYNC_TIMEOUT)
- parseio->parse_dtime.parse_stime = *ctime;
+ low = parseio->parse_lformat;
+ high = low + 1; /* scan just one format */
}
-
- /*
- * could be a sync event - call sync routine if needed
- */
- if (parseio->parse_syncflags & SYNC_START)
- for (i = low; i < high; i++)
- {
- register clockformat_t *fmt = clockformats[i];
-
- if ((parseio->parse_index == 0) ||
- ((fmt->flags & SYNC_START) && (fmt->startsym == ch)))
- {
- parseprintf(DD_PARSE, ("parse_ioread: SYNC_START event\n"));
- if (fmt->syncevt)
- fmt->syncevt(parseio, ctime, fmt->data, SYNC_START);
- }
- }
- parseio->parse_index = 1;
- parseio->parse_data[0] = ch;
- parseprintf(DD_PARSE, ("parse: parse_ioread: buffer start\n"));
}
else
{
- register unsigned short i;
+ low = 0;
+ high = nformats; /* scan all non fixed formats */
+ }
+
+ if (low != high)
+ {
+ index = ch >> 3;
+ mask = 1 << (ch & 0x7);
- if (parseio->parse_index < parseio->parse_dsize)
+ if ((parseio->parse_syncflags & SYNC_CHAR) &&
+ (parseio->parse_syncsym[index] & mask))
{
+ register clockformat_t *fmt;
+ register unsigned short i;
/*
- * collect into buffer
+ * got a sync event - call sync routine
*/
- parseprintf(DD_PARSE, ("parse: parse_ioread: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
- parseio->parse_data[parseio->parse_index++] = ch;
- }
- if ((parseio->parse_endsym[index] & mask) ||
- (parseio->parse_index >= parseio->parse_dsize))
+ for (i = low; i < high; i++)
+ {
+ fmt = clockformats[i];
+
+ if ((fmt->flags & SYNC_CHAR) &&
+ (fmt->syncsym == ch))
+ {
+ parseprintf(DD_PARSE, ("parse_ioread: SYNC_CHAR event\n"));
+ if (fmt->syncevt)
+ fmt->syncevt(parseio, ctime, fmt->data, SYNC_CHAR);
+ }
+ }
+ }
+
+ if ((((parseio->parse_syncflags & SYNC_START) &&
+ (parseio->parse_startsym[index] & mask)) ||
+ (parseio->parse_index == 0)) ||
+ ((parseio->parse_syncflags & SYNC_TIMEOUT) &&
+ timedout(parseio, ctime)))
{
+ register unsigned short i;
+ /*
+ * packet start - re-fill buffer
+ */
+ if (parseio->parse_index)
+ {
+ /*
+ * filled buffer - thus not end character found
+ * do processing now
+ */
+ parseio->parse_data[parseio->parse_index] = '\0';
+
+ updated = timepacket(parseio);
+ bcopy(parseio->parse_data, parseio->parse_ldata, parseio->parse_index+1);
+ parseio->parse_ldsize = parseio->parse_index+1;
+ if (parseio->parse_syncflags & SYNC_TIMEOUT)
+ parseio->parse_dtime.parse_stime = *ctime;
+ }
+
/*
- * packet end - process buffer
+ * could be a sync event - call sync routine if needed
*/
- if (parseio->parse_syncflags & SYNC_END)
+ if (parseio->parse_syncflags & SYNC_START)
for (i = low; i < high; i++)
{
register clockformat_t *fmt = clockformats[i];
- if ((fmt->flags & SYNC_END) && (fmt->endsym == ch))
+ if ((parseio->parse_index == 0) ||
+ ((fmt->flags & SYNC_START) && (fmt->startsym == ch)))
{
- parseprintf(DD_PARSE, ("parse_ioread: SYNC_END event\n"));
+ parseprintf(DD_PARSE, ("parse_ioread: SYNC_START event\n"));
if (fmt->syncevt)
- fmt->syncevt(parseio, ctime, fmt->data, SYNC_END);
+ fmt->syncevt(parseio, ctime, fmt->data, SYNC_START);
}
}
- parseio->parse_data[parseio->parse_index] = '\0';
- updated = timepacket(parseio);
- bcopy(parseio->parse_data, parseio->parse_ldata, parseio->parse_index+1);
- parseio->parse_ldsize = parseio->parse_index+1;
- parseio->parse_index = 0;
- parseprintf(DD_PARSE, ("parse: parse_ioread: buffer end\n"));
+ parseio->parse_index = 1;
+ parseio->parse_data[0] = ch;
+ parseprintf(DD_PARSE, ("parse: parse_ioread: buffer start\n"));
+ }
+ else
+ {
+ register unsigned short i;
+
+ if (parseio->parse_index < parseio->parse_dsize)
+ {
+ /*
+ * collect into buffer
+ */
+ parseprintf(DD_PARSE, ("parse: parse_ioread: buffer[%d] = 0x%x\n", parseio->parse_index, ch));
+ parseio->parse_data[parseio->parse_index++] = ch;
+ }
+
+ if ((parseio->parse_endsym[index] & mask) ||
+ (parseio->parse_index >= parseio->parse_dsize))
+ {
+ /*
+ * packet end - process buffer
+ */
+ if (parseio->parse_syncflags & SYNC_END)
+ for (i = low; i < high; i++)
+ {
+ register clockformat_t *fmt = clockformats[i];
+
+ if ((fmt->flags & SYNC_END) && (fmt->endsym == ch))
+ {
+ parseprintf(DD_PARSE, ("parse_ioread: SYNC_END event\n"));
+ if (fmt->syncevt)
+ fmt->syncevt(parseio, ctime, fmt->data, SYNC_END);
+ }
+ }
+ parseio->parse_data[parseio->parse_index] = '\0';
+ updated = timepacket(parseio);
+ bcopy(parseio->parse_data, parseio->parse_ldata, parseio->parse_index+1);
+ parseio->parse_ldsize = parseio->parse_index+1;
+ parseio->parse_index = 0;
+ parseprintf(DD_PARSE, ("parse: parse_ioread: buffer end\n"));
+ }
}
}
@@ -476,7 +533,9 @@ parse_ioread(parseio, ch, ctime)
#ifdef DEBUG
if ((updated & CVT_MASK) != CVT_NONE)
- parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated));
+ {
+ parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated));
+ }
#endif
parseio->parse_dtime.parse_status = updated;
@@ -537,6 +596,7 @@ parse_iodone(parseio)
/*
* we need to clean up certain flags for the next round
*/
+ parseprintf(DD_PARSE, ("parse_iodone: DONE\n"));
parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */
}
@@ -550,7 +610,7 @@ parse_iodone(parseio)
time_t
parse_to_unixtime(clock, cvtrtc)
register clocktime_t *clock;
- register unsigned LONG *cvtrtc;
+ register u_long *cvtrtc;
{
#define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); }
static int days_of_month[] =
@@ -646,7 +706,7 @@ parse_to_unixtime(clock, cvtrtc)
int
Stoi(s, zp, cnt)
char *s;
- LONG *zp;
+ long *zp;
int cnt;
{
char *b = s;
@@ -710,24 +770,24 @@ Strok(s, m)
return !*m;
}
-unsigned LONG
+u_long
updatetimeinfo(parseio, t, usec, flags)
register parse_t *parseio;
register time_t t;
- register unsigned LONG usec;
- register unsigned LONG flags;
+ register u_long usec;
+ register u_long flags;
{
- register LONG usecoff;
- register LONG mean;
- LONG delta[PARSE_DELTA];
+ register long usecoff;
+ register long mean;
+ long delta[PARSE_DELTA];
#ifdef PARSEKERNEL
usecoff = (t - parseio->parse_dtime.parse_stime.tv.tv_sec) * 1000000
- parseio->parse_dtime.parse_stime.tv.tv_usec + usec;
#else
- extern LONG tstouslo[];
- extern LONG tstousmid[];
- extern LONG tstoushi[];
+ extern long tstouslo[];
+ extern long tstousmid[];
+ extern long tstoushi[];
TSFTOTVU(parseio->parse_dtime.parse_stime.fp.l_uf, usecoff);
usecoff = -usecoff;
@@ -756,7 +816,7 @@ updatetimeinfo(parseio, t, usec, flags)
{ /* Yes - it's slow sort */
if (delta[s] > delta[k])
{
- register LONG tmp;
+ register long tmp;
tmp = delta[k];
delta[k] = delta[s];
@@ -772,9 +832,9 @@ updatetimeinfo(parseio, t, usec, flags)
*/
while ((n - i) > 8)
{
- register LONG top = delta[n-1];
- register LONG mid = delta[(n+i)>>1];
- register LONG low = delta[i];
+ register long top = delta[n-1];
+ register long mid = delta[(n+i)>>1];
+ register long low = delta[i];
if ((top - mid) > (mid - low))
{
@@ -823,7 +883,8 @@ updatetimeinfo(parseio, t, usec, flags)
}
parseprintf(DD_PARSE,("parse: updatetimeinfo: T=%x+%d usec, useccoff=%d, usecerror=%d, usecdisp=%d\n",
- t, usec, usecoff, parseio->parse_dtime.parse_usecerror, parseio->parse_dtime.parse_usecdisp));
+ (int)t, (int)usec, (int)usecoff, (int)parseio->parse_dtime.parse_usecerror,
+ (int)parseio->parse_dtime.parse_usecdisp));
#ifdef PARSEKERNEL
@@ -855,7 +916,7 @@ syn_simple(parseio, ts, format, why)
register parse_t *parseio;
register timestamp_t *ts;
register struct format *format;
- register unsigned LONG why;
+ register u_long why;
{
parseio->parse_dtime.parse_stime = *ts;
}
@@ -866,7 +927,7 @@ syn_simple(parseio, ts, format, why)
* handle a pps time stamp
*/
/*ARGSUSED*/
-unsigned LONG
+u_long
pps_simple(parseio, status, ptime)
register parse_t *parseio;
register int status;
@@ -883,26 +944,25 @@ pps_simple(parseio, status, ptime)
*
* process a data packet
*/
-static unsigned LONG
+static u_long
timepacket(parseio)
register parse_t *parseio;
{
register int k;
register unsigned short format;
register time_t t;
- register unsigned LONG cvtsum = 0;/* accumulated CVT_FAIL errors */
- unsigned LONG cvtrtc; /* current conversion result */
+ register u_long cvtsum = 0;/* accumulated CVT_FAIL errors */
+ u_long cvtrtc; /* current conversion result */
clocktime_t clock;
+ bzero(&clock, sizeof clock);
format = parseio->parse_lformat;
k = 0;
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)
+ switch ((cvtrtc = clockformats[format]->convert ? clockformats[format]->convert(parseio->parse_data, parseio->parse_index, clockformats[format]->data, &clock, parseio->parse_pdata) : CVT_NONE) & CVT_MASK)
{
case CVT_FAIL:
parseio->parse_badformat++;
@@ -924,13 +984,16 @@ timepacket(parseio)
*/
parseio->parse_badformat++;
cvtsum = CVT_BADFMT;
-
break;
case CVT_OK:
k = 1;
break;
+ case CVT_SKIP:
+ k = 2;
+ break;
+
default:
/* shouldn't happen */
#ifdef PARSEKERNEL
@@ -953,10 +1016,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) :
+ clockformats[format]->convert(parseio->parse_data, parseio->parse_index, clockformats[format]->data, &clock, parseio->parse_pdata) :
CVT_NONE) & CVT_MASK)
{
case CVT_FAIL:
@@ -1006,6 +1067,8 @@ timepacket(parseio)
return CVT_FAIL|cvtsum;
}
+ if (k == 2) return CVT_OK;
+
if ((t = parse_to_unixtime(&clock, &cvtrtc)) == -1)
{
#ifdef PARSEKERNEL
@@ -1162,6 +1225,18 @@ parse_setcs(dct, parse)
* History:
*
* parse.c,v
+ * Revision 3.27 1994/06/01 08:18:33 kardel
+ * more debug info
+ *
+ * Revision 3.26 1994/05/30 10:20:07 kardel
+ * LONG cleanup
+ *
+ * Revision 3.25 1994/05/12 12:49:12 kardel
+ * printf fmt/arg cleanup
+ *
+ * Revision 3.24 1994/03/27 15:01:36 kardel
+ * reorder include file to cope with PTX
+ *
* Revision 3.23 1994/03/25 13:09:02 kardel
* considering FIXEDONLY entries only in FIXEDONLY mode
*
diff --git a/usr.sbin/xntpd/parse/parse_conf.c b/usr.sbin/xntpd/parse/parse_conf.c
index 238dd1234e66..ed306d4a0385 100644
--- a/usr.sbin/xntpd/parse/parse_conf.c
+++ b/usr.sbin/xntpd/parse/parse_conf.c
@@ -46,8 +46,12 @@ extern clockformat_t clock_meinberg[];
extern clockformat_t clock_rawdcf;
#endif
-#ifdef CLOCK_TRIMSV6
-extern clockformat_t clock_trimsv6;
+#ifdef CLOCK_TRIMTAIP
+extern clockformat_t clock_trimtaip;
+#endif
+
+#ifdef CLOCK_TRIMTSIP
+extern clockformat_t clock_trimtsip;
#endif
/*
@@ -69,8 +73,11 @@ clockformat_t *clockformats[] =
#ifdef CLOCK_RAWDCF
&clock_rawdcf,
#endif
-#ifdef CLOCK_TRIMSV6
- &clock_trimsv6,
+#ifdef CLOCK_TRIMTAIP
+ &clock_trimtaip,
+#endif
+#ifdef CLOCK_TRIMTSIP
+ &clock_trimtsip,
#endif
0};
diff --git a/usr.sbin/xntpd/parse/parsesolaris.c b/usr.sbin/xntpd/parse/parsesolaris.c
index 23bc252e8fce..513cd00b4c93 100644
--- a/usr.sbin/xntpd/parse/parsesolaris.c
+++ b/usr.sbin/xntpd/parse/parsesolaris.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/parsesolaris.c,v 3.15 1994/02/15 22:20:51 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/parsesolaris.c,v 3.16 1994/05/30 09:57:40 kardel Exp
*
- * parsesolaris.c,v 3.15 1994/02/15 22:20:51 kardel Exp
+ * parsesolaris.c,v 3.16 1994/05/30 09:57:40 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.15 1994/02/15 22:20:51 kardel Exp";
+static char rcsid[] = "parsesolaris.c,v 3.16 1994/05/30 09:57:40 kardel Exp";
#endif
/*
@@ -139,7 +139,7 @@ int Strcmp(s, t)
/*ARGSUSED*/
int _init(void)
{
- static char revision[] = "3.15";
+ static char revision[] = "3.16";
char *s, *S, *t;
/*
@@ -401,6 +401,11 @@ static int parseopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *credp)
parsebusy++;
q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t), KM_SLEEP);
+ if (q->q_ptr == (caddr_t)0)
+ {
+ return ENOMEM;
+ }
+
parseprintf(DD_OPEN,("parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q, q->q_ptr));
SAFE_WR(q)->q_ptr = q->q_ptr;
parseprintf(DD_OPEN,("parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", SAFE_WR(q), SAFE_WR(q)->q_ptr));
@@ -938,29 +943,38 @@ static int init_zs_linemon(queue_t *q, queue_t *my_q)
*/
szs = (struct savedzsops *) kmem_alloc(sizeof(struct savedzsops), KM_SLEEP);
- parsestream->parse_data = (void *)szs;
+ if (szs == (struct savedzsops *)0)
+ {
+ parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor NOT installed - no memory\n"));
- mutex_enter(zs->zs_excl);
+ return 0;
+ }
+ else
+ {
+ parsestream->parse_data = (void *)szs;
- parsestream->parse_dqueue = q; /* remember driver */
+ mutex_enter(zs->zs_excl);
- szs->zsops = *zs->zs_ops;
- szs->zsops.zsop_xsint = (void (*)())zs_xsisr; /* place our bastard */
- szs->oldzsops = zs->zs_ops;
- emergencyzs = zs->zs_ops;
-
- zs->zs_ops = &szs->zsops; /* hook it up */
- /*
- * XXX: this is usually done via zsopinit()
- * - have yet to find a way to call that routine
- */
- zs->zs_xsint = (void (*)())zs_xsisr;
-
- mutex_exit(zs->zs_excl);
+ parsestream->parse_dqueue = q; /* remember driver */
+
+ szs->zsops = *zs->zs_ops;
+ szs->zsops.zsop_xsint = (void (*)())zs_xsisr; /* place our bastard */
+ szs->oldzsops = zs->zs_ops;
+ emergencyzs = zs->zs_ops;
+
+ zs->zs_ops = &szs->zsops; /* hook it up */
+ /*
+ * XXX: this is usually done via zsopinit()
+ * - have yet to find a way to call that routine
+ */
+ zs->zs_xsint = (void (*)())zs_xsisr;
+
+ mutex_exit(zs->zs_excl);
- parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n"));
+ parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n"));
- return 1;
+ return 1;
+ }
}
}
@@ -1190,6 +1204,9 @@ static void zs_xsisr(struct zscom *zs)
* History:
*
* parsesolaris.c,v
+ * Revision 3.16 1994/05/30 09:57:40 kardel
+ * kmem_alloc checking
+ *
* Revision 3.15 1994/02/15 22:20:51 kardel
* rcsid fixed
*
diff --git a/usr.sbin/xntpd/parse/parsestreams.c b/usr.sbin/xntpd/parse/parsestreams.c
index 45d296337a69..19e5c10e5045 100644
--- a/usr.sbin/xntpd/parse/parsestreams.c
+++ b/usr.sbin/xntpd/parse/parsestreams.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/parsestreams.c,v 3.19 1994/02/24 16:33:54 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/parsestreams.c,v 3.22 1994/06/01 10:41:16 kardel Exp
*
- * parsestreams.c,v 3.19 1994/02/24 16:33:54 kardel Exp
+ * parsestreams.c,v 3.22 1994/06/01 10:41:16 kardel Exp
*
* STREAMS module for reference clocks
* (SunOS4.x)
@@ -16,7 +16,7 @@
*/
#ifndef lint
-static char rcsid[] = "parsestreams.c,v 3.19 1994/02/24 16:33:54 kardel Exp";
+static char rcsid[] = "parsestreams.c,v 3.22 1994/06/01 10:41:16 kardel Exp";
#endif
#include "sys/types.h"
@@ -195,7 +195,7 @@ int xxxinit(fc, vdp, vdi, vds)
}
else
{
- static char revision[] = "3.19";
+ static char revision[] = "3.22";
char *s, *S, *t;
strncpy(ifm->f_name, mname, FMNAMESZ);
@@ -493,6 +493,11 @@ static int parseopen(q, dev, flag, sflag)
#endif
q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t));
+ if (q->q_ptr == (caddr_t)0)
+ {
+ parseprintf(DD_OPEN,("parse: OPEN - FAILED - no memory\n"));
+ return OPENFAIL;
+ }
WR(q)->q_ptr = q->q_ptr;
parse = (parsestream_t *) q->q_ptr;
@@ -1022,24 +1027,33 @@ static int init_zs_linemon(q, my_q)
*/
szs = (struct savedzsops *) kmem_alloc(sizeof(struct savedzsops));
- parsestream->parse_data = (void *)szs;
+ if (szs == (struct savedzsops *)0)
+ {
+ parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor NOT installed - no memory\n"));
- s = splhigh();
+ return 0;
+ }
+ else
+ {
+ parsestream->parse_data = (void *)szs;
- parsestream->parse_dqueue = q; /* remember driver */
+ s = splhigh();
- szs->zsops = *zs->zs_ops;
- szs->zsops.zsop_xsint = (int (*)())zs_xsisr; /* place our bastard */
- szs->oldzsops = zs->zs_ops;
- emergencyzs = zs->zs_ops;
-
- zsopinit(zs, &szs->zsops); /* hook it up */
-
- (void) splx(s);
+ parsestream->parse_dqueue = q; /* remember driver */
- parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n"));
+ szs->zsops = *zs->zs_ops;
+ szs->zsops.zsop_xsint = (int (*)())zs_xsisr; /* place our bastard */
+ szs->oldzsops = zs->zs_ops;
+ emergencyzs = zs->zs_ops;
+
+ zsopinit(zs, &szs->zsops); /* hook it up */
+
+ (void) splx(s);
- return 1;
+ parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n"));
+
+ return 1;
+ }
}
}
@@ -1133,7 +1147,7 @@ static void zs_xsisr(zs)
/*
* logical state
*/
- status = cd_invert ? (zsstatus & (ZSRR0_CD|ZSRR0_SYNC)) == 0 : (zsstatus & (ZSRR0_CD|ZSRR0_SYNC)) != 0;
+ status = cd_invert ? (zsstatus & ZSRR0_SYNC) == 0 : (zsstatus & ZSRR0_SYNC) != 0;
#ifdef PPS_SYNC
if (status)
@@ -1286,8 +1300,17 @@ static void zs_xsisr(zs)
* History:
*
* parsestreams.c,v
+ * Revision 3.22 1994/06/01 10:41:16 kardel
+ * CD seems to happen on ZSRR0_SYNC
+ *
+ * Revision 3.21 1994/06/01 08:18:57 kardel
+ * look at CD only
+ *
+ * Revision 3.20 1994/05/30 09:57:43 kardel
+ * kmem_alloc checking
+ *
* Revision 3.19 1994/02/24 16:33:54 kardel
- * CD events can also be posted on sync flag
+ * CD events can olso be posted on sync flag
*
* Revision 3.18 1994/02/24 14:12:58 kardel
* initial PPS_SYNC support version
diff --git a/usr.sbin/xntpd/parse/util/dcfd.c b/usr.sbin/xntpd/parse/util/dcfd.c
index 23934a8e104e..3f04a55c31b9 100644
--- a/usr.sbin/xntpd/parse/util/dcfd.c
+++ b/usr.sbin/xntpd/parse/util/dcfd.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/util/dcfd.c,v 3.15 1994/01/25 19:05:42 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/util/dcfd.c,v 3.18 1994/05/12 12:49:23 kardel Exp
*
- * dcfd.c,v 3.15 1994/01/25 19:05:42 kardel Exp
+ * dcfd.c,v 3.18 1994/05/12 12:49:23 kardel Exp
*
* DCF77 100/200ms pulse synchronisation daemon program (via 50Baud serial line)
*
@@ -703,6 +703,11 @@ static unsigned long cvt_rawdcf(buffer, size, clock)
* if everything went well so far return the result of the symbolic
* conversion routine else just the accumulated errors
*/
+ if (rtc != CVT_NONE)
+ {
+ PRINTF("%-30s", "*** BAD DATA");
+ }
+
return (rtc == CVT_NONE) ? convert_rawdcf(buffer, size, clock) : rtc;
}
@@ -864,9 +869,9 @@ static char * pr_timeval(val)
static char buf[20];
if (val->tv_sec == 0)
- sprintf(buf, "%c0.%06d", (val->tv_usec < 0) ? '-' : '+', abs(val->tv_usec));
+ sprintf(buf, "%c0.%06ld", (val->tv_usec < 0) ? '-' : '+', (long int)abs(val->tv_usec));
else
- sprintf(buf, "%d.%06d", val->tv_sec, abs(val->tv_usec));
+ sprintf(buf, "%ld.%06ld", (long int)val->tv_sec, (long int)abs(val->tv_usec));
return buf;
}
@@ -912,7 +917,7 @@ static void adj_time(offset)
time_offset.tv_sec = offset / 1000000;
time_offset.tv_usec = offset % 1000000;
- LPRINTF("adj_time: %d us ", offset);
+ LPRINTF("adj_time: %ld us ", (long int)offset);
if (adjtime(&time_offset, 0L) == -1)
perror("adjtime()");
}
@@ -937,7 +942,7 @@ static void read_drift(drift_file)
drift_comp = idrift << USECSCALE;
fdrift = (fdrift << USECSCALE) / 1000;
drift_comp += fdrift & (1<<USECSCALE);
- LPRINTF("read_drift: drift_comp %d ", drift_comp);
+ LPRINTF("read_drift: drift_comp %ld ", (long int)drift_comp);
}
}
@@ -957,11 +962,11 @@ static void update_drift(drift_file, offset, reftime)
int idrift = R_SHIFT(drift_comp, USECSCALE);
int fdrift = drift_comp & ((1<<USECSCALE)-1);
- LPRINTF("update_drift: drift_comp %d ", drift_comp);
+ LPRINTF("update_drift: drift_comp %ld ", (long int)drift_comp);
fdrift = (fdrift * 1000) / (1<<USECSCALE);
- fprintf(df, "%4d.%03d %c%d.%06d %.24s\n", idrift, fdrift,
- (offset < 0) ? '-' : '+', abs(offset) / 1000000, abs(offset) % 1000000,
- asctime(localtime(&reftime)));
+ fprintf(df, "%4d.%03d %c%ld.%06ld %.24s\n", idrift, fdrift,
+ (offset < 0) ? '-' : '+', (long int)(abs(offset) / 1000000),
+ (long int)(abs(offset) % 1000000), asctime(localtime(&reftime)));
fclose(df);
LPRINTF("update_drift: %d.%03d ppm ", idrift, fdrift);
}
@@ -1023,8 +1028,9 @@ static void adjust_clock(offset, drift_file, reftime)
drift_comp = -MAX_DRIFT;
update_drift(drift_file, usecoffset, reftime);
- LPRINTF("clock_adjust: %s, clock_adjust %d, drift_comp %d(%d) ",
- pr_timeval(offset), R_SHIFT(clock_adjust, USECSCALE) , R_SHIFT(drift_comp, USECSCALE), drift_comp);
+ LPRINTF("clock_adjust: %s, clock_adjust %ld, drift_comp %ld(%ld) ",
+ pr_timeval(offset),(long int) R_SHIFT(clock_adjust, USECSCALE),
+ (long int)R_SHIFT(drift_comp, USECSCALE), (long int)drift_comp);
}
/*-----------------------------------------------------------------------
@@ -1303,8 +1309,8 @@ main(argc, argv)
memset(term.c_cc, 0, sizeof(term.c_cc));
term.c_cc[VMIN] = 1;
- term.c_cflag = B50|CS8|CREAD|CLOCAL;
- term.c_iflag = 0;
+ term.c_cflag = B50|CS8|CREAD|CLOCAL|PARENB;
+ term.c_iflag = IGNPAR;
term.c_oflag = 0;
term.c_lflag = 0;
@@ -1369,7 +1375,7 @@ main(argc, argv)
(void) alarm(1<<ADJINTERVAL);
#endif
- PRINTF(" DCF77 monitor - Copyright 1993, Frank Kardel\n\n");
+ PRINTF(" DCF77 monitor - Copyright 1993,1994, Frank Kardel\n\n");
pbuf[60] = '\0';
for ( i = 0; i < 60; i++)
@@ -1423,6 +1429,12 @@ main(argc, argv)
}
errs++;
}
+ else
+ if (trace)
+ {
+ PRINTF("\r %.*s ", 59 - offset, &buf[offset]);
+ }
+
buf[0] = c;
@@ -1491,11 +1503,6 @@ main(argc, argv)
if (rtc == CVT_OK)
{
- if (trace && (i == 0))
- {
- PRINTF("\r %.*s ", 59 - offset, &buf[offset]);
- }
-
if (i == 0)
{
/*
diff --git a/usr.sbin/xntpd/parse/util/parsetest.c b/usr.sbin/xntpd/parse/util/parsetest.c
index 21e41289a1c6..7fa62a927b83 100644
--- a/usr.sbin/xntpd/parse/util/parsetest.c
+++ b/usr.sbin/xntpd/parse/util/parsetest.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/util/parsetest.c,v 3.13 1994/02/20 13:04:46 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/util/parsetest.c,v 3.14 1994/05/12 12:49:27 kardel Exp
*
- * parsetest.c,v 3.13 1994/02/20 13:04:46 kardel Exp
+ * parsetest.c,v 3.14 1994/05/12 12:49:27 kardel Exp
*
* Copyright (c) 1989,1990,1991,1992,1993,1994
* Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
@@ -10,7 +10,13 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
- * parsetest.c,v
+ * $Log: parsetest.c,v $
+ * Revision 3.14 1994/05/12 12:49:27 kardel
+ * printf fmt/arg cleanup
+ *
+ * Revision 3.14 1994/05/11 09:25:43 kardel
+ * 3.3r + printf fmt/arg fixes
+ *
* Revision 3.13 1994/02/20 13:04:46 kardel
* parse add/delete second support
*
@@ -59,7 +65,8 @@ static char *strstatus(buffer, state)
{ PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" },
{ PARSEB_DST, "DST" },
{ PARSEB_UTC, "UTC DISPLAY" },
- { PARSEB_LEAP, "LEAP WARNING" },
+ { PARSEB_LEAPADD, "LEAP ADDITION WARNING" },
+ { PARSEB_LEAPDEL, "LEAP DELETION WARNING" },
{ PARSEB_LEAPSECOND, "LEAP SECOND" },
{ PARSEB_ALTERNATE,"ALTERNATE ANTENNA" },
{ PARSEB_TIMECODE, "TIME CODE" },
@@ -194,7 +201,7 @@ main(argc, argv)
parsetime_t parsetime;
struct strioctl strioc;
- printf("parsetest.c,v 3.13 1994/02/20 13:04:46 kardel Exp\n");
+ printf("parsetest.c,v 3.11 1994/01/23 19:00:01 kardel Exp\n");
while (ioctl(fd, I_POP, 0) == 0)
;
@@ -215,7 +222,7 @@ main(argc, argv)
perror("ioctl(fd, I_STR(PARSEIOC_GETSTAT))");
exit(1);
}
- printf("parse status: %04x\n", dct.parsestatus.flags);
+ printf("parse status: %04lx\n", (unsigned long)dct.parsestatus.flags);
dct.parsestatus.flags |= PARSE_STAT_FILTER;
strioc.ic_cmd = PARSEIOC_SETSTAT;
@@ -232,7 +239,7 @@ main(argc, argv)
perror("ioctl(fd, I_STR(PARSEIOC_GETSTAT))");
exit(1);
}
- printf("parse status: %04x\n", dct.parsestatus.flags);
+ printf("parse status: %04lx\n", (unsigned long)dct.parsestatus.flags);
while (read(fd, &parsetime, sizeof(parsetime)) == sizeof(parsetime))
{
@@ -245,15 +252,16 @@ main(argc, argv)
tmp1[24] = '\0';
tmp2[24] = '\0';
- printf("%s (+%06dus) %s PPS: %s (+%06dus), ", tmp1, parsetime.parse_stime.tv.tv_usec, tmp, tmp2, parsetime.parse_ptime.tv.tv_usec);
+ printf("%s (+%06ldus) %s PPS: %s (+%06ldus), ", tmp1, (long int)parsetime.parse_stime.tv.tv_usec, tmp, tmp2,
+ (long int)parsetime.parse_ptime.tv.tv_usec);
strstatus(tmp, parsetime.parse_state);
- printf("state: 0x%x (%s) error: %dus, dispersion: %dus, Status: 0x%x (%s)\n",
- parsetime.parse_state,
+ printf("state: 0x%lx (%s) error: %ldus, dispersion: %ldus, Status: 0x%lx (%s)\n",
+ (unsigned long)parsetime.parse_state,
tmp,
- parsetime.parse_usecerror,
- parsetime.parse_usecdisp,
- parsetime.parse_status,
+ (long)parsetime.parse_usecerror,
+ (long)parsetime.parse_usecdisp,
+ (unsigned long)parsetime.parse_status,
parsestatus(parsetime.parse_status, tmp1));
}
diff --git a/usr.sbin/xntpd/parse/util/testdcf.c b/usr.sbin/xntpd/parse/util/testdcf.c
index 560ab27c4369..73c8d893c398 100644
--- a/usr.sbin/xntpd/parse/util/testdcf.c
+++ b/usr.sbin/xntpd/parse/util/testdcf.c
@@ -1,7 +1,7 @@
/*
- * /src/NTP/REPOSITORY/v3/parse/util/testdcf.c,v 3.11 1994/02/02 17:45:55 kardel Exp
+ * /src/NTP/REPOSITORY/v3/parse/util/testdcf.c,v 3.13 1994/05/12 12:49:31 kardel Exp
*
- * testdcf.c,v 3.11 1994/02/02 17:45:55 kardel Exp
+ * testdcf.c,v 3.13 1994/05/12 12:49:31 kardel Exp
*
* simple DCF77 100/200ms pulse test program (via 50Baud serial line)
*
@@ -354,8 +354,8 @@ main(argc, argv)
memset(term.c_cc, 0, sizeof(term.c_cc));
term.c_cc[VMIN] = 1;
- term.c_cflag = B50|CS8|CREAD|CLOCAL;
- term.c_iflag = 0;
+ term.c_cflag = B50|CS8|CREAD|CLOCAL|PARENB;
+ term.c_iflag = IGNPAR;
term.c_oflag = 0;
term.c_lflag = 0;
@@ -411,8 +411,8 @@ main(argc, argv)
}
if (t.tv_sec > 1 ||
- t.tv_sec == 1 &&
- t.tv_usec > 500000)
+ (t.tv_sec == 1 &&
+ t.tv_usec > 500000))
{
printf("%c %.*s ", pat[i % (sizeof(pat)-1)], 59 - offset, &buf[offset]);
@@ -453,8 +453,8 @@ main(argc, argv)
{
printf("%s, %2d:%02d:%02d, %d.%02d.%02d, <%s%s%s%s>",
wday[clock.wday],
- clock.hour, clock.minute, i, clock.day, clock.month,
- clock.year,
+ (int)clock.hour, (int)clock.minute, (int)i, (int)clock.day, (int)clock.month,
+ (int)clock.year,
(clock.flags & DCFB_ALTERNATE) ? "R" : "_",
(clock.flags & DCFB_ANNOUNCE) ? "A" : "_",
(clock.flags & DCFB_DST) ? "D" : "_",
diff --git a/usr.sbin/xntpd/refclocks/rclk.DATUM b/usr.sbin/xntpd/refclocks/rclk.DATUM
new file mode 100644
index 000000000000..3639e4a21b4b
--- /dev/null
+++ b/usr.sbin/xntpd/refclocks/rclk.DATUM
@@ -0,0 +1,22 @@
+#!/bin/sh -
+CMD="$1"
+shift;
+
+. refclocks/setup
+
+case "$CMD" in
+ info)
+ echo " DATUM - use Datum Programmable Time System"
+ ;;
+ check)
+ if check "$RCONFIG" '$0 ~ /DATUM/'; then
+ echo "DATUM - Datum Programmable Time System"
+ fi
+ ;;
+ config)
+ if check "$REFCONF" '$0 ~ /DATUM/' ||
+ ( [ ! "$REFCONF" ] && query "Include DATUM reference support (DATUM)" n); then
+ echo "-DDATUM" >> $RCONFIG
+ fi
+ ;;
+esac
diff --git a/usr.sbin/xntpd/refclocks/rclk.MOTO b/usr.sbin/xntpd/refclocks/rclk.MOTO
new file mode 100644
index 000000000000..d6e11f8e0193
--- /dev/null
+++ b/usr.sbin/xntpd/refclocks/rclk.MOTO
@@ -0,0 +1,29 @@
+#!/bin/sh -
+CMD="$1"
+shift;
+
+. refclocks/setup
+
+case "$CMD" in
+ info)
+ echo " MOTO - Motorola GPS clock"
+ ;;
+ check)
+ if check "$RCONFIG" '$0 ~ /MOTO/'; then
+ echo "MOTO - Motorola GPS clock"
+ fi
+ ;;
+ config)
+ if check "$REFCONF" '$0 ~ /MOTO/' ||
+ ( [ ! "$REFCONF" ] && query "Include Motorola clock (MOTO)" n); then
+ if check "$PPSFEATURES" '$0 ~ /CD/' &&
+ [ "$PPSOK" -eq 1 ] &&
+ (check "$REFCONF" '$0 ~ /MOTOPPS/' ||
+ ( [ ! "$REFCONF" ] && query " Use Motorola for PPS" n)); then
+ echo "-DMOTOPPS" >> $RCONFIG
+ else
+ echo "-DMOTO" >> $RCONFIG
+ fi
+ fi
+ ;;
+esac
diff --git a/usr.sbin/xntpd/refclocks/rclk.NMEA b/usr.sbin/xntpd/refclocks/rclk.NMEA
new file mode 100644
index 000000000000..f5054651a2f7
--- /dev/null
+++ b/usr.sbin/xntpd/refclocks/rclk.NMEA
@@ -0,0 +1,23 @@
+case "$CMD" in
+ info)
+ echo " NMEA - NMEA GPS station clock"
+ ;;
+ check)
+ if check "$RCONFIG" '$0 ~ /NMEA/'; then
+ echo "NMEA - NMEA GPS station clock"
+ fi
+ ;;
+ config)
+ if check "$REFCONF" '$0 ~ /NMEA/' ||
+ ( [ ! "$REFCONF" ] && query "Include NMEA GPS station clock (NMEA)" n); then
+ if check "$PPSFEATURES" '$0 ~ /CD/' &&
+ [ "$PPSOK" -eq 1 ] &&
+ (check "$REFCONF" '$0 ~ /NMEAPPS/' ||
+ ( [ ! "$REFCONF" ] && query " Use NMEA for PPS" n)); then
+ echo "-DNMEAPPS" >> $RCONFIG
+ else
+ echo "-DNMEA" >> $RCONFIG
+ fi
+ fi
+ ;;
+esac
diff --git a/usr.sbin/xntpd/refclocks/rclk.PARSE b/usr.sbin/xntpd/refclocks/rclk.PARSE
index b91ed8bf8153..5211ccca3620 100644
--- a/usr.sbin/xntpd/refclocks/rclk.PARSE
+++ b/usr.sbin/xntpd/refclocks/rclk.PARSE
@@ -15,7 +15,8 @@ if check "$DEFS" '$0 ~ /HAVE_SYSV_TTYS|STREAM|HAVE_TERMIOS/'; then
echo " Raw DCF77 signal (100/200ms pulses)"
echo " GPS:"
echo " Meinberg GPS 166"
- echo " Trimble GPS SV6"
+ echo " Trimble GPS (TAIP Protocol)"
+ echo " Trimble GPS (TSIP Protocol)"
;;
check)
if check "$RCONFIG" '$0 ~ /PARSE/ && $0 ~ /CLOCK/'; then
@@ -24,7 +25,8 @@ if check "$DEFS" '$0 ~ /HAVE_SYSV_TTYS|STREAM|HAVE_TERMIOS/'; then
if check "$RCONFIG" '$0 ~ /CLOCK_MEINBERG/'; then echon ",MEINBERG"; fi
if check "$RCONFIG" '$0 ~ /CLOCK_SCHMID/'; then echon ",SCHMID"; fi
if check "$RCONFIG" '$0 ~ /CLOCK_DCF7000/'; then echon ",DCF7000"; fi
- if check "$RCONFIG" '$0 ~ /CLOCK_TRIMSV6/'; then echon ",Trimble SV6"; fi
+ if check "$RCONFIG" '$0 ~ /CLOCK_TRIMTAIP/'; then echon ",Trimble GPS (TAIP)"; fi
+ if check "$RCONFIG" '$0 ~ /CLOCK_TRIMTSIP/'; then echon ",Trimble GPS (TSIP)"; fi
if check "$RCONFIG" '$0 ~ /CLOCK_RAWDCF/'; then echon ",Raw DCF77 pulses"; fi
echo
fi
@@ -40,8 +42,10 @@ if check "$DEFS" '$0 ~ /HAVE_SYSV_TTYS|STREAM|HAVE_TERMIOS/'; then
( [ ! "$REFCONF" ] && query " Include support for Schmid DCF77 clock" y); then echo "-DCLOCK_SCHMID" >> $RCONFIG; fi
if check "$REFCONF" '$0 ~ /DCF7000|ELV/' ||
( [ ! "$REFCONF" ] && query " Include support for ELV/DCF7000 clock" y); then echo "-DCLOCK_DCF7000" >> $RCONFIG; fi
- if check "$REFCONF" '$0 ~ /TRIMBLE/' ||
- ( [ ! "$REFCONF" ] && query " Include support for Trimble SV6 GPS receiver" y); then echo "-DCLOCK_TRIMSV6" >> $RCONFIG; fi
+ if check "$REFCONF" '$0 ~ /TRIMTAIP/' ||
+ ( [ ! "$REFCONF" ] && query " Include support for Trimble GPS receiver (TAIP Protocol)" y); then echo "-DCLOCK_TRIMTAIP" >> $RCONFIG; fi
+ if check "$REFCONF" '$0 ~ /TRIMTSIP/' ||
+ ( [ ! "$REFCONF" ] && query " Include support for Trimble GPS receiver (TSIP Protocol)" y); then echo "-DCLOCK_TRIMTSIP" >> $RCONFIG; fi
if check "$REFCONF" '$0 ~ /RAWDCF/' ||
( [ ! "$REFCONF" ] && query " Include support for raw DCF77 time code" y); then echo "-DCLOCK_RAWDCF" >> $RCONFIG; fi
fi
diff --git a/usr.sbin/xntpd/refclocks/rconfig b/usr.sbin/xntpd/refclocks/rconfig
index 75f43fad2087..e49c559bf797 100644
--- a/usr.sbin/xntpd/refclocks/rconfig
+++ b/usr.sbin/xntpd/refclocks/rconfig
@@ -23,10 +23,15 @@ if [ "$rcfg" = "refclocks/rclk.*" ]; then
else
config="`egrep '^[ ]*CLOCKDEFS[ ]*=' Config.local | sed 's/\([^#]*\)#.*$/\1/g; s/[ ]*CLOCKDEFS[ ]*=//g; s/-D//g; s/[ ][ ]*/ /g; s/^ *//g; s/ *$//g;'`"
DEFS="`egrep '^[ ]*DEFS[ ]*=' Config | sed 's/\([^#]*\)#.*$/\1/g; s/[ ]*DEFS[ ]*=//g; s/-D//g; s/[ ][ ]*/ /g; s/^ *//g; s/ *$//g;'`"
+ DEFSLOCAL="`egrep '^[ ]*DEFS_LOCAL[ ]*=' Config.local | sed 's/\([^#]*\)#.*$/\1/g; s/[ ]*DEFS_LOCAL[ ]*=//g; s/-D//g; s/[ ][ ]*/ /g; s/^ *//g; s/ *$//g;'`"
if [ ! "$REFCONF" ]; then
echo
echo "Current configuration"
echo
+ if check "$DEFSLOCAL" '$0 ~ /MCAST/'; then
+ echo "==> MULTICAST SUPPORT (if available)"
+ echo
+ fi
for i in $rcfg
do
sh $i check "$config" "" "" "$DEFS" "$REFCONF"
@@ -78,6 +83,12 @@ else
PPS="-DPPS $PPS"
fi
fi
+ if (check "$REFCONF" '$0 ~ /MCAST/' ||
+ ( [ ! "$REFCONF" ] && query "Do you want allow for multicast support (if available) ?" y)); then
+ MCAST="-DMCAST"
+ else
+ MCAST=""
+ fi
for i in $rcfg
do
sh $i config "$RCONFIG" "$PPSFEATURES" "$PPSOK" "$DEFS" "$REFCONF"
@@ -98,7 +109,7 @@ else
fi
fi
if sed -e 's/^[ ]*CLOCKDEFS[ ]*=.*$/CLOCKDEFS='"$CLOCKDEFS"'/;' \
- -e 's/^[ ]*DEFS_LOCAL[ ]*=.*$/DEFS_LOCAL= $(DEFS_OPT) '"$PPS"'/;' \
+ -e 's/^[ ]*DEFS_LOCAL[ ]*=.*$/DEFS_LOCAL= $(DEFS_OPT) '"$PPS $MCAST"'/;' \
Config.local > Config.local.new; then
mv Config.local Config.local.old &&
mv Config.local.new Config.local &&
@@ -106,7 +117,7 @@ else
echo
echo "New configuration defines:"
echo " CLOCKDEFS=$CLOCKDEFS"
- echo " DEFS_LOCAL="'$(DEFS_OPT)'" $PPS"
+ echo " DEFS_LOCAL="'$(DEFS_OPT)'" $PPS $MCAST"
echo
echo "Configuration updated"
else
diff --git a/usr.sbin/xntpd/scripts/Guess.sh b/usr.sbin/xntpd/scripts/Guess.sh
index 88dcb1a5ef86..9b3180bf0e25 100755
--- a/usr.sbin/xntpd/scripts/Guess.sh
+++ b/usr.sbin/xntpd/scripts/Guess.sh
@@ -4,7 +4,7 @@ if [ -f /bin/uname -o -f /usr/bin/uname ]; then
set `uname -a | tr '[A-Z]' '[a-z]'`
# set `cat test | tr '[A-Z]' '[a-z]'`
case "$1" in
- convexos) case "$3" in
+ convexos) case "$4" in
10.*) guess="convexos10" ;;
esac
;;
@@ -23,7 +23,8 @@ if [ -f /bin/uname -o -f /usr/bin/uname ]; then
case "$3" in
4.1*) guess="sunos4" ;;
5.1) guess="sunos5.1" ;;
- 5.*) guess="sunos5.2" ;;
+ 5.2) guess="sunos5.2" ;;
+ 5.*) guess="sunos5.3" ;;
esac
;;
irix) case "$3" in
@@ -63,6 +64,9 @@ if [ -f /bin/uname -o -f /usr/bin/uname ]; then
"netbsd")
guess="netbsd"
;;
+ "4.4bsd")
+ guess="4.4bsd"
+ ;;
# now the fun starts - there are vendors that
# do not really identify their OS in uname.
# Fine - now I look at our version and hope
diff --git a/usr.sbin/xntpd/scripts/install.sh b/usr.sbin/xntpd/scripts/install.sh
index 5dd98315d82c..1bc4989de16a 100755
--- a/usr.sbin/xntpd/scripts/install.sh
+++ b/usr.sbin/xntpd/scripts/install.sh
@@ -87,7 +87,7 @@ fi
(cp $source $destination &&
chmod $mode $destination &&
chown $owner $destination &&
- chgrp $group $destination) || exit 1
+ chgrp $group $destination) || true # exit 1
# /bin/rm -f $OLDdestination
diff --git a/usr.sbin/xntpd/util/Makefile.tmpl b/usr.sbin/xntpd/util/Makefile.tmpl
index be1681f3af54..e30292f3e1ce 100644
--- a/usr.sbin/xntpd/util/Makefile.tmpl
+++ b/usr.sbin/xntpd/util/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:10:58 jbj Exp
+# Makefile.tmpl
#
PROGRAM= tickadj
#
diff --git a/usr.sbin/xntpd/util/ntptime.c b/usr.sbin/xntpd/util/ntptime.c
index 858fe7cba481..15159051b8e8 100644
--- a/usr.sbin/xntpd/util/ntptime.c
+++ b/usr.sbin/xntpd/util/ntptime.c
@@ -17,6 +17,7 @@
#include "ntp_fp.h"
#include "ntp_unixtime.h"
+#include "sys/timex.h"
#include "ntp_stdlib.h"
#ifndef SYS_DECOSF1
@@ -24,11 +25,9 @@
#endif /* SYS_DECOSF1 */
#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
#define SYS_ntp_gettime NTP_SYSCALL_GET
#endif /* KERNEL_PLL */
@@ -147,14 +146,16 @@ main(argc, argv)
#endif
if (cost) {
- for (c=0; c< sizeof times / sizeof times[0]; c++) {
+ for (c = 0; c < sizeof times / sizeof times[0]; c++) {
(void)ntp_gettime(&ntv);
- if (pll_control < 0) break;
+ if (pll_control < 0)
+ break;
times[c] = ntv.time.tv_usec;
}
if (pll_control >= 0) {
printf("[ us %06d:", times[0]);
- for (c=1; c< sizeof times / sizeof times[0]; c++) printf(" %d", times[c] - times[c-1]);
+ for (c = 1; c < sizeof times / sizeof times[0]; c++)
+ printf(" %d", times[c] - times[c - 1]);
printf(" ]\n");
}
}
@@ -169,7 +170,8 @@ main(argc, argv)
/*
* Fetch timekeeping data and display.
*/
- if ((status = ntp_gettime(&ntv)) < 0)
+ status = ntp_gettime(&ntv);
+ if (status < 0)
perror("ntp_gettime() call fails");
else {
printf("ntp_gettime() returns code %d\n", status);
@@ -182,13 +184,14 @@ main(argc, argv)
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,
- ntv.time.tv_sec, ntv.time.tv_usec,
- ctime(&ntv.time.tv_sec));
+ ts.l_ui, ts.l_uf, ntv.time.tv_sec, ntv.time.tv_usec,
+ ctime(&ntv.time.tv_sec));
}
- if ((status = ntp_adjtime(&ntx)) < 0) perror((errno == EPERM) ?
- ">> Must be root to set kernel values\n>> ntp_adjtime() call fails" :
- ">> ntp_adjtime() call fails");
+ status = ntp_adjtime(&ntx);
+ if (status < 0)
+ perror((errno == EPERM) ?
+ "Must be root to set kernel values\nntp_adjtime() call fails" :
+ "ntp_adjtime() call fails");
else {
printf("ntp_adjtime() returns code %d\n", status);
ftemp = ntx.freq;
diff --git a/usr.sbin/xntpd/util/precision.c b/usr.sbin/xntpd/util/precision.c
index 69af19fb92ec..6961475b4920 100644
--- a/usr.sbin/xntpd/util/precision.c
+++ b/usr.sbin/xntpd/util/precision.c
@@ -1,23 +1,27 @@
#include <sys/types.h>
#include <sys/time.h>
+#include "ntp_unixtime.h"
#define DEFAULT_SYS_PRECISION -99
+int default_get_resolution();
int default_get_precision();
int
main() {
- printf("log2(precision) = %d\n", default_get_precision());
+ printf("log2(resolution) = %d, log2(precision) = %d\n",
+ default_get_resolution(),
+ default_get_precision());
return 0;
}
-/* Find the precision of the system clock by watching how the current time
+/* Find the resolution of the system clock by watching how the current time
* changes as we read it repeatedly.
*
* struct timeval is only good to 1us, which may cause problems as machines
* get faster, but until then the logic goes:
*
- * If a machine has precision (i.e. accurate timing info) > 1us, then it will
+ * If a machine has resolution (i.e. accurate timing info) > 1us, then it will
* probably use the "unused" low order bits as a counter (to force time to be
* a strictly increaing variable), incrementing it each time any process
* requests the time [[ or maybe time will stand still ? ]].
@@ -28,7 +32,7 @@ main() {
* THEN this machine is "counting" with the low order bits
* ELIF this is not the first time round the loop
* THEN this machine *WAS* counting, and has now stepped
- * ELSE this machine has precision < time to read clock
+ * ELSE this machine has resolution < time to read clock
*
* SO: if it exits on the first loop, assume "full accuracy" (1us)
* otherwise, take the log2(observered difference, rounded UP)
@@ -47,9 +51,11 @@ main() {
#define MINSTEP 5 /* some systems increment uS on each call */
/* Don't use "1" as some *other* process may read too*/
/*We assume no system actually *ANSWERS* in this time*/
+#define MAXSTEP 20000 /* maximum clock increment (us) */
+#define MINLOOPS 5 /* minimum number of step samples */
#define MAXLOOPS HUSECS /* Assume precision < .1s ! */
-int default_get_precision()
+int default_get_resolution()
{
struct timeval tp;
struct timezone tzp;
@@ -57,7 +63,7 @@ int default_get_precision()
int i;
long diff;
long val;
- int minsteps = 2; /* need at least this many steps */
+ int minsteps = MINLOOPS; /* need at least this many steps */
gettimeofday(&tp, &tzp);
last = tp.tv_usec;
@@ -69,13 +75,76 @@ int default_get_precision()
last = tp.tv_usec;
}
- printf("precision calculation given %dus after %d loop%s\n",
+ printf("resolution = %ld usec after %d loop%s\n",
diff, i, (i==1) ? "" : "s");
diff = (diff *3)/2;
- if (i >= MAXLOOPS) diff = 1; /* No STEP, so FAST machine */
- if (i == 0) diff = 1; /* time to read clock >= precision */
+ if (i >= MAXLOOPS) {
+ printf(
+ " (Boy this machine is fast ! %d loops without a step)\n",
+ MAXLOOPS);
+ diff = 1; /* No STEP, so FAST machine */
+ }
+ if (i == 0) {
+ printf(
+" (The resolution is less than the time to read the clock -- Assume 1us)\n");
+ diff = 1; /* time to read clock >= resolution */
+ }
for (i=0, val=HUSECS; val>0; i--, val >>= 1) if (diff >= val) return i;
+ printf(" (Oh dear -- that wasn't expected ! I'll guess !)\n");
return DEFAULT_SYS_PRECISION /* Something's BUST, so lie ! */;
}
+/* ===== Rest of this code lifted straight from xntpd/ntp_proto.c ! ===== */
+
+/*
+ * This routine calculates the differences between successive calls to
+ * gettimeofday(). If a difference is less than zero, the us field
+ * has rolled over to the next second, so we add a second in us. If
+ * the difference is greater than zero and less than MINSTEP, the
+ * clock has been advanced by a small amount to avoid standing still.
+ * If the clock has advanced by a greater amount, then a timer interrupt
+ * has occurred and this amount represents the precision of the clock.
+ * In order to guard against spurious values, which could occur if we
+ * happen to hit a fat interrupt, we do this for MINLOOPS times and
+ * keep the minimum value obtained.
+ */
+int default_get_precision()
+{
+ struct timeval tp;
+ struct timezone tzp;
+ long last;
+ int i;
+ long diff;
+ long val;
+ long usec;
+
+ usec = 0;
+ val = MAXSTEP;
+ GETTIMEOFDAY(&tp, &tzp);
+ last = tp.tv_usec;
+ for (i = 0; i < MINLOOPS && usec < HUSECS;) {
+ GETTIMEOFDAY(&tp, &tzp);
+ diff = tp.tv_usec - last;
+ last = tp.tv_usec;
+ if (diff < 0)
+ diff += DUSECS;
+ usec += diff;
+ if (diff > MINSTEP) {
+ i++;
+ if (diff < val)
+ val = diff;
+ }
+ }
+ printf("precision = %ld usec after %d loop%s\n",
+ val, i, (i == 1) ? "" : "s");
+ if (usec >= HUSECS) {
+ printf(" (Boy this machine is fast ! usec was %ld)\n",
+ usec);
+ val = MINSTEP; /* val <= MINSTEP; fast machine */
+ }
+ diff = HUSECS;
+ for (i = 0; diff > val; i--)
+ diff >>= 1;
+ return (i);
+}
diff --git a/usr.sbin/xntpd/util/tickadj.c b/usr.sbin/xntpd/util/tickadj.c
index caec06871795..dc40fa799f6d 100644
--- a/usr.sbin/xntpd/util/tickadj.c
+++ b/usr.sbin/xntpd/util/tickadj.c
@@ -7,8 +7,12 @@
*/
#include <stdio.h>
+#if !defined(SYS_VAX) && !defined(SYS_BSD)
+#include <unistd.h>
+#endif /* SYS_VAX */
+
#ifdef SYS_LINUX
-#include <sys/timex.h>
+#include "sys/timex.h"
struct timex txc;
@@ -42,7 +46,9 @@ main(int argc, char ** argv)
#else /* not Linux... kmem tweaking: */
#include <sys/types.h>
+#ifndef SYS_BSD
#include <sys/file.h>
+#endif
#include <sys/stat.h>
#if defined(SYS_AUX3) || defined(SYS_AUX2)
@@ -69,7 +75,7 @@ main(int argc, char ** argv)
#endif
#endif
-#ifdef SYS_PTX
+#if defined(SYS_PTX) || defined(SYS_IX86OSF1)
#define L_SET SEEK_SET
#endif
@@ -557,7 +563,7 @@ readvar(fd, off, var)
}
if (i != sizeof(int)) {
(void) fprintf(stderr, "%s: read expected %d, got %d\n",
- progname, sizeof(int), i);
+ progname, (int)sizeof(int), i);
exit(1);
}
}
diff --git a/usr.sbin/xntpd/util/timetrim.c b/usr.sbin/xntpd/util/timetrim.c
index 052a587a7dff..a1635c158c42 100644
--- a/usr.sbin/xntpd/util/timetrim.c
+++ b/usr.sbin/xntpd/util/timetrim.c
@@ -1,5 +1,5 @@
/*
- * timetrim.c,v 3.1 1993/07/06 01:11:06 jbj Exp
+ * timetrim.c
*
* "timetrim" allows setting and adjustment of the system clock frequency
* trim parameter on Silicon Graphics machines. The trim value native
diff --git a/usr.sbin/xntpd/xntpd/Makefile.tmpl b/usr.sbin/xntpd/xntpd/Makefile.tmpl
index 6a5a2b1f81c3..919d2a0c9174 100644
--- a/usr.sbin/xntpd/xntpd/Makefile.tmpl
+++ b/usr.sbin/xntpd/xntpd/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:11:10 jbj Exp
+# Makefile.tmpl
#
PROGRAM= xntpd
#
@@ -29,24 +29,28 @@ TOP=../
SOURCE= ntp_config.c ntp_control.c ntp_io.c ntp_leap.c \
ntp_loopfilter.c ntp_monitor.c ntp_peer.c ntp_proto.c \
ntp_refclock.c ntp_request.c ntp_restrict.c ntp_timer.c \
- ntp_unixclock.c ntp_util.c ntpd.c refclock_chu.c \
- refclock_conf.c refclock_local.c refclock_pst.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 refclock_trak.c \
- ntp_intres.c ntp_filegen.c
+ ntp_unixclock.c ntp_util.c ntp_intres.c ntp_filegen.c ntpd.c \
+ refclock_conf.c refclock_chu.c refclock_local.c \
+ refclock_pst.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 \
+ refclock_trak.c refclock_datum.c refclock_acts.c \
+ refclock_heath.c, refclock_nmea.c refclock_moto.c \
+ refclock_atom.c
OBJS= ntp_config.o ntp_control.o ntp_io.o ntp_leap.o \
ntp_loopfilter.o ntp_monitor.o ntp_peer.o ntp_proto.o \
ntp_refclock.o ntp_request.o ntp_restrict.o ntp_timer.o \
- ntp_unixclock.o ntp_util.o ntpd.o refclock_chu.o \
- refclock_conf.o refclock_local.o refclock_pst.o \
- refclock_wwvb.o refclock_goes.o refclock_mx4200.o \
- refclock_parse.o refclock_as2201.o refclock_omega.o \
- refclock_tpro.o refclock_leitch.o refclock_irig.o \
- refclock_msfees.o refclock_gpstm.o refclock_trak.o \
- ntp_intres.o ntp_filegen.o
+ ntp_unixclock.o ntp_util.o ntp_intres.o ntp_filegen.o ntpd.o \
+ refclock_conf.o refclock_chu.o refclock_local.o \
+ refclock_pst.o refclock_wwvb.o refclock_goes.o \
+ refclock_mx4200.o refclock_parse.o refclock_as2201.o \
+ refclock_omega.o refclock_tpro.o refclock_leitch.o \
+ refclock_irig.o refclock_msfees.o refclock_gpstm.o \
+ refclock_trak.o refclock_datum.o refclock_acts.o \
+ refclock_heath.o refclock_nmea.o refclock_moto.o \
+ refclock_atom.o
all: $(PROGRAM)
@@ -144,3 +148,21 @@ refclock_trak.o: refclock_trak.c
refclock_gpstm.o: refclock_gpstm.c
$(CC) $(COPTS) $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) $(INCL) -c $*.c
+
+refclock_datum.o: refclock_datum.c
+ $(CC) $(COPTS) $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) $(INCL) -c $*.c
+
+refclock_acts.o: refclock_acts.c
+ $(CC) $(COPTS) $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) $(INCL) -c $*.c
+
+refclock_heath.o: refclock_heath.c
+ $(CC) $(COPTS) $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) $(INCL) -c $*.c
+
+refclock_nmea.o: refclock_nmea.c
+ $(CC) $(COPTS) $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) $(INCL) -c $*.c
+
+refclock_moto.o: refclock_moto.c
+ $(CC) $(COPTS) $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) $(INCL) -c $*.c
+
+refclock_atom.o: refclock_atom.c
+ $(CC) $(COPTS) $(DEFS) $(DEFS_LOCAL) $(CLOCKDEFS) $(INCL) -c $*.c
diff --git a/usr.sbin/xntpd/xntpd/ntp_config.c b/usr.sbin/xntpd/xntpd/ntp_config.c
index 8f356ac8c2e7..385e53623f8e 100644
--- a/usr.sbin/xntpd/xntpd/ntp_config.c
+++ b/usr.sbin/xntpd/xntpd/ntp_config.c
@@ -1,17 +1,12 @@
/*
- * ntp_config.c - read and apply configuration information
+ k ntp_config.c - read and apply configuration information
*/
-#define RESOLVE_INTERNAL /* gdt */
-
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
-
-#ifdef RESOLVE_INTERNAL
-#include <sys/time.h>
-#endif
+#include <sys/time.h>
#include "ntpd.h"
#include "ntp_io.h"
@@ -42,35 +37,33 @@
/*
* We understand the following configuration entries and defaults.
*
- * 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 ]
+ * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
+ * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
* precision -7
- * broadcast 128.100.224.255 [ version 3 ] [ key 0 ] [ ttl 1 ]
+ * broadcast [ addr ] [ version 3 ] [ key 0 ] [ ttl 1 ]
* broadcastclient
* multicastclient [224.0.1.1]
* broadcastdelay 0.0102
- * authenticate yes|no
- * monitor yes|no
+ * authenticate yes|no XXX depredated
+ * monitor yes|no XXX depredated
* authdelay 0.00842
- * pps [ delay 0.000247 ] [ baud 38400 ]
- * restrict 128.100.100.0 [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery
+ * restrict [ addr ] [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery
* driftfile file_name
* keys file_name
* 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 [ ... ]
+ * trap [ addr ]
+ * fudge [ addr ] [ stratum ] [ refid ] ...
* pidfile [ ]
- * logfile [ ]
* setvar [ ]
- *
- * And then some. See the manual page.
+ * enable auth|bclient|pll|pps|monitor|stats
+ * disable auth|bclient|pll|pps|monitor|stats
+ * phone ...
*/
/*
@@ -99,13 +92,14 @@
#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 CONFIG_PIDFILE 22
+#define CONFIG_SETVAR 23
+#define CONFIG_CLIENTLIMIT 24
+#define CONFIG_CLIENTPERIOD 25
+#define CONFIG_MULTICASTCLIENT 26
+#define CONFIG_ENABLE 27
+#define CONFIG_DISABLE 28
+#define CONFIG_PHONE 29
#define CONF_MOD_VERSION 1
#define CONF_MOD_KEY 2
@@ -113,9 +107,7 @@
#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
+#define CONF_MOD_MODE 7
#define CONF_RES_MASK 1
#define CONF_RES_IGNORE 2
@@ -134,8 +126,8 @@
#define CONF_FDG_TIME1 1
#define CONF_FDG_TIME2 2
-#define CONF_FDG_VALUE1 3
-#define CONF_FDG_VALUE2 4
+#define CONF_FDG_STRATUM 3
+#define CONF_FDG_REFID 4
#define CONF_FDG_FLAG1 5
#define CONF_FDG_FLAG2 6
#define CONF_FDG_FLAG3 7
@@ -148,15 +140,6 @@
#define CONF_FGEN_FLAG_ENABLE 5
#define CONF_FGEN_FLAG_DISABLE 6
-#define CONF_BAUD_300 1
-#define CONF_BAUD_600 2
-#define CONF_BAUD_1200 3
-#define CONF_BAUD_2400 4
-#define CONF_BAUD_4800 5
-#define CONF_BAUD_9600 6
-#define CONF_BAUD_19200 7
-#define CONF_BAUD_38400 8
-
/*
* Translation table - keywords to function index
*/
@@ -165,6 +148,9 @@ struct keyword {
int keytype;
};
+/*
+ * Command keywords
+ */
static struct keyword keywords[] = {
{ "peer", CONFIG_PEER },
{ "server", CONFIG_SERVER },
@@ -177,7 +163,6 @@ static struct keyword keywords[] = {
{ "keys", CONFIG_KEYS },
{ "monitor", CONFIG_MONITOR },
{ "authdelay", CONFIG_AUTHDELAY },
- { "pps", CONFIG_PPS },
{ "restrict", CONFIG_RESTRICT },
{ "broadcastdelay", CONFIG_BDELAY },
{ "trustedkey", CONFIG_TRUSTEDKEY },
@@ -185,20 +170,21 @@ static struct keyword keywords[] = {
{ "controlkey", CONFIG_CONTROLKEY },
{ "trap", CONFIG_TRAP },
{ "fudge", CONFIG_FUDGE },
- { "resolver", CONFIG_RESOLVER },
{ "statsdir", CONFIG_STATSDIR },
{ "filegen", CONFIG_FILEGEN },
{ "statistics", CONFIG_STATISTICS },
{ "pidfile", CONFIG_PIDFILE },
- { "logfile", CONFIG_LOGFILE },
{ "setvar", CONFIG_SETVAR },
{ "clientlimit", CONFIG_CLIENTLIMIT },
{ "clientperiod", CONFIG_CLIENTPERIOD },
+ { "enable", CONFIG_ENABLE },
+ { "disable", CONFIG_DISABLE },
+ { "phone", CONFIG_PHONE },
{ "", CONFIG_UNKNOWN }
};
/*
- * Modifier keywords
+ * "peer", "server", "broadcast" modifier keywords
*/
static struct keyword mod_keywords[] = {
{ "version", CONF_MOD_VERSION },
@@ -206,21 +192,13 @@ static struct keyword mod_keywords[] = {
{ "minpoll", CONF_MOD_MINPOLL },
{ "maxpoll", CONF_MOD_MAXPOLL },
{ "prefer", CONF_MOD_PREFER },
- { "ttl", CONF_MOD_TTL },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * PPS modifier keywords
- */
-static struct keyword pps_keywords[] = {
- { "delay", CONF_PPS_DELAY },
- { "baud", CONF_PPS_BAUD },
+ { "mode", CONF_MOD_MODE }, /* reference clocks */
+ { "ttl", CONF_MOD_TTL }, /* NTP peers */
{ "", CONFIG_UNKNOWN }
};
/*
- * Special restrict keywords
+ * "restrict" modifier keywords
*/
static struct keyword res_keywords[] = {
{ "mask", CONF_RES_MASK },
@@ -231,29 +209,14 @@ static struct keyword res_keywords[] = {
{ "nomodify", CONF_RES_NOMODIFY },
{ "nopeer", CONF_RES_NOPEER },
{ "notrap", CONF_RES_NOTRAP },
- { "lowpriotrap", CONF_RES_LPTRAP },
+ { "lowpriotrap", CONF_RES_LPTRAP },
{ "ntpport", CONF_RES_NTPPORT },
{ "limited", CONF_RES_LIMITED },
{ "", CONFIG_UNKNOWN }
};
/*
- * Baud rate keywords
- */
-static struct keyword baud_keywords[] = {
- { "300", CONF_BAUD_300 },
- { "600", CONF_BAUD_600 },
- { "1200", CONF_BAUD_1200 },
- { "2400", CONF_BAUD_2400 },
- { "4800", CONF_BAUD_4800 },
- { "9600", CONF_BAUD_9600 },
- { "19200", CONF_BAUD_19200 },
- { "38400", CONF_BAUD_38400 },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * Keywords for the trap command
+ * "trap" modifier keywords
*/
static struct keyword trap_keywords[] = {
{ "port", CONF_TRAP_PORT },
@@ -263,13 +226,13 @@ static struct keyword trap_keywords[] = {
/*
- * Keywords for the fudge command
+ * "fudge" modifier keywords
*/
static struct keyword fudge_keywords[] = {
{ "time1", CONF_FDG_TIME1 },
{ "time2", CONF_FDG_TIME2 },
- { "value1", CONF_FDG_VALUE1 },
- { "value2", CONF_FDG_VALUE2 },
+ { "stratum", CONF_FDG_STRATUM },
+ { "refid", CONF_FDG_REFID },
{ "flag1", CONF_FDG_FLAG1 },
{ "flag2", CONF_FDG_FLAG2 },
{ "flag3", CONF_FDG_FLAG3 },
@@ -279,7 +242,7 @@ static struct keyword fudge_keywords[] = {
/*
- * Keywords for the filegen command
+ * "filegen" modifier keywords
*/
static struct keyword filegen_keywords[] = {
{ "file", CONF_FGEN_FILE },
@@ -291,6 +254,9 @@ static struct keyword filegen_keywords[] = {
{ "", CONFIG_UNKNOWN }
};
+/*
+ * "type" modifier keywords
+ */
static struct keyword fgen_types[] = {
{ "none", FILEGEN_NONE },
{ "pid", FILEGEN_PID },
@@ -302,12 +268,25 @@ static struct keyword fgen_types[] = {
{ "", CONFIG_UNKNOWN}
};
+/*
+ * "enable", "disable" modifier keywords
+ */
+static struct keyword flags_keywords[] = {
+ { "auth", PROTO_AUTHENTICATE },
+ { "bclient", PROTO_BROADCLIENT },
+ { "pll", PROTO_PLL },
+ { "pps", PROTO_PPS },
+ { "monitor", PROTO_MONITOR },
+ { "stats", PROTO_FILEGEN },
+ { "", CONFIG_UNKNOWN }
+};
/*
* Limits on things
*/
#define MAXTOKENS 20 /* 20 tokens on line */
#define MAXLINE 1024 /* maximum length of line */
+#define MAXPHONE 5 /* maximum number of phone strings */
#define MAXFILENAME 128 /* maximum length of a file name (alloca()?) */
@@ -333,20 +312,21 @@ static char res_file[20]; /* enough for /tmp/xntpXXXXXX\0 */
#ifdef DEBUG
extern int debug;
#endif
-extern char *FindConfig();
- char *progname;
-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, int, U_LONG));
-static void do_resolve P((char *, U_LONG, char *));
-#ifdef RESOLVE_INTERNAL
-static void do_resolve_internal P((void));
-#endif /* RESOLVE_INTERNAL */
-static void abort_resolve P((void));
-static RETSIGTYPE catchchild P((int));
+extern char *FindConfig();
+ char *progname;
+ char sys_phone[MAXPHONE][MAXDIAL]; /* ACTS phone numbers */
+static char *xntp_options = "abc:dD:e:f:k:l:mp:r:s:t:v:V:";
+
+/*
+ * Function prototypes
+ */
+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, int, u_long));
+static void do_resolve_internal P((void));
+static void abort_resolve P((void));
+static RETSIGTYPE catchchild P((int));
/*
* getstartup - search through the options looking for a debugging flag
@@ -360,6 +340,7 @@ getstartup(argc, argv)
int errflg;
int c;
extern int ntp_optind;
+ extern char *ntp_optarg;
debug = 0; /* no debugging by default */
@@ -385,6 +366,10 @@ getstartup(argc, argv)
case 'd':
++debug;
break;
+ case 'D':
+ debug = strtol(ntp_optarg, 0, 0);
+ printf("Debug1: %s -> %x = %d\n", ntp_optarg, debug, debug);
+ break;
case '?':
++errflg;
break;
@@ -428,7 +413,7 @@ getconfig(argc, argv)
int minpoll;
int maxpoll;
int ttl;
- U_LONG peerkey;
+ u_long peerkey;
int peerflags;
int hmode;
struct sockaddr_in peeraddr;
@@ -441,17 +426,12 @@ getconfig(argc, argv)
struct interface *localaddr;
char *config_file;
struct refclockstat clock;
- int have_resolver;
-#ifdef RESOLVE_INTERNAL
- int resolve_internal;
-#endif
- char resolver_name[MAXFILENAME];
int have_keyfile;
char keyfile[MAXFILENAME];
extern int ntp_optind;
extern char *ntp_optarg;
extern char *Version;
- extern U_LONG info_auth_keyid;
+ extern u_long info_auth_keyid;
FILEGEN *filegen;
/*
@@ -464,7 +444,8 @@ getconfig(argc, argv)
config_file = CONFIG_FILE;
progname = argv[0];
res_fp = NULL;
- have_resolver = have_keyfile = 0;
+ have_keyfile = 0;
+ memset((char *)sys_phone, 0, sizeof(sys_phone));
/*
* install a non default variable with this daemon version
@@ -472,21 +453,17 @@ getconfig(argc, argv)
(void) sprintf(line, "daemon_version=\"%s\"", Version);
set_sys_var(line, strlen(line)+1, RO);
-#ifdef RESOLVE_INTERNAL
- resolve_internal = 1;
-#endif
-
/*
* Decode argument list
*/
while ((c = ntp_getopt(argc, argv, xntp_options)) != EOF) {
switch (c) {
case 'a':
- proto_config(PROTO_AUTHENTICATE, (LONG)1);
+ proto_config(PROTO_AUTHENTICATE, 1);
break;
case 'b':
- proto_config(PROTO_BROADCLIENT, (LONG)1);
+ proto_config(PROTO_BROADCLIENT, 1);
break;
case 'c':
@@ -500,6 +477,12 @@ getconfig(argc, argv)
errflg++;
#endif /* DEBUG */
break;
+ case 'D':
+#ifdef DEBUG
+ debug = strtol(ntp_optarg, 0, 0);
+ printf("Debug2: %s -> %x = %d\n", ntp_optarg, debug, debug);
+#endif /* DEBUG */
+ break;
case 'e':
do {
@@ -529,7 +512,7 @@ getconfig(argc, argv)
getauthkeys(ntp_optarg);
if ((int)strlen(ntp_optarg) >= MAXFILENAME) {
syslog(LOG_ERR,
- "key file name too LONG (>%d, sigh), no name resolution possible",
+ "key file name too long (>%d, sigh), no name resolution possible",
MAXFILENAME);
} else {
have_keyfile = 1;
@@ -538,7 +521,7 @@ getconfig(argc, argv)
break;
case 'm':
- proto_config(PROTO_MULTICAST_ADD, INADDR_NTP);
+ proto_config(PROTO_MULTICAST_ADD, htonl(INADDR_NTP));
break;
case 'p':
@@ -569,22 +552,23 @@ getconfig(argc, argv)
case 't':
do {
- int tkey;
+ u_long tkey;
- tkey = atoi(ntp_optarg);
+ tkey = atol(ntp_optarg);
if (tkey <= 0 || tkey > NTP_MAXKEY) {
syslog(LOG_ERR,
"command line trusted key %s is unlikely",
ntp_optarg);
} else {
- authtrust(tkey, (LONG)1);
+ authtrust(tkey, 1);
}
} while (0);
break;
case 'v':
case 'V':
- set_sys_var(ntp_optarg, strlen(ntp_optarg)+1, RW | ((c == 'V') ? DEF : 0));
+ set_sys_var(ntp_optarg, strlen(ntp_optarg)+1,
+ RW | ((c == 'V') ? DEF : 0));
break;
default:
@@ -622,8 +606,8 @@ getconfig(argc, argv)
if (ntokens < 2) {
syslog(LOG_ERR,
- "No address for %s, line ignored",
- tokens[0]);
+ "No address for %s, line ignored",
+ tokens[0]);
break;
}
@@ -638,24 +622,24 @@ getconfig(argc, argv)
#endif
ISBADADR(&peeraddr)) {
syslog(LOG_ERR,
- "attempt to configure invalid address %s",
- ntoa(&peeraddr));
+ "attempt to configure invalid address %s",
+ ntoa(&peeraddr));
break;
}
}
peerversion = NTP_VERSION;
minpoll = NTP_MINDPOLL;
- maxpoll = NTP_MAXPOLL;
+ maxpoll = NTP_MAXDPOLL;
peerkey = 0;
peerflags = 0;
- ttl = 1;
+ ttl = 0;
for (i = 2; i < ntokens; i++)
switch (matchkey(tokens[i], mod_keywords)) {
case CONF_MOD_VERSION:
if (i >= ntokens-1) {
syslog(LOG_ERR,
- "peer/server version requires an argument");
+ "peer/server version requires an argument");
errflg = 1;
break;
}
@@ -663,26 +647,20 @@ getconfig(argc, argv)
if ((u_char)peerversion > NTP_VERSION
|| (u_char)peerversion < NTP_OLDVERSION) {
syslog(LOG_ERR,
- "inappropriate version number %s, line ignored",
- tokens[i]);
+ "inappropriate version number %s, line ignored",
+ tokens[i]);
errflg = 1;
}
break;
case CONF_MOD_KEY:
- /*
- * XXX
- * This is bad because atoi
- * returns 0 on errors. Do
- * something later.
- */
if (i >= ntokens-1) {
syslog(LOG_ERR,
- "key: argument required");
+ "key: argument required");
errflg = 1;
break;
}
- peerkey = (U_LONG)atoi(tokens[++i]);
+ peerkey = atol(tokens[++i]);
peerflags |= FLAG_AUTHENABLE;
break;
@@ -725,6 +703,16 @@ getconfig(argc, argv)
ttl = atoi(tokens[++i]);
break;
+ case CONF_MOD_MODE:
+ if (i >= ntokens-1) {
+ syslog(LOG_ERR,
+ "mode: argument required");
+ errflg = 1;
+ break;
+ }
+ ttl = atoi(tokens[++i]);
+ break;
+
case CONFIG_UNKNOWN:
errflg = 1;
break;
@@ -753,10 +741,10 @@ getconfig(argc, argv)
i = atoi(tokens[1]);
if (i >= 0 || i < -25)
syslog(LOG_ERR,
- "unlikely precision %s, line ignored",
- tokens[1]);
+ "unlikely precision %s, line ignored",
+ tokens[1]);
else
- proto_config(PROTO_PRECISION, (LONG)i);
+ proto_config(PROTO_PRECISION, i);
}
break;
@@ -774,54 +762,28 @@ getconfig(argc, argv)
stats_config(STATS_PID_FILE, (char *)0);
break;
- case CONFIG_LOGFILE: {
-#ifdef SYSLOG_FILE
- extern int syslogit;
-
- syslogit = 0;
- if (ntokens >= 2) {
- FILE *new_file;
- new_file = fopen(tokens[1], "a");
- if (new_file != NULL) {
- if (syslog_file != NULL)
- (void)fclose(syslog_file);
- syslog_file = new_file;
- }
- else
- syslog(LOG_ERR,
- "Cannot open log file %s",
- tokens[1]);
- }
- else
- syslog(LOG_ERR, "logfile needs one argument");
-
-#else
- syslog(LOG_ERR, "logging to logfile not compiled into xntpd - logfile \"%s\" ignored", (ntokens == 2) ? tokens[1] : "");
-#endif
- } break;
-
case CONFIG_BROADCASTCLIENT:
- proto_config(PROTO_BROADCLIENT, (U_LONG)1);
+ proto_config(PROTO_BROADCLIENT, 1);
break;
case CONFIG_MULTICASTCLIENT:
if (ntokens > 1) {
for (i = 1; i < ntokens; i++) {
- if (getnetnum(tokens[i], &peeraddr, 1));
+ if (getnetnum(tokens[i], &peeraddr, 1))
proto_config(PROTO_MULTICAST_ADD,
peeraddr.sin_addr.s_addr);
}
} else
- proto_config(PROTO_MULTICAST_ADD, INADDR_NTP);
+ proto_config(PROTO_MULTICAST_ADD, htonl(INADDR_NTP));
break;
case CONFIG_AUTHENTICATE:
errflg = 0;
if (ntokens >= 2) {
if (STREQ(tokens[1], "yes"))
- proto_config(PROTO_AUTHENTICATE, (LONG)1);
+ proto_config(PROTO_AUTHENTICATE, 1);
else if (STREQ(tokens[1], "no"))
- proto_config(PROTO_AUTHENTICATE, (LONG)0);
+ proto_config(PROTO_AUTHENTICATE, 0);
else
errflg++;
} else {
@@ -830,7 +792,7 @@ getconfig(argc, argv)
if (errflg)
syslog(LOG_ERR,
- "should be `authenticate yes|no'");
+ "should be `authenticate yes|no'");
break;
case CONFIG_KEYS:
@@ -838,8 +800,8 @@ getconfig(argc, argv)
getauthkeys(tokens[1]);
if ((int)strlen(tokens[1]) >= MAXFILENAME) {
syslog(LOG_ERR,
- "key file name too LONG (>%d, sigh), no name resolution possible",
- MAXFILENAME);
+ "key file name too long (>%d, sigh), no name resolution possible",
+ MAXFILENAME);
} else {
have_keyfile = 1;
(void)strcpy(keyfile, tokens[1]);
@@ -862,7 +824,7 @@ getconfig(argc, argv)
if (errflg)
syslog(LOG_ERR,
- "should be `monitor yes|no'");
+ "should be `monitor yes|no'");
break;
case CONFIG_AUTHDELAY:
@@ -871,74 +833,25 @@ getconfig(argc, argv)
if (!atolfp(tokens[1], &tmp)) {
syslog(LOG_ERR,
- "authdelay value %s undecodable",
- tokens[1]);
+ "authdelay value %s undecodable",
+ tokens[1]);
} else if (tmp.l_ui != 0) {
syslog(LOG_ERR,
- "authdelay value %s is unlikely",
- tokens[1]);
+ "authdelay value %s is unlikely",
+ tokens[1]);
} else {
proto_config(PROTO_AUTHDELAY, tmp.l_f);
}
}
break;
- case CONFIG_PPS:
- for (i = 1 ; i < ntokens ; i++) {
- switch(matchkey(tokens[i],pps_keywords)) {
- case CONF_PPS_DELAY:
- if (i >= ntokens-1) {
- syslog(LOG_ERR,
- "pps delay requires an argument");
- errflg = 1;
- break;
- }
- {
- l_fp tmp;
-
- if (!atolfp(tokens[++i],&tmp)) {
- syslog(LOG_ERR,
- "pps delay value %s undecodable",
- tokens[i]);
- } else {
- loop_config(LOOP_PPSDELAY, &tmp, 0);
- }
- }
- break;
- case CONF_PPS_BAUD:
- if (i >= ntokens-1) {
- syslog(LOG_ERR,
- "pps baud requires an argument");
- errflg = 1;
- break;
- }
- {
- int tmp;
-
- if (matchkey(tokens[++i],baud_keywords)) {
- tmp = atoi(tokens[i]);
- if (tmp < 19200) {
- syslog(LOG_WARNING,
- "pps baud %d unlikely\n", tmp);
- }
- loop_config(LOOP_PPSBAUD, NULL, tmp);
- }
- }
- break;
- case CONFIG_UNKNOWN:
- errflg = 1;
- break;
- }
- }
- break;
-
case CONFIG_RESTRICT:
if (ntokens < 2) {
syslog(LOG_ERR, "restrict requires an address");
break;
}
if (STREQ(tokens[1], "default"))
- peeraddr.sin_addr.s_addr = INADDR_ANY;
+ peeraddr.sin_addr.s_addr = htonl(INADDR_ANY);
else if (!getnetnum(tokens[1], &peeraddr, 1))
break;
@@ -954,7 +867,7 @@ getconfig(argc, argv)
case CONF_RES_MASK:
if (i >= ntokens-1) {
syslog(LOG_ERR,
- "mask keyword needs argument");
+ "mask keyword needs argument");
errflg++;
break;
}
@@ -1008,11 +921,11 @@ getconfig(argc, argv)
break;
}
}
- if (SRCADR(&peeraddr) == INADDR_ANY)
+ if (SRCADR(&peeraddr) == htonl(INADDR_ANY))
maskaddr.sin_addr.s_addr = 0;
if (!errflg)
restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
- (int)peerkey, peerversion);
+ (int)peerkey, peerversion);
break;
case CONFIG_BDELAY:
@@ -1021,12 +934,12 @@ getconfig(argc, argv)
if (!atolfp(tokens[1], &tmp)) {
syslog(LOG_ERR,
- "broadcastdelay value %s undecodable",
- tokens[1]);
+ "broadcastdelay value %s undecodable",
+ tokens[1]);
} else if (tmp.l_ui != 0) {
syslog(LOG_ERR,
- "broadcastdelay value %s is unlikely",
- tokens[1]);
+ "broadcastdelay value %s is unlikely",
+ tokens[1]);
} else {
proto_config(PROTO_BROADDELAY, tmp.l_f);
}
@@ -1035,13 +948,13 @@ getconfig(argc, argv)
case CONFIG_TRUSTEDKEY:
for (i = 1; i < ntokens; i++) {
- U_LONG tkey;
+ u_long tkey;
- tkey = (U_LONG) atoi(tokens[i]);
+ tkey = atol(tokens[i]);
if (tkey == 0) {
syslog(LOG_ERR,
- "trusted key %s unlikely",
- tokens[i]);
+ "trusted key %s unlikely",
+ tokens[i]);
} else {
authtrust(tkey, 1);
}
@@ -1050,21 +963,21 @@ getconfig(argc, argv)
case CONFIG_REQUESTKEY:
if (ntokens >= 2) {
- U_LONG rkey;
+ u_long rkey;
if (!atouint(tokens[1], &rkey)) {
syslog(LOG_ERR,
- "%s is undecodeable as request key",
- tokens[1]);
+ "%s is undecodeable as request key",
+ tokens[1]);
} else if (rkey == 0) {
syslog(LOG_ERR,
- "%s makes a poor request keyid",
- tokens[1]);
+ "%s makes a poor request keyid",
+ tokens[1]);
} else {
#ifdef DEBUG
if (debug > 3)
printf(
- "set info_auth_key to %lu\n", rkey);
+ "set info_auth_key to %lu\n", rkey);
#endif
info_auth_keyid = rkey;
}
@@ -1073,14 +986,14 @@ getconfig(argc, argv)
case CONFIG_CONTROLKEY:
if (ntokens >= 2) {
- U_LONG ckey;
- extern U_LONG ctl_auth_keyid;
+ u_long ckey;
+ extern u_long ctl_auth_keyid;
- ckey = (U_LONG)atoi(tokens[1]);
+ ckey = atol(tokens[1]);
if (ckey == 0) {
syslog(LOG_ERR,
- "%s makes a poor control keyid",
- tokens[1]);
+ "%s makes a poor control keyid",
+ tokens[1]);
} else {
ctl_auth_keyid = ckey;
}
@@ -1090,7 +1003,7 @@ getconfig(argc, argv)
case CONFIG_TRAP:
if (ntokens < 2) {
syslog(LOG_ERR,
- "no address for trap command, line ignored");
+ "no address for trap command, line ignored");
break;
}
if (!getnetnum(tokens[1], &peeraddr, 1))
@@ -1107,7 +1020,7 @@ getconfig(argc, argv)
case CONF_TRAP_PORT:
if (i >= ntokens-1) {
syslog(LOG_ERR,
- "trap port requires an argument");
+ "trap port requires an argument");
errflg = 1;
break;
}
@@ -1115,7 +1028,7 @@ getconfig(argc, argv)
if (peerversion <= 0
|| peerversion > 32767) {
syslog(LOG_ERR,
- "invalid port number %s, trap ignored",
+ "invalid port number %s, trap ignored",
tokens[i]);
errflg = 1;
}
@@ -1124,13 +1037,13 @@ getconfig(argc, argv)
case CONF_TRAP_INTERFACE:
if (i >= ntokens-1) {
syslog(LOG_ERR,
- "trap interface requires an argument");
+ "trap interface requires an argument");
errflg = 1;
break;
}
if (!getnetnum(tokens[++i],
- &maskaddr, 1)) {
+ &maskaddr, 1)) {
errflg = 1;
break;
}
@@ -1138,8 +1051,8 @@ getconfig(argc, argv)
localaddr = findinterface(&maskaddr);
if (localaddr == NULL) {
syslog(LOG_ERR,
- "can't find interface with address %s",
- ntoa(&maskaddr));
+ "can't find interface with address %s",
+ ntoa(&maskaddr));
errflg = 1;
}
break;
@@ -1159,17 +1072,17 @@ getconfig(argc, argv)
if (localaddr == NULL)
localaddr = any_interface;
if (!ctlsettrap(&peeraddr, localaddr, 0,
- NTP_VERSION))
+ NTP_VERSION))
syslog(LOG_ERR,
- "can't set trap for %s, no resources",
- ntoa(&peeraddr));
+ "can't set trap for %s, no resources",
+ ntoa(&peeraddr));
}
break;
case CONFIG_FUDGE:
if (ntokens < 2) {
syslog(LOG_ERR,
- "no address for fudge command, line ignored");
+ "no address for fudge command, line ignored");
break;
}
if (!getnetnum(tokens[1], &peeraddr, 1))
@@ -1177,8 +1090,8 @@ getconfig(argc, argv)
if (!ISREFCLOCKADR(&peeraddr)) {
syslog(LOG_ERR,
- "%s is inappropriate address for the fudge command, line ignored",
- ntoa(&peeraddr));
+ "%s is inappropriate address for the fudge command, line ignored",
+ ntoa(&peeraddr));
break;
}
@@ -1186,13 +1099,13 @@ getconfig(argc, argv)
errflg = 0;
for (i = 2; i < ntokens-1; i++) {
switch (c = matchkey(tokens[i],
- fudge_keywords)) {
+ fudge_keywords)) {
case CONF_FDG_TIME1:
if (!atolfp(tokens[++i],
- &clock.fudgetime1)) {
+ &clock.fudgetime1)) {
syslog(LOG_ERR,
- "fudge %s time1 value in error",
- ntoa(&peeraddr));
+ "fudge %s time1 value in error",
+ ntoa(&peeraddr));
errflg = i;
break;
}
@@ -1201,40 +1114,34 @@ getconfig(argc, argv)
case CONF_FDG_TIME2:
if (!atolfp(tokens[++i],
- &clock.fudgetime2)) {
+ &clock.fudgetime2)) {
syslog(LOG_ERR,
- "fudge %s time2 value in error",
- ntoa(&peeraddr));
+ "fudge %s time2 value in error",
+ ntoa(&peeraddr));
errflg = i;
break;
}
clock.haveflags |= CLK_HAVETIME2;
break;
- case CONF_FDG_VALUE1:
+ case CONF_FDG_STRATUM:
if (!atoint(tokens[++i],
- &clock.fudgeval1)) {
+ (long *)&clock.fudgeval1)) {
syslog(LOG_ERR,
- "fudge %s value1 value in error",
- ntoa(&peeraddr));
+ "fudge %s stratum value in error",
+ ntoa(&peeraddr));
errflg = i;
break;
}
clock.haveflags |= CLK_HAVEVAL1;
break;
- case CONF_FDG_VALUE2:
- if (!atoint(tokens[++i],
- &clock.fudgeval2)) {
- syslog(LOG_ERR,
- "fudge %s value2 value in error",
- ntoa(&peeraddr));
- errflg = i;
- break;
- }
+ case CONF_FDG_REFID:
+ strncpy((char *)&clock.fudgeval2,
+ tokens[++i], 4);
clock.haveflags |= CLK_HAVEVAL2;
break;
-
+
case CONF_FDG_FLAG1:
case CONF_FDG_FLAG2:
case CONF_FDG_FLAG3:
@@ -1242,8 +1149,8 @@ getconfig(argc, argv)
if (!atouint(tokens[++i], &peerkey)
|| peerkey > 1) {
syslog(LOG_ERR,
- "fudge %s flag value in error",
- ntoa(&peeraddr));
+ "fudge %s flag value in error",
+ ntoa(&peeraddr));
errflg = i;
break;
}
@@ -1285,27 +1192,11 @@ getconfig(argc, argv)
*/
if (!errflg) {
refclock_control(&peeraddr, &clock,
- (struct refclockstat *)0);
+ (struct refclockstat *)0);
}
#endif
break;
- case CONFIG_RESOLVER:
- if (ntokens >= 2) {
- if (strlen(tokens[1]) >= (size_t)MAXFILENAME) {
- syslog(LOG_ERR,
- "resolver path name too LONG (>%d, sigh), no name resolution possible",
- MAXFILENAME);
- break;
- }
- strcpy(resolver_name, tokens[1]);
- have_resolver = 1;
-#ifdef RESOLVE_INTERNAL
- resolve_internal = 0;
-#endif
- }
- break;
-
case CONFIG_STATSDIR:
if (ntokens >= 2) {
stats_config(STATS_STATSDIR,tokens[1]);
@@ -1318,14 +1209,14 @@ getconfig(argc, argv)
if (filegen == NULL) {
syslog(LOG_ERR,
- "no statistics named %s available",
- tokens[i]);
+ "no statistics named %s available",
+ tokens[i]);
continue;
}
#ifdef DEBUG
if (debug > 3)
printf("enabling filegen for %s statistics \"%s%s\"\n",
- tokens[i], filegen->prefix, filegen->basename);
+ tokens[i], filegen->prefix, filegen->basename);
#endif
filegen->flag |= FGEN_FLAG_ENABLED;
}
@@ -1334,15 +1225,15 @@ getconfig(argc, argv)
case CONFIG_FILEGEN:
if (ntokens < 2) {
syslog(LOG_ERR,
- "no id for filegen command, line ignored");
+ "no id for filegen command, line ignored");
break;
}
filegen = filegen_get(tokens[1]);
if (filegen == NULL) {
syslog(LOG_ERR,
- "unknown filegen \"%s\" ignored",
- tokens[1]);
+ "unknown filegen \"%s\" ignored",
+ tokens[1]);
break;
}
/*
@@ -1360,8 +1251,8 @@ getconfig(argc, argv)
case CONF_FGEN_FILE:
if (i >= ntokens - 1) {
syslog(LOG_ERR,
- "filegen %s file requires argument",
- tokens[1]);
+ "filegen %s file requires argument",
+ tokens[1]);
errflg = i;
break;
}
@@ -1370,16 +1261,16 @@ getconfig(argc, argv)
case CONF_FGEN_TYPE:
if (i >= ntokens -1) {
syslog(LOG_ERR,
- "filegen %s type requires argument",
- tokens[1]);
+ "filegen %s type requires argument",
+ tokens[1]);
errflg = i;
break;
}
peerkey = matchkey(tokens[++i], fgen_types);
if (peerkey == CONFIG_UNKNOWN) {
syslog(LOG_ERR,
- "filegen %s unknown type \"%s\"",
- tokens[1], tokens[i]);
+ "filegen %s unknown type \"%s\"",
+ tokens[1], tokens[i]);
errflg = i;
break;
}
@@ -1409,70 +1300,98 @@ getconfig(argc, argv)
break;
case CONFIG_SETVAR:
- if (ntokens < 2)
- {
- syslog(LOG_ERR,
- "no value for setvar command - line ignored");
- }
- else
- {
- set_sys_var(tokens[1], strlen(tokens[1])+1, RW |
- ((((ntokens > 2) && !strcmp(tokens[2], "default"))) ? DEF : 0));
- }
+ if (ntokens < 2) {
+ syslog(LOG_ERR,
+ "no value for setvar command - line ignored");
+ } else {
+ set_sys_var(tokens[1], strlen(tokens[1])+1, RW |
+ ((((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)
- {
+ if (ntokens < 2) {
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;
- }
- }
+ "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];
+
+#ifdef DEBUG
+ if (debug)
+ sprintf(bp, "client_limit=%lu", i);
+#endif
+ 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)
- {
+ if (ntokens < 2) {
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;
- }
- }
+ "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=%ld", i);
+ set_sys_var(bp, strlen(bp)+1, RO);
+ client_limit_period = i;
+ }
+ }
+ break;
+
+ case CONFIG_ENABLE:
+ for (i = 1; i < ntokens; i++) {
+ int flag;
+
+ flag = matchkey(tokens[i], flags_keywords);
+ if (flag == CONFIG_UNKNOWN) {
+ syslog(LOG_ERR,
+ "enable unknown flag %s",
+ tokens[i]);
+ errflg = 1;
+ break;
+ }
+ proto_config(flag, 1L);
+ }
+ break;
+
+ case CONFIG_DISABLE:
+ for (i = 1; i < ntokens; i++) {
+ int flag;
+
+ flag = matchkey(tokens[i], flags_keywords);
+ if (flag == CONFIG_UNKNOWN) {
+ syslog(LOG_ERR,
+ "disable unknown flag %s",
+ tokens[i]);
+ errflg = 1;
+ break;
+ }
+ proto_config(flag, 0L);
+ }
+ break;
+
+ case CONFIG_PHONE:
+ for (i = 1; i < ntokens && i < MAXPHONE; i++) {
+ (void)strncpy(sys_phone[i - 1],
+ tokens[i], MAXDIAL);
+ }
+ sys_phone[i - 1][0] = '\0';
break;
}
}
@@ -1482,38 +1401,7 @@ getconfig(argc, argv)
/*
* Need name resolution
*/
- errflg = 0;
-#ifdef RESOLVE_INTERNAL
- if ( resolve_internal )
- do_resolve_internal();
- else
- {
-#endif
-
- if (info_auth_keyid == 0) {
- syslog(LOG_ERR,
- "no request key defined, peer name resolution not possible");
- errflg++;
- }
- if (!have_resolver) {
- syslog(LOG_ERR,
- "no resolver defined, peer name resolution not possible");
- errflg++;
- }
- if (!have_keyfile) {
- syslog(LOG_ERR,
- "no key file specified, peer name resolution not possible");
- errflg++;
- }
-
- if (!errflg)
-
- do_resolve(resolver_name, info_auth_keyid, keyfile);
- else
- abort_resolve();
-#ifdef RESOLVE_INTERNAL
- }
-#endif
+ do_resolve_internal();
}
}
@@ -1622,7 +1510,7 @@ getnetnum(num, addr, complain)
register int i;
register int temp;
char buf[80]; /* will core dump on really stupid stuff */
- U_LONG netnum;
+ u_long netnum;
/* XXX ELIMINATE replace with decodenetnum */
cp = num;
@@ -1648,7 +1536,7 @@ getnetnum(num, addr, complain)
netnum += temp;
#ifdef DEBUG
if (debug > 3)
- printf("getnetnum %s step %d buf %s temp %d netnum %d\n",
+ printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
num, i, buf, temp, netnum);
#endif
}
@@ -1676,7 +1564,7 @@ getnetnum(num, addr, complain)
addr->sin_addr.s_addr = htonl(netnum);
#ifdef DEBUG
if (debug > 1)
- printf("getnetnum given %s, got %s (%x)\n",
+ printf("getnetnum given %s, got %s (%lx)\n",
num, ntoa(addr), netnum);
#endif
return 1;
@@ -1711,7 +1599,7 @@ save_resolve(name, mode, version, minpoll, maxpoll, flags, ttl, keyid)
int maxpoll;
int flags;
int ttl;
- U_LONG keyid;
+ u_long keyid;
{
if (res_fp == NULL) {
(void) strcpy(res_file, RES_TEMPFILE);
@@ -1754,186 +1642,76 @@ abort_resolve()
}
+#define KEY_TYPE_ASCII 3
+
/*
- * do_resolve - start up the resolver program
+ * do_resolve_internal - start up the resolver function (not program)
*/
static void
-do_resolve(program, auth_keyid, keyfile)
- char *program;
- U_LONG auth_keyid;
- char *keyfile;
+do_resolve_internal()
{
- register LONG i;
- register char **ap;
- /* 1 progname + 5 -d's + 1 -r + keyid + keyfile + tempfile + 1 */
- char *argv[15];
- char numbuf[15];
- /*
- * Clean environment so the resolver is consistant
- */
- static char *resenv[] = {
- "HOME=/",
- "SHELL=/bin/sh",
- "TERM=dumb",
- "USER=root",
- NULL
- };
+ int i;
+
+ extern u_long req_keyid; /* request keyid */
+ extern char *req_file; /* name of the file with config info */
+ extern u_long info_auth_keyid;
if (res_fp == NULL) {
/* belch */
- syslog(LOG_ERR, "internal error in do_resolve: res_fp == NULL");
+ syslog(LOG_ERR,
+ "internal error in do_resolve_internal: res_fp == NULL");
exit(1);
}
+
+ /* we are done with this now */
(void) fclose(res_fp);
res_fp = NULL;
- ap = argv;
- *ap++ = program;
-
- /*
- * xntpres [-d ...] -r key# keyfile tempfile
- */
-#ifdef DEBUG
- i = debug;
- if (i > 5)
- i = 5;
- while (i-- > 0)
- *ap++ = "-d";
-#endif
- *ap++ = "-r";
-
- (void) sprintf(numbuf, "%lu", auth_keyid);
- *ap++ = numbuf;
- *ap++ = keyfile;
- *ap++ = res_file;
- *ap = NULL;
+ /* find a keyid */
+ if (info_auth_keyid == 0)
+ req_keyid = 65535;
+ else
+ req_keyid = info_auth_keyid;
+
+ /* if doesn't exist, make up one at random */
+ if (!authhavekey(req_keyid)) {
+ char rankey[9];
+ struct timeval now;
+
+ /* generate random key */
+ GETTIMEOFDAY(&now, (struct timezone *)0);
+ srand(now.tv_sec * now.tv_usec);
+ for (i = 0; i < 8; i++)
+ rankey[i] = (rand() % 255) + 1;
+ rankey[8] = 0;
+ authusekey(req_keyid, KEY_TYPE_ASCII, rankey);
+ }
+ /* save keyid so we will accept config requests with it */
+ info_auth_keyid = req_keyid;
+ req_file = res_file; /* set up pointer to res file */
(void) signal_no_reset(SIGCHLD, catchchild);
i = fork();
if (i == 0) {
/*
- * In child here, close up all descriptors and
- * exec the resolver program. Close the syslog()
- * facility gracefully in case we must reopen it.
+ * this used to close everything
+ * I don't think this is necessary
*/
- (void) signal(SIGCHLD, SIG_DFL);
- closelog();
-#if defined(NTP_POSIX_SOURCE) && !defined(SYS_386BSD)
- i = sysconf(_SC_OPEN_MAX);
-#else
- i = getdtablesize();
-#endif
-#ifdef DEBUG
- while (i-- > 2)
-#else
- while (i-- > 0)
-#endif
- (void) close(i);
- (void) execve(program, argv, resenv);
+ (void) signal_no_reset(SIGCHLD, SIG_DFL);
+ ntp_intres();
/*
- * If we got here, the exec screwed up. Open the log file
- * and print something so we don't die without complaint
+ * If we got here, the intres code screwed up.
+ * Print something so we don't die without complaint
*/
-#ifndef LOG_DAEMON
- openlog("xntpd", LOG_PID);
-#else
-#ifndef LOG_NTP
-#define LOG_NTP LOG_DAEMON
-#endif
- openlog("xntpd", LOG_PID | LOG_NDELAY, LOG_NTP);
-#endif /* LOG_DAEMON */
- syslog(LOG_ERR, "exec of resolver %s failed!", program);
+ syslog(LOG_ERR, "call to ntp_intres lost");
abort_resolve();
exit(1);
}
-
if (i == -1) {
- syslog(LOG_ERR, "fork() failed, can't start %s", program);
+ syslog(LOG_ERR, "fork() failed, can't start ntp_intres");
(void) signal_no_reset(SIGCHLD, SIG_DFL);
abort_resolve();
}
}
-
-
-#ifdef RESOLVE_INTERNAL
-
-#define KEY_TYPE_ASCII 3
-
-/*
- * do_resolve_internal - start up the resolver function (not program)
- */
-static void
-do_resolve_internal()
-{
- int i;
-
- extern U_LONG req_keyid; /* request keyid */
- extern char *req_file; /* name of the file with configuration info */
- extern U_LONG info_auth_keyid;
-
- if (res_fp == NULL) {
- /* belch */
- syslog(LOG_ERR, "internal error in do_resolve_internal: res_fp == NULL");
- exit(1);
- }
-
- /* we are done with this now */
- (void) fclose(res_fp);
- res_fp = NULL;
-
- /* find a keyid */
- if (info_auth_keyid == 0)
- req_keyid = 65535;
- else
- req_keyid = info_auth_keyid;
-
- /* if doesn't exist, make up one at random */
- if ( ! authhavekey(req_keyid) )
- {
- char rankey[9];
- struct timeval now;
-
- /* generate random key */
- GETTIMEOFDAY(&now, (struct timezone *)0);
- srand(now.tv_sec * now.tv_usec);
-
- for ( i = 0; i < 8; i++ )
- rankey[i] = (rand() % 255) + 1;
- rankey[8] = 0;
-
- authusekey(req_keyid, KEY_TYPE_ASCII, rankey);
- }
-
- /* save keyid so we will accept config requests with it */
- info_auth_keyid = req_keyid;
-
- req_file = res_file; /* set up pointer to res file */
-
- (void) signal_no_reset(SIGCHLD, catchchild);
-
- i = fork();
- if (i == 0) {
- /* this used to close everything
- * I don't think this is necessary */
- (void) signal_no_reset(SIGCHLD, SIG_DFL);
-
- ntp_intres();
-
- /*
- * If we got here, the intres code screwed up.
- * Print something so we don't die without complaint
- */
- syslog(LOG_ERR, "call to ntp_intres lost");
- abort_resolve();
- exit(1);
- }
-
- if (i == -1) {
- syslog(LOG_ERR, "fork() failed, can't start ntp_intres");
- (void) signal_no_reset(SIGCHLD, SIG_DFL);
- abort_resolve();
- }
-}
-#endif
diff --git a/usr.sbin/xntpd/xntpd/ntp_control.c b/usr.sbin/xntpd/xntpd/ntp_control.c
index ef9c37a6751d..0f1dc2b4d494 100644
--- a/usr.sbin/xntpd/xntpd/ntp_control.c
+++ b/usr.sbin/xntpd/xntpd/ntp_control.c
@@ -3,11 +3,12 @@
*/
#include <stdio.h>
#include <ctype.h>
-#include <signal.h>
#include <sys/types.h>
+#include <signal.h>
#include <sys/time.h>
#include "ntpd.h"
+#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_control.h"
#include "ntp_stdlib.h"
@@ -41,18 +42,13 @@ static void ctl_flushpkt P((int));
static void ctl_putdata P((char *, int, int));
static void ctl_putstr P((char *, char *, int));
static void ctl_putlfp P((char *, l_fp *));
-
-#ifdef UNUSED
-static void ctl_putulfp P((char *, l_fp *));
-#endif /* UNUSED */
-
static void ctl_putfp P((char *, s_fp));
static void ctl_putufp P((char *, u_fp));
-static void ctl_putuint P((char *, U_LONG));
-static void ctl_puthex P((char *, U_LONG));
-static void ctl_putint P((char *, LONG));
+static void ctl_putuint P((char *, u_long));
+static void ctl_puthex P((char *, u_long));
+static void ctl_putint P((char *, long));
static void ctl_putts P((char *, l_fp *));
-static void ctl_putadr P((char *, U_LONG));
+static void ctl_putadr P((char *, u_long));
static void ctl_putid P((char *, char *));
static void ctl_putarray P((char *, s_fp *, int));
static void ctl_putsys P((int));
@@ -61,7 +57,7 @@ static void ctl_putpeer P((int, struct peer *));
static void ctl_putclock P((int, struct refclockstat *, int));
#endif /* REFCLOCK */
static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
-static unsigned long count_var P((struct ctl_var *));
+static u_long count_var P((struct ctl_var *));
static void control_unspec P((struct recvbuf *, int));
static void read_status P((struct recvbuf *, int));
static void read_variables P((struct recvbuf *, int));
@@ -101,7 +97,7 @@ static struct ctl_var sys_var[] = {
{ CS_PEERID, RO, "peer" }, /* 9 */
{ CS_OFFSET, RO, "phase" }, /* 10 */
{ CS_DRIFT, RO, "freq" }, /* 11 */
- { CS_COMPLIANCE, RO, "compliance" }, /* 12 */
+ { CS_COMPLIANCE, RO, "error" }, /* 12 */
{ CS_CLOCK, RO, "clock" }, /* 13 */
{ CS_LEAPIND, RW, "leapindicator" }, /* 14 */
{ CS_LEAPWARNING, RW, "leapwarning" }, /* 15 */
@@ -231,8 +227,8 @@ static struct ctl_var clock_var[] = {
{ CC_BADDATA, RO, "baddata" }, /* 6 */
{ CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */
{ CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */
- { CC_FUDGEVAL1, RO, "fudgeval1" }, /* 9 */
- { CC_FUDGEVAL2, RO, "fudgeval2" }, /* 10 */
+ { CC_FUDGEVAL1, RO, "stratum" }, /* 9 */
+ { CC_FUDGEVAL2, RO, "refid" }, /* 10 */
{ CC_FLAGS, RO, "flags" }, /* 11 */
{ CC_DEVICE, RO, "device" }, /* 12 */
{ CC_VARLIST, RO, "clock_var_list" },/* 13 */
@@ -304,30 +300,36 @@ static struct utsname utsname;
* set peer->sstclktype to something different than CTL_SST_TS_UNSPEC.
*/
static u_char clocktypes[] = {
- CTL_SST_TS_NTP, /* REFCLK_NONE */
- CTL_SST_TS_UNSPEC, /* REFCLK_LOCALCLOCK */
- 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 */
- CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK */
- CTL_SST_TS_HF, /* REFCLK_CHU */
+ CTL_SST_TS_NTP, /* REFCLK_NONE (0) */
+ CTL_SST_TS_LOCAL, /* REFCLK_LOCALCLOCK (1) */
+ CTL_SST_TS_UHF, /* REFCLK_GPS_TRAK (2) */
+ CTL_SST_TS_HF, /* REFCLK_WWV_PST (3) */
+ CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM (4) */
+ CTL_SST_TS_UHF, /* REFCLK_GOES_TRUETIME (5) */
+ CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) */
+ CTL_SST_TS_HF, /* REFCLK_CHU (7) */
CTL_SST_TS_LF, /* REFCLOCK_PARSE - default value - driver supplies actual value in peer->sstclktype */
- CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM_HP */
- CTL_SST_TS_UHF, /* REFCLK_GPS_AS2201 */
- CTL_SST_TS_LF, /* REFCLK_OMEGA_TRUETIME */
- CTL_SST_TS_UNSPEC, /* Future expansion */
- CTL_SST_TS_UNSPEC, /* Future expansion */
- CTL_SST_TS_UNSPEC, /* Future expansion */
- CTL_SST_TS_UNSPEC /* Future expansion */
+ CTL_SST_TS_LF, /* REFCLK_GPS_MX4200 (9) */
+ CTL_SST_TS_UHF, /* REFCLK_GPS_AS2201 (10) */
+ CTL_SST_TS_LF, /* REFCLK_OMEGA_TRUETIME (11) */
+ CTL_SST_TS_UHF, /* REFCLK_IRIG_TPRO (12) */
+ CTL_SST_TS_ATOM, /* REFCLK_ATOM_LEITCH (13) */
+ CTL_SST_TS_LF, /* REFCLK_MSF_EES (14) */
+ CTL_SST_TS_UHF, /* REFCLK_GPSTM_TRUETIME (15) */
+ CTL_SST_TS_UHF, /* REFCLK_IRIG_BANCOMM (16) */
+ CTL_SST_TS_UHF, /* REFCLK_GPS_DATU (17) */
+ CTL_SST_TS_TELEPHONE, /* REFCLK_NIST_ACT (18) */
+ CTL_SST_TS_HF, /* REFCLK_WWV_HEATH (19) */
+ CTL_SST_TS_UHF, /* REFCLK_GPS_NMEA (20) */
+ CTL_SST_TS_UHF, /* REFCLK_GPS_MOTO (21) */
+ CTL_SST_TS_ATOM /* REFCLK_ATOM_PPS (22) */
};
-
/*
* Keyid used for authenticating write requests.
*/
-U_LONG ctl_auth_keyid;
+u_long ctl_auth_keyid;
/*
* We keep track of the last error reported by the system internally
@@ -339,21 +341,21 @@ static u_char ctl_sys_num_events;
/*
* Statistic counters to keep track of requests and responses.
*/
-U_LONG ctltimereset; /* time stats reset */
-U_LONG numctlreq; /* number of requests we've received */
-U_LONG numctlbadpkts; /* number of bad control packets */
-U_LONG numctlresponses; /* number of resp packets sent with data */
-U_LONG numctlfrags; /* number of fragments sent */
-U_LONG numctlerrors; /* number of error responses sent */
-U_LONG numctltooshort; /* number of too short input packets */
-U_LONG numctlinputresp; /* number of responses on input */
-U_LONG numctlinputfrag; /* number of fragments on input */
-U_LONG numctlinputerr; /* number of input pkts with err bit set */
-U_LONG numctlbadoffset; /* number of input pkts with nonzero offset */
-U_LONG numctlbadversion; /* number of input pkts with unknown version */
-U_LONG numctldatatooshort; /* data too short for count */
-U_LONG numctlbadop; /* bad op code found in packet */
-U_LONG numasyncmsgs; /* number of async messages we've sent */
+u_long ctltimereset; /* time stats reset */
+u_long numctlreq; /* number of requests we've received */
+u_long numctlbadpkts; /* number of bad control packets */
+u_long numctlresponses; /* number of resp packets sent with data */
+u_long numctlfrags; /* number of fragments sent */
+u_long numctlerrors; /* number of error responses sent */
+u_long numctltooshort; /* number of too short input packets */
+u_long numctlinputresp; /* number of responses on input */
+u_long numctlinputfrag; /* number of fragments on input */
+u_long numctlinputerr; /* number of input pkts with err bit set */
+u_long numctlbadoffset; /* number of input pkts with nonzero offset */
+u_long numctlbadversion; /* number of input pkts with unknown version */
+u_long numctldatatooshort; /* data too short for count */
+u_long numctlbadop; /* bad op code found in packet */
+u_long numasyncmsgs; /* number of async messages we've sent */
/*
* Imported from the I/O module
@@ -368,7 +370,7 @@ extern int debug;
/*
* Imported from the timer module
*/
-extern U_LONG current_time;
+extern u_long current_time;
extern struct peer *assoc_hash[];
extern int pps_control; /* flag for 1-pps signal present */
@@ -380,7 +382,7 @@ extern u_char sys_stratum;
extern s_char sys_precision;
extern s_fp sys_rootdelay;
extern u_fp sys_rootdispersion;
-extern U_LONG sys_refid;
+extern u_long sys_refid;
extern l_fp sys_reftime;
extern l_fp sys_refskew;
extern u_char sys_poll;
@@ -390,7 +392,7 @@ extern struct peer *sys_peer;
*/
extern l_fp last_offset;
extern s_fp drift_comp;
-extern int time_constant;
+extern u_fp sys_maxd;
extern int pll_control;
/*
* Imported from the leap module
@@ -419,7 +421,7 @@ static struct interface *lcl_inter;
static u_char res_authenticate;
static u_char res_authokay;
-static U_LONG res_keyid;
+static u_long res_keyid;
#define MAXDATALINELEN (72)
@@ -480,14 +482,14 @@ ctl_error(errcode)
if (res_authenticate) {
int maclen;
- *(U_LONG *)((u_char *)&rpkt + CTL_HEADER_LEN)
+ *(u_long *)((u_char *)&rpkt + CTL_HEADER_LEN)
= htonl(res_keyid);
maclen =
authencrypt(res_keyid, (U_LONG *)&rpkt, CTL_HEADER_LEN);
- sendpkt(rmt_addr, lcl_inter, (struct pkt *)&rpkt,
+ sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
CTL_HEADER_LEN + maclen);
} else {
- sendpkt(rmt_addr, lcl_inter, (struct pkt *)&rpkt,
+ sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
CTL_HEADER_LEN);
}
numctlerrors++;
@@ -596,17 +598,17 @@ process_control(rbufp, restrict)
properlen = (properlen + 7) & ~7;
- if ((rbufp->recv_length & (sizeof(U_LONG)-1)) == 0
+ if ((rbufp->recv_length & (sizeof(u_long)-1)) == 0
&& (maclen = (rbufp->recv_length - properlen)) >= MIN_MAC_LEN
&& maclen <= MAX_MAC_LEN) {
res_authenticate = 1;
- res_keyid = ntohl(*(U_LONG *)((u_char *)pkt + properlen));
+ res_keyid = ntohl(*(u_long *)((u_char *)pkt + properlen));
#ifdef DEBUG
if (debug >= 3)
printf(
- "recv_len %d, properlen %d, wants auth with keyid %d, MAC length=%d\n",
+ "recv_len %d, properlen %d, wants auth with keyid %ld, MAC length=%d\n",
rbufp->recv_length, properlen, res_keyid, maclen);
#endif
if (!authhavekey(res_keyid)) {
@@ -728,15 +730,18 @@ ctlsysstatus()
register u_char clock;
clock = CTL_SST_TS_UNSPEC;
- if (sys_peer != 0)
- if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC)
+ if (sys_peer != 0) {
+ if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
clock = sys_peer->sstclktype;
- else {
+ if (pps_control)
+ clock |= CTL_SST_TS_PPS;
+ } 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);
}
@@ -788,6 +793,7 @@ ctl_flushpkt(more)
rpkt.sequence = htons(ctl_trap[i].tr_sequence);
sendpkt(&ctl_trap[i].tr_addr,
ctl_trap[i].tr_localaddr,
+ -4,
(struct pkt *)&rpkt, sendlen);
if (!more)
ctl_trap[i].tr_sequence++;
@@ -808,14 +814,14 @@ ctl_flushpkt(more)
*datapt++ = '\0';
totlen++;
}
- *(U_LONG *)datapt = htonl(res_keyid);
+ *(u_long *)datapt = htonl(res_keyid);
maclen =
authencrypt(res_keyid, (U_LONG *)&rpkt, totlen);
- sendpkt(rmt_addr, lcl_inter, (struct pkt *)&rpkt,
+ sendpkt(rmt_addr, lcl_inter, -5, (struct pkt *)&rpkt,
totlen + maclen);
} else {
- sendpkt(rmt_addr, lcl_inter, (struct pkt *)&rpkt,
+ sendpkt(rmt_addr, lcl_inter, -6, (struct pkt *)&rpkt,
sendlen);
}
if (more)
@@ -935,33 +941,6 @@ ctl_putlfp(tag, ts)
}
-#ifdef UNUSED
-/*
- * ctl_putlfp - write a tagged, unsigned l_fp into the response
- */
-static void
-ctl_putulfp(tag, ts)
- char *tag;
- l_fp *ts;
-{
- register char *cp, *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- cq = ulfptoms(ts, 3);
- while (*cq != '\0')
- *cp++ = *cq++;
-
- ctl_putdata(buffer, cp - buffer, 0);
-}
-#endif /* UNUSED */
-
-
/*
* ctl_putfp - write a tagged s_fp number into the response
*/
@@ -1018,7 +997,7 @@ ctl_putufp(tag, ufp)
static void
ctl_putuint(tag, uval)
char *tag;
- U_LONG uval;
+ u_long uval;
{
register char *cp, *cq;
char buffer[200];
@@ -1029,7 +1008,7 @@ ctl_putuint(tag, uval)
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "%u", uval);
+ (void) sprintf(cp, "%lu", uval);
while (*cp != '\0')
cp++;
@@ -1043,7 +1022,7 @@ ctl_putuint(tag, uval)
static void
ctl_puthex(tag, uval)
char *tag;
- U_LONG uval;
+ u_long uval;
{
register char *cp, *cq;
char buffer[200];
@@ -1068,7 +1047,7 @@ ctl_puthex(tag, uval)
static void
ctl_putint(tag, ival)
char *tag;
- LONG ival;
+ long ival;
{
register char *cp, *cq;
char buffer[200];
@@ -1079,7 +1058,7 @@ ctl_putint(tag, ival)
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "%d", ival);
+ (void) sprintf(cp, "%ld", ival);
while (*cp != '\0')
cp++;
@@ -1119,7 +1098,7 @@ ctl_putts(tag, ts)
static void
ctl_putadr(tag, addr)
char *tag;
- U_LONG addr;
+ u_long addr;
{
register char *cp, *cq;
char buffer[200];
@@ -1225,13 +1204,13 @@ ctl_putsys(varid)
switch (varid) {
case CS_LEAP:
- ctl_putuint(sys_var[CS_LEAP].text, (U_LONG)sys_leap);
+ ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
break;
case CS_STRATUM:
- ctl_putuint(sys_var[CS_STRATUM].text, (U_LONG)sys_stratum);
+ ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
break;
case CS_PRECISION:
- ctl_putint(sys_var[CS_PRECISION].text, (LONG)sys_precision);
+ ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
break;
case CS_ROOTDELAY:
ctl_putfp(sys_var[CS_ROOTDELAY].text, sys_rootdelay);
@@ -1241,23 +1220,23 @@ ctl_putsys(varid)
sys_rootdispersion);
break;
case CS_REFID:
- if (sys_stratum <= 1)
- ctl_putid(sys_var[CS_REFID].text, (char *)&sys_refid);
- else
+ if (sys_stratum > 1)
ctl_putadr(sys_var[CS_REFID].text, sys_refid);
+ else
+ ctl_putid(sys_var[CS_REFID].text, (char *)&sys_refid);
break;
case CS_REFTIME:
ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
break;
case CS_POLL:
- ctl_putuint(sys_var[CS_POLL].text, (U_LONG)sys_poll);
+ ctl_putuint(sys_var[CS_POLL].text, sys_poll);
break;
case CS_PEERID:
if (sys_peer == NULL)
- ctl_putuint(sys_var[CS_PEERID].text, (U_LONG)0);
+ ctl_putuint(sys_var[CS_PEERID].text, 0);
else
ctl_putuint(sys_var[CS_PEERID].text,
- (U_LONG)sys_peer->associd);
+ sys_peer->associd);
break;
case CS_OFFSET:
ctl_putlfp(sys_var[CS_OFFSET].text, &last_offset);
@@ -1266,17 +1245,17 @@ ctl_putsys(varid)
ctl_putfp(sys_var[CS_DRIFT].text, drift_comp);
break;
case CS_COMPLIANCE:
- ctl_putuint(sys_var[CS_COMPLIANCE].text, (U_LONG)time_constant);
+ ctl_putufp(sys_var[CS_COMPLIANCE].text, sys_maxd);
break;
case CS_CLOCK:
get_systime(&tmp);
ctl_putts(sys_var[CS_CLOCK].text, &tmp);
break;
case CS_LEAPIND:
- ctl_putuint(sys_var[CS_LEAPIND].text, (U_LONG)leap_indicator);
+ ctl_putuint(sys_var[CS_LEAPIND].text, leap_indicator);
break;
case CS_LEAPWARNING:
- ctl_putuint(sys_var[CS_LEAPWARNING].text, (U_LONG)leap_warning);
+ ctl_putuint(sys_var[CS_LEAPWARNING].text, leap_warning);
break;
case CS_PROCESSOR:
#ifndef HAVE_UNAME
@@ -1297,7 +1276,7 @@ ctl_putsys(varid)
#endif /* HAVE_UNAME */
break;
case CS_KEYID:
- ctl_putuint(sys_var[CS_KEYID].text, (U_LONG)0);
+ ctl_putuint(sys_var[CS_KEYID].text, 0);
break;
case CS_REFSKEW:
ctl_putlfp(sys_var[CS_REFSKEW].text, &sys_refskew);
@@ -1378,15 +1357,15 @@ ctl_putpeer(varid, peer)
switch (varid) {
case CP_CONFIG:
ctl_putuint(peer_var[CP_CONFIG].text,
- (U_LONG)((peer->flags & FLAG_CONFIG) != 0));
+ ((peer->flags & FLAG_CONFIG) != 0));
break;
case CP_AUTHENABLE:
ctl_putuint(peer_var[CP_AUTHENABLE].text,
- (U_LONG)((peer->flags & FLAG_AUTHENABLE) != 0));
+ ((peer->flags & FLAG_AUTHENABLE) != 0));
break;
case CP_AUTHENTIC:
ctl_putuint(peer_var[CP_AUTHENTIC].text,
- (U_LONG)((peer->flags & FLAG_AUTHENTIC) != 0));
+ ((peer->flags & FLAG_AUTHENTIC) != 0));
break;
case CP_SRCADR:
ctl_putadr(peer_var[CP_SRCADR].text,
@@ -1394,33 +1373,40 @@ ctl_putpeer(varid, peer)
break;
case CP_SRCPORT:
ctl_putuint(peer_var[CP_SRCPORT].text,
- (U_LONG)ntohs(peer->srcadr.sin_port));
+ ntohs(peer->srcadr.sin_port));
break;
case CP_DSTADR:
ctl_putadr(peer_var[CP_DSTADR].text,
- peer->dstadr->sin.sin_addr.s_addr);
+ peer->processed ?
+ peer->cast_flags & MDF_BCAST ?
+ peer->dstadr->bcast.sin_addr.s_addr:
+ peer->cast_flags ?
+ peer->dstadr->sin.sin_addr.s_addr ?
+ peer->dstadr->sin.sin_addr.s_addr:
+ peer->dstadr->bcast.sin_addr.s_addr:
+ 8 : 12);
break;
case CP_DSTPORT:
ctl_putuint(peer_var[CP_DSTPORT].text,
- (U_LONG)ntohs(peer->dstadr->sin.sin_port));
+ ntohs(peer->dstadr->sin.sin_port));
break;
case CP_LEAP:
- ctl_putuint(peer_var[CP_LEAP].text, (U_LONG)peer->leap);
+ ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
break;
case CP_HMODE:
- ctl_putuint(peer_var[CP_HMODE].text, (U_LONG)peer->hmode);
+ ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
break;
case CP_STRATUM:
- ctl_putuint(peer_var[CP_STRATUM].text, (U_LONG)peer->stratum);
+ ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
break;
case CP_PPOLL:
- ctl_putuint(peer_var[CP_PPOLL].text, (U_LONG)peer->ppoll);
+ ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
break;
case CP_HPOLL:
- ctl_putuint(peer_var[CP_HPOLL].text, (U_LONG)peer->hpoll);
+ ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
break;
case CP_PRECISION:
- ctl_putint(peer_var[CP_PRECISION].text, (LONG)peer->precision);
+ ctl_putint(peer_var[CP_PRECISION].text, peer->precision);
break;
case CP_ROOTDELAY:
ctl_putfp(peer_var[CP_ROOTDELAY].text, peer->rootdelay);
@@ -1431,7 +1417,12 @@ ctl_putpeer(varid, peer)
break;
case CP_REFID:
if (peer->stratum > 1)
- ctl_putadr(peer_var[CP_REFID].text, peer->refid);
+ if (peer->flags & FLAG_REFCLOCK)
+ ctl_putadr(peer_var[CP_REFID].text,
+ peer->srcadr.sin_addr.s_addr);
+ else
+ ctl_putadr(peer_var[CP_REFID].text,
+ peer->refid);
else
ctl_putid(peer_var[CP_REFID].text,
(char *)&peer->refid);
@@ -1449,13 +1440,13 @@ ctl_putpeer(varid, peer)
ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
break;
case CP_REACH:
- ctl_puthex(peer_var[CP_REACH].text, (U_LONG)peer->reach);
+ ctl_puthex(peer_var[CP_REACH].text, peer->reach);
break;
case CP_FLASH:
- ctl_puthex(peer_var[CP_FLASH].text, (U_LONG)peer->flash);
+ ctl_puthex(peer_var[CP_FLASH].text, peer->flash);
break;
case CP_VALID:
- ctl_putuint(peer_var[CP_VALID].text, (U_LONG)peer->valid);
+ ctl_putuint(peer_var[CP_VALID].text, peer->valid);
break;
case CP_TIMER:
ctl_putuint(peer_var[CP_TIMER].text,
@@ -1486,7 +1477,7 @@ ctl_putpeer(varid, peer)
(s_fp *)peer->filter_error, (int)peer->filter_nextpt);
break;
case CP_PMODE:
- ctl_putuint(peer_var[CP_PMODE].text, (U_LONG)peer->pmode);
+ ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
break;
case CP_RECEIVED:
ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
@@ -1552,8 +1543,7 @@ ctl_putclock(varid, clock, mustput)
case CC_TYPE:
if (mustput || clock->clockdesc == NULL
|| *(clock->clockdesc) == '\0') {
- ctl_putuint(clock_var[CC_TYPE].text,
- (U_LONG)clock->type);
+ ctl_putuint(clock_var[CC_TYPE].text, clock->type);
}
break;
case CC_TIMECODE:
@@ -1561,7 +1551,7 @@ ctl_putclock(varid, clock, mustput)
(int)clock->lencode);
break;
case CC_POLL:
- ctl_putuint(clock_var[CC_POLL].text, (U_LONG)clock->polls);
+ ctl_putuint(clock_var[CC_POLL].text, clock->polls);
break;
case CC_NOREPLY:
ctl_putuint(clock_var[CC_NOREPLY].text, clock->noresponse);
@@ -1589,14 +1579,17 @@ ctl_putclock(varid, clock, mustput)
break;
case CC_FUDGEVAL2:
if (mustput || (clock->haveflags & CLK_HAVEVAL2))
- ctl_putint(clock_var[CC_FUDGEVAL2].text,
- clock->fudgeval2);
+ if (clock->fudgeval1 > 1)
+ ctl_putadr(clock_var[CC_FUDGEVAL2].text,
+ clock->fudgeval2);
+ else
+ ctl_putid(clock_var[CC_FUDGEVAL2].text,
+ (char *)&clock->fudgeval2);
break;
case CC_FLAGS:
if (mustput || (clock->haveflags &
(CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4)))
- ctl_putuint(clock_var[CC_FLAGS].text,
- (U_LONG)clock->flags);
+ ctl_putuint(clock_var[CC_FLAGS].text, clock->flags);
break;
case CC_DEVICE:
if (clock->clockdesc == NULL || *(clock->clockdesc) == '\0') {
@@ -1966,8 +1959,8 @@ write_variables(rbufp, restrict)
register struct ctl_var *v;
register int ext_var;
char *valuep;
- LONG val;
- u_char leapind, leapwarn;
+ long val;
+ int leapind, leapwarn;
/*
* If he's trying to write into a peer tell him no way
@@ -1985,8 +1978,8 @@ write_variables(rbufp, restrict)
/*
* Set flags to not-in-sync so we can tell when we get something.
*/
- leapind = (u_char)~0;
- leapwarn = (u_char)~0;
+ leapind = ~0;
+ leapwarn = ~0;
/*
* Look through the variables. Dump out at the first sign of trouble.
@@ -2037,13 +2030,13 @@ write_variables(rbufp, restrict)
switch(v->code) {
case CS_LEAP:
case CS_LEAPIND:
- leapind = (u_char)val;
+ leapind = val;
break;
case CS_LEAPWARNING:
- leapwarn = (u_char)val;
+ leapwarn = val;
break;
default:
- ctl_error(CERR_UNSPEC); /* our fault, really */
+ ctl_error(CERR_UNSPEC); /* our fault, really */
return;
}
}
@@ -2052,7 +2045,7 @@ write_variables(rbufp, restrict)
/*
* If we got anything, do it.
*/
- if (leapind != (u_char)~0 || leapwarn != (u_char)~0) {
+ if (leapind != ~0 || leapwarn != ~0) {
if (!leap_setleap((int)leapind, (int)leapwarn)) {
ctl_error(CERR_PERMISSION);
return;
@@ -2436,18 +2429,32 @@ report_event(err, peer)
if (!(err & PEER_EVENT)) {
if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
ctl_sys_num_events++;
- if (ctl_sys_last_event != (u_char)err)
- syslog(LOG_INFO, "system event %x status %x",
- err, ctlsysstatus());
- ctl_sys_last_event = (u_char)err;
+ if (ctl_sys_last_event != (u_char)err) {
+ syslog(LOG_INFO, "system event %x status %x",
+ err, ctlsysstatus());
+#ifdef DEBUG
+ if (debug)
+ printf("report_event: system event %x status %x\n",
+ err, ctlsysstatus());
+#endif
+ ctl_sys_last_event = (u_char)err;
+ }
} else if (peer != 0) {
peer->last_event = (u_char)(err & ~PEER_EVENT);
if (peer->num_events < CTL_PEER_MAXEVENTS)
- peer->num_events++;
+ peer->num_events++;
syslog(LOG_INFO, "peer %s event %x status %x",
ntoa(&peer->srcadr), err, ctlpeerstatus(peer));
+#ifdef DEBUG
+ if (debug)
+ printf("peer %s event %x status %x\n",
+ ntoa(&peer->srcadr), err, ctlpeerstatus(peer));
+#endif
} else {
syslog(LOG_ERR, "report_event: err %x, no peer", err);
+#ifdef DEBUG
+ printf("report_event: err %x, no peer\n", err);
+#endif
return;
}
@@ -2489,10 +2496,8 @@ report_event(err, peer)
clock.kv_list = (struct ctl_var *)0;
refclock_control(&peer->srcadr,
- (struct refclockstat *)0,
- &clock);
- ctl_puthex("refclockstatus",
- (U_LONG)ctlclkstatus(&clock));
+ (struct refclockstat *)0, &clock);
+ ctl_puthex("refclockstatus", ctlclkstatus(&clock));
for (i = 1; i <= CC_MAXCODE; i++)
ctl_putclock(i, &clock, 0);
@@ -2528,7 +2533,7 @@ report_event(err, peer)
&clock);
ctl_puthex("refclockstatus",
- (U_LONG)ctlclkstatus(&clock));
+ ctlclkstatus(&clock));
for (i = 1; i <= CC_MAXCODE; i++)
ctl_putclock(i, &clock, 0);
@@ -2572,11 +2577,11 @@ ctl_clr_stats()
numasyncmsgs = 0;
}
-static unsigned long
+static u_long
count_var(k)
struct ctl_var *k;
{
- register unsigned long c;
+ register u_long c;
c = 0;
while (k && !(k++->flags & EOV))
@@ -2588,10 +2593,10 @@ count_var(k)
char *
add_var(kv, size, def)
struct ctl_var **kv;
- unsigned long size;
+ u_long size;
int def;
{
- register unsigned long c;
+ register u_long c;
register struct ctl_var *k;
c = count_var(*kv);
@@ -2617,7 +2622,7 @@ void
set_var(kv, data, size, def)
struct ctl_var **kv;
char *data;
- unsigned long size;
+ u_long size;
int def;
{
register struct ctl_var *k;
@@ -2665,7 +2670,7 @@ set_var(kv, data, size, def)
void
set_sys_var(data, size, def)
char *data;
- unsigned long size;
+ u_long size;
int def;
{
set_var(&ext_sys_var, data, size, def);
diff --git a/usr.sbin/xntpd/xntpd/ntp_filegen.c b/usr.sbin/xntpd/xntpd/ntp_filegen.c
index 55cf1aebab13..4c23bed44f06 100644
--- a/usr.sbin/xntpd/xntpd/ntp_filegen.c
+++ b/usr.sbin/xntpd/xntpd/ntp_filegen.c
@@ -25,7 +25,7 @@
#include "ntp_stdlib.h"
/*
- * NTP is intended to run LONG periods of time without restart.
+ * NTP is intended to run long periods of time without restart.
* Thus log and statistic files generated by NTP will grow large.
*
* this set of routines provides a central interface
@@ -43,7 +43,7 @@ extern int errno;
/*
* imported from timer
*/
-extern U_LONG current_time;
+extern u_long current_time;
/*
* redefine this if your system dislikes filename suffixes like
@@ -60,7 +60,7 @@ extern U_LONG current_time;
extern int debug;
#endif
-static void filegen_open P((FILEGEN *, U_LONG));
+static void filegen_open P((FILEGEN *, u_long));
static int valid_fileref P((char *, char *));
#ifdef UNUSED
static FILEGEN *filegen_unregister P((char *));
@@ -74,7 +74,7 @@ static FILEGEN *filegen_unregister P((char *));
static void
filegen_open(gen, newid)
FILEGEN *gen;
- U_LONG newid;
+ u_long newid;
{
char *filename;
char *basename;
@@ -100,7 +100,7 @@ filegen_open(gen, newid)
case FILEGEN_PID:
filename = emalloc(len + 1 + 1 + 10);
- sprintf(filename,"%s%c#%d", basename, SUFFIX_SEP, newid);
+ sprintf(filename,"%s%c#%ld", basename, SUFFIX_SEP, newid);
break;
case FILEGEN_DAY:
@@ -142,7 +142,7 @@ filegen_open(gen, newid)
case FILEGEN_AGE:
filename = emalloc(len + 1 + 2 + 10);
- sprintf(filename, "%s%ca%08d", basename, SUFFIX_SEP, newid);
+ sprintf(filename, "%s%ca%08ld", basename, SUFFIX_SEP, newid);
break;
}
@@ -156,7 +156,7 @@ filegen_open(gen, newid)
/*
* try to resolve name collisions
*/
- static U_LONG conflicts = 0;
+ static u_long conflicts = 0;
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
@@ -170,7 +170,8 @@ filegen_open(gen, newid)
*/
char *savename = emalloc(len + 1 + 1 + 10 + 10);
sprintf(savename, "%s%c%dC%lu",
- basename, SUFFIX_SEP, getpid(), conflicts++);
+ basename, SUFFIX_SEP, getpid(),
+ (u_long)conflicts++);
if (rename(basename, savename) != 0)
syslog(LOG_ERR," couldn't save %s: %m", basename);
free(savename);
@@ -207,7 +208,7 @@ filegen_open(gen, newid)
#ifdef DEBUG
if (debug > 3)
printf("opening filegen (type=%d/id=%lu) \"%s\"\n",
- gen->type, newid, filename);
+ gen->type, (u_long)newid, filename);
#endif
if (fp == NULL) {
@@ -265,9 +266,9 @@ filegen_open(gen, newid)
void
filegen_setup(gen,now)
FILEGEN *gen;
- U_LONG now;
+ u_long now;
{
- U_LONG new_gen = ~0;
+ u_long new_gen = ~0;
struct calendar cal;
if (!(gen->flag & FGEN_FLAG_ENABLED)) {
@@ -450,9 +451,10 @@ filegen_get(name)
while(f) {
if (f->name == name || strcmp(name, f->name) == 0) {
-#ifdef DEBUG
+#ifdef XXX /* this gives the Alpha compiler fits */
if (debug > 3)
- printf("filegen_get(\"%s\") = %x\n", name, (u_int)f->filegen);
+ printf("filegen_get(\"%s\") = %x\n", name,
+ (u_int)f->filegen);
#endif
return f->filegen;
}
@@ -472,13 +474,13 @@ filegen_register(name, filegen)
{
struct filegen_entry **f = &filegen_registry;
-#ifdef DEBUG
+#ifdef XXX /* this gives the Alpha compiler fits */
if (debug > 3)
printf("filegen_register(\"%s\",%x)\n", name, (u_int)filegen);
#endif
while (*f) {
if ((*f)->name == name || strcmp(name, (*f)->name) == 0) {
-#ifdef DEBUG
+#ifdef XXX /* this gives the Alpha compiler fits */
if (debug > 4) {
printf("replacing filegen %x\n", (u_int)(*f)->filegen);
}
diff --git a/usr.sbin/xntpd/xntpd/ntp_intres.c b/usr.sbin/xntpd/xntpd/ntp_intres.c
index 5ff4af4d8242..c05354b6837d 100644
--- a/usr.sbin/xntpd/xntpd/ntp_intres.c
+++ b/usr.sbin/xntpd/xntpd/ntp_intres.c
@@ -1,4 +1,4 @@
-/* ntp_intres.c,v 3.1 1993/07/06 01:11:16 jbj Exp
+/*
* ripped off from ../xnptres/xntpres.c by Greg Troxel 4/2/92
* routine callable from xntpd, rather than separate program
* also, key info passed in via a global, so no key file needed.
@@ -118,7 +118,7 @@ static int sockfd = -1;
/* stuff to be filled in by caller */
-U_LONG req_keyid; /* request keyid */
+u_long req_keyid; /* request keyid */
char *req_file; /* name of the file with configuration info */
/* end stuff to be filled in */
@@ -130,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, 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 *));
@@ -147,9 +147,10 @@ ntp_intres()
{
FILE *in;
+#ifdef DEBUG
if ( debug )
- syslog(LOG_INFO, "ntp_intres running");
-
+ syslog(LOG_INFO, "ntp_intres running");
+#endif
/* check out auth stuff */
if (!authhavekey(req_keyid)) {
@@ -171,7 +172,7 @@ ntp_intres()
readconf(in, req_file);
(void) fclose(in);
- if ( ! debug )
+ if (!debug )
(void) unlink(req_file);
/*
@@ -289,7 +290,7 @@ addentry(name, mode, version, minpoll, maxpoll, flags, ttl, keyid)
int maxpoll;
int flags;
int ttl;
- U_LONG keyid;
+ u_long keyid;
{
register char *cp;
register struct conf_entry *ce;
@@ -308,7 +309,7 @@ addentry(name, mode, version, minpoll, maxpoll, flags, ttl, keyid)
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_keyid = keyid;
ce->ce_next = NULL;
if (confentries == NULL) {
@@ -466,7 +467,7 @@ request(conf)
auth1crypt(req_keyid, (U_LONG *)&reqpkt, REQ_LEN_NOMAC);
gettstamp(&ts);
- M_ADDUF(ts.l_ui, ts.l_uf, SKEWTIME);
+ L_ADDUF(&ts, SKEWTIME);
HTONL_FP(&ts, &reqpkt.tstamp);
n = auth2crypt(req_keyid, (U_LONG *)&reqpkt, REQ_LEN_NOMAC);
@@ -683,7 +684,7 @@ readconf(fp, name)
{
register int i;
char *token[NUMTOK];
- U_LONG intval[NUMTOK];
+ u_long intval[NUMTOK];
int flags;
char buf[MAXLINESIZE];
char *bp;
diff --git a/usr.sbin/xntpd/xntpd/ntp_io.c b/usr.sbin/xntpd/xntpd/ntp_io.c
index 551df510dc37..dcb68efd9089 100644
--- a/usr.sbin/xntpd/xntpd/ntp_io.c
+++ b/usr.sbin/xntpd/xntpd/ntp_io.c
@@ -1,4 +1,4 @@
-/* ntp_io.c,v 3.1 1993/07/06 01:11:17 jbj Exp
+/*
* xntp_io.c - input/output routines for xntpd. The socket-opening code
* was shamelessly stolen from ntpd.
*/
@@ -7,12 +7,13 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/ioctl.h>
#include <sys/time.h>
-
-#ifdef MCAST
-#include "ntp_in.h"
-#endif /* MCAST */
+#ifndef __bsdi__
+#include <netinet/in.h>
+#endif
+#if defined(__bsdi__) || defined(SYS_NETBSD) || defined(SYS_FREEBSD) || defined(SYS_AIX)
+#include <sys/ioctl.h>
+#endif
#include "ntpd.h"
#include "ntp_select.h"
@@ -21,6 +22,10 @@
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#if defined(MCAST) && !defined(IP_ADD_MEMBERSHIP)
+#undef MCAST
+#endif
+
#if defined(BSD)&&!defined(sun)&&!defined(SYS_SINIXM)
#if BSD >= 199006
#define HAVE_VARIABLE_IFR_LENGTH
@@ -61,7 +66,7 @@
#define BLOCKIO() ((void) block_sigio())
#define UNBLOCKIO() ((void) unblock_sigio())
#else
-#define BLOCKIO()
+#define BLOCKIO()
#define UNBLOCKIO()
#endif
@@ -76,15 +81,15 @@
/*
* Memory allocation
*/
-U_LONG full_recvbufs; /* number of recvbufs on fulllist */
-U_LONG free_recvbufs; /* number of recvbufs on freelist */
+u_long full_recvbufs; /* number of recvbufs on fulllist */
+u_long free_recvbufs; /* number of recvbufs on freelist */
static struct recvbuf *freelist; /* free buffers */
static struct recvbuf *fulllist; /* lifo buffers with data */
static struct recvbuf *beginlist; /* fifo buffers with data */
-U_LONG total_recvbufs; /* total recvbufs currently in use */
-U_LONG lowater_additions; /* number of times we have added memory */
+u_long total_recvbufs; /* total recvbufs currently in use */
+u_long lowater_additions; /* number of times we have added memory */
static struct recvbuf initial_bufs[RECV_INIT]; /* initial allocation */
@@ -92,15 +97,15 @@ static struct recvbuf initial_bufs[RECV_INIT]; /* initial allocation */
/*
* Other statistics of possible interest
*/
-U_LONG packets_dropped; /* total number of packets dropped on reception */
-U_LONG packets_ignored; /* packets received on wild card interface */
-U_LONG packets_received; /* total number of packets received */
-U_LONG packets_sent; /* total number of packets sent */
-U_LONG packets_notsent; /* total number of packets which couldn't be sent */
+u_long packets_dropped; /* total number of packets dropped on reception */
+u_long packets_ignored; /* packets received on wild card interface */
+u_long packets_received; /* total number of packets received */
+u_long packets_sent; /* total number of packets sent */
+u_long packets_notsent; /* total number of packets which couldn't be sent */
-U_LONG handler_calls; /* number of calls to interrupt handler */
-U_LONG handler_pkts; /* number of pkts received by handler */
-U_LONG io_timereset; /* time counters were reset */
+u_long handler_calls; /* number of calls to interrupt handler */
+u_long handler_pkts; /* number of pkts received by handler */
+u_long io_timereset; /* time counters were reset */
/*
* Interface stuff
@@ -128,16 +133,16 @@ int maxactivefd;
/*
* Imported from ntp_timer.c
*/
-extern U_LONG current_time;
+extern u_long current_time;
extern int errno;
extern int debug;
-static int create_sockets P((unsigned int));
+static int create_sockets P((u_int));
static int open_socket P((struct sockaddr_in *, int));
static void close_socket P((int));
#ifdef HAVE_SIGNALED_IO
-static int init_clock_sig P(());
+static int init_clock_sig P(());
static void init_socket_sig P((int));
static void set_signal P(());
static RETSIGTYPE sigio_handler P((int));
@@ -202,7 +207,7 @@ init_io()
*/
static int
create_sockets(port)
- unsigned int port;
+ u_int port;
{
#ifdef STREAMS_TLI
struct strioctl ioc;
@@ -223,7 +228,7 @@ create_sockets(port)
*/
inter_list[0].sin.sin_family = AF_INET;
inter_list[0].sin.sin_port = port;
- inter_list[0].sin.sin_addr.s_addr = INADDR_ANY;
+ inter_list[0].sin.sin_addr.s_addr = htonl(INADDR_ANY);
(void) strncpy(inter_list[0].name, "wildcard",
sizeof(inter_list[0].name));
inter_list[0].mask.sin_addr.s_addr = htonl(~0);
@@ -231,9 +236,6 @@ 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) {
@@ -246,7 +248,7 @@ create_sockets(port)
i = 1;
- ifc.ifc_len = sizeof(buf);
+ ifc.ifc_len = sizeof(buf);
#ifdef STREAMS_TLI
ioc.ic_cmd = SIOCGIFCONF;
ioc.ic_timout = 0;
@@ -382,13 +384,13 @@ create_sockets(port)
}
inter_list[i].mask = *(struct sockaddr_in *)&ifreq.ifr_addr;
- /*
+ /*
* look for an already existing source interface address. If
- * the machine has multiple point to point interfaces, then
+ * the machine has multiple point to point interfaces, then
* the local address may appear more than once.
- */
+ */
for (j=0; j < i; j++)
- if (inter_list[j].sin.sin_addr.s_addr ==
+ if (inter_list[j].sin.sin_addr.s_addr ==
inter_list[i].sin.sin_addr.s_addr) {
break;
}
@@ -406,6 +408,15 @@ create_sockets(port)
inter_list[i].flags & INT_BROADCAST);
}
+#if defined(MCAST) && !defined(sun) && !defined(SYS_BSDI) && !defined(SYS_DECOSF1) && !defined(SYS_44BSD)
+ /*
+ * enable possible multicast reception on the broadcast socket
+ */
+ inter_list[0].bcast.sin_addr.s_addr = htonl(INADDR_ANY);
+ inter_list[0].bcast.sin_family = AF_INET;
+ inter_list[0].bcast.sin_port = port;
+#endif /* MCAST */
+
/*
* Blacklist all bound interface addresses
*/
@@ -419,7 +430,7 @@ create_sockets(port)
if (debug > 2) {
printf("create_sockets: ninterfaces=%d\n", ninterfaces);
for (i = 0; i < ninterfaces; i++) {
- printf("interface %d: fd=%d, bfd=%d, name=%.8s, flags=0x%x\n",
+ printf("interface %d: fd=%d, bfd=%d, name=%.8s, flags=0x%x\n",
i,
inter_list[i].fd,
inter_list[i].bfd,
@@ -454,7 +465,7 @@ io_setbclient()
if (inter_list[i].flags & INT_BCASTOPEN)
continue;
#ifdef SOLARIS
- inter_list[i].bcast.sin_addr.s_addr = INADDR_ANY;
+ inter_list[i].bcast.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
#ifndef SYS_DOMAINOS
inter_list[i].bfd = open_socket(&inter_list[i].bcast, 0);
@@ -464,30 +475,85 @@ io_setbclient()
}
-#ifdef MCAST
/*
* io_multicast_add() - add multicast group address
*/
void
io_multicast_add(addr)
- U_LONG addr;
+ u_long addr;
{
- int fd = inter_list[0].fd;
+#ifdef MCAST
struct ip_mreq mreq;
-
- if (!IN_CLASSD(addr))
+ int i = ninterfaces; /* Use the next interface */
+ u_long haddr = ntohl(addr);
+ struct in_addr iaddr;
+ int s;
+ struct sockaddr_in *sinp;
+
+ iaddr.s_addr = addr;
+
+ if (!IN_CLASSD(haddr))
+ { syslog(LOG_ERR,
+ "cannot add multicast address %s as it is not class D",
+ inet_ntoa(iaddr));
return;
+ }
+
+ for (i=0; i<ninterfaces; i++) {
+ /* Already have this address */
+ if (inter_list[i].sin.sin_addr.s_addr == addr) return;
+ /* found a free slot */
+ if (inter_list[i].sin.sin_addr.s_addr == 0 &&
+ inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
+ inter_list[i].flags == 0) break;
+ }
+ sinp = &(inter_list[i].sin);
+
+ memset((char *)&mreq, 0, sizeof(mreq));
+ memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
+ sinp->sin_family = AF_INET;
+ sinp->sin_addr = iaddr;
+ sinp->sin_port = htons(123);
+
+ s = open_socket(sinp, 0);
+ /* Try opening a socket for the specified class D address */
+ /* This works under SunOS 4.x, but not OSF1 .. :-( */
+ if (s < 0) {
+ memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
+ i = 0;
+ /* HACK ! -- stuff in an address */
+ inter_list[i].bcast.sin_addr.s_addr = addr;
+ syslog(LOG_ERR, "...multicast address %s using wildcard socket",
+ inet_ntoa(iaddr));
+ }
+ else {
+ inter_list[i].fd = s;
+ inter_list[i].bfd = -1;
+ (void) strncpy(inter_list[i].name, "multicast",
+ sizeof(inter_list[i].name));
+ inter_list[i].mask.sin_addr.s_addr = htonl(~0);
+ }
+
/*
* 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,
+ mreq.imr_multiaddr = iaddr;
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char *)&mreq, sizeof(mreq)) == -1)
- syslog(LOG_ERR, "setsockopt IP_ADD_MEMBERSHIP fails: %m");
-}
+ syslog(LOG_ERR,
+ "setsockopt IP_ADD_MEMBERSHIP fails: %m for %x / %x (%s)",
+ mreq.imr_multiaddr, mreq.imr_interface.s_addr,
+ inet_ntoa(iaddr));
+ inter_list[i].flags |= INT_MULTICAST;
+ if (i >= ninterfaces) ninterfaces = i+1;
+#else /* MCAST */
+ struct in_addr iaddr;
+ iaddr.s_addr = addr;
+ syslog(LOG_ERR, "cannot add multicast address %s as no MCAST support",
+ inet_ntoa(iaddr));
#endif /* MCAST */
-
+}
/*
* io_unsetbclient - close the broadcast client sockets
@@ -506,38 +572,66 @@ io_unsetbclient()
}
-#ifdef MCAST
/*
* io_multicast_del() - delete multicast group address
*/
void
io_multicast_del(addr)
- U_LONG addr;
+ u_long addr;
{
- int fd = inter_list[0].fd;
+#ifdef MCAST
+ int i;
struct ip_mreq mreq;
+ struct sockaddr_in sinaddr;
- if (!IN_CLASSD(addr))
+ if (!IN_CLASSD(addr)) {
+ sinaddr.sin_addr.s_addr = addr;
+ syslog(LOG_ERR,
+ "invalid multicast address %s", ntoa(&sinaddr));
return;
+ }
+
/*
- * disable reception of multicast packets
+ * 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");
-}
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ for (i = 0; i < ninterfaces; i++) {
+ if (!(inter_list[i].flags & INT_MULTICAST))
+ continue;
+ if (!(inter_list[i].fd < 0))
+ continue;
+ if (addr != inter_list[i].sin.sin_addr.s_addr)
+ continue;
+ if (i != 0) {
+ /* we have an explicit fd, so we can slose it */
+ close_socket(inter_list[i].fd);
+ memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
+ inter_list[i].fd = -1;
+ inter_list[i].bfd = -1;
+ } else {
+ /* We are sharing "any address" port :-( Don't close it! */
+ if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (char *)&mreq, sizeof(mreq)) == -1)
+ syslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails: %m");
+ /* This is **WRONG** -- there may be others ! */
+ /* There should be a count of users ... */
+ inter_list[i].flags &= ~INT_MULTICAST;
+ }
+ }
+#else /* MCAST */
+ syslog(LOG_ERR, "this function requires multicast kernel");
#endif /* MCAST */
+}
/*
* open_socket - open a socket, returning the file descriptor
*/
static int
-open_socket(addr, bcast)
+open_socket(addr, flags)
struct sockaddr_in *addr;
- int bcast;
+ int flags;
{
int fd;
int on = 1, off = 0;
@@ -549,10 +643,6 @@ open_socket(addr, bcast)
/*NOTREACHED*/
}
- if (fd > maxactivefd)
- maxactivefd = fd;
- FD_SET(fd, &activefds);
-
/* set SO_REUSEADDR since we will be binding the same port
number on each interface */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
@@ -566,15 +656,32 @@ 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",
- fd,
- addr->sin_family,
- addr->sin_port,
- addr->sin_addr.s_addr,
- bcast);
+ "bind() fd %d, family %d, port %d, addr %08lx, in_classd=%d flags=%d fails: %%m",
+ fd, addr->sin_family, (int)ntohs(addr->sin_port),
+ (u_long)ntohl(addr->sin_addr.s_addr),
+ IN_CLASSD(ntohl(addr->sin_addr.s_addr)), flags);
syslog(LOG_ERR, buff);
+ close(fd);
+
+ /*
+ * soft fail if opening a class D address
+ */
+ if (IN_CLASSD(ntohl(addr->sin_addr.s_addr)))
+ return -1;
exit(1);
}
+#ifdef DEBUG
+ if (debug)
+ printf("bind() fd %d, family %d, port %d, addr %08lx, flags=%d\n",
+ fd,
+ addr->sin_family,
+ (int)ntohs(addr->sin_port),
+ (u_long)ntohl(addr->sin_addr.s_addr),
+ flags);
+#endif
+ if (fd > maxactivefd)
+ maxactivefd = fd;
+ FD_SET(fd, &activefds);
#ifdef HAVE_SIGNALED_IO
init_socket_sig(fd);
@@ -613,23 +720,9 @@ 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 */
- if (bcast) {
+ if (flags & INT_BROADCAST) {
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
(char *)&on, sizeof(on))) {
syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
@@ -679,7 +772,7 @@ findbcastinter(addr)
{
#ifdef SIOCGIFCONF
register int i;
- register U_LONG netnum;
+ register u_long netnum;
netnum = NSRCADR(addr);
for (i = 1; i < ninterfaces; i++) {
@@ -709,7 +802,7 @@ getrecvbufs()
#ifdef DEBUG
if (debug > 4)
- printf("getrecvbufs: %d handler interrupts, %d frames\n",
+ printf("getrecvbufs: %ld handler interrupts, %ld frames\n",
handler_calls, handler_pkts);
#endif
@@ -726,7 +819,7 @@ getrecvbufs()
*/
#ifdef DEBUG
if (debug > 4)
- printf("getrecvbufs returning %d buffers\n", full_recvbufs);
+ printf("getrecvbufs returning %ld buffers\n", full_recvbufs);
#endif
rb = beginlist;
fulllist = 0;
@@ -787,9 +880,10 @@ freerecvbuf(rb)
* destination is logged.
*/
void
-sendpkt(dest, inter, pkt, len)
+sendpkt(dest, inter, ttl, pkt, len)
struct sockaddr_in *dest;
struct interface *inter;
+ int ttl;
struct pkt *pkt;
int len;
{
@@ -802,6 +896,7 @@ sendpkt(dest, inter, pkt, len)
u_short port;
struct in_addr addr;
};
+
#ifndef ERRORCACHESIZE
#define ERRORCACHESIZE 8
#endif
@@ -813,10 +908,26 @@ sendpkt(dest, inter, pkt, len)
#ifdef DEBUG
if (debug)
- printf("sendpkt(fd=%d %s, %s, %d)\n", inter->fd, ntoa(dest),
- ntoa(&inter->sin), len);
+ printf("%ssendpkt(fd=%d %s, %s, ttl=%d, %d)\n",
+ (ttl >= 0) ? "\tMCAST\t*****" : "",
+ inter->fd, ntoa(dest),
+ ntoa(&inter->sin), ttl, len);
#endif
+#ifdef MCAST
+ /* for the moment we use the bcast option to set multicast ttl */
+ if (ttl >= 0 && ttl != inter->last_ttl) {
+ u_char mttl = ttl;
+
+ /* set the multicast ttl for outgoing packets */
+ if (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
+ &mttl, sizeof(mttl)) == -1) {
+ syslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails: %m");
+ }
+ else inter->last_ttl = ttl;
+ }
+#endif /* MCAST */
+
for (slot = ERRORCACHESIZE; --slot >= 0; )
if (badaddrs[slot].port == dest->sin_port &&
badaddrs[slot].addr.s_addr == dest->sin_addr.s_addr)
@@ -924,7 +1035,7 @@ again:
read(fd, (char *)&rb->recv_space, i);
if (rb->recv_length == -1) {
- syslog(LOG_ERR, "clock read: %m");
+ syslog(LOG_ERR, "clock read fd %d: %m", fd);
rb->next = freelist;
freelist = rb;
free_recvbufs++;
@@ -937,6 +1048,7 @@ again:
*/
rb->recv_srcclock = rp->srcclock;
rb->dstadr = 0;
+ rb->fd = fd;
rb->recv_time = ts;
rb->receiver = rp->clock_recv;
@@ -969,43 +1081,45 @@ again:
break;
fd = inter_list[i].bfd;
}
+ if (fd < 0) continue;
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.
+ * on the wild card socket, just dump the
+ * packet.
*/
-
- if (!(free_recvbufs && i == 0 &&
+ 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
- */
+ /*
+ * these guys manage to put properly addressed
+ * packets into the wildcard queue
+ */
if (free_recvbufs == 0) {
#else
- if (i == 0 || free_recvbufs == 0) {
+ if (i == 0 || free_recvbufs == 0) {
#endif
- char buf[RX_BUFF_SIZE];
-
-#ifndef UDP_WILDCARD_DELIVERY
- (void) read(fd, buf, sizeof buf);
-#else
- fromlen = 0;
- (void) recvfrom(fd, buf, sizeof(buf), 0,
- (struct sockaddr *)0,
- &fromlen);
+ char buf[RX_BUFF_SIZE];
+ struct sockaddr from;
+ fromlen = sizeof from;
+ (void) recvfrom(fd, buf,
+ sizeof(buf), 0,
+ &from, &fromlen);
+#ifdef DEBUG
+ if (debug)
+ printf("ignore/drop on %d(%lu) fd=%d from %s\n",
+ i, free_recvbufs, fd,
+ inet_ntoa(((struct sockaddr_in *) &from)->sin_addr));
#endif
-
- if (i == 0)
- packets_ignored++;
- else
- packets_dropped++;
- continue;
- }
+ if (i == 0)
+ packets_ignored++;
+ else
+ packets_dropped++;
+ continue;
+ }
}
rb = freelist;
@@ -1024,14 +1138,17 @@ again:
freelist = rb;
free_recvbufs++;
#ifdef DEBUG
- if (debug)
- printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd);
+ if (debug)
+ printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd);
#endif
continue;
}
#ifdef DEBUG
- if (debug)
- printf("input_handler: fd=%d length %d\n", fd, rb->recv_length);
+ if (debug)
+ printf("input_handler: fd=%d length %d from %08lx %s\n",
+ fd, rb->recv_length,
+ (u_long)ntohl(rb->recv_srcadr.sin_addr.s_addr) &
+ 0x00000000ffffffff, inet_ntoa(rb->recv_srcadr.sin_addr));
#endif
/*
@@ -1039,6 +1156,7 @@ again:
* put it on the full list and do bookkeeping.
*/
rb->dstadr = &inter_list[i];
+ rb->fd = fd;
rb->recv_time = ts;
rb->receiver = receive;
@@ -1074,7 +1192,7 @@ findinterface(addr)
struct sockaddr_in *addr;
{
register int i;
- register U_LONG saddr;
+ register u_long saddr;
/*
* Just match the address portion.
@@ -1107,7 +1225,7 @@ io_clr_stats()
#ifdef REFCLOCK
-/*
+/*
* This is a hack so that I don't have to fool with these ioctls in the
* pps driver ... we are already non-blocking and turn on SIGIO thru
* another mechanisim
@@ -1243,7 +1361,7 @@ io_closeclock(rio)
* Spical cases first!
*/
#if defined(SYS_HPUX)
-#define CLOCK_DONE
+#define CLOCK_DONE
static int
init_clock_sig(rio)
struct refclockio *rio;
@@ -1273,12 +1391,12 @@ init_clock_sig(rio)
}
return 0;
}
-#endif /* SYS_HPUX */
+#endif /* SYS_HPUX */
#if defined(SYS_AIX)&&!defined(_BSD)
/*
* SYSV compatibility mode under AIX.
*/
-#define CLOCK_DONE
+#define CLOCK_DONE
static int
init_clock_sig(rio)
struct refclockio *rio;
@@ -1302,7 +1420,7 @@ init_clock_sig(rio)
return 0;
}
#endif /* AIX && !BSD */
-#ifndef CLOCK_DONE
+#ifndef CLOCK_DONE
static int
init_clock_sig(rio)
struct refclockio *rio;
@@ -1328,7 +1446,7 @@ static init_clock_sig(rio)
if (ioctl(rio->fd, I_SETSIG, S_INPUT) < 0) {
syslog(LOG_ERR,
"ioctl(I_SETSIG, S_INPUT) fails for clock I/O: %m");
- return 1;
+ return 1;
}
return 0;
}
@@ -1342,7 +1460,7 @@ static init_clock_sig(rio)
* Special cases first!
*/
#if defined(SYS_HPUX) || defined(SYS_LINUX)
-#define SOCKET_DONE
+#define SOCKET_DONE
static void
init_socket_sig(fd)
int fd;
@@ -1380,7 +1498,7 @@ init_socket_sig(fd)
/*
* SYSV compatibility mod under AIX
*/
-#define SOCKET_DONE
+#define SOCKET_DONE
static void
init_socket_sig(fd)
int fd;
@@ -1408,9 +1526,9 @@ init_socket_sig(fd)
#endif /* AIX && !BSD */
#if defined(UDP_BACKWARDS_SETOWN)
/*
- * SunOS 3.5 and Ultirx 2.0
+ * SunOS 3.5 and Ultirx 2.0
*/
-#define SOCKET_DONE
+#define SOCKET_DONE
static void
init_socket_sig(fd)
int fd;
@@ -1635,8 +1753,8 @@ block_io_and_alarm()
{
int mask;
- mask = sigmask(SIGIO)|sigmask(SIGALRM);
- (void)sigblock(mask);
+ mask = sigmask(SIGIO)|sigmask(SIGALRM);
+ (void)sigblock(mask);
}
void
@@ -1659,7 +1777,7 @@ unblock_io_and_alarm()
{
int mask, omask;
- mask = sigmask(SIGIO)|sigmask(SIGALRM);
+ mask = sigmask(SIGIO)|sigmask(SIGALRM);
omask = sigblock(0);
omask &= ~mask;
(void)sigsetmask(omask);
@@ -1668,9 +1786,9 @@ unblock_io_and_alarm()
void
unblock_sigio()
{
- int mask, omask;
-
- mask = sigmask(SIGIO);
+ int mask, omask;
+
+ mask = sigmask(SIGIO);
omask = sigblock(0);
omask &= ~mask;
(void)sigsetmask(omask);
@@ -1681,7 +1799,7 @@ wait_for_signal()
{
int mask, omask;
- mask = sigmask(SIGIO)|sigmask(SIGALRM);
+ mask = sigmask(SIGIO)|sigmask(SIGALRM);
omask = sigblock(0);
omask &= ~mask;
sigpause(omask);
diff --git a/usr.sbin/xntpd/xntpd/ntp_leap.c b/usr.sbin/xntpd/xntpd/ntp_leap.c
index aadbb09dc346..6473362cf652 100644
--- a/usr.sbin/xntpd/xntpd/ntp_leap.c
+++ b/usr.sbin/xntpd/xntpd/ntp_leap.c
@@ -1,4 +1,4 @@
-/* ntp_leap.c,v 3.1 1993/07/06 01:11:18 jbj Exp
+/*
* ntp_leap - maintain leap bits and take action when a leap occurs
*/
#include <stdio.h>
@@ -41,7 +41,7 @@ u_char leap_mask; /* set on day before a potential leap */
* Timer. The timer code imports this so it can call us prior to
* calling out any pending transmits.
*/
-U_LONG leap_timer;
+u_long leap_timer;
/*
* We don't want to do anything drastic if the leap function is handled
@@ -67,18 +67,18 @@ u_char leapbits;
/*
* Imported from the timer module.
*/
-extern U_LONG current_time;
+extern u_long current_time;
/*
* Some statistics counters
*/
-U_LONG leap_processcalls; /* calls to leap_process */
-U_LONG leap_notclose; /* leap found to be a LONG time from now */
-U_LONG leap_monthofleap; /* in the month of a leap */
-U_LONG leap_dayofleap; /* This is the day of the leap */
-U_LONG leap_hoursfromleap; /* only 2 hours from leap */
-U_LONG leap_happened; /* leap process saw the leap */
+u_long leap_processcalls; /* calls to leap_process */
+u_long leap_notclose; /* leap found to be a long time from now */
+u_long leap_monthofleap; /* in the month of a leap */
+u_long leap_dayofleap; /* This is the day of the leap */
+u_long leap_hoursfromleap; /* only 2 hours from leap */
+u_long leap_happened; /* leap process saw the leap */
/*
* Imported from the main module
@@ -86,7 +86,7 @@ U_LONG leap_happened; /* leap process saw the leap */
extern int debug;
-static void setnexttimeout P((U_LONG));
+static void setnexttimeout P((u_long));
/*
* init_leap - initialize the leap module's data.
@@ -114,18 +114,18 @@ init_leap()
void
leap_process()
{
- U_LONG leapnext;
- U_LONG leaplast;
+ u_long leapnext;
+ u_long leaplast;
l_fp ts;
u_char bits;
extern u_char sys_leap;
leap_processcalls++;
get_systime(&ts);
- calleapwhen(ts.l_ui, &leaplast, &leapnext);
+ calleapwhen((u_long)ts.l_ui, &leaplast, &leapnext);
/*
- * Figure out what to do based on how LONG to the next leap.
+ * Figure out what to do based on how long to the next leap.
*/
if (leapnext > OKAYTOSETWARNING) {
if (leaplast < ONEMINUTE) {
@@ -189,7 +189,7 @@ leap_process()
* recomputed.
*/
if ((leapnext - DAYBEFORE) >= DAYBEFORE)
- setnexttimeout((U_LONG)DAYBEFORE);
+ setnexttimeout((u_long)DAYBEFORE);
else
setnexttimeout(leapnext - DAYBEFORE);
return;
@@ -223,7 +223,7 @@ leap_process()
*/
static void
setnexttimeout(secs)
- U_LONG secs;
+ u_long secs;
{
/*
* We try to aim the time out at between 1 and 1+(1<<EVENT_TIMEOUT)
@@ -243,13 +243,13 @@ leap_setleap(indicator, warning)
int indicator;
int warning;
{
- U_LONG leapnext;
- U_LONG leaplast;
+ u_long leapnext;
+ u_long leaplast;
l_fp ts;
int i;
get_systime(&ts);
- calleapwhen(ts.l_ui, &leaplast, &leapnext);
+ calleapwhen((u_long)ts.l_ui, &leaplast, &leapnext);
i = 0;
if (warning != ~0)
diff --git a/usr.sbin/xntpd/xntpd/ntp_loopfilter.c b/usr.sbin/xntpd/xntpd/ntp_loopfilter.c
index 61332b9b6384..168ef3289a6e 100644
--- a/usr.sbin/xntpd/xntpd/ntp_loopfilter.c
+++ b/usr.sbin/xntpd/xntpd/ntp_loopfilter.c
@@ -1,7 +1,6 @@
/*
* ntp_loopfilter.c - implements the NTP loop filter algorithm
*/
-
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
@@ -10,41 +9,10 @@
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
-
-#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
-#include <sys/stat.h>
-#include "ntp_refclock.h"
-#endif /* PPS || PPSCLK || PPSPPS */
-
-#if defined(PPSCLK) || defined(PPSPPS)
-#if defined(HAVE_BSD_TTYS)
-#include <sgtty.h>
-#endif /* HAVE_BSD_TTYS */
-
-#if defined(HAVE_SYSV_TTYS)
-#include <termio.h>
-#endif /* HAVE_SYSV_TTYS */
-
-#ifdef HAVE_TERMIOS
-#include <termios.h>
-#endif
-#if defined(STREAM)
-#include <stropts.h>
-#if defined(PPSCLK)
-#include <sys/clkdefs.h>
-#endif /* PPSCLK */
-#endif /* STREAM */
-
-#endif /* PPSCLK || PPSPPS */
-
-#if defined(PPSPPS)
-#include <sys/ppsclock.h>
-#endif /* PPSPPS */
-
#include "ntp_stdlib.h"
#ifdef KERNEL_PLL
-#include <sys/timex.h>
+#include "sys/timex.h"
#define ntp_gettime(t) syscall(SYS_ntp_gettime, (t))
#define ntp_adjtime(t) syscall(SYS_ntp_adjtime, (t))
#endif /* KERNEL_PLL */
@@ -59,122 +27,83 @@
* seconds. When adjustments are capped inside this range (see
* CLOCK_MAX_{I,F}) both the clock_adjust and the compliance
* registers should be fine. (When the compliance is above 16, it
- * will at most accumulate 2**CLOCK_MULT times the maximum offset,
+ * will at most accumulate 2 ** CLOCK_MULT times the maximum offset,
* which means it fits in a s_fp.)
*
* The skew compensation is a special case. In version 2, it was
- * kept in ms/4s (i.e., CLOCK_FREQ was 10). In version 3 (Section 5)
- * it seems to be 2**-16ms/4s in a s_fp for a maximum of +-125ppm
+ * kept in ms / 4s (i.e., CLOCK_FREQ was 10). In version 3 (Section 5)
+ * it seems to be 2 ** -16ms / 4s in a s_fp for a maximum of +-125ppm
* (stated maximum 100ppm). Since this seems about to change to a
- * larger range, it will be kept in units of 2**-20 (CLOCK_DSCALE)
+ * larger range, it will be kept in units of 2 ** -20 (CLOCK_DSCALE)
* in an s_fp (mainly because that's nearly the same as parts per
* million). Note that this is ``seconds per second'', whereas a
* clock adjustment is a 32-bit fraction of a second to be applied
- * every 2**CLOCK_ADJ seconds; to find it, shift the drift right by
- * (CLOCK_DSCALE-16-CLOCK_ADJ). When updating the drift, on the other
- * hand, the CLOCK_FREQ factor from the spec assumes the value to be
- * in ``seconds per 4 seconds''; to get our units, CLOCK_ADJ must be
+ * every 2 ** CLOCK_ADJ seconds; to find it, shift the drift right by
+ * (CLOCK_DSCALE - 16 - CLOCK_ADJ). When updating the drift, on the
+ * other hand, the CLOCK_FREQ factor from the spec assumes the value to
+ * be in ``seconds per 4 seconds''; to get our units, CLOCK_ADJ must be
* added to the shift.
+ *
+ * Kernel PLL/PPS state machine
+ *
+ * The following state machine is used when the kernel PLL modifications
+ * described in the README.kernel file are present. The initial
+ * configuration routine loop_config() sets up the initial frequency
+ * estimate and tests if the kernel modifications are present. If so and
+ * the PLL mode bit 1 (STA_PLL) of the mode word in the drift file
+ * (ntp.drift) is set, pll_control is set true and the kernel pll is
+ * enabled. If the kernel modifications are present and the PLL mode bit
+ * 2 (STA_PPSFREQ) is set, the kernel PPS frequency discipline is
+ * enabled.
+ *
+ * Each update to a prefer peer sets pps_update true if it survives the
+ * intersection algorithm and its time is within range. The PPS time
+ * discipline is enabled (STA_PPSTIME bit set in the status word) when
+ * pps_update is true and the PPS frequency discipline is enabled. If
+ * the PPS time discipline is enabled and the kernel reports a PPS
+ * signal is present, the pps_control variable is set to the current
+ * time. If the current time is later than pps_control by PPS_MAXAGE
+ * (120 s), this variable is set to zero.
+ *
+ * The pll_enable switch can be set both at configuration time and at
+ * run time using xntpdc. If true, the kernel modifications are active
+ * as described above; if false, the kernel is bypassed entirely (except
+ * for the PPS frequency update, if enabled) and the daemon PLL used
+ * instead.
*/
-
-/*
- * Macro to compute log2(). We don't want to to this very often, but
- * needs what must.
- */
-#define LOG2(r, t) \
- do { \
- LONG x = t; \
- r = 0; \
- while(x >> 1) \
- r++; \
- }
-
#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) */
+#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
/*
* Program variables
*/
- l_fp last_offset; /* last adjustment done */
-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 */
-
- int time_constant; /* log2 of time constant (0 .. 4) */
-static U_LONG tcadj_time; /* last time-constant adjust time */
-
- U_LONG watchdog_timer; /* watchdog timer, in seconds */
-static int first_adjustment; /* 1 if waiting for first adjustment */
-static int tc_counter; /* time-constant hold counter */
-
-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 */
+ l_fp last_offset; /* last clock offset */
+ u_long last_time; /* time of last clock update (s) */
+ u_fp clock_stability; /* clock stability (ppm) */
+ s_fp clock_frequency; /* clock frequency error (ppm) */
+ s_fp drift_comp; /* pll frequency (ppm) */
+static long clock_adjust; /* clock adjust (fraction only) */
+static s_fp max_comp; /* max frequency offset (ppm) */
+ int tc_counter; /* poll-adjust counter */
+ int pll_status; /* status bits for kernel pll */
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 pll_enable; /* true if pll enabled */
+ u_long pps_control; /* last pps sample time */
+ int pps_update; /* pps update valid */
int fdpps = -1; /* pps file descriptor */
-#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
-/*
- * This module has support for a 1-pps signal to fine-tune the local
- * clock. The signal is optional; when present and operating within
- * given tolerances in frequency and jitter, it is used to discipline
- * the local clock. In order for this to work, the local clock must be
- * set to within +-500 ms by another means, such as a radio clock or
- * NTP itself. The 1-pps signal is connected via a serial port and
- * gadget box consisting of a one-shot and EIA level-converter. When
- * operated at 38.4 kbps with a SPARCstation IPC, this arrangement has a
- * worst-case jitter less than 26 us. The pps delay configuration
- * declaration can be used to compensate for miscellaneous uart and
- * os delays. Allow about 247 us for uart delays at 38400 bps and
- * -1 ms for SunOS streams nonsense.
- */
-
-/*
- * A really messy way to map an integer baud rate to the system baud rate.
- * There should be a better way.
- */
-#define SYS_BAUD(i) \
- ( i == 38400 ? B38400 : \
- ( i == 19200 ? B19200 : \
- ( i == 9600 ? B9600 : \
- ( i == 4800 ? B4800 : \
- ( i == 2400 ? B2400 : \
- ( i == 1200 ? B1200 : \
- ( i == 600 ? B600 : \
- ( i == 300 ? B300 : 0 ))))))))
-
-#define PPS_BAUD B38400 /* default serial port speed */
-timecode */
-#define PPS_DEV "/dev/pps" /* pps port */
-#define PPS_FAC 3 /* pps shift (log2 trimmed samples) */
-#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 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;
+extern s_fp sys_rootdelay; /* root delay */
+extern u_fp sys_rootdispersion; /* root dispersion */
+extern struct peer *sys_peer; /* system peer pointer */
+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 ntp_io.c
@@ -189,31 +118,13 @@ extern int debug; /* global debug flag */
/*
* Imported from timer module
*/
-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 */
+extern u_long current_time; /* like it says, in seconds */
/*
* Imported from leap module
*/
extern u_char leapbits; /* sanitized leap bits */
-/*
- * Function prototypes
- */
-#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
-int pps_sample P((l_fp *));
-#if defined(PPSCLK)
-static void pps_receive P((struct recvbuf *));
-#endif /* PPSCLK */
-#endif /* PPS || PPSCLK || PPSPPS */
-
#if defined(KERNEL_PLL)
#define MOD_BITS (MOD_OFFSET | MOD_MAXERROR | MOD_ESTERROR | \
MOD_STATUS | MOD_TIMECONST)
@@ -221,7 +132,6 @@ extern int sigvec P((int, struct sigvec *, struct sigvec *));
extern int syscall P((int, void *, ...));
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 */
@@ -232,299 +142,164 @@ static struct sigvec newsigsys; /* new sigvec status */
void
init_loopfilter()
{
- extern U_LONG tsf_maxslew;
- U_LONG tsf_limit;
-#if defined(PPSCLK)
- int fd232;
-#endif /* PPSCLK */
- clock_adjust = 0;
- drift_comp = 0;
- time_constant = 0;
- tcadj_time = 0;
- watchdog_timer = 0;
- tc_counter = 0;
- last_offset.l_i = 0;
- last_offset.l_f = 0;
- first_adjustment = 1;
+ extern u_long tsf_maxslew;
+ u_long tsf_limit;
-/*
- * Limit for drift_comp, minimum of two values. The first is to avoid
- * signed overflow, the second to keep within 75% of the maximum
- * adjustment possible in adj_systime().
- */
+ /*
+ * Limit for drift_comp, minimum of two values. The first is to
+ * avoid signed overflow, the second to keep within 75% of the
+ * maximum adjustment possible in adj_systime().
+ */
max_comp = 0x7fff0000;
tsf_limit = ((tsf_maxslew >> 1) + (tsf_maxslew >> 2));
if ((max_comp >> RSH_DRIFT_TO_ADJ) > tsf_limit)
max_comp = tsf_limit << RSH_DRIFT_TO_ADJ;
- pps_control = 0;
-#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
-#if defined(PPSCLK)
- pps_baud = PPS_BAUD;
-#endif /* PPSCLK */
- pps_delay.l_i = 0;
- pps_delay.l_f = 0;
- pps_time = pps_update = 0;
- nsamples = 0;
-#if defined(PPSCLK)
-
- /*
- * Open pps serial port. We don't care if the serial port comes
- * up; if not, we just use the timecode. Therefore, if anything
- * goes wrong, just reclaim the resources and continue.
- */
- fd232 = open(PPS_DEV, O_RDONLY);
- if (fd232 == -1) {
- syslog(LOG_ERR, "loopfilter: open of %s: %m", PPS_DEV);
- return;
- }
-
-#if !defined(HPUXGADGET) /* dedicated to Ken Stone */
-#if defined(HAVE_SYSV_TTYS)
- /*
- * System V serial line parameters (termio interface)
- */
- PPSCLK SUPPORT NOT AVAILABLE IN TERMIO INTERFACE
-#endif /* HAVE_SYSV_TTYS */
-#if defined(HAVE_TERMIOS)
- /*
- * POSIX serial line parameters (termios interface)
- *
- * The PPSCLK option provides timestamping at the driver level.
- * It uses a 1-pps signal and level converter (gadget box) and
- * requires the tty_clk streams module and SunOS 4.1.1 or
- * later.
- */
- { struct termios ttyb, *ttyp;
-
- ttyp = &ttyb;
- if (tcgetattr(fd232, ttyp) < 0) {
- syslog(LOG_ERR,
- "loopfilter: tcgetattr(%s): %m", PPS_DEV);
- goto screwed;
- }
- ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
- ttyp->c_oflag = 0;
- ttyp->c_cflag = PPS_BAUD|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,
- "loopfilter: tcsetattr(%s): %m", PPS_DEV);
- goto screwed;
- }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- syslog(LOG_ERR,
- "loopfilter: tcflush(%s): %m", PPS_DEV);
- goto screwed;
- }
- }
-#endif /* HAVE_TERMIOS */
-#if defined(STREAM)
- while (ioctl(fd232, I_POP, 0 ) >= 0) ;
- if (ioctl(fd232, I_PUSH, "clk") < 0) {
- syslog(LOG_ERR,
- "loopfilter: ioctl(%s, I_PUSH, clk): %m", PPS_DEV);
- goto screwed;
- }
- if (ioctl(fd232, CLK_SETSTR, PPS_XCPT) < 0) {
- syslog(LOG_ERR,
- "loopfilter: ioctl(%s, CLK_SETSTR, PPS_XCPT): %m", PPS_DEV);
- goto screwed;
- }
-#endif /* STREAM */
-#if defined(HAVE_BSD_TTYS)
- /*
- * 4.3bsd serial line parameters (sgttyb interface)
- *
- * The PPSCLK option provides timestamping at the driver level.
- * It uses a 1-pps signal and level converter (gadget box) and
- * requires the tty_clk line discipline and 4.3bsd or later.
- */
- { struct sgttyb ttyb;
- int ldisc = CLKLDISC;
-
- if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "loopfilter: ioctl(%s, TIOCGETP): %m", PPS_DEV);
- goto screwed;
- }
- ttyb.sg_ispeed = ttyb.sg_ospeed = PPS_BAUD;
- ttyb.sg_erase = ttyb.sg_kill = '\r';
- ttyb.sg_flags = RAW;
- if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "loopfilter: ioctl(%s, TIOCSETP): %m", PPS_DEV);
- goto screwed;
- }
- if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR,
- "loopfilter: ioctl(%s, TIOCSETD): %m", PPS_DEV);
- goto screwed;
- }
- }
-#endif /* HAVE_BSD_TTYS */
-#endif /* HPUXGADGET */
- fdpps = fd232;
-
/*
- * Insert in device list.
+ * Reset clockworks
*/
- io.clock_recv = pps_receive;
- io.srcclock = (caddr_t)NULL;
- io.datalen = 0;
- io.fd = fdpps;
-#if defined(HPUXGADGET)
- if (!io_addclock_simple(&io))
-#else
- if (!io_addclock(&io))
-#endif /* HPUXGADGET */
- goto screwed;
- return;
+ drift_comp = 0;
+ clock_adjust = 0;
+ tc_counter = 0;
+ sys_poll = NTP_MINPOLL;
- /*
- * Something broke. Reclaim resources.
- */
-screwed:
- (void)close(fdpps);
- return;
-#endif /* PPSCLK */
-#endif /* PPS || PPSCLK || PPSPPS */
+ L_CLR(&last_offset);
+ last_time = 0;
+ clock_frequency = 0;
+ clock_stability = 0;
+ pps_update = pps_control = 0;
}
/*
* local_clock - the NTP logical clock loop filter. Returns 1 if the
- * clock was stepped, 0 if it was slewed and -1 if it is
- * hopeless.
+ * clock was stepped, 0 if it was slewed and -1 if it is hopeless.
*/
int
local_clock(fp_offset, peer)
l_fp *fp_offset; /* best offset estimate */
struct peer *peer; /* from peer - for messages */
{
- register LONG offset;
- register U_LONG tmp_ui;
- register U_LONG tmp_uf;
- register LONG tmp;
- int isneg;
+ long offset;
+ long tmp;
+ int return_code;
+ l_fp ftmp;
+ s_fp stmp;
+ u_fp smax;
+ long allan;
+ long interval;
#if defined(KERNEL_PLL)
struct timex ntv;
#endif /* KERNEL_PLL */
+ /*
+ * Initialize estimated measurement error and Allan variance
+ * intercept point. The measurement error is assumed the sum of
+ * the peer dispersion plus select dispersion, which seems
+ * reasonable. The Allan variance intercept point is assumed
+ * at MAXSEC for reference clocks and twice that for peer
+ * clocks, which seems cowardly.
+ */
+ if (peer->refclktype)
+ allan = CLOCK_MAXSEC;
+ else
+ allan = CLOCK_MAXSEC << 1;
+
+ if (!last_time)
+ last_time = current_time;
+ interval = (long)(current_time - last_time);
+ clock_adjust = 0;
+ offset = fp_offset->l_f;
+ smax = peer->dispersion + peer->selectdisp;
+ return_code = 0;
+
#ifdef DEBUG
if (debug > 1)
- printf("local_clock(%s, %s)\n", lfptoa(fp_offset, 6),
- ntoa(&peer->srcadr));
+ printf(
+ "local_clock: offset %s peer %s watch %ld)\n",
+ lfptoa(fp_offset, 6), ntoa(&peer->srcadr),
+ interval);
#endif
/*
- * Take the absolute value of the offset
- */
- tmp_ui = fp_offset->l_ui;
- tmp_uf = fp_offset->l_uf;
- if (M_ISNEG(tmp_ui, tmp_uf)) {
- M_NEG(tmp_ui, tmp_uf);
- isneg = 1;
- } else
- isneg = 0;
-
- /*
* If the clock is way off, don't tempt fate by correcting it.
*/
- if (tmp_ui >= CLOCK_WAYTOOBIG) {
+ ftmp = *fp_offset;
+ if (L_ISNEG(&ftmp))
+ L_NEG(&ftmp);
+ if (ftmp.l_ui >= CLOCK_WAYTOOBIG) {
syslog(LOG_ERR,
- "Clock appears to be %u seconds %s, something may be wrong",
- tmp_ui, isneg>0?"fast":"slow");
+ "time error %s is way too large (set clock manually)",
+ lfptoa(fp_offset, 6));
#ifndef BIGTIMESTEP
return (-1);
#endif /* BIGTIMESTEP */
- }
/*
- * Save this offset for later perusal
+ * If the magnitude of the offset is greater than CLOCK.MAX
+ * (128 ms), reset the time and frequency. We are quite
+ * aggresive here, since the intrinsic clock oscillator
+ * frequency error can be quite large, sometimes over +-300 ppm.
+ * With something this large and a noisy peer, the casual time
+ * updates wander right through the acceptable range, causing
+ * this section to trigger.
*/
- last_offset = *fp_offset;
+ } else if (ftmp.l_ui > CLOCK_MAX_I || (ftmp.l_ui == CLOCK_MAX_I
+ && ftmp.l_uf >= CLOCK_MAX_F)) {
+ tc_counter = 0;
+ sys_poll = peer->minpoll;
- /*
- * 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. */
- syslog(LOG_INFO,
- "clock correction %s too large (ignored)\n",
- lfptoa(fp_offset, 6));
- return (0);
- }
- syslog(LOG_NOTICE, "clock reset (%s) %s\n",
+ /*
+ * Either we are not in synchronization, or we have gone
+ * CLOCK_MINSTEP (900 s) since the last acceptable
+ * update. We step the clock and leave the frequency
+ * alone. Since the clock filter has been reset, the
+ * dispersions will be high upon recovery and the quick-
+ * march code below will trigger to keep the clock in
+ * bounds.
+ */
+ if (sys_leap == LEAP_NOTINSYNC || interval >
+ CLOCK_MINSTEP) {
+ step_systime(fp_offset);
+ syslog(LOG_NOTICE,
+
+ "time reset (%s) %s s",
#ifdef SLEWALWAYS
- "slew",
+ "slew",
#else
- "step",
+ "step",
#endif
- lfptoa(fp_offset, 6));
- step_systime(fp_offset);
- clock_adjust = 0;
- watchdog_timer = 0;
- first_adjustment = 1;
- pps_update = 0;
- return (1);
- }
+ lfptoa(fp_offset, 6));
+ return_code = 1;
+
+ /*
+ * The local clock is out of range, but we haven't
+ * allowed enough time for the peer (usually a radio
+ * clock) to recover after a leap second. Pretend we wuz
+ * never here.
+ */
+ } else
+ return (return_code);
/*
- * Here we've got an offset small enough to slew. Note that
- * since the offset is small we don't have to carry the damned
- * high order longword in our calculations.
- *
- * The time constant and sample interval are approximated with
- * shifts, as in Section 5 of the v3 spec. The spec procedure
- * looks strange, as an interval of 64 to 127 seconds seems to
- * cause multiplication with 128 (and so on). This code lowers
- * the multiplier by one bit.
- *
- * The time constant update goes after adjust and skew updates,
- * as in appendix G.
- */
- /*
- * If pps samples are valid, update offset, root delay and
- * 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;
- offset = LFPTOFP(&pps_offset);
- if (offset < 0)
- offset = -offset;
- sys_rootdispersion = offset + pps_dispersion;
- }
- offset = last_offset.l_f;
-
- /*
- * The pll_control is active when the phase-lock code is
+ * This code segment works when the clock-adjustment code is
* implemented in the kernel, which at present is only in the
- * (modified) SunOS 4.1.x, Ultrix 4.3 and OSF/1 kernels. In the
+ * (modified) SunOS 4.1, Ultrix 4.3 and OSF/1 kernels. In the
* case of the DECstation 5000/240 and Alpha AXP, additional
- * kernal modifications provide a true microsecond clock. We
- * 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.
- */
- if (pll_control) {
+ * kernel modifications provide a true microsecond clock. We
+ * know the scaling of the frequency variable (s_fp) is the same
+ * as the kernel variable (1 << SHIFT_USEC = 16).
+ */
#if defined(KERNEL_PLL)
+ } else if (pll_control && pll_enable) {
+ l_fp pps_offset;
+ u_fp pps_dispersion;
+
+ /*
+ * We initialize the structure for the ntp_adjtime()
+ * system call. We have to convert everything to
+ * microseconds first. Afterwards, remember the
+ * frequency offset for the drift file.
+ */
memset((char *)&ntv, 0, sizeof ntv);
ntv.modes = MOD_BITS;
if (offset >= 0) {
@@ -533,210 +308,310 @@ local_clock(fp_offset, peer)
TSFTOTVU(-offset, ntv.offset);
ntv.offset = -ntv.offset;
}
- TSFTOTVU(sys_rootdispersion + sys_rootdelay / 2, ntv.maxerror);
+ TSFTOTVU(sys_rootdispersion + sys_rootdelay / 2,
+ ntv.maxerror);
TSFTOTVU(sys_rootdispersion, ntv.esterror);
- ntv.status = pll_status;
- if (pps_update)
+ ntv.status = pll_status & (STA_PLL | STA_PPSFREQ);
+ if (pps_update && pll_status & STA_PPSFREQ)
ntv.status |= STA_PPSTIME;
if (sys_leap & LEAP_ADDSECOND &&
- sys_leap & LEAP_DELSECOND)
+ 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;
+ ntv.constant = min(peer->ppoll, sys_poll) - NTP_MINPOLL;
(void)ntp_adjtime(&ntv);
drift_comp = ntv.freq;
- if (ntv.status & STA_PPSTIME && ntv.status & STA_PPSSIGNAL
- && ntv.shift) {
- if (ntv.offset >= 0) {
+ pll_status = ntv.status;
+
+ /*
+ * If the kernel pps discipline is working, monitor its
+ * performance.
+ */
+ if (pll_status & STA_PPSTIME && pll_status &
+ STA_PPSSIGNAL && ntv.shift) {
+ if (ntv.offset >= 0)
TVUTOTSF(ntv.offset, offset);
- } else {
+ 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);
+ L_CLR(&pps_offset);
+ L_ADDF(&pps_offset, offset);
TVUTOTSF(ntv.jitter, tmp);
pps_dispersion = (tmp >> 16) & 0xffff;
- pps_time = current_time;
+ if (!pps_control)
+ syslog(LOG_INFO,
+ "kernel pps sync enabled");
+ pps_control = 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) {
- clock_adjust = -((-offset) >> time_constant);
- } else {
- clock_adjust = offset >> time_constant;
+ ctlsysstatus(), fp_offset, 0,
+ pps_dispersion);
}
+#endif /* KERNEL_PLL */
- /*
- * 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 {
+ /*
+ * If the dispersion exceeds 128 ms, we need to quick-march it
+ * to nominal zero offset and wait for the next update. This is
+ * necessary when the intrinsic frequency error is large and the
+ * clock has drifted during the interval the clock filter was
+ * stabilizing. Note that, if unsynchronized, the dispersion is
+ * always greater than 128 ms, so we don't need a check for
+ * that.
+ */
+ } else if (smax > CLOCK_MAX_FP) {
+ clock_adjust = offset;
+
+ /*
+ * If the dispersion has increased substantially over the
+ * previous value, we have a spike which probably should be
+ * suppressed. A factor of eight has been found reasonable by
+ * simulation.
+ */
+ } else if (smax > sys_maxd << 3) {
+ return (0);
+
+ /*
+ * If the interval between corrections is less than the Allan
+ * variance intercept point, we use a phase-lock loop to compute
+ * new values of time and frequency. The bandwidth is controlled
+ * by the time constant, which is adjusted in response to the
+ * phase error and dispersion. Note the frequency is not changed
+ * if the local clock driver is in control.
+ */
+ } else if (interval < allan) {
+ int time_constant = min(peer->ppoll, sys_poll) -
+ NTP_MINPOLL;
+ int ltmp = interval;
+
+ if (offset < 0)
+ clock_adjust = -(-offset >> time_constant);
+ else
+ clock_adjust = offset >> time_constant;
+ if (interval && !(peer->refclktype ==
+ REFCLK_LOCALCLOCK)) {
tmp = peer->maxpoll;
- tmp_uf = watchdog_timer;
- if (tmp_uf == 0)
- tmp_uf = 1;
- while (tmp_uf < (1 << peer->maxpoll)) {
+ while (ltmp < (1 << peer->maxpoll)) {
tmp--;
- tmp_uf <<= 1;
+ ltmp <<= 1;
}
-
- /*
- * 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;
+ tmp = (RSH_FRAC_TO_FREQ - tmp) + time_constant +
+ time_constant;
if (offset < 0)
- tmp = -((-offset) >> tmp);
+ tmp = -(-offset >> tmp);
else
tmp = offset >> tmp;
drift_comp += tmp;
- if (drift_comp > max_comp)
- drift_comp = max_comp;
- else if (drift_comp < -max_comp)
- drift_comp = -max_comp;
}
+
+ /*
+ * If the interval between corrections is greater than the Allan
+ * variance intercept point, we use a hybrid frequency-lock loop
+ * to compute new values of phase and frequency. The following
+ * code is based on ideas suggested by Judah Levine of NIST and
+ * used in his "lockclock" implementation of ACTS. The magic
+ * factor of 4 in the left shift is to convert from s_fp to ppm.
+ */
+ } else {
+ clock_adjust = offset;
+ stmp = (offset / interval) << 4;
+ if (stmp < 0)
+ drift_comp -= -stmp >> CLOCK_G;
+ else
+ drift_comp += stmp >> CLOCK_G;
}
- watchdog_timer = 0;
/*
- * Determine when to adjust the time constant and poll interval.
+ * As a sanity check, we clamp the frequency not to exceed the
+ * slew rate of the stock Unix adjtime() system call. Finally,
+ * do a little housekeeping.
*/
- 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)
- tmp = -tmp;
- tmp = tmp >> (16 + CLOCK_WEIGHTTC - time_constant);
- if (tmp > sys_maxd) {
- tc_counter = 0;
- time_constant--;
+ if (drift_comp > max_comp)
+ drift_comp = max_comp;
+ else if (drift_comp < -max_comp)
+ drift_comp = -max_comp;
+ if (interval > (1 << (peer->minpoll - 1))) {
+
+ /*
+ * Determine when to adjust the poll interval. We do
+ * this regardless of what source controls the loop,
+ * since we might flap back and forth between sources.
+ */
+ stmp = LFPTOFP(fp_offset);
+ if (stmp < 0)
+ stmp = -stmp;
+ if (stmp > smax) {
+ tc_counter -= (int)sys_poll << 1;
+ if (tc_counter < -CLOCK_LIMIT) {
+ tc_counter = -CLOCK_LIMIT;
+ if (sys_poll > peer->minpoll) {
+ sys_poll--;
+ tc_counter = 0;
+ }
+ }
} else {
- tc_counter++;
- if (tc_counter > CLOCK_HOLDTC) {
- tc_counter = 0;
- time_constant++;
+ tc_counter += (int)sys_poll;
+ if (tc_counter > CLOCK_LIMIT) {
+ tc_counter = CLOCK_LIMIT;
+ if (sys_poll < peer->maxpoll) {
+ sys_poll++;
+ tc_counter = 0;
+ }
}
}
- if (time_constant < (int)(peer->minpoll - NTP_MINPOLL))
- time_constant = peer->minpoll - NTP_MINPOLL;
- if (time_constant > (int)(peer->maxpoll - NTP_MINPOLL))
- time_constant = peer->maxpoll - NTP_MINPOLL;
+
+ /*
+ * Calculate the frequency offset and frequency
+ * stability. These are useful for performance
+ * monitoring, but do not affect the loop variables. The
+ * results are scaled as a s_fp in ppm, because we know
+ * more than we should.
+ */
+ ftmp = *fp_offset;
+ L_SUB(&ftmp, &last_offset);
+ clock_frequency = (LFPTOFP(&ftmp) / interval) << 20;
+ if (clock_frequency < -max_comp)
+ clock_frequency = -max_comp;
+ else if (clock_frequency > max_comp)
+ clock_frequency = max_comp;
+ stmp = clock_frequency;
+ if (stmp < 0)
+ stmp = -stmp;
+ stmp -= clock_stability;
+ if (stmp < 0)
+ clock_stability -= -stmp >> NTP_MAXD;
+ else
+ clock_stability += stmp >> NTP_MAXD;
}
- sys_poll = (u_char)(NTP_MINPOLL + time_constant);
+ last_offset = *fp_offset;
+ last_time = current_time;
#ifdef DEBUG
if (debug > 1)
- printf("adj %s, drft %s, tau %3i\n",
- mfptoa((clock_adjust<0?-1:0), clock_adjust, 6),
- fptoa(drift_comp, 6), time_constant);
+ printf(
+ "local_clock: phase %s freq %s err %s allan %ld poll %d\n",
+ mfptoa((clock_adjust < 0 ? -1 : 0), clock_adjust,
+ 6), fptoa(drift_comp, 3), fptoa(smax, 6), allan,
+ sys_poll);
#endif /* DEBUG */
- (void) record_loop_stats(&last_offset, &drift_comp, time_constant);
+ (void) record_loop_stats(fp_offset, drift_comp, sys_poll);
/*
* Whew. I've had enough.
*/
- return (0);
+ return (return_code);
}
/*
- * adj_host_clock - Called every 2**CLOCK_ADJ seconds to update host clock
+ * adj_host_clock - Called every 1 << CLOCK_ADJ seconds to update host
+ * clock
*/
void
adj_host_clock()
{
- register LONG adjustment;
-#if defined(PPSPPS)
- struct ppsclockev ev;
- l_fp ts;
-#endif /* PPSPPS */
-
- watchdog_timer += (1 << CLOCK_ADJ);
- if (watchdog_timer >= NTP_MAXAGE) {
- first_adjustment = 1; /* don't use next offset for freq */
- }
- if (sys_refskew.l_i >= NTP_MAXSKEW)
- sys_refskew.l_f = 0; /* clamp it */
- else
- L_ADDUF(&sys_refskew, NTP_SKEWINC);
+ register long adjustment;
+ l_fp offset;
-#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
-#if defined(PPSPPS)
/*
- * Note that nothing ugly happens even if the CIOGETEV ioctl is
- * not configured. Correct for signal delays (!) for ultimate
- * finick.
+ * Update the dispersion since the last update. Don't allow
+ * frequency measurements over periods longer than NTP_MAXAGE
+ * (86400 s = one day).
*/
- if (fdpps != -1 && ioctl(fdpps, CIOGETEV, (caddr_t)&ev) >= 0) {
- static int last_serial = 0; /* avoid stale events */
-
- if (last_serial != ev.serial) {
- TVUTOTSF(ev.tv.tv_usec, ts.l_uf);
- ts.l_ui = 0; /* seconds don't matter here */
- L_SUB(&ts, &pps_delay);
- ts.l_uf = ~ts.l_uf; /* map [0.5..1[ into [-0.5..0[ */
- ts.l_ui = (ts.l_f < 0) ? ~0 : 0; /* sign extension */
- (void)pps_sample(&ts);
- last_serial = ev.serial;
- }
- }
-#endif /* PPSPPS */
-#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");
- pps_control = 1;
- } else {
+ if (current_time - last_time > NTP_MAXAGE)
+ last_time = 0;
+ L_ADDUF(&sys_refskew, NTP_SKEWINC);
+
+ /*
+ * Declare PPS kernel unsync if the pps signal has been heard
+ * during the last few minutes.
+ */
+ if (pps_control && current_time - pps_control > PPS_MAXAGE) {
if (pps_control)
- syslog(LOG_INFO, "PPS synch lost");
+ syslog(LOG_INFO, "kernel pps sync disabled");
pps_control = 0;
}
/*
- * Resist the following code if the phase-lock loop has been
- * implemented in the kernel.
+ * If the phase-lock loop is not implemented in the kernel, we
+ * do it the hard way using incremental adjustments and the
+ * adjtime() system call.
*/
- if (pll_control)
+ if (pll_control && pll_enable)
return;
adjustment = clock_adjust;
if (adjustment < 0)
- adjustment = -((-adjustment) >> CLOCK_PHASE);
+ adjustment = -(-adjustment >> CLOCK_PHASE);
else
adjustment >>= CLOCK_PHASE;
clock_adjust -= adjustment;
if (drift_comp < 0)
- adjustment -= ((-drift_comp) >> RSH_DRIFT_TO_ADJ);
+ adjustment -= -drift_comp >> RSH_DRIFT_TO_ADJ;
else
adjustment += drift_comp >> RSH_DRIFT_TO_ADJ;
- { l_fp offset;
- offset.l_i = 0;
- offset.l_f = adjustment;
- adj_systime(&offset);
+ /*
+ * Intricate wrinkle. If the local clock driver is in use and
+ * selected for synchronization, somebody else may be tinker the
+ * adjtime() syscall. In this case we have to avoid calling
+ * adjtime(), since that may truncate the other guy's requests.
+ * That means the local clock fudge time and frequency
+ * adjustments don't work in that case. Caveat empty.
+ */
+ if (sys_peer) {
+ if (sys_peer->refclktype == REFCLK_LOCALCLOCK &&
+ sys_peer->flags & FLAG_PREFER)
+ return;
}
+ L_CLR(&offset);
+ L_ADDF(&offset, adjustment);
+ adj_systime(&offset);
+}
+
+
+/*
+ * adj_frequency - adjust local clock frequency
+ */
+void
+adj_frequency(freq)
+ s_fp freq; /* frequency (ppm) */
+{
+#if defined(KERNEL_PLL)
+ struct timex ntv;
+#endif /* KERNEL_PLL */
+
+ /*
+ * This routine adjusts the frequency offset. It is used by the
+ * local clock driver to adjust frequency when no external
+ * discipline source is available and by the acts driver when
+ * the interval between updates is greater than 1 <<
+ * NTP_MAXPOLL. Note that the maximum offset is limited by
+ * max_comp when the daemon pll is used, but the maximum may be
+ * different when the kernel pll is used.
+ */
+ drift_comp += freq;
+ if (drift_comp > max_comp)
+ drift_comp = max_comp;
+ else if (drift_comp < -max_comp)
+ drift_comp = -max_comp;
+#if defined(KERNEL_PLL)
+ /*
+ * If the phase-lock code is implemented in the kernel, set the
+ * kernel frequency as well, but be sure to set drift_comp to
+ * the actual frequency.
+ */
+ if (!(pll_control && pll_enable))
+ return;
+ memset((char *)&ntv, 0, sizeof ntv);
+ ntv.modes = MOD_FREQUENCY;
+ ntv.freq = freq + drift_comp;
+ (void)ntp_adjtime(&ntv);
+ drift_comp = ntv.freq;
+#endif /* KERNEL_PLL */
}
@@ -749,106 +624,76 @@ loop_config(item, lfp_value, int_value)
l_fp *lfp_value;
int int_value;
{
- s_fp tmp;
#if defined(KERNEL_PLL)
struct timex ntv;
#endif /* KERNEL_PLL */
+#ifdef DEBUG
+ if (debug) {
+ printf("loop_config %d %s %x\n", item,
+ lfptoa(lfp_value, 3), int_value);
+ }
+#endif
switch (item) {
- case LOOP_DRIFTCOMP:
- tmp = LFPTOFP(lfp_value);
- if (tmp >= max_comp || tmp <= -max_comp) {
- syslog(LOG_ERR,
- "loop_config: frequency offset %s in ntp.conf file is too large",
- fptoa(tmp, 5));
- } else {
- drift_comp = tmp;
+
+ case LOOP_DRIFTCOMP:
+ drift_comp = LFPTOFP(lfp_value);
+ if (drift_comp > max_comp)
+ drift_comp = max_comp;
+ if (drift_comp < -max_comp)
+ drift_comp = -max_comp;
#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. We do this
+ * whether or not the use of the kernel mods is
+ * requested, in order to clear out the trash from
+ * possible prior customers.
+ */
+ memset((char *)&ntv, 0, sizeof ntv);
+ pll_status = int_value & (STA_PLL | STA_PPSFREQ);
+ if (pll_status & STA_PLL)
pll_control = 1;
- pll_status = STA_PLL | STA_PPSFREQ;
- ntv.modes = MOD_BITS | MOD_FREQUENCY;
- ntv.offset = 0;
+ else
+ pll_control = 0;
+ ntv.modes = MOD_BITS | MOD_FREQUENCY;
+ if (pll_status) {
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;
- if ((sigvec(SIGSYS, &newsigsys, &sigsys)))
- syslog(LOG_ERR,
- "sigvec() fails to save SIGSYS trap: %m\n");
- (void)ntp_adjtime(&ntv);
- if ((sigvec(SIGSYS, &sigsys, (struct sigvec *)NULL)))
- syslog(LOG_ERR,
- "sigvec() fails to restore SIGSYS trap: %m\n");
- 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 */
-
+ ntv.constant = sys_poll - NTP_MINPOLL;
}
+ newsigsys.sv_handler = pll_trap;
+ newsigsys.sv_mask = 0;
+ newsigsys.sv_flags = 0;
+ if ((sigvec(SIGSYS, &newsigsys, &sigsys)))
+ syslog(LOG_ERR,
+ "sigvec() fails to save SIGSYS trap: %m");
+ (void)ntp_adjtime(&ntv);
+ if ((sigvec(SIGSYS, &sigsys,
+ (struct sigvec *)NULL)))
+ syslog(LOG_ERR,
+ "sigvec() fails to restore SIGSYS trap: %m");
+ 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 */
break;
-
- case LOOP_PPSDELAY:
- pps_delay = *lfp_value;
- break;
-
-#if defined(PPSCLK)
- case LOOP_PPSBAUD:
-#if defined(HAVE_TERMIOS)
- /*
- * System V TERMIOS serial line parameters
- * (termios interface)
- */
- { struct termios ttyb, *ttyp;
- if (fdpps == -1)
- return;
-
- ttyp = &ttyb;
- if (tcgetattr(fdpps, ttyp) < 0)
- return;
- ttyp->c_cflag = CS8|CLOCAL|CREAD | int_value;
- if (tcsetattr(fdpps, TCSANOW, ttyp) < 0)
- return;
- }
-#endif /* HAVE_TERMIOS */
-#if defined(HAVE_BSD_TTYS)
-
- /*
- * 4.3bsd serial line parameters (sgttyb interface)
- */
- { struct sgttyb ttyb;
-
- if (fdpps == -1 || ioctl(fdpps, TIOCGETP, &ttyb) < 0)
- return;
- ttyb.sg_ispeed = ttyb.sg_ospeed = SYS_BAUD(int_value);
- if (ioctl(fdpps, TIOCSETP, &ttyb) < 0)
- return;
- }
-#endif /* HAVE_BSD_TTYS */
- pps_baud = int_value;
- break;
-#endif /* PPSCLK */
- default:
+ default:
/* sigh */
break;
}
}
+
#if defined(KERNEL_PLL)
/*
* _trap - trap processor for undefined syscalls
@@ -865,128 +710,3 @@ pll_trap()
}
#endif /* KERNEL_PLL */
-#if defined(PPSCLK)
-/*
- * pps_receive - compute and store 1-pps signal offset
- *
- * This routine is called once per second when the 1-pps signal is
- * present. It calculates the offset of the local clock relative to the
- * 1-pps signal and saves in a circular buffer for later use. If the
- * clock line discipline is active, its timestamp is used; otherwise,
- * the buffer timestamp is used.
- */
-static void
-pps_receive(rbufp)
- struct recvbuf *rbufp;
-{
- u_char *dpt; /* buffer pointer */
- l_fp ts; /* l_fp temps */
- int dpend; /* buffer length */
-
- /*
- * Set up pointers, check the buffer length, discard intercept
- * character and convert unix timeval to timestamp format.
- */
- dpt = (u_char *)&rbufp->recv_space;
- dpend = rbufp->recv_length;
-#if !defined(HPUXGADGET)
- dpt++;
- dpend--;
-#endif /* HPUXGADGET */
- if (dpend != sizeof(struct timeval) || !buftvtots((char *)dpt, &ts))
- ts = rbufp->recv_time;
-
- /*
- * Correct for uart and os delay and process sample offset.
- */
- L_SUB(&ts, &pps_delay);
- L_NEG(&ts);
- (void)pps_sample(&ts);
-}
-#endif /* PPSCLK */
-
-#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS)
-/*
- * pps_sample - process pps sample offset
- */
-int pps_sample(tsr)
- l_fp *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.
- */
- ts = *tsr;
- lftemp.l_i = lftemp.l_f = 0;
- M_ADDF(lftemp.l_i, lftemp.l_f, ts.l_f);
- if (ts.l_f <= -CLOCK_MAX_F || ts.l_f >= CLOCK_MAX_F) {
- pps_time = 0;
- return (-1);
- }
-
- /*
- * Save the sample in a circular buffer for later processing.
- */
- nsamples++;
- i = ((int)(nsamples)) % NPPS;
- samples[i] = lftemp.l_f;
- if (i != NPPS-1)
- return (0);
-
- /*
- * When the buffer fills up, construct an array of sorted
- * samples.
- */
- pps_time = current_time;
- for (i = 0; i < NPPS; i++) {
- sort[i] = samples[i];
- for (j = 0; j < i; j++) {
- if (sort[j] > sort[i]) {
- ltemp = sort[j];
- sort[j] = sort[i];
- sort[i] = ltemp;
- }
- }
- }
-
- /*
- * Compute offset as the average of all samples in the filter
- * less PPS_TRIM samples trimmed from the beginning and end,
- * dispersion as the difference between max and min of samples
- * retained. The system stratum, root delay and root dispersion
- * are also set here.
- */
- pps_offset.l_i = pps_offset.l_f = 0;
- for (i = PPS_TRIM; i < NPPS - PPS_TRIM; i++)
- M_ADDF(pps_offset.l_i, pps_offset.l_f, sort[i]);
- if (L_ISNEG(&pps_offset)) {
- L_NEG(&pps_offset);
- for (i = 0; i < PPS_FAC; i++)
- L_RSHIFT(&pps_offset);
- L_NEG(&pps_offset);
- } else {
- for (i = 0; i < PPS_FAC; i++)
- L_RSHIFT(&pps_offset);
- }
- lftemp.l_i = 0;
- lftemp.l_f = sort[NPPS-1-PPS_TRIM] - sort[PPS_TRIM];
- 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, 0, pps_dispersion);
- return (0);
-}
-#endif /* PPS || PPSCLK || PPSPPS */
-
diff --git a/usr.sbin/xntpd/xntpd/ntp_monitor.c b/usr.sbin/xntpd/xntpd/ntp_monitor.c
index e2d2eb51adac..55bd5d542b90 100644
--- a/usr.sbin/xntpd/xntpd/ntp_monitor.c
+++ b/usr.sbin/xntpd/xntpd/ntp_monitor.c
@@ -1,6 +1,7 @@
-/* ntp_monitor.c,v 3.1 1993/07/06 01:11:21 jbj Exp
+/*
* ntp_monitor.c - monitor who is using the xntpd server
*/
+#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
@@ -33,6 +34,8 @@
* hit the memory limit. Then we free memory by grabbing entries off
* the tail for the MRU list, unlinking from the hash table, and
* reinitializing.
+ *
+ * trimmed back memory consumption ... jdg 8/94
*/
/*
@@ -40,9 +43,15 @@
* with the illicit knowlege that we can only return somewhat less
* than 8K bytes in a mode 7 response packet, and that each structure
* will require about 20 bytes of space in the response.
+ *
+ * ... I don't believe the above is true anymore ... jdg
*/
-#define MAXMONMEM 400 /* we allocate up to 400 structures */
+#ifndef MAXMONMEM
+#define MAXMONMEM 600 /* we allocate up to 400 structures */
+#endif
+#ifndef MONMEMINC
#define MONMEMINC 40 /* allocate them 40 at a time */
+#endif
/*
* Hashing stuff
@@ -55,17 +64,15 @@
* Pointers to the hash table, the MRU list and the count table. Memory
* for the hash and count tables is only allocated if monitoring is turned on.
*/
-static struct mon_data *mon_hash; /* Pointer to array of hash buckets */
-static int *mon_hash_count; /* Point to hash count stats keeper */
+static struct mon_data *mon_hash[MON_HASH_SIZE]; /* array of list ptrs */
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.
*/
-static struct mon_data *mon_free;
+static struct mon_data *mon_free; /* the free list or null if none */
-static int mon_free_mem; /* number of structures on free list */
static int mon_total_mem; /* total number of structures allocated */
static int mon_mem_increments; /* number of times we've called malloc() */
@@ -79,9 +86,10 @@ static int mon_have_memory;
/*
* Imported from the timer module
*/
-extern U_LONG current_time;
+extern u_long current_time;
static void mon_getmoremem P((void));
+static void remove_from_hash P((struct mon_data *));
/*
* init_mon - initialize monitoring global data
@@ -96,12 +104,10 @@ init_mon()
mon_enabled = MON_OFF;
mon_have_memory = 0;
- mon_free_mem = 0;
mon_total_mem = 0;
mon_mem_increments = 0;
- mon_free = 0;
- mon_hash = 0;
- mon_hash_count = 0;
+ mon_free = NULL;
+ memset((char *)&mon_hash[0], 0, sizeof mon_hash);
memset((char *)&mon_mru_list, 0, sizeof mon_mru_list);
memset((char *)&mon_fifo_list, 0, sizeof mon_fifo_list);
}
@@ -114,8 +120,6 @@ void
mon_start(mode)
int mode;
{
- register struct mon_data *md;
- register int i;
if (mon_enabled != MON_OFF) {
mon_enabled |= mode;
@@ -125,26 +129,13 @@ mon_start(mode)
return; /* Ooops.. */
if (!mon_have_memory) {
- mon_hash = (struct mon_data *)
- emalloc(MON_HASH_SIZE * sizeof(struct mon_data));
- memset((char *)mon_hash, 0,
- MON_HASH_SIZE*sizeof(struct mon_data));
- mon_hash_count = (int *)emalloc(MON_HASH_SIZE * sizeof(int));
- mon_free_mem = 0;
mon_total_mem = 0;
mon_mem_increments = 0;
- mon_free = 0;
+ mon_free = NULL;
mon_getmoremem();
mon_have_memory = 1;
}
- md = mon_hash;
- for (i = 0; i < MON_HASH_SIZE; i++, md++) {
- md->hash_next = md;
- md->hash_prev = md;
- *(mon_hash_count + i) = 0;
- }
-
mon_mru_list.mru_next = &mon_mru_list;
mon_mru_list.mru_prev = &mon_mru_list;
@@ -162,7 +153,7 @@ void
mon_stop(mode)
int mode;
{
- register struct mon_data *md;
+ register struct mon_data *md, *md_next;
register int i;
if (mon_enabled == MON_OFF)
@@ -177,15 +168,14 @@ mon_stop(mode)
/*
* Put everything back on the free list
*/
- md = mon_hash;
- for (i = 0; i < MON_HASH_SIZE; i++, md++) {
- if (md->hash_next != md) {
- md->hash_prev->hash_next = mon_free;
- mon_free = md->hash_next;
- mon_free_mem += *(mon_hash_count + i);
- md->hash_next = md;
- md->hash_prev = md;
- *(mon_hash_count + i) = 0;
+ for (i = 0; i < MON_HASH_SIZE; i++) {
+ md = mon_hash[i]; /* get next list */
+ mon_hash[i] = NULL; /* zero the list head */
+ while (md != NULL) {
+ md_next = md->hash_next;
+ md->hash_next = mon_free;
+ mon_free = md;
+ md = md_next;
}
}
@@ -206,10 +196,9 @@ monitor(rbufp)
{
register struct pkt *pkt;
register struct mon_data *md;
- register U_LONG netnum;
+ register u_long netnum;
register int hash;
register int mode;
- register struct mon_data *mdhash;
if (mon_enabled == MON_OFF)
return;
@@ -219,9 +208,11 @@ monitor(rbufp)
hash = MON_HASH(netnum);
mode = PKT_MODE(pkt->li_vn_mode);
- md = (mon_hash + hash)->hash_next;
- while (md != (mon_hash + hash)) {
- if (md->rmtadr == netnum && md->mode == (u_char)mode) {
+ md = mon_hash[hash];
+ while (md != NULL) {
+ if (md->rmtadr == netnum &&
+ /* ?? md->interface == rbufp->dstadr && ?? */
+ md->mode == (u_char)mode) {
md->lasttime = current_time;
md->count++;
md->version = PKT_VERSION(pkt->li_vn_mode);
@@ -248,16 +239,16 @@ monitor(rbufp)
* guy. Get him some memory, either from the free list
* or from the tail of the MRU list.
*/
- if (mon_free_mem == 0 && mon_total_mem >= MAXMONMEM) {
+ if (mon_free == NULL && mon_total_mem >= MAXMONMEM) {
/*
* Get it from MRU list
*/
md = mon_mru_list.mru_prev;
md->mru_prev->mru_next = &mon_mru_list;
mon_mru_list.mru_prev = md->mru_prev;
- md->hash_next->hash_prev = md->hash_prev;
- md->hash_prev->hash_next = md->hash_next;
- *(mon_hash_count + MON_HASH(md->rmtadr)) -= 1;
+
+ remove_from_hash(md);
+
/*
* Get it from FIFO list
*/
@@ -265,11 +256,10 @@ monitor(rbufp)
md->fifo_next->fifo_prev = md->fifo_prev;
} else {
- if (mon_free_mem == 0)
- mon_getmoremem();
+ if (mon_free == NULL) /* if free list empty */
+ mon_getmoremem(); /* then get more */
md = mon_free;
mon_free = md->hash_next;
- mon_free_mem--;
}
/*
@@ -282,18 +272,19 @@ monitor(rbufp)
md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
md->mode = (u_char) mode;
md->version = PKT_VERSION(pkt->li_vn_mode);
+ md->interface = rbufp->dstadr;
+ md->cast_flags = ((rbufp->dstadr->flags & INT_MULTICAST) &&
+ rbufp->fd == md->interface->fd) ? MDF_MCAST: rbufp->fd ==
+ md->interface->bfd ? MDF_BCAST : MDF_UCAST;
/*
- * Shuffle him into the hash table, inserting him at the
- * end. Also put him on top of the MRU list
+ * Drop him into front of the hash table.
+ * 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;
- md->hash_prev = mdhash->hash_prev;
- mdhash->hash_prev->hash_next = md;
- mdhash->hash_prev = md;
- *(mon_hash_count + MON_HASH(netnum)) += 1;
+
+ md->hash_next = mon_hash[hash];
+ mon_hash[hash] = md;
md->mru_next = mon_mru_list.mru_next;
md->mru_prev = &mon_mru_list;
@@ -315,7 +306,7 @@ mon_getmoremem()
{
register struct mon_data *md;
register int i;
- struct mon_data *freedata;
+ struct mon_data *freedata; /* 'old' free list (null) */
md = (struct mon_data *)emalloc(MONMEMINC * sizeof(struct mon_data));
freedata = mon_free;
@@ -331,7 +322,28 @@ mon_getmoremem()
*/
md->hash_next = freedata;
- mon_free_mem += MONMEMINC;
mon_total_mem += MONMEMINC;
mon_mem_increments++;
}
+
+static void
+remove_from_hash(md)
+struct mon_data *md;
+{ register int hash;
+ register struct mon_data *md_prev;
+
+ hash = MON_HASH(md->rmtadr);
+ if (mon_hash[hash] == md) {
+ mon_hash[hash] = md->hash_next;
+ } else {
+ md_prev = mon_hash[hash];
+ while (md_prev->hash_next != md) {
+ md_prev = md_prev->hash_next;
+ if (md_prev == NULL) {
+ /* logic error */
+ return;
+ }
+ }
+ md_prev->hash_next = md->hash_next;
+ }
+}
diff --git a/usr.sbin/xntpd/xntpd/ntp_peer.c b/usr.sbin/xntpd/xntpd/ntp_peer.c
index 9d8ec35dee78..389cc2c75671 100644
--- a/usr.sbin/xntpd/xntpd/ntp_peer.c
+++ b/usr.sbin/xntpd/xntpd/ntp_peer.c
@@ -1,4 +1,4 @@
-/* ntp_peer.c,v 3.1 1993/07/06 01:11:22 jbj Exp
+/*
* ntp_peer.c - management of data maintained for peer associations
*/
#include <stdio.h>
@@ -49,11 +49,11 @@ u_short current_association_ID;
/*
* Miscellaneous statistic counters which may be queried.
*/
-U_LONG peer_timereset; /* time stat counters were zeroed */
-U_LONG findpeer_calls; /* number of calls to findpeer */
-U_LONG assocpeer_calls; /* number of calls to findpeerbyassoc */
-U_LONG peer_allocations; /* number of allocations from the free list */
-U_LONG peer_demobilizations; /* number of structs freed to free list */
+u_long peer_timereset; /* time stat counters were zeroed */
+u_long findpeer_calls; /* number of calls to findpeer */
+u_long assocpeer_calls; /* number of calls to findpeerbyassoc */
+u_long peer_allocations; /* number of allocations from the free list */
+u_long peer_demobilizations; /* number of structs freed to free list */
int total_peer_structs; /* number of peer structs in circulation */
/*
@@ -64,7 +64,7 @@ extern struct interface *any_interface;
/*
* Timer queue and current time. Imported from the timer module.
*/
-extern U_LONG current_time;
+extern u_long current_time;
extern struct event timerqueue[];
/*
@@ -77,7 +77,7 @@ static struct peer init_peer_alloc[INIT_PEER_ALLOC];
* we try to get their poll update timers initialized to different values
* to prevent us from sending big clumps of data all at once.
*/
-U_LONG init_peer_starttime;
+u_long init_peer_starttime;
extern int initializing;
extern int debug;
@@ -192,12 +192,14 @@ findexistingpeer(addr, start_peer)
* findpeer - find and return a peer in the hash table.
*/
struct peer *
-findpeer(srcadr, dstadr)
+findpeer(srcadr, dstadr, fd)
struct sockaddr_in *srcadr;
struct interface *dstadr;
+ int fd;
{
register struct peer *any_inter_peer;
register struct peer *peer;
+ register struct peer *best = (struct peer *) 0;
int hash;
findpeer_calls++;
@@ -207,9 +209,16 @@ findpeer(srcadr, dstadr)
for (peer = peer_hash[hash]; peer != 0; peer = peer->next) {
if (NSRCADR(srcadr) == NSRCADR(&peer->srcadr)
&& NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
- if (peer->dstadr == dstadr)
- return peer; /* got it! */
+ if (peer->dstadr == dstadr) {
+ int rfd = (peer->cast_flags & MDF_BCAST) ?
+ dstadr->bfd : dstadr->fd;
+
+ if (rfd == fd)
+ return peer; /* got it! */
+ best = peer;
+ }
if (peer->dstadr == any_interface) {
+
/*
* We shouldn't have more than one
* instance of the peer in the table,
@@ -223,9 +232,22 @@ findpeer(srcadr, dstadr)
"two instances of default interface for %s in hash table",
ntoa(srcadr));
}
+
+ /*
+ * Multicast hacks to determine peer when a
+ * packet arrives and there exists an assoc.
+ * with src in client/server mode
+ */
+ if (((dstadr == any_interface) || (peer->cast_flags &
+ MDF_MCAST)) && peer->flags & FLAG_MCAST2)
+ return peer;
}
}
+ if(best) {
+ return best;
+ }
+
/*
* If we didn't find the specific peer but found a wild card,
* modify the interface and return him.
@@ -349,13 +371,13 @@ peer_config(srcadr, dstadr, hmode, version, minpoll, maxpoll, flags, ttl, key)
int maxpoll;
int flags;
int ttl;
- U_LONG key;
+ u_long key;
{
register struct peer *peer;
#ifdef DEBUG
if (debug)
- printf("peer_config: addr %s mode %d version %d minpoll %d maxpoll %d flags %d ttl %d key %u\n",
+ printf("peer_config: addr %s mode %d version %d minpoll %d maxpoll %d flags %d ttl %d key %lu\n",
ntoa(srcadr), hmode, version, minpoll, maxpoll, flags,
ttl, key);
#endif
@@ -387,8 +409,10 @@ peer_config(srcadr, dstadr, hmode, version, minpoll, maxpoll, flags, ttl, key)
peer->maxpoll = (u_char)maxpoll;
peer->hpoll = peer->minpoll;
peer->ppoll = peer->minpoll;
- peer->flags = ((u_char)(flags|FLAG_CONFIG))
- |(peer->flags & (FLAG_REFCLOCK|FLAG_DEFBDELAY));
+ peer->flags = ((u_char)(flags | FLAG_CONFIG)) |
+ (peer->flags & FLAG_REFCLOCK);
+ peer->cast_flags = (hmode == MODE_BROADCAST) ?
+ IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)) ? MDF_MCAST : MDF_BCAST : MDF_UCAST;
peer->ttl = (u_char)ttl;
peer->keyid = key;
return peer;
@@ -418,7 +442,7 @@ newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, ttl, key)
int minpoll;
int maxpoll;
int ttl;
- U_LONG key;
+ u_long key;
{
register struct peer *peer;
register int i;
@@ -427,8 +451,8 @@ newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, ttl, key)
* Some dirt here. Some of the initialization requires
* knowlege of our system state.
*/
- extern U_LONG sys_bdelay;
- extern LONG sys_clock;
+ extern s_fp sys_bdelay;
+ extern long sys_clock;
if (peer_free_count == 0)
getmorepeermem();
@@ -453,6 +477,11 @@ newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, ttl, key)
peer->dstadr = findbcastinter(srcadr);
else
peer->dstadr = any_interface;
+ peer->cast_flags = (hmode == MODE_BROADCAST) ?
+ (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr))) ? MDF_MCAST : MDF_BCAST :
+ (hmode == MODE_BCLIENT || hmode == MODE_MCLIENT) ?
+ (peer->dstadr->flags & INT_MULTICAST) ? MDF_MCAST : MDF_BCAST :
+ MDF_UCAST;
peer->hmode = (u_char)hmode;
peer->version = (u_char)version;
peer->minpoll = (u_char)minpoll;
@@ -462,7 +491,6 @@ newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll, ttl, key)
peer->ttl = ttl;
peer->keyid = key;
peer->estbdelay = sys_bdelay;
- peer->flags |= FLAG_DEFBDELAY;
peer->leap = LEAP_NOTINSYNC;
peer->precision = DEFPRECISION;
peer->dispersion = NTP_MAXDISPERSE;
@@ -616,8 +644,6 @@ peer_reset(peer)
peer->processed = 0;
peer->badauth = 0;
peer->bogusorg = 0;
- peer->bogusrec = 0;
- peer->bogusdelay = 0;
peer->oldpkt = 0;
peer->seldisptoolarge = 0;
peer->selbroken = 0;
diff --git a/usr.sbin/xntpd/xntpd/ntp_proto.c b/usr.sbin/xntpd/xntpd/ntp_proto.c
index a3f744eae881..7889d9315e47 100644
--- a/usr.sbin/xntpd/xntpd/ntp_proto.c
+++ b/usr.sbin/xntpd/xntpd/ntp_proto.c
@@ -1,4 +1,4 @@
-/* ntp_proto.c,v 3.1 1993/07/06 01:11:23 jbj Exp
+/*
* ntp_proto.c - NTP version 3 protocol machinery
*/
#include <stdio.h>
@@ -10,50 +10,51 @@
#include "ntp_unixtime.h"
/*
- * System variables are declared here. See Section 3.2 of
- * the specification.
+ * System variables are declared here. See Section 3.2 of the
+ * specification.
*/
u_char sys_leap; /* system leap indicator */
u_char sys_stratum; /* stratum of system */
s_char sys_precision; /* local clock precision */
s_fp sys_rootdelay; /* distance to current sync source */
u_fp sys_rootdispersion; /* dispersion of system clock */
-U_LONG sys_refid; /* reference source for local clock */
+u_long sys_refid; /* reference source for local clock */
l_fp sys_offset; /* combined offset from clock_select */
u_fp sys_maxd; /* dispersion of selected peer */
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 */
-extern LONG sys_clock; /* second part of current time - now in systime.c */
-LONG sys_lastselect; /* sys_clock at last synch-dist update */
+struct peer *sys_peer; /* our current peer */
+u_char sys_poll; /* log2 of system poll interval */
+extern long sys_clock; /* second part of current time */
+long sys_lastselect; /* sys_clock at last synch update */
/*
- * Non-specified system state variables.
+ * Nonspecified system state variables.
*/
int sys_bclient; /* we set our time to broadcasts */
-U_LONG sys_bdelay; /* default delay to use for broadcasting */
+s_fp sys_bdelay; /* broadcast client default delay */
int sys_authenticate; /* authenticate time used for syncing */
-
-U_LONG sys_authdelay; /* ts fraction, time it takes for encrypt() */
+u_char consensus_leap; /* mitigated leap bits */
+u_long sys_authdelay; /* encryption time (l_fp fraction) */
+u_char leap_consensus; /* consensus of survivor leap bits */
/*
* Statistics counters
*/
-U_LONG sys_stattime; /* time when we started recording */
-U_LONG sys_badstratum; /* packets with invalid incoming stratum */
-U_LONG sys_oldversionpkt; /* old version packets received */
-U_LONG sys_newversionpkt; /* new version packets received */
-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_limitrejected; /* pkts rejected due toclient count per net */
+u_long sys_stattime; /* time when we started recording */
+u_long sys_badstratum; /* packets with invalid stratum */
+u_long sys_oldversionpkt; /* old version packets received */
+u_long sys_newversionpkt; /* new version packets received */
+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 auth */
+u_long sys_limitrejected; /* pkts rejected due toclient count per net */
/*
* Imported from ntp_timer.c
*/
-extern U_LONG current_time;
+extern u_long current_time;
extern struct event timerqueue[];
/*
@@ -64,11 +65,16 @@ extern struct interface *any_interface;
/*
* Imported from ntp_loopfilter.c
*/
-extern int pps_control;
-extern U_LONG pps_update;
+extern int pll_enable;
+extern int pps_update;
+
+/*
+ * Imported from ntp_util.c
+ */
+extern int stats_control;
/*
- * The peer hash table. Imported from ntp_peer.c
+ * The peer hash table. Imported from ntp_peer.c
*/
extern struct peer *peer_hash[];
extern int peer_hash_count[];
@@ -81,18 +87,40 @@ extern int debug;
static void clear_all P((void));
/*
- * transmit - Transmit Procedure. See Section 3.4.1 of the specification.
+ * transmit - Transmit Procedure. See Section 3.4.1 of the
+ * specification.
*/
void
transmit(peer)
register struct peer *peer;
{
struct pkt xpkt; /* packet to send */
- U_LONG peer_timer;
+ u_long peer_timer;
+ u_fp precision;
+ int bool;
- if ((peer->hmode != MODE_BROADCAST && peer->hmode != MODE_BCLIENT) ||
- (peer->hmode == MODE_BROADCAST && sys_leap != LEAP_NOTINSYNC)) {
- U_LONG xkeyid;
+ /*
+ * We need to be very careful about honking uncivilized time. If
+ * not operating in broadcast mode, honk in all except broadcast
+ * client mode. If operating in broadcast mode and synchronized
+ * to a real source, honk except when the peer is the local-
+ * clock driver and the prefer flag is not set. In other words,
+ * in broadcast mode we never honk unless known to be
+ * synchronized to real time.
+ */
+ bool = 0;
+ if (peer->hmode != MODE_BROADCAST) {
+ if (peer->hmode != MODE_BCLIENT)
+ bool = 1;
+ } else if (sys_peer != 0 && sys_leap != LEAP_NOTINSYNC) {
+ if (!(sys_peer->refclktype == REFCLK_LOCALCLOCK &&
+ !(sys_peer->flags & FLAG_PREFER)))
+ bool = 1;
+ }
+ if (bool) {
+ u_long xkeyid;
+ int find_rtt = (peer->cast_flags & MDF_MCAST) &&
+ peer->hmode != MODE_BROADCAST;
/*
* Figure out which keyid to include in the packet
@@ -108,38 +136,43 @@ transmit(peer)
/*
* Make up a packet to send.
*/
- xpkt.li_vn_mode
- = PKT_LI_VN_MODE(sys_leap, peer->version, peer->hmode);
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
+ peer->version, peer->hmode);
xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
xpkt.ppoll = peer->hpoll;
xpkt.precision = sys_precision;
xpkt.rootdelay = HTONS_FP(sys_rootdelay);
- xpkt.rootdispersion =
- HTONS_FP(sys_rootdispersion +
- (FP_SECOND >> (-(int)sys_precision)) +
- LFPTOFP(&sys_refskew));
+ precision = FP_SECOND >> -(int)sys_precision;
+ if (precision == 0)
+ precision = 1;
+ xpkt.rootdispersion = HTONS_FP(sys_rootdispersion +
+ precision + LFPTOFP(&sys_refskew));
xpkt.refid = sys_refid;
HTONL_FP(&sys_reftime, &xpkt.reftime);
HTONL_FP(&peer->org, &xpkt.org);
HTONL_FP(&peer->rec, &xpkt.rec);
/*
- * Decide whether to authenticate or not. If so, call encrypt()
- * to fill in the rest of the frame. If not, just add in the
- * xmt timestamp and send it quick.
+ * Decide whether to authenticate or not. If so, call
+ * encrypt() to fill in the rest of the frame. If not,
+ * just add in the xmt timestamp and send it quick.
*/
if (peer->flags & FLAG_AUTHENABLE) {
int sendlen;
xpkt.keyid = htonl(xkeyid);
- auth1crypt(xkeyid, (U_LONG *)&xpkt, LEN_PKT_NOMAC);
+ auth1crypt(xkeyid, (U_LONG *)&xpkt,
+ LEN_PKT_NOMAC);
get_systime(&peer->xmt);
L_ADDUF(&peer->xmt, sys_authdelay);
HTONL_FP(&peer->xmt, &xpkt.xmt);
sendlen = auth2crypt(xkeyid, (U_LONG *)&xpkt,
LEN_PKT_NOMAC);
- sendpkt(&(peer->srcadr), peer->dstadr, &xpkt,
- sendlen + LEN_PKT_NOMAC);
+ sendpkt(&peer->srcadr, find_rtt ?
+ any_interface : peer->dstadr,
+ ((peer->cast_flags & MDF_MCAST) && !find_rtt) ?
+ peer->ttl : -7, &xpkt, sendlen +
+ LEN_PKT_NOMAC);
#ifdef DEBUG
if (debug > 1)
printf("transmit auth to %s\n",
@@ -148,15 +181,21 @@ transmit(peer)
peer->sent++;
} else {
/*
- * Get xmt timestamp, then send it without mac field
+ * Get xmt timestamp, then send it without mac
+ * field
*/
+ int find_rtt = (peer->cast_flags & MDF_MCAST) &&
+ peer->dstadr != any_interface;
get_systime(&(peer->xmt));
HTONL_FP(&peer->xmt, &xpkt.xmt);
- sendpkt(&(peer->srcadr), peer->dstadr, &xpkt,
- LEN_PKT_NOMAC);
+ sendpkt(&(peer->srcadr), find_rtt ?
+ any_interface : peer->dstadr,
+ ((peer->cast_flags & MDF_MCAST) && !find_rtt) ?
+ peer->ttl : -8, &xpkt, LEN_PKT_NOMAC);
#ifdef DEBUG
if (debug > 1)
- printf("transmit to %s\n", ntoa(&(peer->srcadr)));
+ printf("transmit to %s\n",
+ ntoa(&(peer->srcadr)));
#endif
peer->sent++;
}
@@ -166,40 +205,49 @@ transmit(peer)
u_char opeer_reach;
/*
* Determine reachability and diddle things if we
- * haven't heard from the host for a while.
+ * haven't heard from the host for a while. If we are
+ * about to become unreachable and are a
+ * broadcast/multicast client, the server has refused to
+ * boogie in client/server mode, so we switch to
+ * MODE_BCLIENT anyway and wait for subsequent
+ * broadcasts.
*/
opeer_reach = peer->reach;
+ if (opeer_reach & 0x80 && peer->flags & FLAG_MCAST2) {
+ peer->hmode = MODE_BCLIENT;
+ }
peer->reach <<= 1;
if (peer->reach == 0) {
if (opeer_reach != 0)
report_event(EVNT_UNREACH, peer);
/*
* Clear this guy out. No need to redo clock
- * selection since by now this guy won't be a player
+ * selection since by now this guy won't be a
+ * player
*/
if (peer->flags & FLAG_CONFIG) {
if (opeer_reach != 0) {
peer_clear(peer);
- peer->timereachable = current_time;
+ peer->timereachable =
+ current_time;
}
- } else {
- unpeer(peer);
- return;
}
/*
- * While we have a chance, if our system peer
- * is zero or his stratum is greater than the
- * last known stratum of this guy, make sure
- * hpoll is clamped to the minimum before
- * resetting the timer.
- * If the peer has been unreachable for a while
- * and we have a system peer who is at least his
- * equal, we may want to ramp his polling interval
- * up to avoid the useless traffic.
+ * While we have a chance, if our system peer is
+ * zero or his stratum is greater than the last
+ * known stratum of this guy, make sure hpoll is
+ * clamped to the minimum before resetting the
+ * timer. If the peer has been unreachable for a
+ * while and we have a system peer who is at
+ * least his equal, we may want to ramp his
+ * polling interval up to avoid the useless
+ * traffic.
*/
- if (sys_peer == 0
- || sys_peer->stratum > peer->stratum) {
+ if (sys_peer == 0) {
+ peer->hpoll = peer->minpoll;
+ peer->unreach = 0;
+ } else if (sys_peer->stratum > peer->stratum) {
peer->hpoll = peer->minpoll;
peer->unreach = 0;
} else {
@@ -223,8 +271,9 @@ transmit(peer)
peer->valid--;
if (peer->hpoll > peer->minpoll)
peer->hpoll--;
- off.l_ui = off.l_uf = 0;
- clock_filter(peer, &off, (s_fp)0, (u_fp)NTP_MAXDISPERSE);
+ L_CLR(&off);
+ clock_filter(peer, &off, (s_fp)0,
+ (u_fp)NTP_MAXDISPERSE);
if (peer->flags & FLAG_SYSPEER)
clock_select();
} else {
@@ -238,24 +287,34 @@ transmit(peer)
}
/*
- * Finally, adjust the hpoll variable for special conditions.
+ * Finally, adjust the hpoll variable for special conditions. If
+ * we are a broadcast/multicast client, we use the server poll
+ * interval if listening for broadcasts and one-eighth this
+ * interval if in client/server mode. The following clamp
+ * prevents madness. If this is the system poll, sys_poll
+ * controls hpoll.
*/
- 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->flags & FLAG_MCAST2) {
+ if (peer->hmode == MODE_BCLIENT)
+ peer->hpoll = peer->ppoll;
+ else
+ peer->hpoll = peer->ppoll - 3;
+ } else if (peer->flags & FLAG_SYSPEER)
+ peer->hpoll = sys_poll;
+ if (peer->hpoll < peer->minpoll)
+ peer->hpoll = peer->minpoll;
/*
- * Arrange for our next timeout. hpoll will be less than
- * maxpoll for sure.
+ * Arrange for our next timeout. hpoll will be less than maxpoll
+ * for sure.
*/
if (peer->event_timer.next != 0)
/*
* Oops, someone did already.
*/
TIMER_DEQUEUE(&peer->event_timer);
- peer_timer = 1 << (int)max((u_char)min(peer->ppoll, peer->hpoll), peer->minpoll);
+ peer_timer = 1 << (int)max((u_char)min(peer->ppoll,
+ peer->hpoll), peer->minpoll);
peer->event_timer.event_time = current_time + peer_timer;
TIMER_ENQUEUE(timerqueue, &peer->event_timer);
}
@@ -274,7 +333,7 @@ receive(rbufp)
int has_mac;
int trustable;
int is_authentic;
- U_LONG hiskeyid;
+ u_long hiskeyid;
struct peer *peer2;
#ifdef DEBUG
@@ -313,7 +372,7 @@ receive(rbufp)
}
/*
- * Catch private mode packets. Dump it if queries not allowed.
+ * Catch private mode packets. Dump it if queries not allowed.
*/
if (PKT_MODE(pkt->li_vn_mode) == MODE_PRIVATE) {
if (restrict & RES_NOQUERY)
@@ -340,16 +399,16 @@ 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()
+ * 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;
+ extern u_long client_limit;
sys_limitrejected++;
syslog(LOG_NOTICE,
- "rejected mode %d request from %s - per net client limit (%d) exceeded",
+ "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;
@@ -364,36 +423,34 @@ receive(rbufp)
}
/*
- * Find the peer. This will return a null if this guy
- * isn't in the database.
+ * Find the peer. This will return a null if this guy isn't in
+ * the database.
*/
- peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr);
+ peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, rbufp->fd);
/*
* Check the length for validity, drop the packet if it is
- * not as expected.
- *
- * If this is a client mode poll, go no further. Send back
- * his time and drop it.
+ * not as expected. If this is a client mode poll, go no
+ * further. Send back his time and drop it.
*
* The scheme we use for authentication is this. If we are
* running in non-authenticated mode, we accept both frames
* which are authenticated and frames which aren't, but don't
- * authenticate. We do record whether the frame had a mac field
+ * authenticate. We do record whether the frame had a mac field
* or not so we know what to do on output.
*
* If we are running in authenticated mode, we only trust frames
* which have authentication attached, which are validated and
- * which are using one of our trusted keys. We respond to all
- * other pollers without saving any state. If a host we are
+ * which are using one of our trusted keys. We respond to all
+ * other pollers without saving any state. If a host we are
* passively peering with changes his key from a trusted one to
* an untrusted one, we immediately unpeer with him, reselect
* the clock and treat him as an unmemorable client (this is
* a small denial-of-service hole I'll have to think about).
* If a similar event occurs with a configured peer we drop the
- * frame and hope he'll revert to our key again. If we get a
+ * frame and hope he'll revert to our key again. If we get a
* frame which can't be authenticated with the given key, we
- * drop it. Either we disagree on the keys or someone is trying
+ * drop it. Either we disagree on the keys or someone is trying
* some funny stuff.
*/
@@ -405,9 +462,10 @@ receive(rbufp)
has_mac = rbufp->recv_length - LEN_PKT_NOMAC;
hiskeyid = ntohl(pkt->keyid);
#ifdef DEBUG
- if (debug > 3)
- printf("receive: pkt is %d octets, mac %d octets long, keyid %d\n",
- rbufp->recv_length, has_mac, hiskeyid);
+ if (debug > 2)
+ printf(
+ "receive: pkt is %d octets, mac %d octets long, keyid %ld\n",
+ rbufp->recv_length, has_mac, hiskeyid);
#endif
} else if (rbufp->recv_length == LEN_PKT_NOMAC) {
hiskeyid = 0;
@@ -415,15 +473,14 @@ receive(rbufp)
} else {
#ifdef DEBUG
if (debug > 2)
- printf("receive: bad length %d (not > %d or == %d)\n",
- rbufp->recv_length, LEN_PKT_MAC, LEN_PKT_NOMAC);
+ printf("receive: bad length %d %ld\n",
+ rbufp->recv_length, sizeof(struct pkt));
#endif
sys_badlength++;
return;
}
-
/*
* Figure out his mode and validate it.
*/
@@ -432,7 +489,8 @@ receive(rbufp)
if (debug > 2)
printf("receive: his mode %d\n", hismode);
#endif
- if (PKT_VERSION(pkt->li_vn_mode) == NTP_OLDVERSION && hismode == 0) {
+ if (PKT_VERSION(pkt->li_vn_mode) == NTP_OLDVERSION && hismode ==
+ 0) {
/*
* Easy. If it is from the NTP port it is
* a sym act, else client.
@@ -452,34 +510,43 @@ receive(rbufp)
}
}
-
/*
- * If he included a mac field, decrypt it to see if it is authentic.
+ * If he included a mac field, decrypt it to see if it is
+ * authentic.
*/
is_authentic = 0;
if (has_mac) {
if (authhavekey(hiskeyid)) {
- if (authdecrypt(hiskeyid, (U_LONG *)pkt, LEN_PKT_NOMAC)) {
+ if (!authistrusted(hiskeyid)) {
+ sys_badauth++;
+#ifdef DEBUG
+ if (debug > 3)
+ printf("receive: untrusted keyid\n");
+#endif
+ return;
+ }
+ if (authdecrypt(hiskeyid, (U_LONG *)pkt,
+ LEN_PKT_NOMAC)) {
is_authentic = 1;
#ifdef DEBUG
if (debug > 3)
- printf("receive: authdecrypt succeeds\n");
+ printf("receive: authdecrypt succeeds\n");
#endif
} else {
sys_badauth++;
#ifdef DEBUG
if (debug > 3)
- printf("receive: authdecrypt fails\n");
+ printf("receive: authdecrypt fails\n");
#endif
}
}
}
/*
- * If this is someone we don't remember from a previous association,
- * dispatch him now. Either we send something back quick, we
- * ignore him, or we allocate some memory for him and let
- * him continue.
+ * If this is someone we don't remember from a previous
+ * association, dispatch him now. Either we send something back
+ * quick, we ignore him, or we allocate some memory for him and
+ * let him continue.
*/
if (peer == 0) {
int mymode;
@@ -493,15 +560,13 @@ receive(rbufp)
* later. If not, send his time quick.
*/
if (restrict & RES_NOPEER) {
- fast_xmit(rbufp, (int)hismode, is_authentic);
+ fast_xmit(rbufp, (int)hismode,
+ is_authentic);
return;
}
break;
case MODE_PASSIVE:
-#ifdef MCAST
- /* process the packet to determine the rt-delay */
-#endif /* MCAST */
case MODE_SERVER:
/*
* These are obvious errors. Ignore.
@@ -519,11 +584,9 @@ receive(rbufp)
/*
* Sort of a repeat of the above...
*/
-/*
if ((restrict & RES_NOPEER) || !sys_bclient)
return;
-*/
- mymode = MODE_BCLIENT;
+ mymode = MODE_MCLIENT;
break;
}
@@ -531,9 +594,10 @@ receive(rbufp)
* Okay, we're going to keep him around. Allocate him
* some memory.
*/
- peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr, mymode,
- PKT_VERSION(pkt->li_vn_mode), NTP_MINDPOLL,
- NTP_MAXPOLL, 0, hiskeyid);
+ peer = newpeer(&rbufp->recv_srcadr,
+ rbufp->dstadr, mymode, PKT_VERSION(pkt->li_vn_mode),
+ NTP_MINDPOLL, NTP_MAXDPOLL, 0, hiskeyid);
+
if (peer == 0) {
/*
* The only way this can happen is if the
@@ -559,8 +623,10 @@ receive(rbufp)
*/
if (!(peer->flags & FLAG_CONFIG)) {
if (has_mac) {
+ if (!(peer->reach && peer->keyid != hiskeyid)) {
peer->keyid = hiskeyid;
peer->flags |= FLAG_AUTHENABLE;
+ }
} else {
peer->keyid = 0;
peer->flags &= ~FLAG_AUTHENABLE;
@@ -577,8 +643,8 @@ receive(rbufp)
} else {
/*
* If this guy is authenable, and has been authenticated
- * in the past, but just failed the authentic test, report
- * the event.
+ * in the past, but just failed the authentic test,
+ * report the event.
*/
if (peer->flags & FLAG_AUTHENABLE
&& peer->flags & FLAG_AUTHENTIC)
@@ -595,38 +661,33 @@ receive(rbufp)
trustable = 1;
if (sys_authenticate && trustable) {
- if (!(peer->flags & FLAG_CONFIG)
- || (peer->flags & FLAG_AUTHENABLE))
- trustable = 0;
-
- if (has_mac) {
- if (authistrusted(hiskeyid)) {
- if (is_authentic) {
- trustable = 1;
- } else {
- trustable = 0;
- peer->badauth++;
- }
+ if (!(peer->flags & FLAG_CONFIG) ||
+ (peer->flags & FLAG_AUTHENABLE)) {
+ if (has_mac && is_authentic)
+ trustable = 1;
+ else
+ trustable = 0;
}
- }
}
/*
- * Dispose of the packet based on our respective modes. We
+ * Dispose of the packet based on our respective modes. We
* don't drive this with a table, though we probably could.
*/
switch (peer->hmode) {
case MODE_ACTIVE:
case MODE_CLIENT:
/*
- * Active mode associations are configured. If the data
- * isn't trustable, ignore it and hope this guy brightens
- * up. Else accept any data we get and process it.
+ * Active mode associations are configured. If the data
+ * isn't trustable, ignore it and hope this guy
+ * brightens up. Else accept any data we get and process
+ * it.
*/
switch (hismode) {
case MODE_ACTIVE:
case MODE_PASSIVE:
case MODE_SERVER:
+ case MODE_BROADCAST:
process_packet(peer, pkt, &(rbufp->recv_time),
has_mac, trustable);
break;
@@ -635,25 +696,20 @@ receive(rbufp)
if (peer->hmode == MODE_ACTIVE)
fast_xmit(rbufp, hismode, is_authentic);
return;
-
- case MODE_BROADCAST:
- /*
- * No good for us, we want real time.
- */
- break;
}
break;
case MODE_PASSIVE:
/*
* Passive mode associations are (in the current
- * implementation) always dynamic. If we get an
- * invalid header, break the connection. I hate
- * doing this since it seems like a waste. Oh, well.
+ * implementation) always dynamic. If we get an invalid
+ * header, break the connection. I hate doing this since
+ * it seems like a waste. Oh, well.
*/
switch (hismode) {
case MODE_ACTIVE:
- if (process_packet(peer, pkt, &(rbufp->recv_time),
+ if (process_packet(peer, pkt,
+ &(rbufp->recv_time),
has_mac, trustable) == 0) {
unpeer(peer);
clock_select();
@@ -680,34 +736,35 @@ receive(rbufp)
case MODE_BCLIENT:
/*
- * Broadcast client pseudo-mode. We accept both server
- * and broadcast data. Passive mode data is an error.
+ * Broadcast client pseudo-mode. We accept both server
+ * and broadcast data. Passive mode data is an error.
*/
switch (hismode) {
case MODE_ACTIVE:
/*
- * This guy wants to give us real time when we've
- * been existing on lousy broadcasts! Create a
- * passive mode association and do it that way,
- * but keep the old one in case the packet turns
- * out to be bad.
+ * This guy wants to give us real time when
+ * we've been existing on lousy broadcasts!
+ * Create a passive mode association and do it
+ * that way, but keep the old one in case the
+ * packet turns out to be bad.
*/
peer2 = newpeer(&rbufp->recv_srcadr,
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) {
+ if (process_packet(peer2, pkt,
+ &rbufp->recv_time, has_mac, trustable) == 0) {
/*
- * Strange situation. We've been receiving
- * broadcasts from him which we liked, but
- * we don't like his active mode stuff.
- * Keep his old peer structure and send
- * him some time quickly, we'll figure it
- * out later.
+ * Strange situation. We've been
+ * receiving broadcasts from him which
+ * we liked, but we don't like his
+ * active mode stuff. Keep his old peer
+ * structure and send him some time
+ * quickly, we'll figure it out later.
*/
unpeer(peer2);
- fast_xmit(rbufp, (int)hismode, is_authentic);
+ fast_xmit(rbufp, (int)hismode,
+ is_authentic);
} else
/*
* Drop the old association
@@ -728,15 +785,40 @@ receive(rbufp)
*/
break;
}
+ break;
+
+ case MODE_MCLIENT:
+ /*
+ * This mode is temporary and does not appear outside
+ * this routine. It lasts only from the time the
+ * broadcast/multicast is recognized until the
+ * association is instantiated. Note that we start up in
+ * client/server mode to initially synchronize the
+ * clock.
+ */
+ switch (hismode) {
+ case MODE_BROADCAST:
+ peer->flags |= FLAG_MCAST1 | FLAG_MCAST2;
+ peer->hmode = MODE_CLIENT;
+ process_packet(peer, pkt, &rbufp->recv_time,
+ has_mac, trustable);
+ break;
+
+ case MODE_SERVER:
+ case MODE_PASSIVE:
+ case MODE_ACTIVE:
+ case MODE_CLIENT:
+ break;
+ }
}
}
/*
- * process_packet - Packet Procedure, a la Section 3.4.3 of the specification.
- * Or almost, at least. If we're in here we have a reasonable
- * expectation that we will be having a long term relationship
- * with this host.
+ * process_packet - Packet Procedure, a la Section 3.4.3 of the
+ * specification. Or almost, at least. If we're in here we have a
+ * reasonable expectation that we will be having a long term
+ * relationship with this host.
*/
int
process_packet(peer, pkt, recv_ts, has_mac, trustable)
@@ -746,12 +828,13 @@ process_packet(peer, pkt, recv_ts, has_mac, trustable)
int has_mac;
int trustable; /* used as "valid header" */
{
- U_LONG t23_ui = 0, t23_uf = 0;
- U_LONG t10_ui, t10_uf;
+ l_fp t10, t23;
s_fp di, ei, p_dist, p_disp;
l_fp ci, p_rec, p_xmt, p_org;
int randomize;
u_char ostratum, oreach;
+ U_LONG temp;
+ u_fp precision;
sys_processed++;
peer->processed++;
@@ -780,49 +863,44 @@ process_packet(peer, pkt, recv_ts, has_mac, trustable)
peer->bogusorg++;
peer->flash |= TEST2; /* bogus packet */
}
- if ((p_rec.l_ui == 0 && p_rec.l_uf == 0) ||
- (p_org.l_ui == 0 && p_org.l_uf == 0))
+ if (L_ISZERO(&p_rec) || L_ISZERO(&p_org))
peer->flash |= TEST3; /* unsynchronized */
} else {
- if (p_org.l_ui == 0 && p_org.l_uf == 0)
+ if (L_ISZERO(&p_org))
peer->flash |= TEST3; /* unsynchronized */
}
peer->org = p_xmt; /* reuse byte-swapped pkt->xmt */
peer->ppoll = pkt->ppoll;
/*
- * Call poll_update(). This will either start us, if the
+ * Call poll_update(). This will either start us, if the
* association is new, or drop the polling interval if the
* association is existing and ppoll has been reduced.
*/
poll_update(peer, peer->hpoll, randomize);
+
/*
* Test for valid header (tests 5 through 8)
*/
if (trustable == 0) /* test 5 */
peer->flash |= TEST5; /* authentication failed */
+ temp = ntohl(pkt->reftime.l_ui);
if (PKT_LEAP(pkt->li_vn_mode) == LEAP_NOTINSYNC || /* test 6 */
- p_xmt.l_ui < ntohl(pkt->reftime.l_ui) ||
- p_xmt.l_ui >= (ntohl(pkt->reftime.l_ui) + NTP_MAXAGE)) {
- peer->seltooold++; /* test 6 */
+ p_xmt.l_ui < temp || p_xmt.l_ui >= temp + NTP_MAXAGE)
peer->flash |= TEST6; /* peer clock unsynchronized */
- }
if (!(peer->flags & FLAG_CONFIG) && /* test 7 */
(PKT_TO_STRATUM(pkt->stratum) >= NTP_MAXSTRATUM ||
PKT_TO_STRATUM(pkt->stratum) > sys_stratum))
peer->flash |= TEST7; /* peer stratum out of bounds */
if (p_dist >= NTP_MAXDISPERSE /* test 8 */
|| p_dist <= (-NTP_MAXDISPERSE)
- || p_disp >= NTP_MAXDISPERSE) {
- peer->disttoolarge++;
+ || p_disp >= NTP_MAXDISPERSE)
peer->flash |= TEST8; /* delay/dispersion too big */
- }
/*
* If the packet header is invalid (tests 5 through 8), exit
*/
-
if (peer->flash & (TEST5 | TEST6 | TEST7 | TEST8)) {
#ifdef DEBUG
@@ -864,65 +942,78 @@ process_packet(peer, pkt, recv_ts, has_mac, trustable)
peer->reach |= 1;
/*
- * If running in a normal polled association, calculate the round
- * trip delay (di) and the clock offset (ci). We use the equations
- * (reordered from those in the spec):
+ * If running in a client/server association, calculate the
+ * clock offset c, roundtrip delay d and dispersion e. We use
+ * the equations (reordered from those in the spec). Note that,
+ * in a broadcast association, org has been set to the time of
+ * last reception. Note the computation of dispersion includes
+ * the system precision plus that due to the frequency error
+ * since the originate time.
*
- * d = (t2 - t3) - (t1 - t0)
* c = ((t2 - t3) + (t1 - t0)) / 2
+ * d = (t2 - t3) - (t1 - t0)
+ * e = (org - rec) (seconds only)
+ */
+ t10 = p_xmt; /* compute t1 - t0 */
+ L_SUB(&t10, &peer->rec);
+ t23 = p_rec; /* compute t2 - t3 */
+ L_SUB(&t23, &p_org);
+ ci = t10;
+ precision = FP_SECOND >> -(int)sys_precision;
+ if (precision == 0)
+ precision = 1;
+ ei = precision + peer->rec.l_ui - p_org.l_ui;
+
+ /*
+ * If running in a broacast association, the clock offset is (t1
+ * - t0) corrected by the one-way delay, but we can't measure
+ * that directly; therefore, we start up in client/server mode,
+ * calculate the clock offset, using the engineered refinement
+ * algorithms, while also receiving broadcasts. When a broadcast
+ * is received in client/server mode, we calculate a correction
+ * factor to use after switching back to broadcast mode. We know
+ * NTP_SKEWFACTOR == 16, which accounts for the simplified ei
+ * calculation.
*
- * If running as a broadcast client, these change. di becomes
- * equal to two times our broadcast delay, while the offset
- * becomes equal to:
- *
- * c = (t1 - t0) + estbdelay
- */
- t10_ui = p_xmt.l_ui; /* pkt->xmt == t1 */
- t10_uf = p_xmt.l_uf;
- M_SUB(t10_ui, t10_uf, peer->rec.l_ui, peer->rec.l_uf); /*peer->rec==t0*/
-
- if (PKT_MODE(pkt->li_vn_mode) != MODE_BROADCAST) {
- t23_ui = p_rec.l_ui; /* pkt->rec == t2 */
- t23_uf = p_rec.l_uf;
- M_SUB(t23_ui, t23_uf, p_org.l_ui, p_org.l_uf); /*pkt->org==t3*/
- }
+ * If FLAG_MCAST2 is set, we are a broadcast/multicast client.
+ * If FLAG_MCAST1 is set, we haven't calculated the propagation
+ * delay. If hmode is MODE_CLIENT, we haven't set the local
+ * clock in client/server mode. Initially, we come up
+ * MODE_CLIENT. When the clock is first updated and FLAG_MCAST2
+ * is set, we switch from MODE_CLIENT to MODE_BCLIENT.
+ */
+ if (peer->pmode == MODE_BROADCAST) {
+ if (peer->flags & FLAG_MCAST1) {
+ if (peer->hmode == MODE_BCLIENT)
+ peer->flags &= ~FLAG_MCAST1;
+ L_SUB(&ci, &peer->offset);
+ L_NEG(&ci);
+ peer->estbdelay = LFPTOFP(&ci);
+ return (1);
- /* now have (t2 - t3) and (t0 - t1). Calculate (ci), (di) and (ei) */
- ci.l_ui = t10_ui;
- ci.l_uf = t10_uf;
- ei = (FP_SECOND >> (-(int)sys_precision));
+ }
+ FPTOLFP(peer->estbdelay, &t10);
+ L_ADD(&ci, &t10);
+ di = peer->delay;
- /*
- * 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);
- M_SUB(t23_ui, t23_uf, t10_ui, t10_uf);
- di = MFPTOFP(t23_ui, t23_uf);
- ei += peer->rec.l_ui - p_org.l_ui;
+ L_ADD(&ci, &t23);
+ L_RSHIFT(&ci);
+ L_SUB(&t23, &t10);
+ di = LFPTOFP(&t23);
}
+
#ifdef DEBUG
if (debug > 3)
printf("offset: %s, delay %s, error %s\n",
- lfptoa(&ci, 9), fptoa(di, 4), fptoa(ei, 4));
+ lfptoa(&ci, 6), fptoa(di, 5), fptoa(ei, 5));
#endif
if (di >= NTP_MAXDISPERSE || di <= (-NTP_MAXDISPERSE)
- || ei >= NTP_MAXDISPERSE) { /* test 4 */
- peer->bogusdelay++;
+ || ei >= NTP_MAXDISPERSE) /* test 4 */
peer->flash |= TEST4; /* delay/dispersion too big */
- }
/*
- * If the packet data is invalid (tests 1 through 4), exit
+ * If the packet data is invalid (tests 1 through 4), exit.
*/
if (peer->flash) {
@@ -942,28 +1033,25 @@ process_packet(peer, pkt, recv_ts, has_mac, trustable)
}
/*
- * This one is valid. Mark it so, give it to clock_filter(),
+ * This one is valid. Mark it so, give it to clock_filter().
*/
clock_filter(peer, &ci, di, (u_fp)ei);
/*
- * If this guy was previously unreachable, report him
- * reachable.
+ * If this guy was previously unreachable, report him reachable.
* Note we do this here so that the peer values we return are
* the updated ones.
*/
- if (oreach == 0) {
+ if (oreach == 0)
report_event(EVNT_REACH, peer);
-#ifdef DEBUG
- if (debug)
- printf("proto: peer reach %d\n", peer->minpoll);
-#endif /* DEBUG */
- }
/*
- * Now update the clock.
+ * Now update the clock. If we have found a system peer and this
+ * is a broadcast/multicast client, switch to listen mode.
*/
clock_update(peer);
+ if (sys_peer && peer->flags & FLAG_MCAST2)
+ peer->hmode = MODE_BCLIENT;
return(1);
}
@@ -985,103 +1073,67 @@ clock_update(peer)
printf("clock_update(%s)\n", ntoa(&peer->srcadr));
#endif
- record_peer_stats(&peer->srcadr, ctlpeerstatus(peer), &peer->offset,
- peer->delay, peer->dispersion);
+ record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
+ &peer->offset, peer->delay, peer->dispersion);
/*
- * Call the clock selection algorithm to see
- * if this update causes the peer to change.
+ * Call the clock selection algorithm to see if this update
+ * causes the peer to change. If this is not the system peer,
+ * quit now.
*/
clock_select();
-
- /*
- * Quit if this peer isn't the system peer. Other peers
- * used in the combined offset are not allowed to set
- * system variables or update the clock.
- */
if (peer != sys_peer)
return;
/*
- * Quit if the sys_peer is too far away.
- */
- if (peer->synch >= NTP_MAXDISTANCE)
- return;
-
- /*
- * Update the system state
+ * Update the system state. This updates the system stratum,
+ * leap bits, root delay, root dispersion, reference ID and
+ * reference time. We also update select dispersion and max
+ * frequency error.
*/
oleap = sys_leap;
ostratum = sys_stratum;
- /*
- * get leap value (usually the peer leap unless overridden by local configuration)
- */
- sys_leap = leap_actual(peer->leap & leap_mask);
- /*
- * N.B. peer->stratum was guaranteed to be less than
- * NTP_MAXSTRATUM by the receive procedure.
- * We assume peer->update == sys_clock because
- * clock_filter was called right before this function.
- * If the pps signal is in control, the system variables are
- * set in the ntp_loopfilter.c module.
- */
- if (!pps_control) {
- sys_stratum = peer->stratum + 1;
- d = peer->delay;
- if (d < 0)
- d = -d;
- sys_rootdelay = peer->rootdelay + d;
- sys_maxd = peer->dispersion + peer->selectdisp;
- d = peer->soffset;
- if (d < 0)
- d = -d;
- d += sys_maxd;
- if (!peer->flags & FLAG_REFCLOCK && d < NTP_MINDISPERSE)
- d = NTP_MINDISPERSE;
- sys_rootdispersion = peer->rootdispersion + d;
- }
-
- /*
- * Hack for reference clocks. Sigh. This is the
- * only real silly part, though, so the analogy isn't
- * bad.
- */
- if (peer->flags & FLAG_REFCLOCK && peer->stratum == STRATUM_REFCLOCK)
- sys_refid = peer->refid;
- else {
- if (pps_control)
- memmove((char *)&sys_refid, PPSREFID, 4);
- else
- sys_refid = peer->srcadr.sin_addr.s_addr;
- }
+ sys_stratum = peer->stratum + 1;
+ if (sys_stratum == 1)
+ sys_refid = peer->refid;
+ else
+ sys_refid = peer->srcadr.sin_addr.s_addr;
+ sys_reftime = peer->rec;
+ d = peer->delay;
+ if (d < 0)
+ d = -d;
+ sys_rootdelay = peer->rootdelay + d;
+ d = peer->soffset;
+ if (d < 0)
+ d = -d;
+ d += peer->dispersion + peer->selectdisp;
+ if (!peer->flags & FLAG_REFCLOCK && d < NTP_MINDISPERSE)
+ d = NTP_MINDISPERSE;
+ sys_rootdispersion = peer->rootdispersion + d;
/*
- * Report changes. Note that we never sync to
- * an unsynchronized host.
+ * Reset/adjust the system clock. Watch for timewarps here.
*/
- if (oleap == LEAP_NOTINSYNC)
- report_event(EVNT_SYNCCHG, (struct peer *)0);
- else if (ostratum != sys_stratum)
- report_event(EVNT_PEERSTCHG, (struct peer *)0);
-
- sys_reftime = peer->rec;
- sys_refskew.l_i = 0; sys_refskew.l_f = NTP_SKEWINC;
-
switch (local_clock(&sys_offset, peer)) {
case -1:
+
/*
- * Clock is too screwed up. Just exit for now.
+ * Clock is too screwed up. Just exit for now.
*/
report_event(EVNT_SYSFAULT, (struct peer *)0);
exit(1);
/*NOTREACHED*/
case 0:
+
/*
* Clock was slewed. Continue on normally.
*/
+ sys_leap = leap_consensus & leap_mask;
+ L_CLR(&sys_refskew);
break;
case 1:
+
/*
* Clock was stepped. Clear filter registers
* of all peers.
@@ -1093,20 +1145,17 @@ clock_update(peer)
report_event(EVNT_CLOCKRESET, (struct peer *)0);
break;
}
- if (sys_stratum > 1)
- sys_refid = peer->srcadr.sin_addr.s_addr;
- else {
- if (peer->flags & FLAG_REFCLOCK)
- sys_refid = peer->refid;
- else
- memmove((char *)&sys_refid, PPSREFID, 4);
- }
+ sys_maxd = peer->dispersion + peer->selectdisp;
+ if (oleap != sys_leap)
+ report_event(EVNT_SYNCCHG, (struct peer *)0);
+ if (ostratum != sys_stratum)
+ report_event(EVNT_PEERSTCHG, (struct peer *)0);
}
-
/*
- * poll_update - update peer poll interval. See Section 3.4.8 of the spec.
+ * poll_update - update peer poll interval. See Section 3.4.8 of the
+ * spec.
*/
void
poll_update(peer, new_hpoll, randomize)
@@ -1115,7 +1164,7 @@ poll_update(peer, new_hpoll, randomize)
int randomize;
{
register struct event *evp;
- register U_LONG new_timer;
+ register u_long new_timer;
u_char newpoll, oldpoll;
#ifdef DEBUG
@@ -1127,7 +1176,8 @@ 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 || peer->hmode == MODE_BROADCAST)
+ if (peer->flags & FLAG_REFCLOCK || peer->hmode ==
+ MODE_BROADCAST)
return;
/*
@@ -1163,9 +1213,10 @@ poll_update(peer, new_hpoll, randomize)
}
/* hpoll <= maxpoll for sure */
- newpoll = max((u_char)min(peer->ppoll, peer->hpoll), peer->minpoll);
- if (randomize == POLL_MAKERANDOM ||
- (randomize == POLL_RANDOMCHANGE && newpoll != oldpoll))
+ 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))
+ ranp2(newpoll - 1) + current_time;
else
@@ -1190,24 +1241,14 @@ clear_all()
for (i = 0; i < HASH_SIZE; i++)
for (peer = peer_hash[i]; peer != 0; peer = peer->next) {
- /*
- * We used to drop all unconfigured pollers here.
- * The problem with doing this is that if your best
- * time source is unconfigured (there are reasons
- * for doing this) and you drop him, he may not
- * get around to polling you for a long time. Hang
- * on to everyone, dropping their polling intervals
- * to the minimum.
- */
peer_clear(peer);
}
/*
- * Clear sys_peer. We'll sync to one later.
+ * Clear sys_peer. We'll sync to one later.
*/
sys_peer = 0;
sys_stratum = STRATUM_UNSPEC;
-
}
@@ -1260,10 +1301,10 @@ clock_filter(peer, sample_offset, sample_delay, sample_error)
s_fp sample_delay;
u_fp sample_error;
{
- register int i;
+ register int i, j, k, n;
register u_char *ord;
- register s_fp sample_distance, sample_soffset, skew;
s_fp distance[NTP_SHIFT];
+ long skew, skewmax;
#ifdef DEBUG
if (debug)
@@ -1273,92 +1314,87 @@ clock_filter(peer, sample_offset, sample_delay, sample_error)
#endif
/*
- * Update sample errors and calculate distances.
- * We know NTP_SKEWFACTOR == 16
+ * Update sample errors and calculate distances. Also initialize
+ * sort index vector. We know NTP_SKEWFACTOR == 16
*/
skew = sys_clock - peer->update;
peer->update = sys_clock;
- for (i = 0; i < NTP_SHIFT; i++) {
- distance[i] = peer->filter_error[i];
- if (peer->filter_error[i] < NTP_MAXDISPERSE) {
- peer->filter_error[i] += skew;
- distance[i] += (peer->filter_delay[i] >> 1);
- }
- }
-
- /*
- * We keep a sort by distance of the current contents of the
- * shift registers. We update this by (1) removing the
- * register we are going to be replacing from the sort, and
- * (2) reinserting it based on the new distance value.
- */
ord = peer->filter_order;
- sample_distance = sample_error + (sample_delay >> 1);
- sample_soffset = LFPTOFP(sample_offset);
-
- for (i = 0; i < NTP_SHIFT-1; i++) /* find old value */
- if (ord[i] == peer->filter_nextpt)
- break;
- for ( ; i < NTP_SHIFT-1; i++) /* i is current, move everything up */
- ord[i] = ord[i+1];
- /* Here, last slot in ord[] is empty */
-
- if (sample_error >= NTP_MAXDISPERSE)
- /*
- * Last slot for this guy.
- */
- i = NTP_SHIFT-1;
- else {
- register int j;
- register u_fp *errorp;
-
- errorp = peer->filter_error;
- /*
- * Find where he goes in, then shift everyone else down
- */
- 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];
+ j = peer->filter_nextpt;
+ for (i = 0; i < NTP_SHIFT; i++) {
+ peer->filter_error[j] += (u_fp)skew;
+ if (peer->filter_error[j] > NTP_MAXDISPERSE)
+ peer->filter_error[j] = NTP_MAXDISPERSE;
+ distance[i] = peer->filter_error[j] +
+ (peer->filter_delay[j] >> 1);
+ ord[i] = j;
+ if (--j < 0)
+ j += NTP_SHIFT;
}
- ord[i] = peer->filter_nextpt;
/*
- * Got everything in order. Insert sample in current register
- * and increment nextpt.
+ * Insert the new sample at the beginning of the register.
*/
peer->filter_delay[peer->filter_nextpt] = sample_delay;
peer->filter_offset[peer->filter_nextpt] = *sample_offset;
- peer->filter_soffset[peer->filter_nextpt] = sample_soffset;
+ peer->filter_soffset[peer->filter_nextpt] =
+ LFPTOFP(sample_offset);
peer->filter_error[peer->filter_nextpt] = sample_error;
- distance[peer->filter_nextpt] = sample_distance;
+ distance[0] = sample_error + (sample_delay >> 1);
+
+ /*
+ * Sort the samples in the register by distance. The winning
+ * sample will be in ord[0]. Sort the samples only if the
+ * samples are not too old and the delay is meaningful.
+ */
+ skewmax = 0;
+ for (n = 0; n < NTP_SHIFT && sample_delay; n++) {
+ for (j = 0; j < n && skewmax <
+ CLOCK_MAXSEC; j++) {
+ if (distance[j] > distance[n]) {
+ s_fp ftmp;
+
+ ftmp = distance[n];
+ k = ord[n];
+ distance[n] = distance[j];
+ ord[n] = ord[j];
+ distance[j] = ftmp;
+ ord[j] = k;
+ }
+ }
+ skewmax += (1 << peer->hpoll);
+ }
peer->filter_nextpt++;
if (peer->filter_nextpt >= NTP_SHIFT)
peer->filter_nextpt = 0;
/*
- * Now compute the dispersion, and assign values to delay and
- * offset. If there are no samples in the register, delay and
- * offset are not touched and dispersion is set to the maximum.
+ * We compute the dispersion as per the spec. Note that, to make
+ * things simple, both the l_fp and s_fp offsets are retained
+ * and that the s_fp could be nonsense if the l_fp is greater
+ * than about 32000 s. However, the sanity checks in
+ * ntp_loopfilter() require the l_fp offset to be less than 1000
+ * s anyway, so not to worry.
*/
if (peer->filter_error[ord[0]] >= NTP_MAXDISPERSE) {
peer->dispersion = NTP_MAXDISPERSE;
} else {
- register s_fp d;
+ s_fp d;
+ u_fp y;
peer->delay = peer->filter_delay[ord[0]];
peer->offset = peer->filter_offset[ord[0]];
peer->soffset = LFPTOFP(&peer->offset);
peer->dispersion = peer->filter_error[ord[0]];
- for (i = 1; i < NTP_SHIFT; i++) {
- if (peer->filter_error[ord[i]] >= NTP_MAXDISPERSE)
+
+ y = 0;
+ for (i = NTP_SHIFT - 1; i > 0; i--) {
+ if (peer->filter_error[ord[i]] >=
+ NTP_MAXDISPERSE)
d = NTP_MAXDISPERSE;
else {
- d = peer->filter_soffset[ord[i]]
- - peer->filter_soffset[ord[0]];
+ d = peer->filter_soffset[ord[i]] -
+ peer->filter_soffset[ord[0]];
if (d < 0)
d = -d;
if (d > NTP_MAXDISPERSE)
@@ -1367,24 +1403,22 @@ clock_filter(peer, sample_offset, sample_delay, sample_error)
/*
* XXX This *knows* NTP_FILTER is 1/2
*/
- peer->dispersion += (u_fp)(d) >> i;
+ y = ((u_fp)d + y) >> 1;
}
+ peer->dispersion += y;
+
/*
* Calculate synchronization distance backdated to
- * sys_lastselect (clock_select will fix it).
- * We know NTP_SKEWFACTOR == 16
+ * sys_lastselect (clock_select will fix it). We know
+ * NTP_SKEWFACTOR == 16.
*/
d = peer->delay;
if (d < 0)
d = -d;
d += peer->rootdelay;
- peer->synch = (d>>1)
- + peer->rootdispersion + peer->dispersion
- - (sys_clock - sys_lastselect);
+ peer->synch = (d >> 1) + peer->rootdispersion +
+ peer->dispersion - (sys_clock - sys_lastselect);
}
- /*
- * We're done
- */
}
@@ -1401,11 +1435,16 @@ clock_select()
register int j;
register int n;
register int allow, found, k;
- /* XXX correct? */
- s_fp low = 0x7ffffff;
- s_fp high = 0x00000000;
+ s_fp low = 0x7fffffff;
+ s_fp high = -0x7ffffff;
u_fp synch[NTP_MAXCLOCK], error[NTP_MAXCLOCK];
struct peer *osys_peer;
+ struct peer *typeacts = 0;
+ struct peer *typelocal = 0;
+ struct peer *typepps = 0;
+ struct peer *typeprefer = 0;
+ struct peer *typesystem = 0;
+
static int list_alloc = 0;
static struct endpoint *endpoint;
static int *index;
@@ -1417,6 +1456,11 @@ clock_select()
printf("clock_select()\n");
#endif
+ /*
+ * Initizialize. If a prefer peer does not survive this thing,
+ * the pps_update switch will remain zero.
+ */
+ pps_update = 0;
nlist = 0;
for (n = 0; n < HASH_SIZE; n++)
nlist += peer_hash_count[n];
@@ -1459,22 +1503,24 @@ clock_select()
peer->flags &= ~FLAG_SYSPEER;
/*
- * Update synch distance (NTP_SKEWFACTOR == 16)
+ * Update synch distance (NTP_SKEWFACTOR == 16).
+ * Note synch distance check instead of spec
+ * dispersion check. Naughty.
*/
peer->synch += (sys_clock - sys_lastselect);
if (peer->reach == 0)
continue; /* unreachable */
- if (peer->stratum > 1 &&
- peer->refid == peer->dstadr->sin.sin_addr.s_addr)
+ if (peer->stratum > 1 && peer->refid ==
+ peer->dstadr->sin.sin_addr.s_addr)
continue; /* sync loop */
if (peer->stratum >= NTP_MAXSTRATUM ||
peer->stratum > sys_stratum)
continue; /* bad stratum */
- if (peer->dispersion >= NTP_MAXDISPERSE) {
+ if (peer->dispersion >= NTP_MAXDISTANCE) {
peer->seldisptoolarge++;
- continue; /* too noisy or broken */
+ continue; /* too noisy or broken */
}
if (peer->org.l_ui < peer->reftime.l_ui) {
peer->selbroken++;
@@ -1482,15 +1528,34 @@ clock_select()
}
/*
- * This one seems sane.
+ * Don't allow the local-clock or acts drivers
+ * in the kitchen at this point, unless the
+ * prefer peer. Do that later, but only if
+ * nobody else is around.
+ */
+ if (peer->refclktype == REFCLK_LOCALCLOCK) {
+ typelocal = peer;
+ if (!(peer->flags & FLAG_PREFER))
+ continue; /* no local clock */
+ }
+ if (peer->refclktype == REFCLK_NIST_ACTS) {
+ typeacts = peer;
+ if (!(peer->flags & FLAG_PREFER))
+ continue; /* no acts */
+ }
+
+ /*
+ * If we get this far, we assume the peer is
+ * acceptable.
*/
peer->was_sane = 1;
peer_list[nlist++] = peer;
/*
- * Insert each interval endpoint on the sorted list.
+ * Insert each interval endpoint on the sorted
+ * list.
*/
- e = peer->soffset + peer->synch; /* Upper end */
+ e = peer->soffset + peer->synch; /* Upper end */
for (i = nl3 - 1; i >= 0; i--) {
if (e >= endpoint[index[i]].val)
break;
@@ -1533,7 +1598,7 @@ clock_select()
i = 0;
j = nl3 - 1;
- allow = nlist; /* falsetickers assumed */
+ allow = nlist; /* falsetickers assumed */
found = 0;
while (allow > 0) {
allow--;
@@ -1556,14 +1621,30 @@ clock_select()
low = endpoint[index[i++]].val;
high = endpoint[index[j--]].val;
}
+
+ /*
+ * If no survivors remain at this point, check if the acts or
+ * local clock drivers have been found. If so, nominate one of
+ * them as the only survivor. Otherwise, give up and declare us
+ * unsynchronized.
+ */
if ((allow << 1) >= nlist) {
- if (debug)
- printf("clock_select: no intersection\n");
- if (sys_peer != 0)
- report_event(EVNT_PEERSTCHG, (struct peer *)0);
- sys_peer = 0;
- sys_stratum = STRATUM_UNSPEC;
- return;
+ if (typeacts != 0) {
+ typeacts->was_sane = 1;
+ peer_list[0] = typeacts;
+ nlist = 1;
+ } else if (typelocal != 0) {
+ typelocal->was_sane = 1;
+ peer_list[0] = typelocal;
+ nlist = 1;
+ } else {
+ if (sys_peer != 0)
+ report_event(EVNT_PEERSTCHG,
+ (struct peer *)0);
+ sys_peer = 0;
+ sys_stratum = STRATUM_UNSPEC;
+ return;
+ }
}
#ifdef DEBUG
@@ -1574,18 +1655,19 @@ clock_select()
/*
* Clustering algorithm. Process intersection list to discard
- * outlyers. First, construct candidate list in cluster order.
- * Cluster order is determined by the sum of peer
- * synchronization distance plus scaled stratum.
+ * outlyers. Construct candidate list in cluster order
+ * determined by the sum of peer synchronization distance plus
+ * scaled stratum. We must find at least one peer.
*/
-
j = 0;
for (i = 0; i < nlist; i++) {
peer = peer_list[i];
- if (peer->soffset < low || high < peer->soffset)
+ if (nlist > 1 && (peer->soffset < low || high <
+ peer->soffset))
continue;
peer->correct = 1;
- d = peer->synch + ((U_LONG)peer->stratum << NTP_DISPFACTOR);
+ d = peer->synch + ((u_long)peer->stratum <<
+ NTP_DISPFACTOR);
if (j >= NTP_MAXCLOCK) {
if (d >= synch[j - 1])
continue;
@@ -1603,6 +1685,7 @@ clock_select()
j++;
}
nlist = j;
+
#ifdef DEBUG
if (debug > 2)
for (i = 0; i < nlist; i++)
@@ -1612,9 +1695,11 @@ clock_select()
#endif
/*
- * Now, prune outlyers by root dispersion.
+ * Now, prune outlyers by root dispersion. Continue as long as
+ * there are more than NTP_MINCLOCK survivors and the minimum
+ * select dispersion is greater than the maximum peer
+ * dispersion. Stop if we are about to discard a preferred peer.
*/
-
for (i = 0; i < nlist; i++) {
peer = peer_list[i];
peer->candidate = i + 1;
@@ -1628,7 +1713,7 @@ clock_select()
for (k = i = nlist - 1; i >= 0; i--) {
u_fp sdisp = 0;
- for (j = nlist - 1; j >= 0; j--) {
+ for (j = nlist - 1; j > 0; j--) {
d = peer_list[i]->soffset
- peer_list[j]->soffset;
if (d < 0)
@@ -1665,43 +1750,96 @@ clock_select()
#endif
/*
- * What remains is a list of less than NTP_MINCLOCK peers.
- * First record their order, then choose a peer. If the
- * head of the list has a lower stratum than sys_peer
- * choose him right off. If not, see if sys_peer is in
- * the list. If so, keep him. If not, take the top of
- * the list anyway. Also, clamp the polling intervals.
- */
- osys_peer = sys_peer;
+ * What remains is a list of not greater than NTP_MINCLOCK
+ * peers. We want only a peer at the lowest stratum to become
+ * the system peer, although all survivors are eligible for the
+ * combining algorithm. First record their order, diddle the
+ * flags and clamp the poll intervals. Then, consider the peers
+ * at the lowest stratum. Of these, OR the leap bits on the
+ * assumption that, if some of them honk nonzero bits, they must
+ * know what they are doing. Also, check for prefer and pps
+ * peers. If a prefer peer is found within CLOCK_MAX, update the
+ * pps switch. Of the other peers not at the lowest stratum,
+ * check if the system peer is among them and, if found, zap
+ * him. We note that the head of the list is at the lowest
+ * stratum and that unsynchronized peers cannot survive this
+ * far.
+ */
+ leap_consensus = 0;
for (i = nlist - 1; i >= 0; i--) {
- if (peer_list[i]->flags & FLAG_PREFER)
- sys_peer = peer_list[i];
peer_list[i]->select = i + 1;
peer_list[i]->flags |= FLAG_SYSPEER;
poll_update(peer_list[i], peer_list[i]->hpoll,
POLL_RANDOMCHANGE);
- }
- if (sys_peer == 0 || sys_peer->stratum > peer_list[0]->stratum) {
- sys_peer = peer_list[0];
- } else {
- for (i = 1; i < nlist; i++)
+ if (peer_list[i]->stratum == peer_list[0]->stratum) {
+ leap_consensus |= peer_list[i]->leap;
+ if (peer_list[i]->refclktype == REFCLK_ATOM_PPS)
+ typepps = peer_list[i];
if (peer_list[i] == sys_peer)
- break;
- if (i >= nlist)
- sys_peer = peer_list[0];
+ typesystem = peer_list[i];
+ if (peer_list[i]->flags & FLAG_PREFER) {
+ typeprefer = peer_list[i];
+ if (typeprefer->soffset >= -CLOCK_MAX_FP &&
+ typeprefer->soffset < CLOCK_MAX_FP)
+ pps_update = 1;
+ }
+ } else {
+ if (peer_list[i] == sys_peer)
+ sys_peer = 0;
+ }
}
/*
- * If we got a new system peer from all of this, report the event.
+ * Mitigation rules of the game. There are several types of
+ * peers that make a difference here: (1) prefer local peers
+ * (type REFCLK_LOCALCLOCK with FLAG_PREFER) or prefer acts
+ * peers (type REFCLK_NIST_ATOM with FLAG_PREFER), (2) pps peers
+ * (type REFCLK_ATOM_PPS), (3) remaining prefer peers (flag
+ * FLAG_PREFER), (4) the existing system peer, if any, (5) the
+ * head of the survivor list. Note that only one peer can be
+ * declared prefer. The order of preference is in the order
+ * stated. Note that all of these must be at the lowest stratum,
+ * i.e., the stratum of the head of the survivor list.
*/
- if (osys_peer != sys_peer)
- report_event(EVNT_PEERSTCHG, (struct peer *)0);
+ osys_peer = sys_peer;
+ if (typeprefer && (typeprefer == typelocal || typeprefer ==
+ typeacts || !typepps)) {
+ sys_peer = typeprefer;
+ sys_peer->selectdisp = 0;
+ sys_offset = sys_peer->offset;
+#ifdef DEBUG
+ if (debug)
+ printf("select: prefer offset %s\n",
+ lfptoa(&sys_offset, 6));
+#endif
+ } else if (typepps) {
+ sys_peer = typepps;
+ sys_peer->selectdisp = 0;
+ sys_offset = sys_peer->offset;
+#ifdef DEBUG
+ if (debug)
+ printf("select: pps offset %s\n",
+ lfptoa(&sys_offset, 6));
+#endif
+ } else {
+ if (!typesystem)
+ sys_peer = peer_list[0];
+ clock_combine(peer_list, nlist);
+#ifdef DEBUG
+ if (debug)
+ printf("select: combine offset %s\n",
+ lfptoa(&sys_offset, 6));
+#endif
+ }
/*
- * Combine the offsets of the survivors to form a weighted
- * offset.
+ * If we got a new system peer from all of this, report the
+ * event and clamp the system poll interval.
*/
- clock_combine(peer_list, nlist);
+ if (osys_peer != sys_peer) {
+ sys_poll = sys_peer->minpoll;
+ report_event(EVNT_PEERSTCHG, (struct peer *)0);
+ }
}
/*
@@ -1722,21 +1860,12 @@ clock_combine(peers, npeers)
l_fp diff;
/*
- * Sort peers by cluster distance as in the outlyer algorithm. If
- * the preferred peer is found, use its offset only.
+ * Sort the offsets by synch distance.
*/
k = 0;
for (i = 0; i < npeers; i++) {
- if (peers[i]->stratum > sys_peer->stratum) continue;
- if (peers[i]->flags & FLAG_PREFER) {
- sys_offset = peers[i]->offset;
- pps_update = current_time;
-#ifdef DEBUG
- printf("combine: prefer offset %s\n",
- lfptoa(&sys_offset, 6));
-#endif
- return;
- }
+ if (peers[i]->stratum > sys_peer->stratum)
+ continue;
d = peers[i]->synch;
for (j = k; j > 0; j--) {
if (synch[j - 1] <= d)
@@ -1748,6 +1877,7 @@ clock_combine(peers, npeers)
coffset[j] = peers[i]->offset;
k++;
}
+
/*
* Succesively combine the two offsets with the highest
* distance and enter the result into the sorted list.
@@ -1774,6 +1904,7 @@ clock_combine(peers, npeers)
* we just drop the distant offset.
*/
continue;
+
/*
* The offsets are combined by shifting their
* difference the appropriate number of times and
@@ -1823,21 +1954,14 @@ clock_combine(peers, npeers)
synch[j] = d;
coffset[j] = diff;
}
+
/*
* The result is put where clock_update() can find it.
*/
sys_offset = coffset[0];
-
-#ifdef DEBUG
- if (debug) {
- printf("combine: offset %s\n", lfptoa(&sys_offset, 6));
- }
-#endif
-
}
-
/*
* fast_xmit - fast path send for stateless (non-)associations
*/
@@ -1853,6 +1977,7 @@ fast_xmit(rbufp, rmode, authentic)
u_short xkey = 0;
int docrypt = 0;
l_fp xmt_ts;
+ u_fp precision;
#ifdef DEBUG
if (debug > 1)
@@ -1880,9 +2005,11 @@ fast_xmit(rbufp, rmode, authentic)
xpkt.ppoll = max(NTP_MINPOLL, rpkt->ppoll);
xpkt.precision = sys_precision;
xpkt.rootdelay = HTONS_FP(sys_rootdelay);
+ precision = FP_SECOND >> -(int)sys_precision;
+ if (precision == 0)
+ precision = 1;
xpkt.rootdispersion = HTONS_FP(sys_rootdispersion +
- (FP_SECOND >> (-(int)sys_precision)) +
- LFPTOFP(&sys_refskew));
+ precision + LFPTOFP(&sys_refskew));
xpkt.refid = sys_refid;
HTONL_FP(&sys_reftime, &xpkt.reftime);
xpkt.org = rpkt->xmt;
@@ -1900,7 +2027,7 @@ fast_xmit(rbufp, rmode, authentic)
L_ADDUF(&xmt_ts, sys_authdelay);
HTONL_FP(&xmt_ts, &xpkt.xmt);
maclen = auth2crypt(xkey, (U_LONG *)&xpkt, LEN_PKT_NOMAC);
- sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, &xpkt,
+ sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, -9, &xpkt,
LEN_PKT_NOMAC + maclen);
} else {
/*
@@ -1908,50 +2035,32 @@ fast_xmit(rbufp, rmode, authentic)
*/
get_systime(&xmt_ts);
HTONL_FP(&xmt_ts, &xpkt.xmt);
- sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, &xpkt,
+ sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, -10, &xpkt,
LEN_PKT_NOMAC);
}
}
-/* Find the precision of the system clock by watching how the current time
- * changes as we read it repeatedly.
- *
- * struct timeval is only good to 1us, which may cause problems as machines
- * get faster, but until then the logic goes:
- *
- * If a machine has precision (i.e. accurate timing info) > 1us, then it will
- * probably use the "unused" low order bits as a counter (to force time to be
- * a strictly increaing variable), incrementing it each time any process
- * requests the time [[ or maybe time will stand still ? ]].
- *
- * SO: the logic goes:
- *
- * IF the difference from the last time is "small" (< MINSTEP)
- * THEN this machine is "counting" with the low order bits
- * ELIF this is not the first time round the loop
- * THEN this machine *WAS* counting, and has now stepped
- * ELSE this machine has precision < time to read clock
- *
- * SO: if it exits on the first loop, assume "full accuracy" (1us)
- * otherwise, take the log2(observered difference, rounded UP)
- *
- * MINLOOPS > 1 ensures that even if there is a STEP between the initial call
- * and the first loop, it doesn't stop too early.
- * Making it even greater allows MINSTEP to be reduced, assuming that the
- * chance of MINSTEP-1 other processes getting in and calling gettimeofday
- * between this processes's calls.
- * Reducing MINSTEP may be necessary as this sets an upper bound for the time
- * to actually call gettimeofday.
+/*
+ * Find the precision of this particular machine
*/
+#define DUSECS 1000000 /* us in a s */
+#define HUSECS (1 << 20) /* approx DUSECS for shifting etc */
+#define MINSTEP 5 /* minimum clock increment (ys) */
+#define MAXSTEP 20000 /* maximum clock increment (us) */
+#define MINLOOPS 5 /* minimum number of step samples */
-#define DUSECS 1000000 /* us's as returned by gettime */
-#define HUSECS (1024*1024) /* Hex us's -- used when shifting etc */
-#define MINSTEP 5 /* some systems increment uS on each call */
- /* Don't use "1" as some *other* process may read too*/
- /*We assume no system actually *ANSWERS* in this time*/
-#define MAXLOOPS DUSECS /* if no STEP in a complete second, then FAST machine*/
-#define MINLOOPS 2 /* ensure at least this many loops */
-
+/*
+ * This routine calculates the differences between successive calls to
+ * gettimeofday(). If a difference is less than zero, the us field
+ * has rolled over to the next second, so we add a second in us. If
+ * the difference is greater than zero and less than MINSTEP, the
+ * clock has been advanced by a small amount to avoid standing still.
+ * If the clock has advanced by a greater amount, then a timer interrupt
+ * has occurred and this amount represents the precision of the clock.
+ * In order to guard against spurious values, which could occur if we
+ * happen to hit a fat interrupt, we do this for MINLOOPS times and
+ * keep the minimum value obtained.
+ */
int default_get_precision()
{
struct timeval tp;
@@ -1960,26 +2069,32 @@ int default_get_precision()
int i;
long diff;
long val;
- int minsteps = 2; /* need at least this many steps */
+ long usec;
+ usec = 0;
+ val = MAXSTEP;
GETTIMEOFDAY(&tp, &tzp);
last = tp.tv_usec;
- for (i = - --minsteps; i< MAXLOOPS; i++) {
- gettimeofday(&tp, &tzp);
+ for (i = 0; i < MINLOOPS && usec < HUSECS;) {
+ GETTIMEOFDAY(&tp, &tzp);
diff = tp.tv_usec - last;
- if (diff < 0) diff += DUSECS;
- if (diff > MINSTEP) if (minsteps-- <= 0) break;
last = tp.tv_usec;
+ if (diff < 0)
+ diff += DUSECS;
+ usec += diff;
+ if (diff > MINSTEP) {
+ i++;
+ if (diff < val)
+ val = diff;
+ }
}
-
- syslog(LOG_INFO, "precision calculation given %dus after %d loop%s",
- diff, i, (i==1) ? "" : "s");
-
- diff = (diff*3) / 2; /* round it up 1.5 is approx sqrt(2) */
- if (i >= MAXLOOPS) diff = 1; /* No STEP, so FAST machine */
- if (i == 0) diff = 1; /* time to read clock >= precision */
- for (i=0, val=HUSECS; val>0; i--, val >>= 1) if (diff >= val) return i;
- return DEFAULT_SYS_PRECISION /* Something's BUST, so lie ! */;
+ syslog(LOG_INFO, "precision = %d usec", val);
+ if (usec >= HUSECS)
+ val = MINSTEP; /* val <= MINSTEP; fast machine */
+ diff = HUSECS;
+ for (i = 0; diff > val; i--)
+ diff >>= 1;
+ return (i);
}
/*
@@ -1991,8 +2106,8 @@ init_proto()
l_fp dummy;
/*
- * Fill in the sys_* stuff. Default is don't listen
- * to broadcasting, don't authenticate.
+ * Fill in the sys_* stuff. Default is don't listen to
+ * broadcasting, don't authenticate.
*/
sys_leap = LEAP_NOTINSYNC;
sys_stratum = STRATUM_UNSPEC;
@@ -2000,7 +2115,7 @@ init_proto()
sys_rootdelay = 0;
sys_rootdispersion = 0;
sys_refid = 0;
- sys_reftime.l_ui = sys_reftime.l_uf = 0;
+ L_CLR(&sys_reftime);
sys_refskew.l_i = NTP_MAXSKEW; sys_refskew.l_f = 0;
sys_peer = 0;
sys_poll = NTP_MINPOLL;
@@ -2009,8 +2124,8 @@ init_proto()
sys_bclient = 0;
sys_bdelay = DEFBROADDELAY;
-
sys_authenticate = 0;
+ sys_authdelay = DEFAUTHDELAY;
sys_stattime = 0;
sys_badstratum = 0;
@@ -2021,7 +2136,11 @@ init_proto()
sys_processed = 0;
sys_badauth = 0;
- syslog(LOG_NOTICE, "default precision is initialized to 2**%d", sys_precision);
+ /*
+ * Default these to enable
+ */
+ pll_enable = 1;
+ stats_control = 1;
}
@@ -2031,12 +2150,36 @@ init_proto()
void
proto_config(item, value)
int item;
- U_LONG value;
+ u_long value;
{
/*
* Figure out what he wants to change, then do it
*/
switch (item) {
+ case PROTO_PLL:
+ /*
+ * Turn on/off pll clock correction
+ */
+ pll_enable = (int)value;
+ break;
+
+ case PROTO_MONITOR:
+ /*
+ * Turn on/off monitoring
+ */
+ if (value)
+ mon_start(MON_ON);
+ else
+ mon_stop(MON_ON);
+ break;
+
+ case PROTO_FILEGEN:
+ /*
+ * Turn on/off statistics
+ */
+ stats_control = (int)value;
+ break;
+
case PROTO_BROADCLIENT:
/*
* Turn on/off facility to listen to broadcasts
@@ -2049,25 +2192,19 @@ proto_config(item, value)
break;
case PROTO_MULTICAST_ADD:
- /*
- * Add multicast group address
- */
- if (!sys_bclient) {
- sys_bclient = 1;
- io_setbclient();
- }
-#ifdef MCAST
+ /*
+ * Add muliticast group address
+ */
+ sys_bclient = 1;
io_multicast_add(value);
-#endif /* MCAST */
break;
case PROTO_MULTICAST_DEL:
/*
* Delete multicast group address
*/
-#ifdef MCAST
+ sys_bclient = 1;
io_multicast_del(value);
-#endif /* MCAST */
break;
case PROTO_PRECISION:
@@ -2079,9 +2216,12 @@ proto_config(item, value)
case PROTO_BROADDELAY:
/*
- * Set default broadcast delay
+ * Set default broadcast delay (s_fp)
*/
- sys_bdelay = ((value) + 0x00000800) & 0xfffff000;
+ if (sys_bdelay < 0)
+ sys_bdelay = -(-value >> 16);
+ else
+ sys_bdelay = value >> 16;
break;
case PROTO_AUTHENTICATE:
@@ -2094,10 +2234,9 @@ proto_config(item, value)
case PROTO_AUTHDELAY:
/*
- * Provide an authentication delay value. Round it to
- * the microsecond. This is crude.
+ * Set authentication delay (l_fp fraction)
*/
- sys_authdelay = ((value) + 0x00000800) & 0xfffff000;
+ sys_authdelay = value;
break;
default:
diff --git a/usr.sbin/xntpd/xntpd/ntp_refclock.c b/usr.sbin/xntpd/xntpd/ntp_refclock.c
index 2cb7cc29d9a4..b0248fb80e12 100644
--- a/usr.sbin/xntpd/xntpd/ntp_refclock.c
+++ b/usr.sbin/xntpd/xntpd/ntp_refclock.c
@@ -1,112 +1,246 @@
-/* ntp_refclock.c,v 3.1 1993/07/06 01:11:25 jbj Exp
+/*
* ntp_refclock - processing support for reference clocks
*/
+#ifdef REFCLOCK
+
#include <stdio.h>
#include <sys/types.h>
#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
-#ifdef REFCLOCK
+#ifdef PPS
+#include <sys/ppsclock.h>
+#endif /* PPS */
+
/*
- * Reference clock support is provided here by maintaining the
- * fiction that the clock is actually a peer. As no packets are
- * exchanged with a reference clock, however, we replace the
- * transmit, receive and packet procedures with separate code
- * to simulate them. Refclock_transmit and refclock_receive
- * maintain the peer variables in a state analogous to an
- * actual peer and pass reference clock data on through the
- * filters. Refclock_peer and refclock_unpeer are called to
- * initialize and terminate reference clock associations.
+ * Reference clock support is provided here by maintaining the fiction
+ * that the clock is actually a peer. As no packets are exchanged with a
+ * reference clock, however, we replace the transmit, receive and packet
+ * procedures with separate code to simulate them. Routines
+ * refclock_transmit() and refclock_receive() maintain the peer
+ * variables in a state analogous to an actual peer and pass reference
+ * clock data on through the filters. Routines refclock_peer() and
+ * refclock_unpeer() are called to initialize and terminate reference
+ * clock associations. A set of utility routines is included to open
+ * serial devices, process sample data, edit input lines to extract
+ * embedded timestamps and to peform various debugging functions.
+ *
+ * The main interface used by these routines is the refclockproc
+ * structure, which contains for most drivers the decimal equivalants of
+ * the year, day, month, hour, second and millisecond/microsecond
+ * decoded from the ASCII timecode. Additional information includes the
+ * receive timestamp, exception report, statistics tallies, etc. In
+ * addition, there may be a driver-specific unit structure used for
+ * local control of the device.
+ *
+ * The support routines are passed a pointer to the peer structure,
+ * which is used for all peer-specific processing and contains a pointer
+ * to the refclockproc structure, which in turn containes a pointer to
+ * the unit structure, if used. In addition, some routines expect an
+ * address in the dotted quad form 127.127.t.u, where t is the clock
+ * type and u the unit. A table typeunit[type][unit] contains the peer
+ * structure pointer for each configured clock type and unit.
+ *
+ * Most drivers support the 1-pps signal provided by some radios and
+ * connected via a level converted described in the gadget directory.
+ * The signal is captured using a separate, dedicated serial port and
+ * the tty_clk line discipline/streams modules described in the kernel
+ * directory. For the highest precision, the signal is captured using
+ * the carrier-detect line of the same serial port using the ppsclock
+ * streams module described in the ppsclock directory.
*/
+#define REFCLOCKMAXDISPERSE (FP_SECOND/4) /* max sample dispersion */
+#define MAXUNIT 4 /* max units */
+#ifndef CLKLDISC
+#define CLKLDISC 10 /* XXX temp tty_clk line discipline */
+#endif
+#ifndef CHULDISC
+#define CHULDISC 10 /* XXX temp tty_chu line discipline */
+#endif
/*
- * The refclock configuration table. Imported from refclock_conf.c
+ * The refclock configuration table. Imported from refclock_conf
*/
-extern struct refclock *refclock_conf[];
-extern u_char num_refclock_conf;
+extern struct refclock *refclock_conf[];
+extern u_char num_refclock_conf;
/*
* Imported from the I/O module
*/
-extern struct interface *any_interface;
-extern struct interface *loopback_interface;
+extern struct interface *any_interface;
+extern struct interface *loopback_interface;
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
/*
* Imported from the timer module
*/
-extern U_LONG current_time;
-extern struct event timerqueue[];
+extern u_long current_time;
+extern struct event timerqueue[];
/*
- * Imported from the main and peer modules. We use the same
- * algorithm for spacing out timers at configuration time that
- * the peer module does.
+ * Imported from the main and peer modules. We use the same algorithm
+ * for spacing out timers at configuration time that the peer module
+ * does.
*/
-extern U_LONG init_peer_starttime;
-extern int initializing;
-extern int debug;
+extern u_long init_peer_starttime;
+extern int initializing;
+extern int debug;
+
+/*
+ * Type/unit peer index. Used to find the peer structure for control and
+ * debugging. When all clock drivers have been converted to new style,
+ * this dissapears.
+ */
+static struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT];
+
+
+/*
+ * refclock_report - note the occurance of an event
+ *
+ * This routine presently just remembers the report and logs it, but
+ * does nothing heroic for the trap handler. It tries to be a good
+ * citizen and bothers the system log only if things change.
+ */
+void
+refclock_report(peer, code)
+ struct peer *peer;
+ u_char code;
+{
+ struct refclockproc *pp;
+
+ if (!(pp = peer->procptr))
+ return;
+ if (code == CEVNT_BADREPLY)
+ pp->badformat++;
+ if (code == CEVNT_BADTIME)
+ pp->baddata++;
+ if (code == CEVNT_TIMEOUT)
+ pp->noreply++;
+ if (pp->currentstatus != code) {
+ pp->currentstatus = code;
+ if (code == CEVNT_NOMINAL)
+ return;
+ pp->lastevent = code;
+ if (code == CEVNT_FAULT)
+ syslog(LOG_ERR,
+ "clock %s fault %x", ntoa(&peer->srcadr), code);
+ else {
+ syslog(LOG_INFO,
+ "clock %s event %x", ntoa(&peer->srcadr), code);
+ }
+ }
+}
+
+
+/*
+ * init_refclock - initialize the reference clock drivers
+ *
+ * This routine calls each of the drivers in turn to initialize internal
+ * variables, if necessary. Most drivers have nothing to say at this
+ * point.
+ */
+void
+init_refclock()
+{
+ int i, j;
+
+ for (i = 0; i < num_refclock_conf; i++) {
+ if (refclock_conf[i]->clock_init != noentry)
+ (refclock_conf[i]->clock_init)();
+ for (j = 0; j < MAXUNIT; j++)
+ typeunit[i][j] = 0;
+ }
+}
-static void refclock_transmit P((struct peer *));
/*
* refclock_newpeer - initialize and start a reference clock
+ *
+ * This routine allocates and initializes the interface structure which
+ * supports a reference clock in the form of an ordinary NTP peer. A
+ * driver-specific support routine completes the initialization, if
+ * used. Default peer variables which identify the clock and establish
+ * its reference ID and stratum are set here. It returns one if success
+ * and zero if the clock address is invalid or already running,
+ * insufficient resources are available or the driver declares a bum
+ * rap.
*/
int
refclock_newpeer(peer)
- struct peer *peer;
+ struct peer *peer; /* peer structure pointer */
{
+ struct refclockproc *pp;
u_char clktype;
int unit;
/*
- * Sanity...
+ * Check for valid clock address. If already running, shut it * down first.
*/
if (!ISREFCLOCKADR(&peer->srcadr)) {
syslog(LOG_ERR,
- "Internal error: attempting to initialize %s as reference clock",
+ "refclock_newpeer: clock address %s invalid",
ntoa(&peer->srcadr));
- return 0;
+ return (0);
}
-
clktype = REFCLOCKTYPE(&peer->srcadr);
unit = REFCLOCKUNIT(&peer->srcadr);
+ if (clktype >= num_refclock_conf || unit > MAXUNIT ||
+ refclock_conf[clktype]->clock_start == noentry) {
+ syslog(LOG_ERR,
+ "refclock_newpeer: clock type %d invalid\n",
+ clktype);
+ return (0);
+ }
+ refclock_unpeer(peer);
/*
- * If clktype is invalid, return
+ * Allocate and initialize interface structure
*/
- if (clktype >= num_refclock_conf
- || refclock_conf[clktype]->clock_start == noentry) {
- syslog(LOG_ERR,
- "Can't initialize %s, no support for clock type %d\n",
- ntoa(&peer->srcadr), clktype);
- return 0;
- }
+ if (!(pp = (struct refclockproc *)
+ emalloc(sizeof(struct refclockproc))))
+ return (0);
+ memset((char *)pp, 0, sizeof(struct refclockproc));
+ typeunit[clktype][unit] = peer;
+ peer->procptr = pp;
/*
- * Complete initialization of peer structure.
+ * Initialize structures
*/
peer->refclktype = clktype;
peer->refclkunit = unit;
peer->flags |= FLAG_REFCLOCK;
- peer->stratum = STRATUM_REFCLOCK;
- peer->ppoll = peer->minpoll;
- peer->hpoll = peer->minpoll;
peer->event_timer.peer = peer;
peer->event_timer.event_handler = refclock_transmit;
+ pp->type = clktype;
+ pp->timestarted = current_time;
+ peer->stratum = STRATUM_REFCLOCK;
+ peer->refid = peer->srcadr.sin_addr.s_addr;
+ peer->maxpoll = peer->minpoll;
/*
* Do driver dependent initialization
*/
if (!((refclock_conf[clktype]->clock_start)(unit, peer))) {
- syslog(LOG_ERR, "Clock dependent initialization of %s failed",
- ntoa(&peer->srcadr));
- return 0;
+ free(pp);
+ return (0);
}
+ peer->hpoll = peer->minpoll;
+ peer->ppoll = peer->maxpoll;
+ if (peer->stratum <= 1)
+ peer->refid = pp->refid;
+ else
+ peer->refid = peer->srcadr.sin_addr.s_addr;
/*
- * Set up the timeout for reachability determination.
+ * Set up the timeout for polling and reachability determination
*/
if (initializing) {
init_peer_starttime += (1 << EVENT_TIMEOUT);
@@ -114,10 +248,11 @@ refclock_newpeer(peer)
init_peer_starttime = (1 << EVENT_TIMEOUT);
peer->event_timer.event_time = init_peer_starttime;
} else {
- peer->event_timer.event_time = current_time + (1 << peer->hpoll);
+ peer->event_timer.event_time = current_time +
+ (1 << peer->hpoll);
}
TIMER_ENQUEUE(timerqueue, &peer->event_timer);
- return 1;
+ return (1);
}
@@ -126,42 +261,50 @@ refclock_newpeer(peer)
*/
void
refclock_unpeer(peer)
- struct peer *peer;
+ struct peer *peer; /* peer structure pointer */
{
- /*
- * Do sanity checks. I know who programmed the calling routine!
- */
- if (peer->refclktype >= num_refclock_conf
- || refclock_conf[peer->refclktype]->clock_shutdown == noentry) {
- syslog(LOG_ERR, "Attempting to shutdown %s: no such clock!",
- ntoa(&peer->srcadr));
- return;
- }
+ u_char clktype;
+ int unit;
/*
- * Tell the driver we're finished.
+ * Wiggle the driver to release its resources, then give back
+ * the interface structure.
*/
- (refclock_conf[peer->refclktype]->clock_shutdown)(peer->refclkunit);
+ if (!peer->procptr)
+ return;
+ clktype = peer->refclktype;
+ unit = peer->refclkunit;
+ if (refclock_conf[clktype]->clock_shutdown != noentry)
+ (refclock_conf[clktype]->clock_shutdown)(unit, peer);
+ free(peer->procptr);
+ peer->procptr = 0;
}
/*
- * refclock_transmit - replacement transmit procedure for reference clocks
+ * refclock_transmit - simulate the transmit procedure
+ *
+ * This routine implements the NTP transmit procedure for a reference
+ * clock. This provides a mechanism to call the driver at the NTP poll
+ * interval, as well as provides a reachability mechanism to detect a
+ * broken radio or other madness.
*/
-static void
+void
refclock_transmit(peer)
- struct peer *peer;
+ struct peer *peer; /* peer structure pointer */
{
- u_char opeer_reach;
- int clktype;
+ struct refclockproc *pp;
+ u_char clktype;
int unit;
+ u_char opeer_reach;
+ pp = peer->procptr;
clktype = peer->refclktype;
unit = peer->refclkunit;
peer->sent++;
/*
- * The transmit procedure is supposed to freeze a time stamp.
+ * The transmit procedure is supposed to freeze a timestamp.
* Get one just for fun, and to tell when we last were here.
*/
get_systime(&peer->xmt);
@@ -173,9 +316,9 @@ refclock_transmit(peer)
peer->reach <<= 1;
if (peer->reach == 0) {
/*
- * Clear this one out. No need to redo
- * selection since this fellow will definitely
- * be suffering from dispersion madness.
+ * Clear this one out. No need to redo selection since
+ * this fellow will definitely be suffering from
+ * dispersion madness.
*/
if (opeer_reach != 0) {
peer_clear(peer);
@@ -187,12 +330,11 @@ refclock_transmit(peer)
* Update reachability and poll variables
*/
} else if ((opeer_reach & 3) == 0) {
-
l_fp off;
if (peer->valid > 0)
peer->valid--;
- off.l_ui = off.l_uf = 0;
+ L_CLR(&off);
clock_filter(peer, &off, 0, NTP_MAXDISPERSE);
if (peer->flags & FLAG_SYSPEER)
clock_select();
@@ -200,11 +342,13 @@ refclock_transmit(peer)
peer->valid++;
/*
- * If he wants to be polled, do it.
+ * If he wants to be polled, do it. New style drivers do not use
+ * the unit argument, since the fudge stuff is in the
+ * refclockproc structure.
*/
if (refclock_conf[clktype]->clock_poll != noentry)
(refclock_conf[clktype]->clock_poll)(unit, peer);
-
+
/*
* Finally, reset the timer
*/
@@ -214,22 +358,150 @@ refclock_transmit(peer)
/*
- * refclock_receive - simulate the receive and packet procedures for clocks
+ * Compare two l_fp's - used with qsort()
+ */
+static int
+refclock_cmpl_fp(p1, p2)
+ register void *p1, *p2; /* l_fp to compare */
+{
+
+ if (!L_ISGEQ((l_fp *)p1, (l_fp *)p2))
+ return (-1);
+ if (L_ISEQU((l_fp *)p1, (l_fp *)p2))
+ return (0);
+ return (1);
+}
+
+
+/*
+ * refclock_process - process a pile of samples from the clock
+ *
+ * This routine converts the timecode in the form days, hours, miinutes,
+ * seconds, milliseconds/microseconds to internal timestamp format. It
+ * then calculates the difference from the receive timestamp and
+ * assembles the samples in a shift register. It implements a recursive
+ * median filter to suppress spikes in the data, as well as determine a
+ * rough dispersion estimate. A configuration constant time adjustment
+ * fudgetime1 can be added to the final offset to compensate for various
+ * systematic errors. The routine returns one if success and zero if
+ * failure due to invalid timecode data or very noisy offsets.
+ */
+int
+refclock_process(pp, nstart, nskeep)
+ struct refclockproc *pp; /* peer structure pointer */
+ int nstart; /* stages of median filter */
+ int nskeep; /* stages after outlyer trim */
+{
+ int i, n;
+ l_fp offset, median, lftmp;
+ l_fp off[MAXSTAGE];
+ u_fp disp;
+
+ /*
+ * Compute the timecode timestamp from the days, hours, minutes,
+ * seconds and milliseconds/microseconds of the timecode. Use
+ * clocktime() for the aggregate seconds and the msec/usec for
+ * the fraction, when present. Note that this code relies on the
+ * filesystem time for the years and does not use the years of
+ * the timecode.
+ */
+ pp->nstages = nstart;
+ if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
+ pp->lastrec.l_ui, &pp->yearstart, &pp->lastref.l_ui))
+ return (0);
+ if (pp->usec) {
+ TVUTOTSF(pp->usec, pp->lastref.l_uf);
+ } else {
+ MSUTOTSF(pp->msec, pp->lastref.l_uf);
+ }
+
+ /*
+ * Subtract the receive timestamp from the timecode timestamp
+ * to form the raw offset. Insert in the median filter shift
+ * register.
+ */
+ i = ((int)(pp->coderecv)) % pp->nstages;
+ offset = pp->lastref;
+ L_SUB(&offset, &pp->lastrec);
+ pp->filter[i] = offset;
+ if (pp->coderecv == 0)
+ for (i = 1; i < pp->nstages; i++)
+ pp->filter[i] = pp->filter[0];
+ pp->coderecv++;
+
+ /*
+ * Copy the raw offsets and sort into ascending order
+ */
+ for (i = 0; i < pp->nstages; i++)
+ off[i] = pp->filter[i];
+ qsort((char *)off, pp->nstages, sizeof(l_fp), refclock_cmpl_fp);
+
+ /*
+ * Reject the furthest from the median of nstages samples until
+ * nskeep samples remain.
+ */
+ i = 0;
+ n = pp->nstages;
+ while ((n - i) > nskeep) {
+ lftmp = off[n - 1];
+ median = off[(n + i) / 2];
+ L_SUB(&lftmp, &median);
+ L_SUB(&median, &off[i]);
+ if (L_ISHIS(&median, &lftmp)) {
+ /* reject low end */
+ i++;
+ } else {
+ /* reject high end */
+ n--;
+ }
+ }
+
+ /*
+ * Compute the dispersion based on the difference between the
+ * extremes of the remaining offsets. Add to this the time since
+ * the last clock update, which represents the dispersion
+ * increase with time. We know that NTP_MAXSKEW is 16. If the
+ * sum is greater than the allowed sample dispersion, bail out.
+ * If the loop is unlocked, return the most recent offset;
+ * otherwise, return the median offset. In either case include
+ * the configured fudgetime1 adjustment.
+ */
+ lftmp = off[n - 1];
+ L_SUB(&lftmp, &off[i]);
+ disp = LFPTOFP(&lftmp) + current_time - pp->lasttime;
+ if (disp > REFCLOCKMAXDISPERSE)
+ return (0);
+ pp->offset = offset;
+ L_ADD(&pp->offset, &pp->fudgetime1);
+ pp->dispersion = disp;
+ return (1);
+}
+
+
+/*
+ * refclock_receive - simulate the receive and packet procedures
+ *
+ * This routine simulates the NTP receive and packet procedures for a
+ * reference clock. This provides a mechanism in which the ordinary NTP
+ * filter, selection and combining algorithms can be used to suppress
+ * misbehaving radios and to mitigate between them when more than one is
+ * available for backup.
*/
void
refclock_receive(peer, offset, delay, dispersion, reftime, rectime, leap)
- struct peer *peer;
- l_fp *offset;
- s_fp delay;
- u_fp dispersion;
- l_fp *reftime;
- l_fp *rectime;
- int leap;
+ struct peer *peer; /* peer structure pointer */
+ l_fp *offset; /* computed offset (s) */
+ s_fp delay; /* computed delay to peer */
+ u_fp dispersion; /* computed dispersion to peer */
+ l_fp *reftime; /* time at last clock update */
+ l_fp *rectime; /* time at last peer update */
+ int leap; /* synchronization/leap code */
{
int restrict;
int trustable;
- extern u_char leap_indicator;
+ u_fp precision;
+ peer->received++;
#ifdef DEBUG
if (debug)
printf("refclock_receive: %s %s %s %s)\n",
@@ -238,20 +510,12 @@ refclock_receive(peer, offset, delay, dispersion, reftime, rectime, leap)
#endif
/*
- * The name of this routine is actually a misnomer since
- * we mostly simulate the variable setting of the packet
- * procedure. We do check the flag values, though, and
- * set the trust bits based on this.
+ * The authentication and access-control machinery works, but
+ * its utility may be questionable.
*/
restrict = restrictions(&peer->srcadr);
- if (restrict & (RES_IGNORE|RES_DONTSERVE)) {
- /*
- * Ours is not to reason why...
- */
+ if (restrict & (RES_IGNORE|RES_DONTSERVE))
return;
- }
-
- peer->received++;
peer->processed++;
peer->timereceived = current_time;
if (restrict & RES_DONTTRUST)
@@ -265,155 +529,758 @@ refclock_receive(peer, offset, delay, dispersion, reftime, rectime, leap)
else
peer->flags &= ~FLAG_AUTHENTIC;
}
- if (leap == 0)
- peer->leap = leap_indicator;
- else
- peer->leap = leap;
+ peer->leap = leap;
/*
- * Set the timestamps. rec and org are in local time,
- * while ref is in timecode time.
+ * Set the timestamps. rec and org are in local time, while ref
+ * is in timecode time.
*/
peer->rec = peer->org = *rectime;
peer->reftime = *reftime;
/*
- * If the interface has been set to any_interface, set it
- * to the loop back address if we have one. This is so
- * that peers which are unreachable are easy to see in
- * peer display.
+ * If the interface has been set to any_interface, set it to the
+ * loopback address if we have one. This is so that peers which
+ * are unreachable are easy to see in the peer display.
*/
if (peer->dstadr == any_interface && loopback_interface != 0)
peer->dstadr = loopback_interface;
/*
- * Set peer.pmode based on the hmode. For appearances only.
+ * Set peer.pmode based on the hmode. For appearances only.
*/
switch (peer->hmode) {
+
case MODE_ACTIVE:
peer->pmode = MODE_PASSIVE;
break;
- case MODE_CLIENT:
+
+ default:
peer->pmode = MODE_SERVER;
break;
- default:
- syslog(LOG_ERR, "refclock_receive: internal error, mode = %d",
- peer->hmode);
}
/*
* Abandon ship if the radio came bum. We only got this far
* in order to make pretty billboards, even if bum.
*/
- if (leap == LEAP_NOTINSYNC) return;
+ if (leap == LEAP_NOTINSYNC)
+ return;
/*
* If this guy was previously unreachable, report him
* reachable.
*/
if (peer->reach == 0) report_event(EVNT_REACH, peer);
- peer->reach |= 1;
+ peer->reach |= 1;
/*
- * Give the data to the clock filter and update the clock.
+ * Give the data to the clock filter and update the clock. Note
+ * the clock reading precision initialized by the driver is
+ * added at this point.
*/
- clock_filter(peer, offset, delay, dispersion);
+ precision = FP_SECOND >> -(int)peer->precision;
+ if (precision == 0)
+ precision = 1;
+ refclock_report(peer, CEVNT_NOMINAL);
+ clock_filter(peer, offset, delay, dispersion + precision);
clock_update(peer);
}
/*
- * refclock_control - set and/or return clock values
+ * refclock_gtlin - groom next input line and extract timestamp
+ *
+ * This routine processes the timecode received from the clock and
+ * removes the parity bit and control characters. If a timestamp is
+ * present in the timecode, as produced by the tty_clk line
+ * discipline/streams module, it returns that as the timestamp;
+ * otherwise, it returns the buffer timestamp. The routine return code
+ * is the number of characters in the line.
*/
-void
-refclock_control(srcadr, in, out)
- struct sockaddr_in *srcadr;
- struct refclockstat *in;
- struct refclockstat *out;
+int
+refclock_gtlin(rbufp, lineptr, bmax, tsptr)
+ struct recvbuf *rbufp; /* receive buffer pointer */
+ char *lineptr; /* current line pointer */
+ int bmax; /* remaining characters in line */
+ l_fp *tsptr; /* pointer to timestamp returned */
{
- u_char clktype;
- int unit;
+ char *dpt, *dpend, *dp;
+ int i;
+ l_fp trtmp, tstmp;
+ char c;
+
+ /*
+ * Check for the presence of a timestamp left by the tty_clock
+ * line discipline/streams module and, if present, use that
+ * instead of the buffer timestamp captured by the I/O routines.
+ * We recognize a timestamp by noting its value is earlier than
+ * the buffer timestamp, but not more than one second earlier.
+ */
+ dpt = (char *)&rbufp->recv_space;
+ dpend = dpt + rbufp->recv_length;
+ trtmp = rbufp->recv_time;
+ if (dpend >= dpt + 8) {
+ if (buftvtots(dpend - 8, &tstmp)) {
+ L_SUB(&trtmp, &tstmp);
+ if (trtmp.l_ui == 0) {
+#ifdef DEBUG
+ if (debug) {
+ printf(
+ "refclock_gtlin: fd %d ldisc %s",
+ rbufp->fd,
+ lfptoa(&trtmp, 6));
+ gettstamp(&trtmp);
+ L_SUB(&trtmp, &tstmp);
+ printf(" sigio %s\n",
+ lfptoa(&trtmp, 6));
+ }
+#endif
+ dpend -= 8;
+ trtmp = tstmp;
+ } else
+ trtmp = rbufp->recv_time;
+ }
+ }
+
+ /*
+ * Edit timecode to remove control chars. Don't monkey with the
+ * line buffer if the input buffer contains no ASCII printing
+ * characters.
+ */
+ if (dpend - dpt > bmax - 1)
+ dpend = dpt + bmax - 1;
+ for (dp = lineptr; dpt < dpend; dpt++) {
+ c = *dpt & 0x7f;
+ if (c >= ' ')
+ *dp++ = c;
+ }
+ i = dp - lineptr;
+ if (i > 0)
+ *dp = '\0';
+
+#ifdef DEBUG
+ if (debug)
+ printf("refclock_gtlin: fd %d time %s timecode %d %s\n",
+ rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
+#endif
+ *tsptr = trtmp;
+ return (i);
+}
+
+
+/*
+ * refclock_open - open serial port for reference clock
+ *
+ * This routine opens a serial port for I/O and sets default options. It
+ * returns the file descriptor if success and zero if failure.
+ */
+int
+refclock_open(dev, speed, flags)
+ char *dev; /* device name pointer */
+ int speed; /* serial port speed (code) */
+ int flags; /* line discipline flags */
+{
+ int fd;
+#ifdef HAVE_TERMIOS
+ struct termios ttyb, *ttyp;
+#endif /* HAVE_TERMIOS */
+#ifdef HAVE_SYSV_TTYS
+ struct termio ttyb, *ttyp;
+#endif /* HAVE_SYSV_TTYS */
+#ifdef HAVE_BSD_TTYS
+ struct sgttyb ttyb, *ttyp;
+#endif /* HAVE_BSD_TTYS */
+#ifdef HAVE_MODEM_CONTROL
+ u_long ltemp;
+#endif /* HAVE_MODEM_CONTROL */
+
+ /*
+ * Open serial port and set default options
+ */
+ fd = open(dev, O_RDWR, 0777);
+ if (fd == -1) {
+ syslog(LOG_ERR, "refclock_open: %s: %m", dev);
+ return (0);
+ }
+
+ /*
+ * The following sections initialize the serial line port in
+ * canonical (line-oriented) mode and set the specified line
+ * speed, 8 bits and no parity. The modem control, break, erase
+ * and kill functions are normally disabled. There is a
+ * different section for each terminal interface, as selected at
+ * compile time.
+ */
+ ttyp = &ttyb;
+#ifdef HAVE_TERMIOS
/*
- * Sanity...
+ * POSIX serial line parameters (termios interface)
*/
- if (!ISREFCLOCKADR(srcadr)) {
+ if (tcgetattr(fd, ttyp) < 0) {
syslog(LOG_ERR,
- "Internal error: refclock_control received %s as reference clock",
- ntoa(srcadr));
- return;
+ "refclock_open: fd %d tcgetattr %m", fd);
+ return (0);
}
- clktype = REFCLOCKTYPE(srcadr);
- unit = REFCLOCKUNIT(srcadr);
+ /*
+ * Set canonical mode and local connection; set specified speed,
+ * 8 bits and no parity; map CR to NL; ignore break.
+ */
+ ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
+ ttyp->c_oflag = 0;
+ ttyp->c_cflag = CS8 | CLOCAL | CREAD;
+ (void)cfsetispeed(&ttyb, speed);
+ (void)cfsetospeed(&ttyb, speed);
+ ttyp->c_lflag = ICANON;
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+#ifdef HAVE_MODEM_CONTROL
+ /*
+ * If we have modem control, check to see if modem leads are
+ * active; if so, set remote connection. This is necessary for
+ * the kernel pps mods to work.
+ */
+ ltemp = 0;
+ if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
+ syslog(LOG_ERR,
+ "refclock_open: fd %d TIOCMGET %m", fd);
+#if DEBUG
+ if (debug)
+ printf("refclock_open: fd %d modem status %lx\n",
+ fd, ltemp);
+#endif
+ if (ltemp & TIOCM_DSR)
+ ttyp->c_cflag &= ~CLOCAL;
+#endif /* HAVE_MODEM_CONTROL */
+ if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
+ syslog(LOG_ERR,
+ "refclock_open: fd %d tcsetattr %m", fd);
+ return (0);
+ }
+ if (tcflush(fd, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "refclock_open: fd %d tcflush %m", fd);
+ return (0);
+ }
+#endif /* HAVE_TERMIOS */
+
+#ifdef HAVE_SYSV_TTYS
/*
- * If clktype is invalid, return
+ * System V serial line parameters (termio interface)
+ *
*/
- if (clktype >= num_refclock_conf
- || refclock_conf[clktype]->clock_control == noentry) {
+ if (ioctl(fd, TCGETA, ttyp) < 0) {
syslog(LOG_ERR,
- "Internal error: refclock_control finds %s as not supported",
- ntoa(srcadr));
- return;
+ "refclock_open: fd %d TCGETA %m", fd);
+ return (0);
}
/*
- * Give the stuff to the clock.
+ * Set canonical mode and local connection; set specified speed,
+ * 8 bits and no parity; map CR to NL; ignore break.
+ */
+ ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
+ ttyp->c_oflag = 0;
+ ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
+ ttyp->c_lflag = ICANON;
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+#ifdef HAVE_MODEM_CONTROL
+ /*
+ * If we have modem control, check to see if modem leads are
+ * active; if so, set remote connection. This is necessary for
+ * the kernel pps mods to work.
*/
- (refclock_conf[clktype]->clock_control)(unit, in, out);
+ ltemp = 0;
+ if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
+ syslog(LOG_ERR,
+ "refclock_open: fd %d TIOCMGET %m", fd);
+#if DEBUG
+ if (debug)
+ printf("refclock_open: fd %d modem status %lx\n",
+ fd, ltemp);
+#endif
+ if (ltemp & TIOCM_DSR)
+ ttyp->c_cflag &= ~CLOCAL;
+#endif /* HAVE_MODEM_CONTROL */
+ if (ioctl(fd, TCSETA, ttyp) < 0) {
+ syslog(LOG_ERR,
+ "refclock_open: fd %d TCSETA %m", fd);
+ return (0);
+ }
+#endif /* HAVE_SYSV_TTYS */
+
+#ifdef HAVE_BSD_TTYS
+
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ */
+ if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {
+ syslog(LOG_ERR,
+ "refclock_open: fd %d TIOCGETP %m", fd);
+ return (0);
+ }
+ ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
+ ttyp->sg_flags = EVENP | ODDP | CRMOD;
+ if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {
+ syslog(LOG_ERR,
+ "refclock_open: TIOCSETP %m");
+ return (0);
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ if (!refclock_ioctl(fd, flags)) {
+ (void)close(fd);
+ syslog(LOG_ERR, "refclock_open: fd %d ioctl fails",
+ fd);
+ return (0);
+ }
+ return (fd);
}
+/*
+ * refclock_ioctl - set serial port control functions
+ *
+ * This routine attempts to hide the internal, system-specific details
+ * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD
+ * (sgtty) interfaces with varying degrees of success. The routine sets
+ * up the tty_clk, chu_clk and ppsclock streams module/line discipline,
+ * if compiled in the daemon and requested in the call. The routine
+ * returns one if success and zero if failure.
+ */
+int
+refclock_ioctl(fd, flags)
+ int fd; /* file descriptor */
+ int flags; /* line discipline flags */
+{
+#ifdef HAVE_TERMIOS
+ struct termios ttyb, *ttyp;
+#endif /* HAVE_TERMIOS */
+#ifdef HAVE_SYSV_TTYS
+ struct termio ttyb, *ttyp;
+#endif /* HAVE_SYSV_TTYS */
+#ifdef HAVE_BSD_TTYS
+ struct sgttyb ttyb, *ttyp;
+#endif /* HAVE_BSD_TTYS */
+
+#ifdef DEBUG
+ if (debug)
+ printf("refclock_ioctl: fd %d flags %x\n",
+ fd, flags);
+#endif
+
+ /*
+ * The following sections select optional features, such as
+ * modem control, line discipline and so forth. Some require
+ * specific operating system support in the form of streams
+ * modules, which can be loaded and unloaded at run time without
+ * rebooting the kernel, or line discipline modules, which must
+ * be compiled in the kernel. The streams modules require System
+ * V STREAMS support, while the line discipline modules require
+ * 4.3bsd or later. The checking frenzy is attenuated here,
+ * since the device is already open.
+ *
+ * Note that both the clk and ppsclock modules are optional; the
+ * dang thing still works, but the accuracy improvement using
+ * them will not be available. The ppsclock module is associated
+ * with a specific, declared line and should be used only once.
+ * If requested, the chu module is mandatory, since the driver
+ * will not work without it.
+ *
+ * Use the LDISC_PPS option ONLY with Sun baseboard ttya or
+ * ttyb. Using it with the SPIF multipexor crashes the kernel.
+ */
+ if (flags == 0)
+ return (1);
+
+#if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS))
+ if (flags & (LDISC_CLK | LDISC_CHU | LDISC_PPS | LDISC_ACTS))
+ syslog(LOG_ERR,
+ "refclock_ioctl: unsupported terminal interface");
+ return (0);
+#endif /* HAVE_TERMIOS HAVE_BSD_TTYS */
+
+ ttyp = &ttyb;
+
+#ifdef STREAM
+#ifdef CLK
+
+ /*
+ * The CLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module and System V STREAMS
+ * support.
+ */
+ if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
+ if (ioctl(fd, I_PUSH, "clk") < 0)
+ syslog(LOG_NOTICE,
+ "refclock_ioctl: optional clk streams module unavailable");
+ else {
+ char *str;
+
+ if (flags & LDISC_PPS)
+ str = "\377";
+ else if (flags & LDISC_ACTS)
+ str = "*";
+ else
+ str = "\n";
+ if (ioctl(fd, CLK_SETSTR, str) < 0)
+ syslog(LOG_ERR,
+ "refclock_ioctl: CLK_SETSTR %m");
+ }
+ }
+
+ /*
+ * The ACTS line discipline requires additional line-ending
+ * character '*'.
+ */
+ if (flags & LDISC_ACTS) {
+ (void)tcgetattr(fd, ttyp);
+ ttyp->c_cc[VEOL] = '*';
+ (void)tcsetattr(fd, TCSANOW, ttyp);
+ }
+#else
+ if (flags & LDISC_CLK)
+ syslog(LOG_NOTICE,
+ "refclock_ioctl: optional clk streams module unsupported");
+#endif /* CLK */
+#ifdef CHU
+
+ /*
+ * The CHU option provides timestamping and decoding for the CHU
+ * timecode. It requires the tty_chu streams module and System V
+ * STREAMS support.
+ */
+ if (flags & LDISC_CHU) {
+ (void)tcgetattr(fd, ttyp);
+ ttyp->c_lflag = 0;
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+ ttyp->c_cc[VMIN] = 1;
+ ttyp->c_cc[VTIME] = 0;
+ (void)tcsetattr(fd, TCSANOW, ttyp);
+ (void)tcflush(fd, TCIOFLUSH);
+ while (ioctl(fd, I_POP, 0) >= 0);
+ if (ioctl(fd, I_PUSH, "chu") < 0) {
+ syslog(LOG_ERR,
+ "refclock_ioctl: required chu streams module unavailable");
+ return (0);
+ }
+ }
+#else
+ if (flags & LDISC_CHU) {
+ syslog(LOG_ERR,
+ "refclock_ioctl: required chu streams module unsupported");
+ return (0);
+ }
+#endif /* CHU */
+#ifdef PPS
+
+ /*
+ * The PPS 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 System V STREAMS
+ * support.
+ */
+ if (flags & LDISC_PPS) {
+ if (fdpps != -1) {
+ syslog(LOG_ERR,
+ "refclock_ioctl: ppsclock already configured");
+ return (0);
+ }
+ if (ioctl(fd, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_NOTICE,
+ "refclock_ioctl: optional ppsclock streams module unavailable");
+ else
+ fdpps = fd;
+ }
+#else
+ if (flags & LDISC_PPS)
+ syslog(LOG_NOTICE,
+ "refclock_ioctl: optional ppsclock streams module unsupported");
+#endif /* PPS */
+
+#else /* STREAM */
+
+#ifdef HAVE_TERMIOS
+#ifdef CLK
+
+ /*
+ * The CLK option provides timestamping at the driver level. It
+ * requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
+ (void)tcgetattr(fd, ttyp);
+ ttyp->c_lflag = 0;
+ if (flags & LDISC_CLKPPS)
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\377';
+ else if (flags & LDISC_ACTS) {
+ ttyp->c_cc[VERASE] = '*';
+ ttyp->c_cc[VKILL] = '#';
+ } else
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\n';
+ ttyp->c_cc[VMIN] = 1;
+ ttyp->c_cc[VTIME] = 0;
+ ttyp->c_line = CLKLDISC;
+ (void)tcsetattr(fd, TCSANOW, ttyp);
+ (void)tcflush(fd, TCIOFLUSH);
+ }
+#else
+ if (flags & LDISC_CLK)
+ syslog(LOG_NOTICE,
+ "refclock_ioctl: optional clk line discipline unsupported");
+#endif /* CLK */
+#ifdef CHU
+ /*
+ * The CHU option provides timestamping and decoding for the CHU
+ * timecode. It requires the tty_chu line disciplne and 4.3bsd
+ * or later.
+ */
+ if (flags & LDISC_CHU) {
+ (void)tcgetattr(fd, ttyp);
+ ttyp->c_lflag = 0;
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\r';
+ ttyp->c_cc[VMIN] = 1;
+ ttyp->c_cc[VTIME] = 0;
+ ttyp->c_line = CHULDISC;
+ (void)tcsetattr(fd, TCSANOW, ttyp) < 0);
+ (void)tcflush(fd, TCIOFLUSH);
+ }
+#else
+ if (flags & LDISC_CHU) {
+ syslog(LOG_ERR,
+ "refclock_ioctl: required chu line discipline unsupported");
+ return (0);
+ }
+#endif /* CHU */
+#endif /* HAVE_TERMIOS */
+
+#ifdef HAVE_BSD_TTYS
+#ifdef CLK
+
+ /*
+ * The CLK option provides timestamping at the driver level. It
+ * requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
+ int ldisc = CLKLDISC;
+
+ (void)ioctl(fd, TIOCGETP, (char *)ttyp);
+ if (flags & LDISC_CLKPPS)
+ ttyp->sg_erase = ttyp->sg_kill = '\377';
+ else if (flags & LDISC_ACTS) {
+ ttyp->sg_erase = '*';
+ ttyp->sg_kill = '#';
+ } else
+ ttyp->sg_erase = ttyp->sg_kill = '\r';
+ ttyp->sg_flags = RAW;
+ (void)ioctl(fd, TIOCSETP, ttyp);
+ if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0)
+ syslog(LOG_NOTICE,
+ "refclock_ioctl: optional clk line discipline unavailable");
+ }
+#else
+ if (flags & LDISC_CLK)
+ syslog(LOG_NOTICE,
+ "refclock_ioctl: optional clk line discipline unsupported");
+
+#endif /* CLK */
+#ifdef CHU
+
+ /*
+ * The CHU option provides timestamping and decoding for the CHU
+ * timecode. It requires the tty_chu line disciplne and 4.3bsd
+ * or later.
+ */
+ if (flags & LDISC_CHU) {
+ int ldisc = CHULDISC;
+
+ (void)ioctl(fd, TIOCGETP, (char *)ttyp);
+ ttyp->sg_erase = ttyp->sg_kill = '\r';
+ ttyp->sg_flags = RAW;
+ (void)ioctl(fd, TIOCSETP, (char *)ttyp);
+ if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0) {
+ syslog(LOG_ERR,
+ "refclock_ioctl: required chu line discipline unavailable");
+ return (0);
+ }
+ }
+#else
+ if (flags & LDISC_CHU) {
+ syslog(LOG_ERR,
+ "refclock_ioctl: required chu line discipline unsupported");
+ return (0);
+ }
+#endif /* CHU */
+#endif /* HAVE_BSD_TTYS */
+
+#endif /* STREAM */
+
+ return (1);
+}
+
/*
- * refclock_buginfo - return debugging info
+ * refclock_control - set and/or return clock values
+ *
+ * This routine is used mainly for debugging. It returns designated
+ * values from the interface structure that can be displayed using
+ * xntpdc and the clockstat command. It can also be used to initialize
+ * configuration variables, such as fudgetimes, fudgevalues, reference
+ * ID and stratum.
*/
void
-refclock_buginfo(srcadr, bug)
+refclock_control(srcadr, in, out)
struct sockaddr_in *srcadr;
- struct refclockbug *bug;
+ struct refclockstat *in;
+ struct refclockstat *out;
{
+ struct peer *peer;
+ struct refclockproc *pp;
u_char clktype;
int unit;
/*
- * Sanity...
+ * Check for valid address and running peer
*/
- if (!ISREFCLOCKADR(srcadr)) {
- syslog(LOG_ERR,
- "Internal error: refclock_buginfo received %s as reference clock",
- ntoa(srcadr));
+ if (!ISREFCLOCKADR(srcadr))
return;
- }
-
clktype = REFCLOCKTYPE(srcadr);
unit = REFCLOCKUNIT(srcadr);
+ if (clktype >= num_refclock_conf || unit > MAXUNIT)
+ return;
+ if (!(peer = typeunit[clktype][unit]))
+ return;
+ pp = peer->procptr;
/*
- * If clktype is invalid or call is unsupported, return
+ * Initialize requested data
*/
- if (clktype >= num_refclock_conf ||
- refclock_conf[clktype]->clock_buginfo == noentry) {
- return;
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ pp->fudgetime1 = in->fudgetime1;
+ if (in->haveflags & CLK_HAVETIME2)
+ pp->fudgetime2 = in->fudgetime2;
+ if (in->haveflags & CLK_HAVEVAL1)
+ peer->stratum = in->fudgeval1;
+ if (in->haveflags & CLK_HAVEVAL2)
+ pp->refid = in->fudgeval2;
+ if (peer->stratum <= 1)
+ peer->refid = pp->refid;
+ else
+ peer->refid = peer->srcadr.sin_addr.s_addr;
+ if (in->haveflags & CLK_HAVEFLAG1) {
+ pp->sloppyclockflag &= ~CLK_FLAG1;
+ pp->sloppyclockflag |= in->flags & CLK_FLAG1;
+ }
+ if (in->haveflags & CLK_HAVEFLAG2) {
+ pp->sloppyclockflag &= ~CLK_FLAG2;
+ pp->sloppyclockflag |= in->flags & CLK_FLAG2;
+ }
+ if (in->haveflags & CLK_HAVEFLAG3) {
+ pp->sloppyclockflag &= ~CLK_FLAG3;
+ pp->sloppyclockflag |= in->flags & CLK_FLAG3;
+ }
+ if (in->haveflags & CLK_HAVEFLAG4) {
+ pp->sloppyclockflag &= ~CLK_FLAG4;
+ pp->sloppyclockflag |= in->flags & CLK_FLAG4;
+ }
+ if (in->flags & CLK_FLAG3)
+ (void)refclock_ioctl(pp->io.fd, LDISC_PPS);
+ }
+
+ /*
+ * Readback requested data
+ */
+ if (out != 0) {
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 |
+ CLK_HAVEVAL2 | CLK_HAVEFLAG4;
+ out->fudgetime1 = pp->fudgetime1;
+ out->fudgetime2 = pp->fudgetime2;
+ out->fudgeval1 = peer->stratum;
+ out->fudgeval2 = pp->refid;
+ out->flags = pp->sloppyclockflag;
+
+ out->timereset = current_time - pp->timestarted;
+ out->polls = pp->polls;
+ out->noresponse = pp->noreply;
+ out->badformat = pp->badformat;
+ out->baddata = pp->baddata;
+
+ out->lastevent = pp->lastevent;
+ out->currentstatus = pp->currentstatus;
+ out->type = pp->type;
+ out->clockdesc = pp->clockdesc;
+ out->lencode = pp->lencode;
+ out->lastcode = pp->lastcode;
}
/*
- * Give the stuff to the clock.
+ * Give the stuff to the clock
*/
- (refclock_conf[clktype]->clock_buginfo)(unit, bug);
+ if (refclock_conf[clktype]->clock_control != noentry)
+ (refclock_conf[clktype]->clock_control)(unit, in, out);
}
+
/*
- * init_refclock - initialize the reference clock drivers
+ * refclock_buginfo - return debugging info
+ *
+ * This routine is used mainly for debugging. It returns designated
+ * values from the interface structure that can be displayed using
+ * xntpdc and the clkbug command.
*/
void
-init_refclock()
+refclock_buginfo(srcadr, bug)
+ struct sockaddr_in *srcadr; /* clock address */
+ struct refclockbug *bug; /* output structure */
{
- register u_char i;
+ struct peer *peer;
+ struct refclockproc *pp;
+ u_char clktype;
+ int unit;
+ int i;
- for (i = 0; i < num_refclock_conf; i++) {
- if (refclock_conf[i]->clock_init != noentry)
- (refclock_conf[i]->clock_init)();
- }
+ /*
+ * Check for valid address and peer structure
+ */
+ if (!ISREFCLOCKADR(srcadr))
+ return;
+ clktype = REFCLOCKTYPE(srcadr);
+ unit = REFCLOCKUNIT(srcadr);
+ if (clktype >= num_refclock_conf || unit > MAXUNIT)
+ return;
+ if (!(peer = typeunit[clktype][unit]))
+ return;
+ pp = peer->procptr;
+
+ /*
+ * Copy structure values
+ */
+ bug->nvalues = 8;
+ bug->values[0] = pp->year;
+ bug->values[1] = pp->day;
+ bug->values[2] = pp->hour;
+ bug->values[3] = pp->minute;
+ bug->values[4] = pp->second;
+ bug->values[5] = pp->msec;
+ bug->values[6] = pp->yearstart;
+ bug->values[7] = pp->coderecv;
+
+ bug->ntimes = pp->nstages + 3;
+ if (bug->ntimes > NCLKBUGTIMES)
+ bug->ntimes = NCLKBUGTIMES;
+ bug->stimes = 0xfffffffc;
+ bug->times[0] = pp->lastref;
+ bug->times[1] = pp->lastrec;
+ UFPTOLFP(pp->dispersion, &bug->times[2]);
+ for (i = 0; i < bug->ntimes; i++)
+ bug->times[i + 3] = pp->filter[i];
+
+ /*
+ * Give the stuff to the clock
+ */
+ if (refclock_conf[clktype]->clock_buginfo != noentry)
+ (refclock_conf[clktype]->clock_buginfo)(unit, bug);
}
-#endif
+
+#endif /* REFCLOCK */
diff --git a/usr.sbin/xntpd/xntpd/ntp_request.c b/usr.sbin/xntpd/xntpd/ntp_request.c
index a77669875bea..5b3d481df1ed 100644
--- a/usr.sbin/xntpd/xntpd/ntp_request.c
+++ b/usr.sbin/xntpd/xntpd/ntp_request.c
@@ -1,10 +1,9 @@
-/* ntp_request.c,v 3.1 1993/07/06 01:11:26 jbj Exp
+/*
* ntp_request.c - respond to information requests
*/
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
-#include <sys/ioctl.h>
#include <sys/time.h>
#include "ntpd.h"
@@ -17,7 +16,7 @@
#include "ntp_stdlib.h"
#ifdef KERNEL_PLL
-#include <sys/timex.h>
+#include "sys/timex.h"
#define ntp_gettime(t) syscall(SYS_ntp_gettime, (t))
#define ntp_adjtime(t) syscall(SYS_ntp_adjtime, (t))
#endif /* KERNEL_PLL */
@@ -62,7 +61,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 *, U_LONG));
+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 *));
@@ -70,7 +69,8 @@ static void do_resaddflags P((struct sockaddr_in *, struct interface *, struct r
static void do_ressubflags P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void do_unrestrict P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void do_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
-static void mon_getlist P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+static void mon_getlist_0 P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+static void mon_getlist_1 P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void reset_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void reset_peer P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void do_key_reread P((struct sockaddr_in *, struct interface *, struct req_pkt *));
@@ -125,23 +125,24 @@ static struct req_proc xntp_codes[] = {
{ REQ_RESADDFLAGS, AUTH, sizeof(struct conf_restrict), do_resaddflags },
{ REQ_RESSUBFLAGS, AUTH, sizeof(struct conf_restrict), do_ressubflags },
{ REQ_UNRESTRICT, AUTH, sizeof(struct conf_restrict), do_unrestrict },
- { REQ_MON_GETLIST, NOAUTH, 0, mon_getlist },
+ { REQ_MON_GETLIST, NOAUTH, 0, mon_getlist_0 },
+ { REQ_MON_GETLIST_1, NOAUTH, 0, mon_getlist_1 },
{ REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), reset_stats },
{ REQ_RESET_PEER, AUTH, sizeof(struct conf_unpeer), reset_peer },
{ REQ_REREAD_KEYS, AUTH, 0, do_key_reread },
{ REQ_DO_DIRTY_HACK, AUTH, 0, do_dirty_hack },
{ REQ_DONT_DIRTY_HACK, AUTH, 0, dont_dirty_hack },
- { REQ_TRUSTKEY, AUTH, sizeof(U_LONG), trust_key },
- { REQ_UNTRUSTKEY, AUTH, sizeof(U_LONG), untrust_key },
+ { REQ_TRUSTKEY, AUTH, sizeof(u_long), trust_key },
+ { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), untrust_key },
{ REQ_AUTHINFO, NOAUTH, 0, get_auth_info },
{ REQ_TRAPS, NOAUTH, 0, req_get_traps },
{ REQ_ADD_TRAP, AUTH, sizeof(struct conf_trap), req_set_trap },
{ REQ_CLR_TRAP, AUTH, sizeof(struct conf_trap), req_clr_trap },
- { REQ_REQUEST_KEY, AUTH, sizeof(U_LONG), set_request_keyid },
- { REQ_CONTROL_KEY, AUTH, sizeof(U_LONG), set_control_keyid },
+ { REQ_REQUEST_KEY, AUTH, sizeof(u_long), set_request_keyid },
+ { 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_PRECISION, AUTH, sizeof(LONG), set_precision },
+ { REQ_SET_PRECISION, AUTH, sizeof(long), set_precision },
#ifdef KERNEL_PLL
{ REQ_GET_KERNEL, NOAUTH, 0, get_kernel_info },
#endif /* KERNEL_PLL */
@@ -158,16 +159,16 @@ static struct req_proc xntp_codes[] = {
* Authentication keyid used to authenticate requests. Zero means we
* don't allow writing anything.
*/
-U_LONG info_auth_keyid;
+u_long info_auth_keyid;
/*
* Statistic counters to keep track of requests and responses.
*/
-U_LONG numrequests; /* number of requests we've received */
-U_LONG numresppkts; /* number of resp packets sent with data */
+u_long numrequests; /* number of requests we've received */
+u_long numresppkts; /* number of resp packets sent with data */
-U_LONG errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */
+u_long errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */
/* by the error code */
#ifdef KERNEL_PLL
@@ -187,18 +188,33 @@ extern int debug;
/*
* Imported from the timer module
*/
-extern U_LONG current_time;
+extern u_long current_time;
/*
* Imported from ntp_loopfilter.c
*/
extern int pll_control;
+extern int pll_enable;
+extern int pps_control;
+
+/*
+ * Imported from ntp_monitor.c
+ */
+extern int mon_enabled;
+
+/*
+ * Imported from ntp_util.c
+ */
+extern int stats_control;
+
+extern struct peer *peer_hash[];
+extern struct peer *sys_peer;
/*
* A hack. To keep the authentication module clear of xntp-ism's, we
* include a time reset variable for its stats here.
*/
-static U_LONG auth_timereset;
+static u_long auth_timereset;
/*
* Response packet used by these routines. Also some state information
@@ -258,7 +274,7 @@ req_ack(srcadr, inter, inpkt, errcode)
/*
* send packet and bump counters
*/
- sendpkt(srcadr, inter, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
+ sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
errorcounter[errcode]++;
}
@@ -322,7 +338,7 @@ more_pkt()
rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT);
rpkt.auth_seq = AUTH_SEQ(0, seqno);
rpkt.err_nitems = htons((u_short)nitems);
- sendpkt(toaddr, frominter, (struct pkt *)&rpkt,
+ sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
RESP_HEADER_SIZE+databytes);
numresppkts++;
@@ -388,7 +404,7 @@ flush_pkt()
rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0);
rpkt.auth_seq = AUTH_SEQ(0, seqno);
rpkt.err_nitems = htons((u_short)nitems);
- sendpkt(toaddr, frominter, (struct pkt *)&rpkt,
+ sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
RESP_HEADER_SIZE+databytes);
numresppkts++;
}
@@ -481,20 +497,18 @@ process_private(rbufp, mod_okay)
* time stamp.
*/
if (proc->needs_auth) {
- register U_LONG tmp_ui;
- register U_LONG tmp_uf;
+ l_fp ftmp;
/*
* If this guy is restricted from doing this, don't let him
* If wrong key was used, or packet doesn't have mac, return.
*/
- if (!INFO_IS_AUTH(inpkt->auth_seq)
- || info_auth_keyid == 0
+ if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0
|| ntohl(inpkt->keyid) != info_auth_keyid) {
#ifdef DEBUG
if (debug > 4)
printf(
- "failed auth %d info_auth_keyid %u pkt keyid %u\n",
+ "failed auth %d info_auth_keyid %lu pkt keyid %u\n",
INFO_IS_AUTH(inpkt->auth_seq),
info_auth_keyid, ntohl(inpkt->keyid));
#endif
@@ -504,8 +518,8 @@ process_private(rbufp, mod_okay)
if (rbufp->recv_length > REQ_LEN_MAC) {
#ifdef DEBUG
if (debug > 4)
- printf("failed pkt length pkt %d req %d too long\n",
- rbufp->recv_length, REQ_LEN_MAC);
+ printf("bad pkt length %d\n",
+ rbufp->recv_length);
#endif
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
@@ -523,15 +537,12 @@ process_private(rbufp, mod_okay)
* calculate absolute time difference between xmit time stamp
* and receive time stamp. If too large, too bad.
*/
- tmp_ui = ntohl(inpkt->tstamp.l_ui);
- tmp_uf = ntohl(inpkt->tstamp.l_uf);
- M_SUB(tmp_ui, tmp_uf, rbufp->recv_time.l_ui,
- rbufp->recv_time.l_uf);
- if (M_ISNEG(tmp_ui, tmp_uf))
- M_NEG(tmp_ui, tmp_uf);
+ NTOHL_FP(&inpkt->tstamp, &ftmp);
+ L_SUB(&ftmp, &rbufp->recv_time);
+ if (L_ISNEG(&ftmp))
+ L_NEG(&ftmp);
- if (M_ISHIS(tmp_ui, tmp_uf,
- INFO_TS_MAXSKEW_UI, INFO_TS_MAXSKEW_UF)) {
+ if (ftmp.l_ui >= INFO_TS_MAXSKEW_UI) {
/*
* He's a loser. Tell him.
*/
@@ -588,8 +599,6 @@ peer_list(srcadr, inter, inpkt)
register struct info_peer_list *ip;
register struct peer *pp;
register int i;
- extern struct peer *peer_hash[];
- extern struct peer *sys_peer;
ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_peer_list));
@@ -628,8 +637,6 @@ peer_list_sum(srcadr, inter, inpkt)
register struct info_peer_summary *ips;
register struct peer *pp;
register int i;
- extern struct peer *peer_hash[];
- extern struct peer *sys_peer;
#ifdef DEBUG
if (debug > 2)
@@ -645,10 +652,14 @@ peer_list_sum(srcadr, inter, inpkt)
if (debug > 3)
printf("sum: got one\n");
#endif
- if (pp->dstadr == any_interface)
- ips->dstadr = 0;
- else
- ips->dstadr = pp->dstadr->sin.sin_addr.s_addr;
+ ips->dstadr = (pp->processed) ?
+ pp->cast_flags == MDF_BCAST ?
+ pp->dstadr->bcast.sin_addr.s_addr:
+ pp->cast_flags ?
+ pp->dstadr->sin.sin_addr.s_addr ?
+ pp->dstadr->sin.sin_addr.s_addr:
+ pp->dstadr->bcast.sin_addr.s_addr:
+ 1 : 5;
ips->srcadr = pp->srcadr.sin_addr.s_addr;
ips->srcport = pp->srcadr.sin_port;
ips->stratum = pp->stratum;
@@ -712,7 +723,14 @@ peer_info (srcadr, inter, inpkt)
ipl++;
if ((pp = findexistingpeer(&addr, (struct peer *)0)) == 0)
continue;
- ip->dstadr = NSRCADR(&pp->dstadr->sin);
+ ip->dstadr = (pp->processed) ?
+ pp->cast_flags == MDF_BCAST ?
+ pp->dstadr->bcast.sin_addr.s_addr:
+ pp->cast_flags ?
+ pp->dstadr->sin.sin_addr.s_addr ?
+ pp->dstadr->sin.sin_addr.s_addr:
+ pp->dstadr->bcast.sin_addr.s_addr:
+ 2 : 6;
ip->srcadr = NSRCADR(&pp->srcadr);
ip->srcport = NSRCPORT(&pp->srcadr);
ip->flags = 0;
@@ -743,7 +761,7 @@ peer_info (srcadr, inter, inpkt)
ip->reach = pp->reach;
ip->unreach = pp->unreach;
ip->flash = pp->flash;
- ip->estbdelay = htonl(pp->estbdelay);
+ ip->estbdelay = HTONS_FP(pp->estbdelay);
ip->ttl = pp->ttl;
ip->associd = htons(pp->associd);
ip->rootdelay = HTONS_FP(pp->rootdelay);
@@ -803,7 +821,14 @@ peer_stats (srcadr, inter, inpkt)
ipl++;
if ((pp = findexistingpeer(&addr, (struct peer *)0)) == 0)
continue;
- ip->dstadr = NSRCADR(&pp->dstadr->sin);
+ ip->dstadr = (pp->processed) ?
+ pp->cast_flags == MDF_BCAST ?
+ pp->dstadr->bcast.sin_addr.s_addr:
+ pp->cast_flags ?
+ pp->dstadr->sin.sin_addr.s_addr ?
+ pp->dstadr->sin.sin_addr.s_addr:
+ pp->dstadr->bcast.sin_addr.s_addr:
+ 3 : 7;
ip->srcadr = NSRCADR(&pp->srcadr);
ip->srcport = NSRCPORT(&pp->srcadr);
ip->flags = 0;
@@ -826,21 +851,13 @@ peer_stats (srcadr, inter, inpkt)
= htonl(pp->event_timer.event_time - current_time);
ip->timereachable = htonl(current_time - pp->timereachable);
ip->sent = htonl(pp->sent);
- ip->received = htonl(pp->received);
ip->processed = htonl(pp->processed);
- ip->badlength = 0;
ip->badauth = htonl(pp->badauth);
ip->bogusorg = htonl(pp->bogusorg);
ip->oldpkt = htonl(pp->oldpkt);
- ip->baddelay = 0;
- ip->seldelay = 0;
ip->seldisp = htonl(pp->seldisptoolarge);
ip->selbroken = htonl(pp->selbroken);
- ip->selold = htonl(pp->seltooold);
ip->candidate = pp->candidate;
- ip->falseticker = 0;
- ip->select = pp->select;
- ip->select_total = 0;
ip = (struct info_peer_stats *)more_pkt();
}
flush_pkt();
@@ -866,14 +883,16 @@ sys_info(srcadr, inter, inpkt)
extern s_char sys_precision;
extern s_fp sys_rootdelay;
extern u_fp sys_rootdispersion;
- extern U_LONG sys_refid;
+ extern u_long sys_refid;
extern l_fp sys_reftime;
extern u_char sys_poll;
extern struct peer *sys_peer;
extern int sys_bclient;
- extern U_LONG sys_bdelay;
+ extern s_fp sys_bdelay;
extern int sys_authenticate;
- extern U_LONG sys_authdelay;
+ extern u_long sys_authdelay;
+ extern u_fp clock_stability;
+ extern s_fp clock_frequency;
is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_sys));
@@ -890,6 +909,8 @@ sys_info(srcadr, inter, inpkt)
is->precision = sys_precision;
is->rootdelay = htonl(sys_rootdelay);
is->rootdispersion = htonl(sys_rootdispersion);
+ is->frequency = htonl(clock_frequency);
+ is->stability = htonl(clock_stability);
is->refid = sys_refid;
HTONL_FP(&sys_reftime, &is->reftime);
@@ -899,9 +920,20 @@ sys_info(srcadr, inter, inpkt)
if (sys_bclient)
is->flags |= INFO_FLAG_BCLIENT;
if (sys_authenticate)
- is->flags |= INFO_FLAG_AUTHENABLE;
- HTONL_UF(sys_bdelay, &is->bdelay);
+ is->flags |= INFO_FLAG_AUTHENTICATE;
+ if (pll_enable)
+ is->flags |= INFO_FLAG_PLL;
+ if (pll_control)
+ is->flags |= INFO_FLAG_PLL_SYNC;
+ if (pps_control)
+ is->flags |= INFO_FLAG_PPS_SYNC;
+ if (mon_enabled != MON_OFF)
+ is->flags |= INFO_FLAG_MONITOR;
+ if (stats_control)
+ is->flags |= INFO_FLAG_FILEGEN;
+ is->bdelay = HTONS_FP(sys_bdelay);
HTONL_UF(sys_authdelay, &is->authdelay);
+
(void) more_pkt();
flush_pkt();
}
@@ -921,15 +953,15 @@ sys_stats(srcadr, inter, inpkt)
/*
* Importations from the protocol module
*/
- extern U_LONG sys_stattime;
- extern U_LONG sys_badstratum;
- extern U_LONG sys_oldversionpkt;
- extern U_LONG sys_newversionpkt;
- extern U_LONG sys_unknownversion;
- extern U_LONG sys_badlength;
- extern U_LONG sys_processed;
- extern U_LONG sys_badauth;
- extern U_LONG sys_limitrejected;
+ extern u_long sys_stattime;
+ extern u_long sys_badstratum;
+ extern u_long sys_oldversionpkt;
+ extern u_long sys_newversionpkt;
+ extern u_long sys_unknownversion;
+ extern u_long sys_badlength;
+ extern u_long sys_processed;
+ extern u_long sys_badauth;
+ extern u_long sys_limitrejected;
ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_sys_stats));
@@ -966,10 +998,10 @@ mem_stats(srcadr, inter, inpkt)
*/
extern int peer_hash_count[HASH_SIZE];
extern int peer_free_count;
- extern U_LONG peer_timereset;
- extern U_LONG findpeer_calls;
- extern U_LONG peer_allocations;
- extern U_LONG peer_demobilizations;
+ extern u_long peer_timereset;
+ extern u_long findpeer_calls;
+ extern u_long peer_allocations;
+ extern u_long peer_demobilizations;
extern int total_peer_structs;
ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt,
@@ -1008,18 +1040,18 @@ io_stats(srcadr, inter, inpkt)
/*
* Importations from the io module
*/
- extern U_LONG io_timereset;
- extern U_LONG full_recvbufs;
- extern U_LONG free_recvbufs;
- extern U_LONG total_recvbufs;
- extern U_LONG lowater_additions;
- extern U_LONG packets_dropped;
- extern U_LONG packets_ignored;
- extern U_LONG packets_received;
- extern U_LONG packets_sent;
- extern U_LONG packets_notsent;
- extern U_LONG handler_calls;
- extern U_LONG handler_pkts;
+ extern u_long io_timereset;
+ extern u_long full_recvbufs;
+ extern u_long free_recvbufs;
+ extern u_long total_recvbufs;
+ extern u_long lowater_additions;
+ extern u_long packets_dropped;
+ extern u_long packets_ignored;
+ extern u_long packets_received;
+ extern u_long packets_sent;
+ extern u_long packets_notsent;
+ extern u_long handler_calls;
+ extern u_long handler_pkts;
io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_io_stats));
@@ -1056,10 +1088,10 @@ timer_stats(srcadr, inter, inpkt)
/*
* Importations from the timer module
*/
- extern U_LONG alarm_overflow;
- extern U_LONG timer_timereset;
- extern U_LONG timer_overflows;
- extern U_LONG timer_xmtcalls;
+ extern u_long alarm_overflow;
+ extern u_long timer_timereset;
+ extern u_long timer_overflows;
+ extern u_long timer_xmtcalls;
ts = (struct info_timer_stats *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_timer_stats));
@@ -1091,8 +1123,8 @@ loop_info(srcadr, inter, inpkt)
*/
extern l_fp last_offset;
extern s_fp drift_comp;
- extern int time_constant;
- extern U_LONG watchdog_timer;
+ extern int tc_counter;
+ extern u_long last_time;
li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_loop));
@@ -1100,8 +1132,8 @@ loop_info(srcadr, inter, inpkt)
HTONL_FP(&last_offset, &li->last_offset);
FPTOLFP(drift_comp, &tmp);
HTONL_FP(&tmp, &li->drift_comp);
- li->compliance = htonl(time_constant);
- li->watchdog_timer = htonl(watchdog_timer);
+ li->compliance = htonl(tc_counter);
+ li->watchdog_timer = htonl(current_time - last_time);
(void) more_pkt();
flush_pkt();
@@ -1139,7 +1171,7 @@ do_conf(srcadr, inter, inpkt)
&& cp->hmode != MODE_CLIENT
&& cp->hmode != MODE_BROADCAST)
fl = 1;
- if (cp->flags & ~(CONF_FLAG_AUTHENABLE|CONF_FLAG_PREFER))
+ if (cp->flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER))
fl = 1;
cp++;
}
@@ -1265,7 +1297,7 @@ set_sys_flag(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- setclr_flags(srcadr, inter, inpkt, (U_LONG)1);
+ setclr_flags(srcadr, inter, inpkt, 1);
}
@@ -1278,7 +1310,7 @@ clr_sys_flag(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- setclr_flags(srcadr, inter, inpkt, (U_LONG)0);
+ setclr_flags(srcadr, inter, inpkt, 0);
}
@@ -1290,9 +1322,9 @@ setclr_flags(srcadr, inter, inpkt, set)
struct sockaddr_in *srcadr;
struct interface *inter;
struct req_pkt *inpkt;
- U_LONG set;
+ u_long set;
{
- register U_LONG flags;
+ register u_long flags;
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
@@ -1301,21 +1333,23 @@ setclr_flags(srcadr, inter, inpkt, set)
flags = ((struct conf_sys_flags *)inpkt->data)->flags;
- if (flags
- & ~(SYS_FLAG_BCLIENT | SYS_FLAG_MCLIENT | SYS_FLAG_AUTHENTICATE)) {
+ if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_AUTHENTICATE |
+ SYS_FLAG_PLL | SYS_FLAG_MONITOR |
+ SYS_FLAG_FILEGEN)) {
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
if (flags & SYS_FLAG_BCLIENT)
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, set);
+ if (flags & SYS_FLAG_PLL)
+ proto_config(PROTO_PLL, set);
+ if (flags & SYS_FLAG_MONITOR)
+ proto_config(PROTO_MONITOR, set);
+ if (flags & SYS_FLAG_FILEGEN)
+ proto_config(PROTO_FILEGEN, set);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -1454,7 +1488,7 @@ do_restrict(srcadr, inter, inpkt, op)
bad = 1;
if (cr->flags & ~(RES_ALLFLAGS))
bad = 1;
- if (cr->addr == INADDR_ANY && cr->mask != INADDR_ANY)
+ if (cr->addr == htonl(INADDR_ANY) && cr->mask != htonl(INADDR_ANY))
bad = 1;
cr++;
}
@@ -1490,7 +1524,7 @@ do_restrict(srcadr, inter, inpkt, op)
* mon_getlist - return monitor data
*/
static void
-mon_getlist(srcadr, inter, inpkt)
+mon_getlist_0(srcadr, inter, inpkt)
struct sockaddr_in *srcadr;
struct interface *inter;
struct req_pkt *inpkt;
@@ -1502,7 +1536,7 @@ mon_getlist(srcadr, inter, inpkt)
#ifdef DEBUG
if (debug > 2)
- printf("wants monitor list\n");
+ printf("wants monitor 0 list\n");
#endif
if (!mon_enabled) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
@@ -1530,6 +1564,57 @@ mon_getlist(srcadr, inter, inpkt)
}
/*
+ * mon_getlist - return monitor data
+ */
+static void
+mon_getlist_1(srcadr, inter, inpkt)
+ struct sockaddr_in *srcadr;
+ struct interface *inter;
+ struct req_pkt *inpkt;
+{
+ register struct info_monitor_1 *im;
+ register struct mon_data *md;
+ extern struct mon_data mon_mru_list;
+ extern int mon_enabled;
+
+#ifdef DEBUG
+ if (debug > 2)
+ printf("wants monitor 1 list\n");
+#endif
+ if (!mon_enabled) {
+ req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
+ return;
+ }
+
+ im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt,
+ sizeof(struct info_monitor_1));
+ for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
+ 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->daddr = md->cast_flags == MDF_BCAST ?
+ md->interface->bcast.sin_addr.s_addr :
+ md->cast_flags ?
+ md->interface->sin.sin_addr.s_addr ?
+ md->interface->sin.sin_addr.s_addr :
+ md->interface->bcast.sin_addr.s_addr :
+ 4;
+ im->flags = md->cast_flags;
+ im->port = md->rmtport;
+ im->mode = md->mode;
+ im->version = md->version;
+ im = (struct info_monitor_1 *)more_pkt();
+ }
+ flush_pkt();
+}
+
+/*
* Module entry points and the flags they correspond with
*/
struct reset_entry {
@@ -1557,7 +1642,7 @@ reset_stats(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- U_LONG flags;
+ u_long flags;
struct reset_entry *rent;
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
@@ -1714,11 +1799,11 @@ do_trustkey(srcadr, inter, inpkt, trust)
struct req_pkt *inpkt;
int trust;
{
- register U_LONG *kp;
+ register u_long *kp;
register int items;
items = INFO_NITEMS(inpkt->err_nitems);
- kp = (U_LONG *)inpkt->data;
+ kp = (u_long *)inpkt->data;
while (items-- > 0) {
authtrust(*kp, trust);
kp++;
@@ -1742,14 +1827,13 @@ get_auth_info(srcadr, inter, inpkt)
/*
* Importations from the authentication module
*/
- extern U_LONG authnumkeys;
- extern U_LONG authnumfreekeys;
- extern U_LONG authkeylookups;
- extern U_LONG authkeynotfound;
- extern U_LONG authencryptions;
- extern U_LONG authdecryptions;
- extern U_LONG authdecryptok;
- extern U_LONG authkeyuncached;
+ extern u_long authnumkeys;
+ extern u_long authnumfreekeys;
+ extern u_long authkeylookups;
+ extern u_long authkeynotfound;
+ extern u_long authencryptions;
+ extern u_long authdecryptions;
+ extern u_long authkeyuncached;
ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_auth));
@@ -1760,7 +1844,6 @@ get_auth_info(srcadr, inter, inpkt)
ia->keynotfound = htonl(authkeynotfound);
ia->encryptions = htonl(authencryptions);
ia->decryptions = htonl(authdecryptions);
- ia->decryptok = htonl(authdecryptok);
ia->keyuncached = htonl(authkeyuncached);
ia->timereset = htonl(current_time - auth_timereset);
@@ -1780,18 +1863,16 @@ reset_auth_stats()
/*
* Importations from the authentication module
*/
- extern U_LONG authkeylookups;
- extern U_LONG authkeynotfound;
- extern U_LONG authencryptions;
- extern U_LONG authdecryptions;
- extern U_LONG authdecryptok;
- extern U_LONG authkeyuncached;
+ extern u_long authkeylookups;
+ extern u_long authkeynotfound;
+ extern u_long authencryptions;
+ extern u_long authdecryptions;
+ extern u_long authkeyuncached;
authkeylookups = 0;
authkeynotfound = 0;
authencryptions = 0;
authdecryptions = 0;
- authdecryptok = 0;
authkeyuncached = 0;
auth_timereset = current_time;
}
@@ -1837,7 +1918,7 @@ req_get_traps(srcadr, inter, inpkt)
it->settime = htonl(current_time - tr->tr_settime);
it->origtime = htonl(current_time - tr->tr_origtime);
it->resets = htonl(tr->tr_resets);
- it->flags = htonl((U_LONG)tr->tr_flags);
+ it->flags = htonl((u_long)tr->tr_flags);
it = (struct info_trap *)more_pkt();
}
}
@@ -1951,7 +2032,7 @@ set_request_keyid(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- U_LONG keyid;
+ u_long keyid;
/*
* Restrict ourselves to one item only.
@@ -1961,7 +2042,7 @@ set_request_keyid(srcadr, inter, inpkt)
return;
}
- keyid = ntohl(*((U_LONG *)(inpkt->data)));
+ keyid = ntohl(*((u_long *)(inpkt->data)));
info_auth_keyid = keyid;
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -1977,8 +2058,8 @@ set_control_keyid(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- U_LONG keyid;
- extern U_LONG ctl_auth_keyid;
+ u_long keyid;
+ extern u_long ctl_auth_keyid;
/*
* Restrict ourselves to one item only.
@@ -1988,7 +2069,7 @@ set_control_keyid(srcadr, inter, inpkt)
return;
}
- keyid = ntohl(*((U_LONG *)(inpkt->data)));
+ keyid = ntohl(*((u_long *)(inpkt->data)));
ctl_auth_keyid = keyid;
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -2009,21 +2090,21 @@ get_ctl_stats(srcadr, inter, inpkt)
/*
* Importations from the control module
*/
- extern U_LONG ctltimereset;
- extern U_LONG numctlreq;
- extern U_LONG numctlbadpkts;
- extern U_LONG numctlresponses;
- extern U_LONG numctlfrags;
- extern U_LONG numctlerrors;
- extern U_LONG numctltooshort;
- extern U_LONG numctlinputresp;
- extern U_LONG numctlinputfrag;
- extern U_LONG numctlinputerr;
- extern U_LONG numctlbadoffset;
- extern U_LONG numctlbadversion;
- extern U_LONG numctldatatooshort;
- extern U_LONG numctlbadop;
- extern U_LONG numasyncmsgs;
+ extern u_long ctltimereset;
+ extern u_long numctlreq;
+ extern u_long numctlbadpkts;
+ extern u_long numctlresponses;
+ extern u_long numctlfrags;
+ extern u_long numctlerrors;
+ extern u_long numctltooshort;
+ extern u_long numctlinputresp;
+ extern u_long numctlinputfrag;
+ extern u_long numctlinputerr;
+ extern u_long numctlbadoffset;
+ extern u_long numctlbadversion;
+ extern u_long numctldatatooshort;
+ extern u_long numctlbadop;
+ extern u_long numasyncmsgs;
ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_control));
@@ -2072,13 +2153,13 @@ get_leap_info(srcadr, inter, inpkt)
extern u_char leap_indicator;
extern u_char leap_warning;
extern u_char leapbits;
- extern U_LONG leap_timer;
- extern U_LONG leap_processcalls;
- extern U_LONG leap_notclose;
- extern U_LONG leap_monthofleap;
- extern U_LONG leap_dayofleap;
- extern U_LONG leap_hoursfromleap;
- extern U_LONG leap_happened;
+ extern u_long leap_timer;
+ extern u_long leap_processcalls;
+ extern u_long leap_notclose;
+ extern u_long leap_monthofleap;
+ extern u_long leap_dayofleap;
+ extern u_long leap_hoursfromleap;
+ extern u_long leap_happened;
il = (struct info_leap *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_leap));
@@ -2198,7 +2279,7 @@ get_clock_info(srcadr, inter, inpkt)
ic->noresponse = htonl(clock.noresponse);
ic->badformat = htonl(clock.badformat);
ic->baddata = htonl(clock.baddata);
- ic->timestarted = clock.timereset;
+ ic->timestarted = htonl(clock.timereset);
HTONL_FP(&clock.fudgetime1, &ic->fudgetime1);
HTONL_FP(&clock.fudgetime2, &ic->fudgetime2);
ic->fudgeval1 = htonl(clock.fudgeval1);
@@ -2285,9 +2366,9 @@ set_precision(srcadr, inter, inpkt)
struct interface *inter;
struct req_pkt *inpkt;
{
- register LONG precision;
+ register long precision;
- precision = ntohl(*(LONG *)(inpkt->data));
+ precision = ntohl(*(long *)(inpkt->data));
if (INFO_NITEMS(inpkt->err_nitems) > 1 ||
precision > -1 || precision < -20) {
@@ -2353,10 +2434,9 @@ get_clkbug_info(srcadr, inter, inpkt)
if (i > NUMCBUGTIMES)
i = NUMCBUGTIMES;
ic->ntimes = (u_char)i;
- ic->stimes = htonl((U_LONG)bug.stimes & ((1<<i)-1));
+ ic->stimes = htonl(bug.stimes);
while (--i >= 0) {
- ic->times[i].l_ui = htonl(bug.times[i].l_ui);
- ic->times[i].l_uf = htonl(bug.times[i].l_uf);
+ HTONL_FP(&bug.times[i], &ic->times[i]);
}
ic = (struct info_clkbug *)more_pkt();
diff --git a/usr.sbin/xntpd/xntpd/ntp_restrict.c b/usr.sbin/xntpd/xntpd/ntp_restrict.c
index 43f01f296624..0cc4b7d304b9 100644
--- a/usr.sbin/xntpd/xntpd/ntp_restrict.c
+++ b/usr.sbin/xntpd/xntpd/ntp_restrict.c
@@ -54,10 +54,10 @@ static int restrictcount; /* count of entries in the restriction list */
static struct restrictlist *resfree;
static int numresfree; /* number of structures on free list */
-U_LONG res_calls;
-U_LONG res_found;
-U_LONG res_not_found;
-U_LONG res_timereset;
+u_long res_calls;
+u_long res_found;
+u_long res_not_found;
+u_long res_timereset;
/*
* Parameters of the RES_LIMITED restriction option.
@@ -65,14 +65,14 @@ U_LONG res_timereset;
* 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;
+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;
+u_long res_limited_refcnt;
/*
* Our initial allocation of list entries.
@@ -82,7 +82,7 @@ static struct restrictlist resinit[INITRESLIST];
/*
* Imported from the timer module
*/
-extern U_LONG current_time;
+extern u_long current_time;
/*
* debug flag
@@ -116,7 +116,7 @@ init_restrict()
* list as our default entry. Everything in here
* should be zero for now.
*/
- resinit[0].addr = INADDR_ANY;
+ resinit[0].addr = htonl(INADDR_ANY);
resinit[0].mask = 0;
restrictlist = &resinit[0];
restrictcount = 1;
@@ -137,9 +137,9 @@ init_restrict()
client_limit_period = 3600;
res_limited_refcnt = 0;
- sprintf(bp, "client_limit=%d", client_limit);
+ sprintf(bp, "client_limit=%ld", client_limit);
set_sys_var(bp, strlen(bp)+1, RO);
- sprintf(bp, "client_limit_period=%d", client_limit_period);
+ sprintf(bp, "client_limit_period=%ld", client_limit_period);
set_sys_var(bp, strlen(bp)+1, RO);
}
@@ -153,7 +153,7 @@ restrictions(srcadr)
{
register struct restrictlist *rl;
register struct restrictlist *match;
- register U_LONG hostaddr;
+ register u_long hostaddr;
register int isntpport;
res_calls++;
@@ -210,7 +210,7 @@ restrictions(srcadr)
#ifdef DEBUG
if (debug > 2)
- printf("limited clients check: %d clients, period %d seconds, net is 0x%X\n",
+ printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n",
client_limit, client_limit_period,
netof(hostaddr));
#endif /*DEBUG*/
@@ -238,7 +238,7 @@ restrictions(srcadr)
> client_limit_period) {
#ifdef DEBUG
if (debug > 5)
- printf("checking: %s: ignore: too old: %d\n",
+ printf("checking: %s: ignore: too old: %ld\n",
numtoa(md->rmtadr),
current_time - md->lasttime);
#endif
@@ -259,7 +259,7 @@ restrictions(srcadr)
netof(hostaddr)) {
#ifdef DEBUG
if (debug > 5)
- printf("checking: %s: different net 0x%X\n",
+ printf("checking: %s: different net 0x%lX\n",
numtoa(md->rmtadr),
netof(md->rmtadr));
#endif
@@ -286,7 +286,7 @@ restrictions(srcadr)
}
#ifdef DEBUG
if (debug > 4)
- printf("this one is rank %d in list, limit is %d: %s\n",
+ printf("this one is rank %d in list, limit is %lu: %s\n",
lcnt, client_limit,
(lcnt <= client_limit) ? "ALLOW" : "REJECT");
#endif
@@ -312,8 +312,8 @@ restrict(op, resaddr, resmask, mflags, flags)
int mflags;
int flags;
{
- register U_LONG addr;
- register U_LONG mask;
+ register u_long addr;
+ register u_long mask;
register struct restrictlist *rl;
register struct restrictlist *rlprev;
int i;
@@ -329,7 +329,7 @@ restrict(op, resaddr, resmask, mflags, flags)
* If this is the default address, point at first on list. Else
* go searching for it.
*/
- if (addr == INADDR_ANY) {
+ if (addr == htonl(INADDR_ANY)) {
rlprev = 0;
rl = restrictlist;
} else {
@@ -433,7 +433,7 @@ restrict(op, resaddr, resmask, mflags, flags)
* interface entry.
*/
if (rl != 0
- && rl->addr != INADDR_ANY
+ && rl->addr != htonl(INADDR_ANY)
&& !(rl->mflags & RESM_INTERFACE)) {
rlprev->next = rl->next;
restrictcount--;
diff --git a/usr.sbin/xntpd/xntpd/ntp_timer.c b/usr.sbin/xntpd/xntpd/ntp_timer.c
index e3ba54cd39bc..99551f74a9f3 100644
--- a/usr.sbin/xntpd/xntpd/ntp_timer.c
+++ b/usr.sbin/xntpd/xntpd/ntp_timer.c
@@ -1,4 +1,4 @@
-/* ntp_timer.c,v 3.1 1993/07/06 01:11:29 jbj Exp
+/*
* ntp_event.c - event timer support routines
*/
#include <stdio.h>
@@ -30,18 +30,18 @@ int alarm_flag;
/*
* adjust and hourly counters
*/
-static U_LONG adjust_timer;
-static U_LONG hourly_timer;
+static u_long adjust_timer;
+static u_long hourly_timer;
/*
* Imported from the leap module. The leap timer.
*/
-extern U_LONG leap_timer;
+extern u_long leap_timer;
/*
* Statistics counter for the interested.
*/
-U_LONG alarm_overflow;
+u_long alarm_overflow;
#define HOUR (60*60)
@@ -50,15 +50,15 @@ U_LONG alarm_overflow;
* increments of 2**EVENT_TIMEOUT seconds. The timer queue is the
* hash into which we sort timer entries.
*/
-U_LONG current_time;
+u_long current_time;
struct event timerqueue[TIMER_NSLOTS];
/*
* Stats. Number of overflows and number of calls to transmit().
*/
-U_LONG timer_timereset;
-U_LONG timer_overflows;
-U_LONG timer_xmtcalls;
+u_long timer_timereset;
+u_long timer_overflows;
+u_long timer_xmtcalls;
static RETSIGTYPE alarming P((int));
diff --git a/usr.sbin/xntpd/xntpd/ntp_unixclock.c b/usr.sbin/xntpd/xntpd/ntp_unixclock.c
index 1950d8c06fb3..6b81429ca626 100644
--- a/usr.sbin/xntpd/xntpd/ntp_unixclock.c
+++ b/usr.sbin/xntpd/xntpd/ntp_unixclock.c
@@ -1,4 +1,4 @@
-/* ntp_unixclock.c,v 3.1 1993/07/06 01:11:30 jbj Exp
+/*
* ntp_unixclock.c - routines for reading and adjusting a 4BSD-style
* system clock
*/
@@ -9,7 +9,7 @@
#include <sys/stat.h>
#include <sys/time.h>
-#if defined(SYS_HPUX) || defined(sgi) || defined(SYS_BSDI)
+#if defined(SYS_HPUX) || defined(sgi) || defined(SYS_BSDI) || defined(SYS_44BSD)
#include <sys/param.h>
#include <utmp.h>
#endif
@@ -20,7 +20,7 @@
#include "ntp_stdlib.h"
#if defined(HAVE_LIBKVM)
-#ifdef SYS_BSDI
+#if defined(SYS_BSDI) || defined(SYS_44BSD)
#include <sys/proc.h>
#endif /* SYS_BSDI */
#include <kvm.h>
@@ -61,19 +61,19 @@ extern int debug;
* We also remember the clock precision we computed from the kernel in
* case someone asks us.
*/
-extern LONG adj_precision; /* adj precision in usec (tickadj) */
-extern LONG tvu_maxslew; /* maximum adjust doable in 1<<CLOCK_ADJ sec (usec) */
+extern long adj_precision; /* adj precision in usec (tickadj) */
+extern long tvu_maxslew; /* maximum adjust doable in 1<<CLOCK_ADJ sec (usec) */
-extern U_LONG tsf_maxslew; /* same as above, as LONG format */
+extern u_long tsf_maxslew; /* same as above, as long format */
extern l_fp sys_clock_offset; /* correction for current system time */
/*
* Import sys_clock (it is updated in get_systime)
*/
-extern LONG sys_clock;
+extern long sys_clock;
-static void clock_parms P((U_LONG *, U_LONG *));
+static void clock_parms P((u_long *, u_long *));
/*
* init_systime - initialize the system clock support code, return
@@ -97,9 +97,9 @@ static void clock_parms P((U_LONG *, U_LONG *));
void
init_systime()
{
- U_LONG tickadj;
- U_LONG tick;
- U_LONG hz;
+ u_long tickadj;
+ u_long tick;
+ u_long hz;
/*
* Obtain the values
@@ -107,7 +107,7 @@ init_systime()
clock_parms(&tickadj, &tick);
#ifdef DEBUG
if (debug)
- printf("kernel vars: tickadj = %d, tick = %d\n", tickadj, tick);
+ printf("kernel vars: tickadj = %ld, tick = %ld\n", tickadj, tick);
#endif
/*
@@ -162,14 +162,14 @@ init_systime()
#ifdef DEBUG
if (debug)
printf(
- "adj_precision = %d, tvu_maxslew = %d, tsf_maxslew = 0.%08x\n",
+ "adj_precision = %ld, tvu_maxslew = %ld, tsf_maxslew = 0.%08lx\n",
adj_precision, tvu_maxslew, tsf_maxslew);
#endif
/*
* Set the current offset to 0
*/
- sys_clock_offset.l_ui = sys_clock_offset.l_uf = 0;
+ L_CLR(&sys_clock_offset);
}
#ifdef HAVE_LIBKVM
@@ -180,8 +180,8 @@ init_systime()
*/
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
static struct nlist nl[] = {
#define N_TICKADJ 0
@@ -261,8 +261,8 @@ clock_parms(tickadj, tick)
*/
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
*tick = 10000; /* microseconds */
*tickadj = 80; /* microseconds */
@@ -275,8 +275,13 @@ clock_parms(tickadj, tick)
#endif
#ifdef SYS_HPUX
+#if defined(hp9000s300)
#define K_TICKADJ_NAME "_tickadj"
#define K_TICK_NAME "_old_tick"
+#else
+#define K_TICKADJ_NAME "tickadj"
+#define K_TICK_NAME "old_tick"
+#endif
#endif
/* The defaults if not defined previously */
@@ -289,8 +294,8 @@ clock_parms(tickadj, tick)
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
register int i;
int kmem;
@@ -377,8 +382,8 @@ clock_parms(tickadj, tick)
}
close(kmem);
- *tickadj = (U_LONG)vars[K_TICKADJ];
- *tick = (U_LONG)vars[K_TICK];
+ *tickadj = (u_long)vars[K_TICKADJ];
+ *tick = (u_long)vars[K_TICK];
#undef K_TICKADJ
#undef K_TICK
@@ -398,8 +403,8 @@ clock_parms(tickadj, tick)
*/
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
int hz;
@@ -427,8 +432,8 @@ clock_parms(tickadj, tick)
*/
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
*tick = 10000;
*tickadj = 150;
@@ -448,8 +453,8 @@ clock_parms(tickadj, tick)
*/
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
#ifdef RS6000
*tickadj = 1000;
@@ -481,8 +486,8 @@ clock_parms(tickadj, tick)
*/
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
register int i;
int kmem;
@@ -560,8 +565,8 @@ clock_parms(tickadj, tick)
}
close(kmem);
- *tickadj = (U_LONG)vars[K_TICKADJ];
- *tick = (U_LONG)(1000000/sysconf(_SC_CLK_TCK));
+ *tickadj = (u_long)vars[K_TICKADJ];
+ *tick = (u_long)(1000000/sysconf(_SC_CLK_TCK));
#undef K_TICKADJ
#undef N_NAME
@@ -569,18 +574,18 @@ clock_parms(tickadj, tick)
#endif /* SOLARIS */
#ifdef SYS_LINUX
-#include <sys/timex.h>
+#include "sys/timex.h"
static void
clock_parms(tickadj, tick)
- U_LONG *tickadj;
- U_LONG *tick;
+ u_long *tickadj;
+ u_long *tick;
{
struct timex txc;
txc.mode = 0;
__adjtimex(&txc);
- *tickadj = (U_LONG)1; /* our adjtime is accurate */
- *tick = (U_LONG)txc.tick;
+ *tickadj = (u_long)1; /* our adjtime is accurate */
+ *tick = (u_long)txc.tick;
}
#endif /* SYS_LINUX */
diff --git a/usr.sbin/xntpd/xntpd/ntp_util.c b/usr.sbin/xntpd/xntpd/ntp_util.c
index 4cbb7ac27f53..540be62a675a 100644
--- a/usr.sbin/xntpd/xntpd/ntp_util.c
+++ b/usr.sbin/xntpd/xntpd/ntp_util.c
@@ -1,4 +1,4 @@
-/* ntp_util.c,v 3.1 1993/07/06 01:11:31 jbj Exp
+/*
* ntp_util.c - stuff I didn't have any other place for
*/
#include <stdio.h>
@@ -59,6 +59,12 @@ static FILEGEN clockstats;
*/
extern int errno;
+/*
+ * This controls whether stats are written to the fileset. Provided
+ * so that xntpdc can turn off stats when the file system fills up.
+ */
+int stats_control;
+
#ifdef DEBUG
extern int debug;
#endif
@@ -116,12 +122,11 @@ init_util()
void
hourly_stats()
{
- int fd;
- char *val;
- int vallen;
+ FILE *fp;
extern l_fp last_offset;
extern s_fp drift_comp;
- extern int time_constant;
+ extern u_char sys_poll;
+ extern int pll_status;
#ifdef DOSYNCTODR
struct timeval tv;
@@ -165,32 +170,21 @@ hourly_stats()
skip:
#endif
- syslog(LOG_INFO, "offset %s freq %s comp %d",
- lfptoa(&last_offset, 6), fptoa(drift_comp, 5), time_constant);
+ syslog(LOG_INFO, "offset %s freq %s poll %d",
+ lfptoa(&last_offset, 6), fptoa(drift_comp, 3),
+ sys_poll);
if (stats_drift_file != 0) {
- fd = open(stats_temp_file, O_WRONLY|O_TRUNC|O_CREAT, 0644);
- if (fd == -1) {
- syslog(LOG_ERR, "can't open %s: %m", stats_temp_file);
+ if ((fp = fopen(stats_temp_file, "w")) == NULL) {
+ syslog(LOG_ERR, "can't open %s: %m",
+ stats_temp_file);
return;
}
-
- val = fptoa(drift_comp, 5);
- vallen = strlen(val);
- /*
- * Hack here. Turn the trailing \0 into a \n and write it.
- */
- val[vallen] = '\n';
- if (write(fd, val, vallen+1) == -1) {
- syslog(LOG_ERR, "write to %s failed: %m",
- stats_temp_file);
- (void) close(fd);
- (void) unlink(stats_temp_file);
- } else {
- (void) close(fd);
- /* atomic */
- (void) rename(stats_temp_file, stats_drift_file);
- }
+ fprintf(fp, "%s %x\n", fptoa(drift_comp, 3),
+ pll_status);
+ (void)fclose(fp);
+ /* atomic */
+ (void) rename(stats_temp_file, stats_drift_file);
}
}
@@ -203,11 +197,11 @@ stats_config(item, value)
int item;
char *value; /* only one type so far */
{
- register char *cp;
FILE *fp;
- int len;
char buf[128];
l_fp old_drift;
+ int temp = 0;
+ int len;
switch(item) {
case STATS_FREQ_FILE:
@@ -222,19 +216,17 @@ stats_config(item, value)
break;
stats_drift_file = emalloc((u_int)(len + 1));
- stats_temp_file = emalloc((u_int)(len + sizeof(".TEMP")));
+ stats_temp_file = emalloc((u_int)(len +
+ sizeof(".TEMP")));
memmove(stats_drift_file, value, len+1);
memmove(stats_temp_file, value, len);
- memmove(stats_temp_file + len, ".TEMP", sizeof(".TEMP"));
+ memmove(stats_temp_file + len, ".TEMP",
+ sizeof(".TEMP"));
L_CLR(&old_drift);
-#ifdef DEBUG
- if (debug > 1) {
- printf("stats drift file %s\n", stats_drift_file);
- printf("stats temp file %s\n", stats_temp_file);
- }
-#endif
-
+ /*
+ * Open drift file and read frequency and mode.
+ */
if ((fp = fopen(stats_drift_file, "r")) == NULL) {
if (errno != ENOENT)
syslog(LOG_ERR, "can't open %s: %m",
@@ -243,71 +235,48 @@ stats_config(item, value)
break;
}
- if (fgets(buf, sizeof buf, fp) == NULL) {
+ if (fscanf(fp, "%s %x", buf, &temp) == 0) {
syslog(LOG_ERR, "can't read %s: %m",
stats_drift_file);
(void) fclose(fp);
loop_config(LOOP_DRIFTCOMP, &old_drift, 0);
break;
}
-
(void) fclose(fp);
-
- /*
- * We allow leading spaces, then the number. Terminate
- * at any trailing space or string terminator.
- */
- cp = buf;
- while (isspace(*cp))
- cp++;
- while (*cp != '\0' && !isspace(*cp))
- cp++;
- *cp = '\0';
-
if (!atolfp(buf, &old_drift)) {
syslog(LOG_ERR, "drift value %s invalid", buf);
break;
}
-
- /*
- * Finally! Give value to the loop filter.
- */
-#ifdef DEBUG
- if (debug > 1) {
- printf("loop_config finds old drift of %s\n",
- lfptoa(&old_drift, 9));
- }
-#endif
- loop_config(LOOP_DRIFTCOMP, &old_drift, 0);
+ loop_config(LOOP_DRIFTCOMP, &old_drift, temp);
break;
case STATS_STATSDIR:
if (strlen(value) >= sizeof(statsdir)) {
syslog(LOG_ERR,
- "value for statsdir too LONG (>%d, sigh)",
+ "value for statsdir too long (>%d, sigh)",
sizeof(statsdir)-1);
} else {
l_fp now;
- strcpy(statsdir,value);
gettstamp(&now);
+ strcpy(statsdir,value);
if(peerstats.prefix == &statsdir[0] &&
peerstats.fp != NULL) {
fclose(peerstats.fp);
peerstats.fp = NULL;
- filegen_setup(&peerstats,now.l_ui);
+ filegen_setup(&peerstats, now.l_ui);
}
if(loopstats.prefix == &statsdir[0] &&
loopstats.fp != NULL) {
fclose(loopstats.fp);
loopstats.fp = NULL;
- filegen_setup(&loopstats,now.l_ui);
+ filegen_setup(&loopstats, now.l_ui);
}
if(clockstats.prefix == &statsdir[0] &&
clockstats.fp != NULL) {
fclose(clockstats.fp);
clockstats.fp = NULL;
- filegen_setup(&clockstats,now.l_ui);
+ filegen_setup(&clockstats, now.l_ui);
}
}
break;
@@ -348,14 +317,16 @@ record_peer_stats(addr, status, offset, delay, dispersion)
u_fp dispersion;
{
struct timeval tv;
- U_LONG day, sec, msec;
+ u_long day, sec, msec;
+ if (!stats_control)
+ return;
GETTIMEOFDAY(&tv, (struct timezone *)NULL);
- day = (U_LONG)tv.tv_sec / 86400 + MJD_1970;
- sec = (U_LONG)tv.tv_sec % 86400;
- msec = (U_LONG)tv.tv_usec / 1000;
+ day = tv.tv_sec / 86400 + MJD_1970;
+ sec = tv.tv_sec % 86400;
+ msec = tv.tv_usec / 1000;
- filegen_setup(&peerstats, (U_LONG)(tv.tv_sec + JAN_1970));
+ filegen_setup(&peerstats, (u_long)(tv.tv_sec + JAN_1970));
if (peerstats.fp != NULL) {
fprintf(peerstats.fp, "%lu %lu.%03lu %s %x %s %s %s\n",
day, sec, msec, ntoa(addr), status, lfptoa(offset, 6),
@@ -374,24 +345,26 @@ record_peer_stats(addr, status, offset, delay, dispersion)
* time constant (log base 2)
*/
void
-record_loop_stats(offset, drift_comp, time_constant)
+record_loop_stats(offset, freq, poll)
l_fp *offset;
- s_fp *drift_comp;
- int time_constant;
+ s_fp freq;
+ u_char poll;
{
struct timeval tv;
- U_LONG day, sec, msec;
+ u_long day, sec, msec;
+ if (!stats_control)
+ return;
GETTIMEOFDAY(&tv, (struct timezone *)NULL);
- day = (U_LONG)tv.tv_sec / 86400 + MJD_1970;
- sec = (U_LONG)tv.tv_sec % 86400;
- msec = (U_LONG)tv.tv_usec / 1000;
+ day = tv.tv_sec / 86400 + MJD_1970;
+ sec = tv.tv_sec % 86400;
+ msec = tv.tv_usec / 1000;
- filegen_setup(&loopstats, (U_LONG)(tv.tv_sec + JAN_1970));
+ filegen_setup(&loopstats, (u_long)(tv.tv_sec + JAN_1970));
if (loopstats.fp != NULL) {
fprintf(loopstats.fp, "%lu %lu.%03lu %s %s %d\n",
day, sec, msec, lfptoa(offset, 6),
- fptoa(*drift_comp, 4), time_constant);
+ fptoa(freq, 4), poll);
fflush(loopstats.fp);
}
}
@@ -411,14 +384,16 @@ record_clock_stats(addr, text)
char *text;
{
struct timeval tv;
- U_LONG day, sec, msec;
+ u_long day, sec, msec;
+ if (!stats_control)
+ return;
GETTIMEOFDAY(&tv, (struct timezone *)NULL);
- day = (U_LONG)tv.tv_sec / 86400 + MJD_1970;
- sec = (U_LONG)tv.tv_sec % 86400;
- msec = (U_LONG)tv.tv_usec / 1000;
+ day = tv.tv_sec / 86400 + MJD_1970;
+ sec = tv.tv_sec % 86400;
+ msec = tv.tv_usec / 1000;
- filegen_setup(&clockstats, (U_LONG)(tv.tv_sec + JAN_1970));
+ filegen_setup(&clockstats, (u_long)(tv.tv_sec + JAN_1970));
if (clockstats.fp != NULL) {
fprintf(clockstats.fp, "%lu %lu.%03lu %s %s\n",
day, sec, msec, ntoa(addr), text);
diff --git a/usr.sbin/xntpd/xntpd/ntpd.c b/usr.sbin/xntpd/xntpd/ntpd.c
index 9ed43c5c4a81..43ae699c97a2 100644
--- a/usr.sbin/xntpd/xntpd/ntpd.c
+++ b/usr.sbin/xntpd/xntpd/ntpd.c
@@ -1,4 +1,4 @@
-/* ntpd.c,v 3.1 1993/07/06 01:11:32 jbj Exp
+/*
* ntpd.c - main program for the fixed point NTP daemon
*/
#include <stdio.h>
@@ -75,7 +75,7 @@ extern char *Version;
*/
extern int alarm_flag;
-#if !defined(SYS_386BSD) && !defined(SYS_BSDI)
+#if !defined(SYS_386BSD) && !defined(SYS_BSDI) && !defined(SYS_44BSD)
/*
* We put this here, since the argument profile is syscall-specific
*/
@@ -130,7 +130,7 @@ main(argc, argv)
exit(0);
{
- unsigned long s;
+ u_long s;
int max_fd;
#if defined(NTP_POSIX_SOURCE) && !defined(SYS_386BSD)
max_fd = sysconf(_SC_OPEN_MAX);
@@ -169,7 +169,7 @@ main(argc, argv)
fid = open("/dev/tty", 2);
if (fid >= 0) {
- (void) ioctl(fid, (U_LONG) TIOCNOTTY,
+ (void) ioctl(fid, (u_long) TIOCNOTTY,
(char *) 0);
(void) close(fid);
}
@@ -279,6 +279,13 @@ main(argc, argv)
#endif /* DEBUG */
/*
+ * Set up signals we should never pay attention to.
+ */
+#ifdef SIGPIPE
+ (void) signal_no_reset(SIGPIPE, SIG_IGN);
+#endif /* SIGPIPE */
+
+ /*
* Call the init_ routines to initialize the data structures.
* Note that init_systime() may run a protocol to get a crude
* estimate of the time as an NTP client when running on the
@@ -307,6 +314,9 @@ main(argc, argv)
init_io();
init_loopfilter();
+ mon_start(MON_ON); /* monitor on by default now */
+ /* turn off in config if unwanted */
+
/*
* Get configuration. This (including argument list parsing) is
* done in a separate module since this will definitely be different
@@ -361,10 +371,8 @@ main(argc, argv)
get_systime(&ts);
(void)input_handler(&ts);
- }
- else if (nfound == -1 && errno != EINTR) {
+ } else if (nfound == -1 && errno != EINTR)
syslog(LOG_ERR, "select() error: %m");
- }
#else
wait_for_signal();
#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_acts.c b/usr.sbin/xntpd/xntpd/refclock_acts.c
new file mode 100644
index 000000000000..af3cabf11c82
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_acts.c
@@ -0,0 +1,895 @@
+/*
+ * refclock_acts - clock driver for the NIST Automated Computer Time
+ * Service aka Amalgamated Containerized Trash Service (ACTS)
+ */
+#if defined(REFCLOCK) && defined(ACTS)
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_unixtime.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the NIST Automated Computer Time Service (ACTS).
+ * It periodically dials a prespecified telephone number, receives the
+ * NIST timecode data and calculates the local clock correction. It is
+ * designed primarily for use as a backup when neither a radio clock nor
+ * connectivity to Internet time servers is available. For the best
+ * accuracy, the individual telephone line/modem delay needs to be
+ * calibrated using outside sources.
+ *
+ * The ACTS is located at NIST Boulder, CO, telephone 303 494 4774. A
+ * toll call from a residence telephone in Newark, DE, costs between 14
+ * and 27 cents, depending on time of day, and from a campus telephone
+ * between 3 and 4 cents, although it is not clear what carrier and time
+ * of day discounts apply in this case. The modem dial string will
+ * differ depending on local telephone configuration, etc., and is
+ * specified by the phone command in the configuration file. The
+ * argument to this command is an AT command for a Hayes compatible
+ * modem.
+ *
+ * The accuracy produced by this driver should be in the range of a
+ * millisecond or two, but may need correction due to the delay
+ * characteristics of the individual modem involved. For undetermined
+ * reasons, some modems work with the ACTS echo-delay measurement scheme
+ * and some don't. This driver tries to do the best it can with what it
+ * gets. Initial experiments with a Practical Peripherals 9600SA modem
+ * here in Delaware suggest an accuracy of a millisecond or two can be
+ * achieved without the scheme by using a fudge time1 value of 65.0 ms.
+ * In either case, the dispersion for a single call involving ten
+ * samples is about 1.3 ms.
+ *
+ * The driver can operate in either of three modes, as determined by
+ * the mode parameter in the server configuration command. In mode 0
+ * (automatic) the driver operates continuously at intervals depending
+ * on the prediction error, as measured by the driver, usually in the
+ * order of several hours. In mode 1 (backup) the driver is enabled in
+ * automatic mode only when no other source of synchronization is
+ * available and when more than MAXOUTAGE (3600 s) have elapsed since
+ * last synchronized by other sources. In mode 2 (manual) the driver
+ * operates only when enabled using a fudge flags switch, as described
+ * below.
+ *
+ * For reliable call management, this driver requires a 1200-bps modem
+ * with a Hayes-compatible command set and control over the modem data
+ * terminal ready (DTR) control line. Present restrictions require the
+ * use of a POSIX-compatible programming interface, although other
+ * interfaces may work as well. The modem setup string is hard-coded in
+ * the driver and may require changes for nonstandard modems or special
+ * circumstances.
+ *
+ * Further information can be found in the README.refclock file in the
+ * xntp3 distribution.
+ *
+ * Fudge Factors
+ *
+ * Ordinarily, the propagation time correction is computed automatically
+ * by ACTS and the driver. When this is not possible or erratic due to
+ * individual modem characteristics, the fudge flag2 switch should be
+ * set to disable the ACTS echo-delay scheme. In any case, the fudge
+ * time1 parameter can be used to adjust the propagation delay as
+ * required.
+ *
+ * The ACTS call interval is determined in one of three ways. In manual
+ * mode a call is initiated by setting fudge flag1 using xntpdc, either
+ * manually or via a cron job. In AUTO mode this flag is set by the peer
+ * timer, which is controlled by the sys_poll variable in response to
+ * measured errors. In backup mode the driver is ordinarily asleep, but
+ * awakes (in auto mode) if all other synchronization sources are lost.
+ * In either auto or backup modes, the call interval increases as long
+ * as the measured errors do not exceed the value of the fudge time2
+ * parameter.
+ *
+ * When the fudge flag1 is set, the ACTS calling program is activated.
+ * This program dials each number listed in the phones command of the
+ * configuration file in turn. If a call attempt fails, the next number
+ * in the list is dialed. The fudge flag1 and counter are reset and the
+ * calling program terminated if (a) a valid clock update has been
+ * determined, (b) no more numbers remain in the list, (c) a device
+ * fault or timeout occurs or (d) fudge flag1 is reset manually using
+ * xntpdc.
+ *
+ * In automatic and backup modes, the driver determines the call
+ * interval using a procedure depending on the measured prediction
+ * error and the fudge time2 parameter. If the error exceeds time2 for a
+ * number of times depending on the current interval, the interval is
+ * decreased, but not less than about 1000 s. If the error is less than
+ * time2 for some number of times, the interval is increased, but not
+ * more than about 18 h. With the default value of zero for fudge time2,
+ * the interval will increase from 1000 s to the 4000-8000-s range, in
+ * which the expected accuracy should be in the 1-2-ms range. Setting
+ * fudge time2 to a large value, like 0.1 s, may result in errors of
+ * that order, but increase the call interval to the maximum. The exact
+ * value for each configuration will depend on the modem and operating
+ * system involved, so some experimentation may be necessary.
+ */
+
+/*
+ * DESCRIPTION OF THE AUTOMATED COMPUTER TELEPHONE SERVICE (ACTS)
+ * (reformatted from ACTS on-line computer help information)
+ *
+ * The following is transmitted (at 1200 baud) following completion of
+ * the telephone connection.
+ *
+ * National Institute of Standards and Technology
+ * Telephone Time Service, Generator 3B
+ * Enter question mark "?" for HELP
+ * D L D
+ * MJD YR MO DA H M S ST S UT1 msADV <OTM>
+ * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:16 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:17 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:18 50 0 +.1 045.0 UTC(NIST) *
+ * 47999 90-04-18 21:39:19 50 0 +.1 037.6 UTC(NIST) #
+ * 47999 90-04-18 21:39:20 50 0 +.1 037.6 UTC(NIST) #
+ * etc..etc...etc.......
+ *
+ * UTC = Universal Time Coordinated, the official world time referred to
+ * the zero meridian.
+ *
+ * DST Daylight savings time characters, valid for the continental
+ * U.S., are set as follows:
+ *
+ * 00 We are on standard time (ST).
+ * 01-49 Now on DST, go to ST when your local time is 2:00 am and
+ * the count is 01. The count is decremented daily at 00
+ * (UTC).
+ * 50 We are on DST.
+ * 51-99 Now on ST, go to DST when your local time is 2:00 am and
+ * the count is 51. The count is decremented daily at 00
+ * (UTC).
+ *
+ * The two DST characters provide up to 48 days advance notice of a
+ * change in time. The count remains at 00 or 50 at other times.
+ *
+ * LS Leap second flag is set to "1" to indicate that a leap second is
+ * to be added as 23:59:60 (UTC) on the last day of the current UTC
+ * month. The LS flag will be reset to "0" starting with 23:59:60
+ * (UTC). The flag will remain on for the entire month before the
+ * second is added. Leap seconds are added as needed at the end of
+ * any month. Usually June and/or December are chosen.
+ *
+ * The leap second flag will be set to a "2" to indicate that a
+ * leap second is to be deleted at 23:59:58--00:00:00 on the last
+ * day of the current month. (This latter provision is included per
+ * international recommendation, however it is not likely to be
+ * required in the near future.)
+ *
+ * DUT1 Approximate difference between earth rotation time (UT1) and
+ * UTC, in steps of 0.1 second: DUT1 = UT1 - UTC.
+ *
+ * MJD Modified Julian Date, often used to tag certain scientific data.
+ *
+ * The full time format is sent at 1200 baud, 8 bit, 1 stop, no parity.
+ * The format at 300 Baud is also 8 bit, 1 stop, no parity. At 300 Baud
+ * the MJD and DUT1 values are deleted and the time is transmitted only
+ * on even seconds.
+ *
+ * Maximum on line time will be 56 seconds. If all lines are busy at any
+ * time, the oldest call will be terminated if it has been on line more
+ * than 28 seconds, otherwise, the call that first reaches 28 seconds
+ * will be terminated.
+ *
+ * Current time is valid at the "on-time" marker (OTM), either "*" or
+ * "#". The nominal on-time marker (*) will be transmitted 45 ms early
+ * to account for the 8 ms required to send 1 character at 1200 Baud,
+ * plus an additional 7 ms for delay from NIST to the user, and
+ * approximately 30 ms "scrambler" delay inherent in 1200 Baud modems.
+ * If the caller echoes all characters, NIST will measure the round trip
+ * delay and advance the on-time marker so that the midpoint of the stop
+ * bit arrives at the user on time. The amount of msADV will reflect the
+ * actual required advance in milliseconds and the OTM will be a "#".
+ *
+ * (The NIST system requires 4 or 5 consecutive delay measurements which
+ * are consistent before switching from "*" to "#". If the user has a
+ * 1200 Baud modem with the same internal delay as that used by NIST,
+ * then the "#" OTM should arrive at the user within +-2 ms of the
+ * correct time.
+ *
+ * However, NIST has studied different brands of 1200 Baud modems and
+ * found internal delays from 24 ms to 40 ms and offsets of the "#" OTM
+ * of +-10 ms. For many computer users, +-10 ms accuracy should be more
+ * than adequate since many computer internal clocks can only be set
+ * with granularity of 20 to 50 ms. In any case, the repeatability of
+ * the offset for the "#" OTM should be within +-2 ms, if the dial-up
+ * path is reciprocal and the user doesn't change the brand or model of
+ * modem used.
+ *
+ * This should be true even if the dial-up path on one day is a land-
+ * line of less than 40 ms (one way) and on the next day is a satellite
+ * link of 260 to 300 ms. In the rare event that the path is one way by
+ * satellite and the other way by land line with a round trip
+ * measurement in the range of 90 to 260 ms, the OTM will remain a "*"
+ * indicating 45 ms advance.
+ *
+ * For user comments write:
+ * NIST-ACTS
+ * Time and Frequency Division
+ * Mail Stop 847
+ * 325 Broadway
+ * Boulder, CO 80303
+ *
+ * Software for setting (PC)DOS compatable machines is available on a
+ * 360-kbyte diskette for $35.00 from: NIST Office of Standard Reference
+ * Materials B311-Chemistry Bldg, NIST, Gaithersburg, MD, 20899, (301)
+ * 975-6776
+ */
+
+/*
+ * Interface definitions
+ */
+#define DEVICE "/dev/acts%d" /* device name and unit */
+#define SPEED232 B1200 /* uart speed (1200 cowardly baud) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define REFID "ACTS" /* reference ID */
+#define DESCRIPTION "NIST Automated Computer Time Service" /* WRU */
+
+#define MODE_AUTO 0 /* automatic mode */
+#define MODE_BACKUP 1 /* backup mode */
+#define MODE_MANUAL 2 /* manual mode */
+
+#define NSAMPLES 3 /* stages of median filter */
+#define MSGCNT 10 /* we need this many ACTS messages */
+#define SMAX 80 /* max token string length */
+#define LENCODE 50 /* length of valid timecode string */
+#define ACTS_MINPOLL 10 /* log2 min poll interval (1024 s) */
+#define ACTS_MAXPOLL 14 /* log2 max poll interval (16384 s) */
+#define MAXOUTAGE 3600 /* max before ACTS kicks in (s) */
+
+/*
+ * Modem control strings. These may have to be changed for some modems.
+ *
+ * AT command prefix
+ * B1 initiate call negotiation using Bell 212A
+ * &C1 enable carrier detect
+ * &D2 hang up and return to command mode on DTR transition
+ * E0 modem command echo disabled
+ * l1 set modem speaker volume to low level
+ * M1 speaker enabled untill carrier detect
+ * Q0 return result codes
+ * V1 return result codes as English words
+ */
+#define MODEM_SETUP "ATB1&C1&D2E0L1M1Q0V1" /* modem setup */
+#define MODEM_HANGUP "ATH" /* modem disconnect */
+
+/*
+ * Timeouts
+ */
+#define IDLE 60 /* idle timeout (s) */
+#define WAIT 2 /* wait timeout (s) */
+#define ANSWER 30 /* answer timeout (s) */
+#define CONNECT 10 /* connect timeout (s) */
+#define TIMECODE 15 /* timecode timeout (s) */
+
+/*
+ * Imported from ntp_timer module
+ */
+extern u_long current_time; /* current time (s) */
+extern u_long last_time; /* last clock update time (s) */
+extern struct event timerqueue[]; /* inner space */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * Imported from ntp_config module
+ */
+extern char sys_phone[][MAXDIAL]; /* modem dial strings */
+
+/*
+ * Imported from ntp_proto module
+ */
+extern struct peer *sys_peer; /* who is running the show */
+extern u_char sys_poll; /* log2 of system poll interval */
+extern struct peer *sys_peer; /* system peer structure pointer */
+
+/*
+ * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
+ * leap.
+ */
+static day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ * Unit control structure
+ */
+struct actsunit {
+ struct event timer; /* timeout timer */
+ int pollcnt; /* poll message counter */
+
+ int state; /* the first one was Delaware */
+ int run; /* call program run switch */
+ int msgcnt; /* count of ACTS messages received */
+ long redial; /* interval to next automatic call */
+ double msADV; /* millisecond advance of last message */
+};
+
+/*
+ * Function prototypes
+ */
+static int acts_start P((int, struct peer *));
+static void acts_shutdown P((int, struct peer *));
+static void acts_receive P((struct recvbuf *));
+static void acts_poll P((int, struct peer *));
+static void acts_timeout P((struct peer *));
+static void acts_disc P((struct peer *));
+static int acts_write P((struct peer *, char *));
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_acts = {
+ acts_start, /* start up driver */
+ acts_shutdown, /* shut down driver */
+ acts_poll, /* transmit poll message */
+ noentry, /* not used (old acts_control) */
+ noentry, /* not used (old acts_init) */
+ noentry, /* not used (old acts_buginfo) */
+ NOFLAGS /* not used */
+};
+
+
+/*
+ * acts_start - open the devices and initialize data for processing
+ */
+static int
+acts_start(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
+ int dtr = TIOCM_DTR;
+
+ /*
+ * Open serial port. Use ACTS line discipline, if available. It
+ * pumps a timestamp into the data stream at every on-time
+ * character '*' found. Note: the port must have modem control
+ * or deep pockets for the phone bill. HP-UX 9.03 users should
+ * have very deep pockets.
+ */
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS)))
+ return (0);
+ if (ioctl(fd, TIOCMBIC, (char *)&dtr) < 0) {
+ syslog(LOG_ERR, "clock %s ACTS no modem control",
+ ntoa(&peer->srcadr));
+ return (0);
+ }
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ if (!(up = (struct actsunit *)
+ emalloc(sizeof(struct actsunit)))) {
+ (void) close(fd);
+ return (0);
+ }
+ memset((char *)up, 0, sizeof(struct actsunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = acts_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+ pp->unitptr = (caddr_t)up;
+
+ /*
+ * Initialize miscellaneous variables
+ */
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ peer->minpoll = ACTS_MINPOLL;
+ peer->maxpoll = ACTS_MAXPOLL;
+
+ /*
+ * Initialize modem and kill DTR. We skedaddle if this comes
+ * bum.
+ */
+ if (!acts_write(peer, MODEM_SETUP)) {
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+
+ /*
+ * Set up the driver timeout
+ */
+ up->timer.peer = (struct peer *)peer;
+ up->timer.event_handler = acts_timeout;
+ up->timer.event_time = current_time + WAIT;
+ TIMER_INSERT(timerqueue, &up->timer);
+ return (1);
+}
+
+
+/*
+ * acts_shutdown - shut down the clock
+ */
+static void
+acts_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ TIMER_DEQUEUE(&up->timer);
+ io_closeclock(&pp->io);
+ free(up);
+}
+
+
+/*
+ * acts_receive - receive data from the serial interface
+ */
+static void
+acts_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ char str[SMAX];
+ int i;
+ l_fp tstmp;
+ u_fp disp;
+ char hangup = '%'; /* ACTS hangup */
+ int day; /* day of the month */
+ int month; /* month of the year */
+ u_long mjd; /* Modified Julian Day */
+ u_int dst; /* daylight/standard time indicator */
+ u_int leap; /* leap-second indicator */
+ double dut1; /* DUT adjustment */
+ double msADV; /* ACTS transmit advance (ms) */
+ char utc[10]; /* this is NIST and you're not */
+ char flag; /* calibration flag */
+
+ /*
+ * Initialize pointers and read the timecode and timestamp. If
+ * the OK modem status code, leave it where folks can find it.
+ */
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX,
+ &pp->lastrec);
+ if (pp->lencode == 0) {
+ if (strcmp(pp->lastcode, "OK") == 0)
+ pp->lencode = 2;
+ return;
+ }
+#ifdef DEBUG
+ if (debug)
+ printf("acts: timecode %d %s\n", pp->lencode,
+ pp->lastcode);
+#endif
+
+ switch (up->state) {
+
+ case 0:
+
+ /*
+ * State 0. We are not expecting anything. Probably
+ * modem disconnect noise. Go back to sleep.
+ */
+ return;
+
+ case 1:
+
+ /*
+ * State 1. We are waiting for the call to be answered.
+ * All we care about here is CONNECT as the first token
+ * in the string. If the modem signals BUSY, ERROR, NO
+ * ANSWER, NO CARRIER or NO DIALTONE, we immediately
+ * hang up the phone. If CONNECT doesn't happen after
+ * ANSWER seconds, hang up the phone. If everything is
+ * okay, start the connect timeout and slide into state
+ * 2.
+ */
+ (void)strncpy(str, strtok(pp->lastcode, " "), SMAX);
+ if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") ==
+ 0 || strcmp(str, "NO") == 0) {
+ TIMER_DEQUEUE(&up->timer);
+ syslog(LOG_NOTICE,
+ "clock %s ACTS modem status %s",
+ ntoa(&peer->srcadr), pp->lastcode);
+ acts_disc(peer);
+ } else if (strcmp(str, "CONNECT") == 0) {
+ TIMER_DEQUEUE(&up->timer);
+ up->timer.event_time = current_time + CONNECT;
+ TIMER_INSERT(timerqueue, &up->timer);
+ up->msgcnt = 0;
+ up->state++;
+ }
+ return;
+
+ case 2:
+
+ /*
+ * State 2. The call has been answered and we are
+ * waiting for the first ACTS message. If this doesn't
+ * happen within the timecode timeout, hang up the
+ * phone. We probably got a wrong number or ACTS is
+ * down.
+ */
+ TIMER_DEQUEUE(&up->timer);
+ up->timer.event_time = current_time + TIMECODE;
+ TIMER_INSERT(timerqueue, &up->timer);
+ up->state++;
+ }
+
+ /*
+ * Real yucky things here. Ignore everything except timecode
+ * messages, as determined by the message length. We told the
+ * terminal routines to end the line with '*' and the line
+ * discipline to strike a timestamp on that character. However,
+ * when the ACTS echo-delay scheme works, the '*' eventually
+ * becomes a '#'. In this case the message is ended by the <CR>
+ * that comes about 200 ms after the '#' and the '#' cannot be
+ * echoed at the proper time. But, this may not be a lose, since
+ * we already have good data from prior messages and only need
+ * the millisecond advance calculated by ACTS. So, if the
+ * message is long enough and has an on-time character at the
+ * right place, we consider the message (but not neccesarily the
+ * timestmap) to be valid.
+ */
+ if (pp->lencode != LENCODE)
+ return;
+
+ /*
+ * We apparently have a valid timecode message, so dismember it
+ * with sscan(). This routine does a good job in spotting syntax
+ * errors without becoming overly pedantic.
+ *
+ * D L D
+ * MJD YR MO DA H M S ST S UT1 msADV OTM
+ * 47222 88-03-02 21:39:15 83 0 +.3 045.0 UTC(NBS) *
+ */
+ if (sscanf(pp->lastcode,
+ "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %s %c",
+ &mjd, &pp->year, &month, &day, &pp->hour, &pp->minute,
+ &pp->second, &dst, &leap, &dut1, &msADV, utc, &flag) != 13) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Some modems can't be trusted (the Practical Peripherals
+ * 9600SA comes to mind) and, even if they manage to unstick
+ * ACTS, the millisecond advance is wrong, so we use CLK_FLAG2
+ * to disable echoes, if neccessary.
+ */
+ if ((flag == '*' || flag == '#') && !(pp->sloppyclockflag &
+ CLK_FLAG2))
+ (void)write(pp->io.fd, &flag, 1);
+
+ /*
+ * Yes, I know this code incorrectly thinks that 2000 is a leap
+ * year. The ACTS timecode format croaks then anyway. Life is
+ * short. Would only the timecode mavens resist the urge to
+ * express months of the year and days of the month in favor of
+ * days of the year.
+ */
+ if (month < 1 || month > 12 || day < 1) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ if (pp->year % 4) {
+ if (day > day1tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day1tab[i];
+ } else {
+ if (day > day2tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day2tab[i];
+ }
+ pp->day = day;
+ if (leap == 1)
+ pp->leap = LEAP_ADDSECOND;
+ else if (pp->leap == 2)
+ pp->leap = LEAP_DELSECOND;
+ else
+ pp->leap = 0;
+ pp->lasttime = current_time;
+
+ /*
+ * Colossal hack here. We process each sample in a trimmed-mean
+ * filter and determine the reference clock offset and
+ * dispersion. The fudge time1 value is added to each sample as
+ * received. If we collect MSGCNT samples before the '#' on-time
+ * character, we use the results of the filter as is. If the '#'
+ * is found before that, the adjusted msADV is used to correct
+ * the propagation delay.
+ */
+ up->msgcnt++;
+ if (flag == '#') {
+ L_CLR(&tstmp);
+ TVUTOTSF((long)((msADV - up->msADV) * 1000.),
+ tstmp.l_uf);
+ L_ADD(&pp->offset, &tstmp);
+ } else {
+ up->msADV = msADV;
+ if (!refclock_process(pp, up->msgcnt, up->msgcnt -
+ up->msgcnt / 3)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ } else if (up->msgcnt < MSGCNT)
+ return;
+ }
+
+ /*
+ * We have a filtered sample offset ready for peer processing.
+ * We use lastrec 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. Finaly, we unhook the
+ * timeout, arm for the next call, fold the tent and go home.
+ * The little dance with the '%' character is an undocumented
+ * ACTS feature that hangs up the phone real quick without
+ * waiting for carrier loss or long-space disconnect, but we do
+ * these clumsy things anyway.
+ */
+ disp = LFPTOFP(&pp->fudgetime2);
+ record_clock_stats(&peer->srcadr, pp->lastcode);
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion +
+ (u_fp)disp, &pp->lastrec, &pp->lastrec, pp->leap);
+ pp->sloppyclockflag &= ~CLK_FLAG1;
+ up->pollcnt = 0;
+ TIMER_DEQUEUE(&up->timer);
+ (void)write(pp->io.fd, &hangup, 1);
+ up->state = 0;
+ acts_disc(peer);
+}
+
+
+/*
+ * acts_poll - called by the transmit routine
+ */
+static void
+acts_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+
+ /*
+ * If the driver is running, we set the enable flag (fudge
+ * flag1), which causes the driver timeout routine to initiate a
+ * call to ACTS. If not, the enable flag can be set using
+ * xntpdc. If this is the sustem peer, then follow the system
+ * poll interval.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ if (up->run) {
+ pp->sloppyclockflag |= CLK_FLAG1;
+ if (peer == sys_peer)
+ peer->hpoll = sys_poll;
+ else
+ peer->hpoll = peer->minpoll;
+ }
+}
+
+
+/*
+ * acts_timeout - called by the timer interrupt
+ */
+static void
+acts_timeout(peer)
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int dtr = TIOCM_DTR;
+
+ /*
+ * If a timeout occurs in other than state 0, the call has
+ * failed. If in state 0, we just see if there is other work to
+ * do.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ if (up->state) {
+ acts_disc(peer);
+ return;
+ }
+ switch (peer->ttl) {
+
+ /*
+ * In manual mode the ACTS calling program is activated
+ * by the xntpdc program using the enable flag (fudge
+ * flag1), either manually or by a cron job.
+ */
+ case MODE_MANUAL:
+ up->run = 0;
+ break;
+
+ /*
+ * In automatic mode the ACTS calling program runs
+ * continuously at intervals determined by the sys_poll
+ * variable.
+ */
+ case MODE_AUTO:
+ if (!up->run)
+ pp->sloppyclockflag |= CLK_FLAG1;
+ up->run = 1;
+ break;
+
+ /*
+ * In backup mode the ACTS calling program is disabled,
+ * unless no system peer has been selected for MAXOUTAGE
+ * (3600 s). Once enabled, it runs until some other NTP
+ * peer shows up.
+ */
+ case MODE_BACKUP:
+ if (!up->run && sys_peer == 0) {
+ if (current_time - last_time > MAXOUTAGE) {
+ up->run = 1;
+ peer->hpoll = peer->minpoll;
+ syslog(LOG_NOTICE,
+ "clock %s ACTS backup started ",
+ ntoa(&peer->srcadr));
+ }
+ } else if (up->run && sys_peer->refclktype !=
+ REFCLK_NIST_ACTS) {
+ peer->hpoll = peer->minpoll;
+ up->run = 0;
+ syslog(LOG_NOTICE,
+ "clock %s ACTS backup stopped",
+ ntoa(&peer->srcadr));
+ }
+ break;
+
+ default:
+ syslog(LOG_NOTICE,
+ "clock %s ACTS invalid mode", ntoa(&peer->srcadr));
+
+ }
+
+ /*
+ * The fudge flag1 is used as an enable/disable; if set either
+ * by the code or via xntpdc, the ACTS calling program is
+ * started; if reset, the phones stop ringing.
+ */
+ if (!(pp->sloppyclockflag & CLK_FLAG1)) {
+ up->pollcnt = 0;
+ up->timer.event_time = current_time + IDLE;
+ TIMER_INSERT(timerqueue, &up->timer);
+ return;
+ }
+
+ /*
+ * Initiate a call to the ACTS service. If we wind up here in
+ * other than state 0, a successful call could not be completed
+ * within minpoll seconds. We advance to the next modem dial
+ * string. If none are left, we log a notice and clear the
+ * enable flag. For future enhancement: call the site RP and
+ * leave an obscene message in his voicemail.
+ */
+ if (sys_phone[up->pollcnt][0] == '\0') {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ syslog(LOG_NOTICE,
+ "clock %s ACTS calling program terminated",
+ ntoa(&peer->srcadr));
+ pp->sloppyclockflag &= ~CLK_FLAG1;
+#ifdef DEBUG
+ if (debug)
+ printf("acts: calling program terminated\n");
+#endif
+ up->pollcnt = 0;
+ up->timer.event_time = current_time + IDLE;
+ TIMER_INSERT(timerqueue, &up->timer);
+ return;
+ }
+
+ /*
+ * Raise DTR, call ACTS and start the answer timeout. We think
+ * it strange if the OK status has not been received from the
+ * modem, but plow ahead anyway.
+ */
+ if (strcmp(pp->lastcode, "OK") != 0)
+ syslog(LOG_NOTICE, "clock %s ACTS no modem status",
+ ntoa(&peer->srcadr));
+ (void)ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr);
+ (void)acts_write(peer, sys_phone[up->pollcnt]);
+ syslog(LOG_NOTICE, "clock %s ACTS calling %s\n",
+ ntoa(&peer->srcadr), sys_phone[up->pollcnt]);
+ up->state = 1;
+ up->pollcnt++;
+ pp->polls++;
+ up->timer.event_time = current_time + ANSWER;
+ TIMER_INSERT(timerqueue, &up->timer);
+}
+
+
+/*
+ * acts_disc - disconnect the call and wait for the ruckus to cool
+ */
+static void
+acts_disc(peer)
+ struct peer *peer;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int dtr = TIOCM_DTR;
+
+ /*
+ * We should never get here other than in state 0, unless a call
+ * has timed out. We drop DTR, which will reliably get the modem
+ * off the air, even while ACTS is hammering away full tilt.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ (void)ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr);
+ if (up->state > 0) {
+ up->state = 0;
+ syslog(LOG_NOTICE, "clock %s ACTS call failed %d",
+ ntoa(&peer->srcadr), up->state);
+#ifdef DEBUG
+ if (debug)
+ printf("acts: call failed %d\n", up->state);
+#endif
+ }
+ up->timer.event_time = current_time + WAIT;
+ TIMER_INSERT(timerqueue, &up->timer);
+}
+
+
+/*
+ * acts_write - write a message to the serial port
+ */
+static int
+acts_write(peer, str)
+ struct peer *peer;
+ char *str;
+{
+ register struct actsunit *up;
+ struct refclockproc *pp;
+ int len;
+ int code;
+ char cr = '\r';
+
+ /*
+ * Not much to do here, other than send the message, handle
+ * debug and report faults.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ len = strlen(str);
+#ifdef DEBUG
+ if (debug)
+ printf("acts: state %d send %d %s\n", up->state, len,
+ str);
+#endif
+ code = write(pp->io.fd, str, len) == len;
+ code |= write(pp->io.fd, &cr, 1) == 1;
+ if (!code)
+ refclock_report(peer, CEVNT_FAULT);
+ return (code);
+}
+
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_as2201.c b/usr.sbin/xntpd/xntpd/refclock_as2201.c
index 97b5837c2f3b..6c60fd0b9447 100644
--- a/usr.sbin/xntpd/xntpd/refclock_as2201.c
+++ b/usr.sbin/xntpd/xntpd/refclock_as2201.c
@@ -1,7 +1,8 @@
/*
- * refclock_gps - clock driver for the Austron 2201A GPS Timing Receiver
+ * refclock_as2201 - clock driver for the Austron 2201A GPS
+ * Timing Receiver
*/
-#if defined(REFCLOCK) && (defined(AS2201) || defined(AS2201CLK) || defined(AS2201PPS))
+#if defined(REFCLOCK) && defined(AS2201)
#include <stdio.h>
#include <ctype.h>
@@ -11,30 +12,11 @@
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
+#include "ntp_stdlib.h"
-#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(HAVE_TERMIOS)
-#include <termios.h>
-#endif
-#if defined(STREAM)
-#include <stropts.h>
-#if defined(AS2201CLK)
-#include <sys/clkdefs.h>
-#endif /* AS2201CLK */
-#endif /* STREAM */
-
-#if defined (AS2201PPS)
+#ifdef PPS
#include <sys/ppsclock.h>
-#endif /* AS2201PPS */
-
-#include "ntp_stdlib.h"
+#endif /* PPS */
/*
* This driver supports the Austron 2200A/2201A GPS Receiver with
@@ -49,7 +31,9 @@
* a multi-line reply showing the corresponding statistics or other
* selected data. Statistics commands are sent in order as determined by
* a vector of commands; these might have to be changed with different
- * radio options.
+ * radio options. If flag4 of the fudge configuration command is set to
+ * 1, the statistics data are written to the clockstats file for later
+ * processing.
*
* In order for this code to work, the radio must be placed in non-
* interactive mode using the "off" command and with a single <cr>
@@ -58,105 +42,68 @@
* timescale using the "ts utc" command.
*
* There are two modes of operation for this driver. The first with
- * undefined AS2201PPS is used with stock kernels and serial-line drivers
- * and works with almost any machine. In this mode the driver assumes
- * the radio captures a timestamp upon receipt of the "*" that begins
- * the driver query. Accuracies in this mode are in the order of a
- * millisecond or two and the receiver can be connected to only one
- * host. The second with AS2201PPS defined can be used for SunOS kernels
- * that have been modified with the ppsclock streams module included in
- * this distribution. In this mode a precise timestamp is available
- * using a gadget box and 1-pps signal from the receiver; however, the
- * sample rate is limited to the polling rate, normally about one poll
- * every 16 seconds. This improves the accuracy to the order of a few
- * tens of microseconds. In addition, the serial output and 1-pps signal
- * can be bussed to additional receivers. For the utmost accuracy, the
- * sample rate can be increased to one per second using the PPSCD
- * define. This improves the accuracy to the order of a few
- * microseconds.
- */
-
-/*
- * Definitions
+ * default configuration is used with stock kernels and serial-line
+ * drivers and works with almost any machine. In this mode the driver
+ * assumes the radio captures a timestamp upon receipt of the "*" that
+ * begins the driver query. Accuracies in this mode are in the order of
+ * a millisecond or two and the receiver can be connected to only one
+ * host.
+ *
+ * The second mode of operation can be used for SunOS kernels that have
+ * been modified with the ppsclock streams module included in this
+ * distribution. The mode is enabled if flag3 of the fudge configuration
+ * command has been set to 1. In this mode a precise timestamp is
+ * available using a gadget box and 1-pps signal from the receiver. This
+ * improves the accuracy to the order of a few tens of microseconds. In
+ * addition, the serial output and 1-pps signal can be bussed to
+ * additional receivers.
*/
-#define MAXUNITS 4 /* max number of GPS units */
-#define GPS232 "/dev/gps%d" /* name of radio device */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
/*
- * Radio interface parameters
+ * GPS Definitions
*/
-#define GPSPRECISION (-15) /* precision assumed (about 30 us) */
-#define GPSREFID "GPS" /* reference id */
-#define GPSDESCRIPTION "Austron 2201A GPS Receiver" /* who we are */
-#define GPSHSREFID 0x7f7f040a /* 127.127.4.10 refid hi strata */
-#define GMT 0 /* hour offset from Greenwich */
-#define NCODES 3 /* stages of median filter */
-#define LENTOC 19 /* yy:ddd:hh:mm:ss.mmm datecode length */
-#define BMAX 100 /* timecode buffer length */
#define SMAX 200 /* statistics buffer length */
-#define CODEDIFF 0x20000000 /* 0.125 seconds as an l_fp fraction */
+#define DEVICE "/dev/gps%d" /* device name and unit */
+#define SPEED232 B9600 /* uart speed (9600 baud) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define REFID "GPS\0" /* reference ID */
+#define DESCRIPTION "Austron 2201A GPS Receiver" /* WRU */
-/*
- * Hack to avoid excercising the multiplier. I have no pride.
- */
-#define MULBY10(x) (((x)<<3) + ((x)<<1))
+#define NSAMPLES 3 /* stages of median filter */
+#define LENTOC 19 /* yy:ddd:hh:mm:ss.mmm timecode lngth */
/*
* Imported from ntp_timer module
*/
-extern U_LONG current_time; /* current time (s) */
+extern u_long current_time; /* current time (s) */
/*
- * Imported from ntp_loopfilter module
+ * Imported from ntpd module
*/
-extern int fdpps; /* pps file descriptor */
+extern int debug; /* global debug flag */
+#ifdef PPS
/*
- * Imported from ntpd module
+ * Imported from loop_filter module
*/
-extern int debug; /* global debug flag */
+extern int fdpps; /* ppsclock file descriptor */
+#endif /* PPS */
/*
- * GPS unit control structure.
+ * AS2201 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 */
- char *lastptr; /* statistics buffer pointer */
- char stats[SMAX]; /* statistics buffer */
- u_char lencode; /* length of last received ASCII string */
- U_LONG lasttime; /* last time clock heard from */
-#ifdef AS2201PPS
- U_LONG lastev; /* last ppsclock second */
-#endif /* AS2201PPS */
- 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 */
- int linect; /* count of lines remaining */
- int index; /* current statistics command */
- /*
- * 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 */
+struct as2201unit {
+ int pollcnt; /* poll message counter */
+
+ char *lastptr; /* statistics buffer pointer */
+ char stats[SMAX]; /* statistics buffer */
+
+#ifdef PPS
+ u_long lastev; /* last ppsclock second */
+#endif /* PPS */
+
+ int linect; /* count of lines remaining */
+ int index; /* current statistics command */
};
/*
@@ -205,385 +152,129 @@ static char stat_command[][30] = {
};
/*
- * 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 as2201_init P(());
-static int as2201_start P((u_int, struct peer *));
-static void as2201_shutdown P((int));
-static void as2201_report_event P((struct gpsunit *, int));
+static int as2201_start P((int, struct peer *));
+static void as2201_shutdown P((int, struct peer *));
static void as2201_receive P((struct recvbuf *));
-static char as2201_process P((struct gpsunit *, l_fp *, u_fp *));
-static void as2201_poll P((int unit, struct peer *));
-static void as2201_control P((u_int, struct refclockstat *, struct refclockstat *));
-static void as2201_buginfo P((int, struct refclockbug *));
+static void as2201_poll P((int, struct peer *));
/*
* Transfer vector
*/
-struct refclock refclock_as2201 = {
- as2201_start, as2201_shutdown, as2201_poll,
- as2201_control, as2201_init, as2201_buginfo, NOFLAGS
+struct refclock refclock_as2201 = {
+ as2201_start, /* start up driver */
+ as2201_shutdown, /* shut down driver */
+ as2201_poll, /* transmit poll message */
+ noentry, /* not used (old as2201_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old as2201_buginfo) */
+ NOFLAGS /* not used */
};
-/*
- * as2201_init - initialize internal gps driver data
- */
-static void
-as2201_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;
- }
-}
-
/*
- * as2201_start - open the GPS devices and initialize data for processing
+ * as2201_start - open the devices and initialize data for processing
*/
static int
as2201_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register struct gpsunit *gps;
- register int i;
- int fd232;
- char as2201dev[20];
-#ifdef AS2201PPS
- struct ppsclockev ev;
-#endif /* AS2201PPS */
+ register struct as2201unit *up;
+ struct refclockproc *pp;
+ int fd;
+ char gpsdev[20];
/*
- * Check configuration info
+ * Open serial port. Use CLK line discipline, if available.
*/
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "gps_start: unit %d invalid", unit);
- return (0);
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "gps_start: unit %d in use", unit);
+ (void)sprintf(gpsdev, DEVICE, unit);
+ if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_CLK)))
return (0);
- }
/*
- * Open serial port
+ * Allocate and initialize unit structure
*/
- (void) sprintf(as2201dev, GPS232, unit);
- fd232 = open(as2201dev, O_RDWR, 0777);
- if (fd232 == -1) {
- syslog(LOG_ERR, "gps_start: open of %s: %m", as2201dev);
+ if (!(up = (struct as2201unit *)
+ emalloc(sizeof(struct as2201unit)))) {
+ (void) close(fd);
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,
- "as2201_start: ioctl(%s, TCGETA): %m", as2201dev);
- 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,
- "as2201_start: ioctl(%s, TCSETA): %m", as2201dev);
- goto screwed;
- }
- }
-#endif /* HAVE_SYSV_TTYS */
-#if defined(HAVE_TERMIOS)
- /*
- * POSIX serial line parameters (termios interface)
- *
- * The AS2201CLK option provides timestamping at the driver level.
- * It requires the tty_clk streams module.
- *
- * The AS2201PPS 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,
- "as2201_start: tcgetattr(%s): %m", as2201dev);
- goto screwed;
- }
- ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
- 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,
- "as2201_start: tcsetattr(%s): %m", as2201dev);
- goto screwed;
- }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- syslog(LOG_ERR,
- "as2201_start: tcflush(%s): %m", as2201dev);
- goto screwed;
- }
- }
-#endif /* HAVE_TERMIOS */
-#ifdef STREAM
-#if defined(AS2201CLK)
- if (ioctl(fd232, I_PUSH, "clk") < 0)
- syslog(LOG_ERR,
- "as2201_start: ioctl(%s, I_PUSH, clk): %m", as2201dev);
- if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
- syslog(LOG_ERR,
- "as2201_start: ioctl(%s, CLK_SETSTR): %m", as2201dev);
-#endif /* AS2201CLK */
-#if defined(AS2201PPS)
- if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
- syslog(LOG_ERR,
- "as2201_start: ioctl(%s, I_PUSH, ppsclock): %m", as2201dev);
- else
- fdpps = fd232;
-#endif /* AS2201PPS */
-#endif /* STREAM */
-#if defined(HAVE_BSD_TTYS)
- /*
- * 4.3bsd serial line parameters (sgttyb interface)
- *
- * The AS2201CLK option provides timestamping at the driver level.
- * It requires the tty_clk line discipline and 4.3bsd or later.
- */
- { struct sgttyb ttyb;
-#if defined(AS2201CLK)
- int ldisc = CLKLDISC;
-#endif /* AS2201CLK */
-
- if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "as2201_start: ioctl(%s, TIOCGETP): %m", as2201dev);
- goto screwed;
- }
- ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
-#if defined(AS2201CLK)
- 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 /* AS2201CLK */
- if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "as2201_start: ioctl(%s, TIOCSETP): %m", as2201dev);
- goto screwed;
- }
-#if defined(AS2201CLK)
- if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR,
- "as2201_start: ioctl(%s, TIOCSETD): %m",as2201dev);
- goto screwed;
- }
-#endif /* AS2201CLK */
- }
-#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));
- }
+ memset((char *)up, 0, sizeof(struct as2201unit));
+ pp = peer->procptr;
+ pp->io.clock_recv = as2201_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
}
- memset((char *)gps, 0, sizeof(struct gpsunit));
- gpsunits[unit] = gps;
+ pp->unitptr = (caddr_t)up;
/*
- * Set up the structures
+ * Initialize miscellaneous variables
*/
- gps->peer = peer;
- gps->unit = (u_char)unit;
- gps->timestarted = current_time;
- gps->lastptr = gps->stats;
- gps->index = 0;
-
- gps->io.clock_recv = as2201_receive;
- gps->io.srcclock = (caddr_t)gps;
- gps->io.datalen = 0;
- gps->io.fd = fd232;
-#ifdef AS2201PPS
- if (ioctl(fd232, CIOGETEV, (caddr_t)&ev) < 0) {
- syslog(LOG_ERR,
- "gps_start: ioctl(%s, CIOGETEV): %m", as2201dev);
- goto screwed;
- } else
- gps->lastev = ev.tv.tv_sec;
-#endif /* AS2201PPS */
- if (!io_addclock(&gps->io)) {
- goto screwed;
- }
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
- /*
- * 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)
- memmove((char *)&peer->refid, GPSREFID, 4);
- else
- peer->refid = htonl(GPSHSREFID);
- unitinuse[unit] = 1;
+ up->lastptr = up->stats;
+ up->index = 0;
return (1);
-
- /*
- * Something broke; abandon ship.
- */
-screwed:
- (void) close(fd232);
- return (0);
-}
-
-/*
- * as2201_shutdown - shut down a GPS clock
- */
-static void
-as2201_shutdown(unit)
- int unit;
-{
- register struct gpsunit *gps;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "gps_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "gps_shutdown: unit %d not in use", unit);
- return;
- }
-
- /*
- * Tell the I/O module to turn us off. We're history.
- */
- gps = gpsunits[unit];
- io_closeclock(&gps->io);
- unitinuse[unit] = 0;
}
/*
- * as2201_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.
+ * as2201_shutdown - shut down the clock
*/
static void
-as2201_report_event(gps, code)
- struct gpsunit *gps;
- int code;
-{
+as2201_shutdown(unit, peer)
+ int unit;
struct peer *peer;
+{
+ register struct as2201unit *up;
+ struct refclockproc *pp;
- 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);
- }
+ pp = peer->procptr;
+ up = (struct as2201unit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
}
/*
- * as2201_receive - receive data from the serial interface
+ * as2201__receive - receive data from the serial interface
*/
static void
as2201_receive(rbufp)
struct recvbuf *rbufp;
{
- register int i;
- register struct gpsunit *gps;
-
-#if defined(AS2201PPS)
- struct ppsclockev ev;
+ register struct as2201unit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
l_fp trtmp;
-#endif /* AS2201PPS */
- register u_char *dpt;
- register char *cp, *dp;
- int dpend;
- l_fp tstmp;
- u_fp dispersion;
+#ifdef PPS
+ long ltemp;
+ struct ppsclockev ev;
+#endif /* PPS */
/*
- * Get the clock this applies to and pointers to the data.
- * Edit the timecode to remove control chars and trashbits.
+ * Initialize pointers and read the timecode and timestamp.
*/
- gps = (struct gpsunit *)rbufp->recv_srcclock;
- dpt = (u_char *)&rbufp->recv_space;
- dpend = rbufp->recv_length;
- if (dpend > BMAX - 1)
- dpend = BMAX - 1;
- cp = dp = gps->lastcode;
- for (i = 0; i < dpend; i++)
- if ((*dp = 0x7f & *dpt++) >= ' ') dp++;
- *dp = '\0';
- gps->lencode = dp - cp;
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct as2201unit *)pp->unitptr;
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX, &trtmp);
#ifdef DEBUG
if (debug)
printf("gps: timecode %d %d %s\n",
- gps->linect, gps->lencode, gps->lastcode);
+ up->linect, pp->lencode, pp->lastcode);
#endif
- if (gps->lencode == 0)
+ if (pp->lencode == 0)
return;
/*
@@ -597,252 +288,136 @@ as2201_receive(rbufp)
* the timecode; in the later case, save the number of lines and
* quietly return.
*/
- if (gps->linect > 0) {
- gps->linect--;
- if ((int)(gps->lastptr - gps->stats + gps->lencode) > SMAX - 2)
+ if (up->linect > 0) {
+ up->linect--;
+ if (up->lastptr - up->stats + pp->lencode > SMAX - 2)
return;
- *gps->lastptr++ = ' ';
- (void)strcpy(gps->lastptr, gps->lastcode);
- gps->lastptr += gps->lencode;
+ *up->lastptr++ = ' ';
+ (void)strcpy(up->lastptr, pp->lastcode);
+ up->lastptr += pp->lencode;
return;
} else {
- if (gps->lencode == 1) {
- gps->linect = atoi(gps->lastcode);
+ if (pp->lencode == 1) {
+ up->linect = atoi(pp->lastcode);
return;
} else {
- record_clock_stats(&(gps->peer->srcadr), gps->stats);
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, up->stats);
#ifdef DEBUG
if (debug)
- printf("gps: stat %s\n", gps->stats);
+ printf("gps: stat %s\n", up->stats);
#endif
}
}
- gps->lastptr = gps->stats;
- *gps->lastptr = '\0';
-
- /*
- * We check the timecode format and decode its contents. The
- * timecode has format yy:ddd:hh:mm:ss.mmm). If it has invalid
- * length or is not in proper format, the driver declares bad
- * format and exits. If the converted decimal values are out of
- * range, the driver declares bad data and exits.
- */
- if (gps->lencode != LENTOC || !isdigit(cp[0]) ||
- !isdigit(cp[1]) || !isdigit(cp[3]) || !isdigit(cp[4]) ||
- !isdigit(cp[5]) || !isdigit(cp[7]) || !isdigit(cp[8]) ||
- !isdigit(cp[10]) || !isdigit(cp[11]) || !isdigit(cp[13]) ||
- !isdigit(cp[14]) || !isdigit(cp[16]) || !isdigit(cp[17]) ||
- !isdigit(cp[18])) {
- gps->badformat++;
- as2201_report_event(gps, CEVNT_BADREPLY);
- return;
- }
+ up->lastptr = up->stats;
+ *up->lastptr = '\0';
/*
- * Convert date and check values.
+ * We get down to business, check the timecode format and decode
+ * its contents. If the timecode has invalid length or is not in
+ * proper format, we declare bad format and exit.
*/
- gps->day = cp[3] - '0';
- gps->day = MULBY10(gps->day) + cp[4] - '0';
- gps->day = MULBY10(gps->day) + cp[5] - '0';
- if (gps->day < 1 || gps->day > 366) {
- gps->baddata++;
- as2201_report_event(gps, CEVNT_BADDATE);
+ if (pp->lencode < LENTOC) {
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
/*
- * Convert time and check values.
+ * Timecode format: "yy:ddd:hh:mm:ss.mmm"
*/
- gps->hour = MULBY10(cp[7] - '0') + cp[8] - '0';
- gps->minute = MULBY10(cp[10] - '0') + cp[11] - '0';
- gps->second = MULBY10(cp[13] - '0') + cp[14] - '0';
- gps->msec = MULBY10(MULBY10(cp[16] - '0') + cp[17] - '0')
- + cp[18] - '0';
- if (gps->hour > 23 || gps->minute > 59 || gps->second > 59) {
- gps->baddata++;
- as2201_report_event(gps, CEVNT_BADTIME);
+ if (sscanf(pp->lastcode, "%2d:%3d:%2d:%2d:%2d.%3d", &pp->year,
+ &pp->day, &pp->hour, &pp->minute, &pp->second, &pp->msec)
+ != 6) {
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
/*
* Test for synchronization (this is a temporary crock).
*/
- if (cp[2] != ':')
- gps->leap = LEAP_NOTINSYNC;
- else
- gps->lasttime = current_time;
-
- /*
- * 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 (!clocktime(gps->day, gps->hour, gps->minute,
- gps->second, GMT, gps->lastrec.l_ui,
- &gps->yearstart, &gps->lastref.l_ui)) {
- gps->baddata++;
- as2201_report_event(gps, CEVNT_BADTIME);
-
- printf("gps: bad data\n");
-
- return;
+ if (pp->lastcode[2] != ':') {
+ pp->leap = LEAP_NOTINSYNC;
+ } else {
+ pp->leap = 0;
+ pp->lasttime = current_time;
}
- MSUTOTSF(gps->msec, gps->lastref.l_uf);
-#if defined(AS2201PPS)
+#ifdef PPS
/*
- * If the pps signal is available and the local time is within
- * +-0.5 second of the timecode, use the pps offset instead.
- * Note that we believe the ppsclock timestamp only if the ioctl
- * works and the new timestamp is greater than the previous one.
+ * If CLK_FLAG3 is set and the local time is within +-0.5 second
+ * of the timecode, use the pps offset instead. Note that we
+ * believe the ppsclock timestamp only if the ioctl works and
+ * the new timestamp is greater than the previous one.
*/
- gps->lastrec = rbufp->recv_time;
- tstmp = gps->lastref;
- L_SUB(&tstmp, &gps->lastrec);
- L_ADD(&tstmp, &(fudgefactor[gps->unit]));
- trtmp = tstmp;
- if (L_ISNEG(&trtmp))
- L_NEG(&trtmp);
- if (trtmp.l_i < CLOCK_MAX_I || (trtmp.l_i == CLOCK_MAX_I
- && (U_LONG)trtmp.l_uf < (U_LONG)CLOCK_MAX_F)) {
- if (ioctl(fdpps, CIOGETEV, (caddr_t)&ev) >= 0) {
- if (gps->lastev < ev.tv.tv_sec) {
- trtmp.l_ui = ev.tv.tv_sec + (U_LONG)JAN_1970;
- TVUTOTSF(ev.tv.tv_usec, trtmp.l_uf);
- L_NEG(&trtmp);
- tstmp.l_i = tstmp.l_f = 0;
- M_ADDF(tstmp.l_i, tstmp.l_f, trtmp.l_f);
+ if (pp->sloppyclockflag & CLK_FLAG3 && fdpps != -1) {
+ if (!clocktime(pp->day, pp->hour, pp->minute,
+ pp->second, GMT, pp->lastrec.l_ui, &pp->yearstart,
+ &pp->lastref.l_ui)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ MSUTOTSF(pp->msec, pp->lastref.l_uf);
+ pp->lastrec = trtmp;
+ L_SUB(&trtmp, &pp->lastref);
+ if (L_ISNEG(&trtmp))
+ L_NEG(&trtmp);
+ if (trtmp.l_i < CLOCK_MAX_I || (trtmp.l_i == CLOCK_MAX_I
+ && trtmp.l_uf < CLOCK_MAX_F)) {
+ if (ioctl(fdpps, CIOGETEV, (caddr_t)&ev) >= 0) {
+ if (up->lastev < ev.tv.tv_sec) {
+ TVUTOTSF(ev.tv.tv_usec, ltemp);
+ pp->lastrec = pp->lastref;
+ L_ADDF(&pp->lastrec, ltemp);
+ }
+ up->lastev = ev.tv.tv_sec;
}
- gps->lastev = ev.tv.tv_sec;
}
}
-#else
- tstmp = gps->lastref;
- L_SUB(&tstmp, &gps->lastrec);
- L_ADD(&tstmp, &(fudgefactor[gps->unit]));
-#endif /* AS2201PPS */
- i = ((int)(gps->coderecv)) % NCODES;
- gps->offset[i] = tstmp;
- gps->coderecv++;
-#if DEBUG
+#endif /* PPS */
+#ifdef DEBUG
if (debug)
printf("gps: times %s %s %s\n",
- ulfptoa(&gps->lastref, 6), ulfptoa(&gps->lastrec, 6),
- lfptoa(&tstmp, 6));
+ ulfptoa(&pp->lastref, 6), ulfptoa(&pp->lastrec, 6),
+ lfptoa(&trtmp, 6));
#endif
/*
- * If the statistics-record switch (CLK_FLAG4) is set,
- * initialize the statistics buffer and send the next command.
- * If not, simply write the timecode to the clockstats file.
- */
- (void)strcpy(gps->lastptr, gps->lastcode);
- gps->lastptr += gps->lencode;
- if (sloppyclockflag[gps->unit] & CLK_FLAG4) {
- *gps->lastptr++ = ' ';
- (void)strcpy(gps->lastptr, stat_command[gps->index]);
- gps->lastptr += strlen(stat_command[gps->index]);
- gps->lastptr--;
- *gps->lastptr = '\0';
- (void)write(gps->io.fd, stat_command[gps->index],
- strlen(stat_command[gps->index]));
- gps->index++;
- if (*stat_command[gps->index] == '\0')
- gps->index = 0;
- }
-
- /*
- * 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.
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!as2201_process(gps, &tstmp, &dispersion)) {
- gps->baddata++;
- as2201_report_event(gps, CEVNT_BADTIME);
+ if (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
return;
}
- refclock_receive(gps->peer, &tstmp, GMT, dispersion,
- &gps->lastrec, &gps->lastrec, gps->leap);
-}
-
-/*
- * as2201_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
-as2201_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;
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
/*
- * 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.
+ * If CLK_FLAG4 is set, initialize the statistics buffer and
+ * send the next command. If not, simply write the timecode to
+ * the clockstats file.
*/
- 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;
- }
- }
+ (void)strcpy(up->lastptr, pp->lastcode);
+ up->lastptr += pp->lencode;
+ if (pp->sloppyclockflag & CLK_FLAG4) {
+ *up->lastptr++ = ' ';
+ (void)strcpy(up->lastptr, stat_command[up->index]);
+ up->lastptr += strlen(stat_command[up->index]);
+ up->lastptr--;
+ *up->lastptr = '\0';
+ (void)write(pp->io.fd, stat_command[up->index],
+ strlen(stat_command[up->index]));
+ up->index++;
+ if (*stat_command[up->index] == '\0')
+ up->index = 0;
}
- 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);
}
+
/*
* as2201_poll - called by the transmit procedure
*
@@ -854,142 +429,25 @@ as2201_poll(unit, peer)
int unit;
struct peer *peer;
{
- struct gpsunit *gps;
+ register struct as2201unit *up;
+ struct refclockproc *pp;
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "gps_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "gps_poll: unit %d not in use", unit);
- return;
- }
- gps = gpsunits[unit];
- if ((current_time - gps->lasttime) > 150)
- as2201_report_event(gpsunits[unit], CEVNT_TIMEOUT);
- gettstamp(&gps->lastrec);
- if (write(gps->io.fd, "\r*toc\r", 6) != 6) {
- syslog(LOG_ERR, "gps_poll: unit %d: %m", gps->unit);
- as2201_report_event(gps, CEVNT_FAULT);
+ /*
+ * Send a "\r*toc\r" to get things going. We go to great pains
+ * to avoid changing state, since there may be more than one
+ * eavesdropper watching the radio.
+ */
+ pp = peer->procptr;
+ up = (struct as2201unit *)pp->unitptr;
+ if (up->pollcnt == 0)
+ refclock_report(peer, CEVNT_TIMEOUT);
+ else
+ up->pollcnt--;
+ gettstamp(&pp->lastrec);
+ if (write(pp->io.fd, "\r*toc\r", 6) != 6) {
+ refclock_report(peer, CEVNT_FAULT);
} else
- gps->polls++;
+ pp->polls++;
}
-/*
- * as2201_control - set fudge factors, return statistics
- */
-static void
-as2201_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- register struct gpsunit *gps;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "gps_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)
- memmove((char *)&peer->refid,
- GPSREFID, 4);
- else
- peer->refid = htonl(GPSHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG4) {
- sloppyclockflag[unit] = in->flags & CLK_FLAG4;
- }
- }
-
- if (out != 0) {
- out->type = REFCLK_GPS_AS2201;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG4;
- 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 = LENTOC;
- out->lastcode = gps->stats;
- 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;
- }
- }
-}
-
-/*
- * as2201_buginfo - return clock dependent debugging info
- */
-static void
-as2201_buginfo(unit, bug)
- int unit;
- register struct refclockbug *bug;
-{
- register struct gpsunit *gps;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "gps_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
+#endif /* REFCLOCK */
diff --git a/usr.sbin/xntpd/xntpd/refclock_atom.c b/usr.sbin/xntpd/xntpd/refclock_atom.c
new file mode 100644
index 000000000000..71fe05d8f0da
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_atom.c
@@ -0,0 +1,499 @@
+/*
+ * refclock_atom - clock driver for 1-pps signals
+ */
+#if defined(REFCLOCK) && defined(ATOM)
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_unixtime.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
+#ifdef PPS
+#include <sys/ppsclock.h>
+#endif /* PPS */
+
+/*
+ * This driver furnishes an interface for pulse-per-second (PPS) signals
+ * produced by a cesium clock, timing receiver or related equipment. It
+ * can be used to remove accumulated jitter and retime a secondary
+ * server when synchronized to a primary server over a congested, wide-
+ * area network and before redistributing the time to local clients.
+ *
+ * In order for this driver to work, the local clock must be set to
+ * within +-500 ms by another means, such as a radio clock or NTP
+ * itself. The 1-pps signal is connected via a serial port and gadget
+ * box consisting of a one-shot and RS232 level converter. When operated
+ * at 38.4 kbps with a SPARCstation IPC, this arrangement has a worst-
+ * case jitter less than 26 us.
+ *
+ * There are three ways in which this driver can be used. The first way
+ * uses the LDISC_PPS line discipline and works only for the baseboard
+ * serial ports of the Sun SPARCstation. The PPS signal is connected via
+ * a gadget box to the carrier detect (CD) line of a serial port and
+ * flag3 of the driver configured for that port is set. This causes the
+ * ppsclock streams module to be configured for that port and capture a
+ * timestamp at the on-time transition of the PPS signal. This driver
+ * then reads the timestamp directly by a designated ioctl() system
+ * call. This provides the most accurate time and least jitter of any
+ * other scheme. There is no need to configure a dedicated device for
+ * this purpose, which ordinarily is the device used for the associated
+ * radio clock.
+ *
+ * The second way uses the LDISC_CLKPPS line discipline and works for
+ * any architecture supporting a serial port. If after a few seconds
+ * this driver finds no ppsclock module configured, it attempts to open
+ * a serial port device /dev/pps%d, where %d is the unit number, and
+ * assign the LDISC_CLKPPS line discipline to it. If the line discipline
+ * fails, no harm is done except the accuracy is reduced somewhat. The
+ * pulse generator in the gadget box is adjusted to produce a start bit
+ * of length 26 usec at 38400 bps. Used with the LDISC_CLKPPS line
+ * discipline, this produces an ASCII DEL character ('\377') followed by
+ * a timestamp at each seconds epoch.
+ *
+ * The third way involves an auxiliary radio clock driver which calls
+ * the PPS driver with a timestamp captured by that driver. This use is
+ * documented in the source code for the driver(s) involved.
+ *
+ * Fudge Factors
+ *
+ * There are no special fudge factors other than the generic and those
+ * explicitly defined above. The fudge time1 parameter can be used to
+ * compensate for miscellaneous UART and OS delays. Allow about 247 us
+ * for uart delays at 38400 bps and about 1 ms for SunOS streams
+ * nonsense.
+ */
+
+/*
+ * Interface definitions
+ */
+#define DEVICE "/dev/pps%d" /* device name and unit */
+#ifdef B38400
+#define SPEED232 B38400 /* uart speed (38400 baud) */
+#else
+#define SPEED232 EXTB /* as above */
+#endif
+#define PRECISION (-20) /* precision assumed (about 1 usec) */
+#define REFID "PPS\0" /* reference ID */
+#define DESCRIPTION "PPS Clock Discipline" /* WRU */
+
+#define PPSMAXDISPERSE (FP_SECOND / 100) /* max sample dispersion */
+#define NSAMPLES 32 /* final stages of median filter */
+#ifdef PPS
+#define PPS_POLL 2 /* ppsclock poll interval (s) */
+#endif /* PPS */
+
+/*
+ * Imported from ntp_timer module
+ */
+extern u_long current_time; /* current time (s) */
+extern struct event timerqueue[]; /* inner space */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+extern int pps_update; /* prefer peer valid update */
+
+/*
+ * Imported from ntp_proto module
+ */
+extern struct peer *sys_peer; /* somebody in charge */
+
+/*
+ * Unit control structure
+ */
+struct atomunit {
+#ifdef PPS
+ struct event timer; /* pps poll interval timer */
+ struct ppsclockev ev; /* ppsclock control */
+#endif /* PPS */
+ int pollcnt; /* poll message counter */
+};
+
+/*
+ * Global variables
+ */
+struct peer *last_atom_peer; /* peer structure pointer */
+
+/*
+ * Function prototypes
+ */
+static int atom_start P((int, struct peer *));
+static void atom_shutdown P((int, struct peer *));
+static void atom_receive P((struct recvbuf *));
+static void atom_poll P((int, struct peer *));
+#ifdef PPS
+static void atom_pps P((struct peer *));
+#endif /* PPS */
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_atom = {
+ atom_start, /* start up driver */
+ atom_shutdown, /* shut down driver */
+ atom_poll, /* transmit poll message */
+ noentry, /* not used (old atom_control) */
+ noentry, /* initialize driver */
+ noentry, /* not used (old atom_buginfo) */
+ NOFLAGS /* not used */
+};
+
+
+/*
+ * atom_start - initialize data for processing
+ */
+static int
+atom_start(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct atomunit *up;
+ struct refclockproc *pp;
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ if (!(up = (struct atomunit *)
+ emalloc(sizeof(struct atomunit))))
+ return (0);
+ memset((char *)up, 0, sizeof(struct atomunit));
+ pp = peer->procptr;
+ pp->unitptr = (caddr_t)up;
+
+ /*
+ * Initialize miscellaneous variables
+ */
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
+ pp->nstages = MAXSTAGE;
+
+#ifdef PPS
+ /*
+ * Arm the timer for the first interrupt. Give it ten seconds to
+ * allow the ppsclock line to be configured, since it could be
+ * assigned to another driver.
+ */
+ up->timer.peer = (struct peer *)peer;
+ up->timer.event_handler = atom_pps;
+ up->timer.event_time = current_time + 10;
+ TIMER_INSERT(timerqueue, &up->timer);
+#endif /* PPS */
+ last_atom_peer = peer;
+ return (1);
+}
+
+
+/*
+ * atom_shutdown - shut down the clock
+ */
+static void
+atom_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct atomunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct atomunit *)pp->unitptr;
+
+ if (last_atom_peer == peer)
+ last_atom_peer = 0;
+#ifdef PPS
+ TIMER_DEQUEUE(&up->timer);
+#endif /* PPS */
+ if (pp->io.fd)
+ io_closeclock(&pp->io);
+ free(up);
+}
+
+/*
+ * pps_sample - process pps sample offset -- backwards compatible
+ * interface
+ */
+int
+pps_sample(tsr)
+ l_fp *tsr;
+{
+ struct peer *peer;
+ struct refclockproc *pp;
+ register struct atomunit *up;
+ int i;
+ l_fp lftemp; /* l_fp temps */
+
+ /*
+ * This routine is called once per second by an auxilliary
+ * routine in another driver. It saves the sign-extended
+ * fraction supplied in the argument in a circular buffer for
+ * processing at the next poll event.
+ */
+ peer = last_atom_peer;
+ if (!peer)
+ return (-1); /* no ATOM configured ? Forget it ! */
+
+ pp = peer->procptr;
+ up = (struct atomunit *)pp->unitptr;
+
+ L_CLR(&lftemp);
+ L_ADDF(&lftemp, tsr->l_f);
+ i = ((int)(pp->coderecv)) % pp->nstages;
+ pp->filter[i] = lftemp;
+ if (pp->coderecv == 0)
+ for (i = 1; i < pp->nstages; i++)
+ pp->filter[i] = pp->filter[0];
+ pp->coderecv++;
+ up->pollcnt = 2;
+
+ /* HACK -- use the local UN*X clock to get the time -- this is wrong */
+ pp->lastrec.l_ui = time(0) - 2 + JAN_1970;
+ pp->lastrec.l_uf = 0;
+
+ return (0);
+}
+
+#ifdef PPS
+/*
+ * atom_pps - receive data from the LDISC_PPS discipline
+ */
+static void
+atom_pps(peer)
+ struct peer *peer;
+{
+ register struct atomunit *up;
+ struct refclockproc *pp;
+ l_fp lftmp;
+ int i;
+
+ /*
+ * This routine is called once per second when the LDISC_PPS
+ * discipline is present. It snatches the pps timestamp from the
+ * kernel and saves the sign-extended fraction in a circular
+ * buffer for processing at the next poll event.
+ */
+ pp = peer->procptr;
+ up = (struct atomunit *)pp->unitptr;
+
+ /*
+ * Arm the timer for the next interrupt
+ */
+ up->timer.event_time = current_time + PPS_POLL;
+ TIMER_INSERT(timerqueue, &up->timer);
+
+ /*
+ * Convert the timeval to l_fp and save for billboards. Sign-
+ * extend the fraction and stash in the buffer. No harm is done
+ * if previous data are overwritten. If the discipline comes bum
+ * or the data grow stale, just forget it.
+ */
+ i = up->ev.serial;
+ if (ioctl(fdpps, CIOGETEV, (caddr_t)&up->ev) < 0)
+ return;
+ if (i == up->ev.serial)
+ return;
+ pp->lastrec.l_ui = up->ev.tv.tv_sec + JAN_1970;
+ TVUTOTSF(up->ev.tv.tv_usec, pp->lastrec.l_uf);
+ L_CLR(&lftmp);
+ L_ADDF(&lftmp, pp->lastrec.l_f);
+ L_NEG(&lftmp);
+ i = ((int)(pp->coderecv)) % pp->nstages;
+ pp->filter[i] = lftmp;
+ if (pp->coderecv == 0)
+ for (i = 1; i < pp->nstages; i++)
+ pp->filter[i] = pp->filter[0];
+ pp->coderecv++;
+ up->pollcnt = 2;
+}
+#endif /* PPS */
+
+/*
+ * atom_receive - receive data from the serial line interface
+ */
+static void
+atom_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register struct atomunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ l_fp lftmp;
+ int i;
+
+ /*
+ * This routine is called once per second when the serial
+ * interface is in use. It snatches the timestamp from the
+ * buffer and saves the sign-extended fraction in a circular
+ * buffer for processing at the next poll event.
+ */
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct atomunit *)pp->unitptr;
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX,
+ &pp->lastrec);
+
+ /*
+ * Save the timestamp for billboards. Sign-extend the fraction
+ * and stash in the buffer. No harm is done if previous data are
+ * overwritten.
+ */
+ L_CLR(&lftmp);
+ L_ADDF(&lftmp, pp->lastrec.l_f);
+ L_NEG(&lftmp);
+ i = ((int)(pp->coderecv)) % pp->nstages;
+ pp->filter[i] = lftmp;
+ if (pp->coderecv == 0)
+ for (i = 1; i < pp->nstages; i++)
+ pp->filter[i] = pp->filter[0];
+ pp->coderecv++;
+ up->pollcnt = 2;
+}
+
+/*
+ * Compare two l_fp's - used with qsort()
+ */
+static int
+atom_cmpl_fp(p1, p2)
+ register void *p1, *p2; /* l_fp to compare */
+{
+
+ if (!L_ISGEQ((l_fp *)p1, (l_fp *)p2))
+ return (-1);
+ if (L_ISEQU((l_fp *)p1, (l_fp *)p2))
+ return (0);
+ return (1);
+}
+
+/*
+ * atom_poll - called by the transmit procedure
+ */
+static void
+atom_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct atomunit *up;
+ struct refclockproc *pp;
+ int i, n;
+ l_fp median, lftmp;
+ l_fp off[MAXSTAGE];
+ u_fp disp;
+
+ /*
+ * At each poll we check for timeout. At the first timeout we
+ * test to see if the LDISC_PPS discipline is present and, if
+ * so, use that. If not, we attempt to open a serial line with
+ * LDISC_CLKPPS discipline. If that fails, we bitch to the log
+ * and clam up.
+ */
+ pp = peer->procptr;
+ up = (struct atomunit *)pp->unitptr;
+ pp->polls++;
+ if (up->pollcnt == 0) {
+ refclock_report(peer, CEVNT_FAULT);
+ return;
+ }
+ up->pollcnt--;
+ if (up->pollcnt == 0) {
+ if (!pp->io.fd && fdpps == -1) {
+ int fd;
+ char device[20];
+
+ /*
+ * Open serial port. Use CLKPPS line discipline,
+ * if available. If unavailable, the code works
+ * anyway, but at reduced accuracy.
+ */
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232,
+ LDISC_CLKPPS))) {
+ refclock_report(peer, CEVNT_FAULT);
+ return;
+ }
+ pp->io.clock_recv = atom_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ refclock_report(peer, CEVNT_FAULT);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Valid time (leap bits zero) is returned only if the prefer
+ * peer has survived the intersection algorithm and within
+ * CLOCK_MAX of local time and not too long ago. This insures
+ * the pps time is within +-0.5 s of the local time and the
+ * seconds numbering is unambiguous.
+ */
+ if (pps_update) {
+ pp->leap = 0;
+ pp->lasttime = current_time;
+ } else
+ pp->leap = LEAP_NOTINSYNC;
+
+ /*
+ * Copy the raw offsets and sort into ascending order
+ */
+ for (i = 0; i < MAXSTAGE; i++)
+ off[i] = pp->filter[i];
+ qsort((char *)off, pp->nstages, sizeof(l_fp), atom_cmpl_fp);
+
+ /*
+ * Reject the furthest from the median of nstages samples until
+ * nskeep samples remain.
+ */
+ i = 0;
+ n = pp->nstages;
+ while ((n - i) > NSAMPLES) {
+ lftmp = off[n - 1];
+ median = off[(n + i) / 2];
+ L_SUB(&lftmp, &median);
+ L_SUB(&median, &off[i]);
+ if (L_ISHIS(&median, &lftmp)) {
+ /* reject low end */
+ i++;
+ } else {
+ /* reject high end */
+ n--;
+ }
+ }
+
+ /*
+ * Compute the dispersion based on the difference between the
+ * extremes of the remaining offsets. Add to this the time since
+ * the last clock update, which represents the dispersion
+ * increase with time. We know that NTP_MAXSKEW is 16. If the
+ * sum is greater than the allowed sample dispersion, bail out.
+ * Otherwise, return the median offset plus the configured
+ * fudgetime1 value.
+ */
+ lftmp = off[n - 1];
+ L_SUB(&lftmp, &off[i]);
+ disp = LFPTOFP(&lftmp) + current_time - pp->lasttime;
+ if (disp > PPSMAXDISPERSE) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ pp->offset = off[(n + 1) / 2];
+ L_ADD(&pp->offset, &pp->fudgetime1);
+ pp->dispersion = disp;
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
+}
+
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_chu.c b/usr.sbin/xntpd/xntpd/refclock_chu.c
index 4596db22e2f5..2488da62e9c0 100644
--- a/usr.sbin/xntpd/xntpd/refclock_chu.c
+++ b/usr.sbin/xntpd/xntpd/refclock_chu.c
@@ -1,7 +1,7 @@
/*
* refclock_chu - clock driver for the CHU time code
*/
-#if defined(REFCLOCK) && (defined(CHU) || defined(CHUCLK) || defined(CHUPPS))
+#if defined(REFCLOCK) && defined(CHU)
#include <stdio.h>
#include <ctype.h>
@@ -11,28 +11,7 @@
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
-
-#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(HAVE_TERMIOS)
-#include <termios.h>
-#endif
-#if defined(STREAM)
-#include <stropts.h>
-#endif /* STREAM */
-
-#if defined (CHUPPS)
-#include <sys/ppsclock.h>
-#endif /* CHUPPS */
-
#include <sys/chudefs.h>
-
#include "ntp_stdlib.h"
/*
@@ -79,29 +58,30 @@
* in this nibble.
*
* The start bit in each character has a precise relationship to
- * the on-time second. Most often UART's synchronize themselves to the
+ * the on-time second. Most often UART's synchronize themselves to the
* start bit and will post an interrupt at the center of the first stop
* bit. Thus each character's interrupt should occur at a fixed offset
- * from the on-time second. This means that a timestamp taken at the
+ * from the on-time second. This means that a timestamp taken at the
* arrival of each character in the code will provide an independent
* estimate of the offset. Since there are 10 characters in the time
- * code and the code is sent 9 times per minute, this means you potentially
- * get 90 offset samples per minute. Much of the code in here is dedicated
- * to producing a single offset estimate from these samples.
+ * code and the code is sent 9 times per minute, this means you
+ * potentially get 90 offset samples per minute. Much of the code in
+ * here is dedicated to producing a single offset estimate from these
+ * samples.
*
- * A note about the line discipline. It is possible to receive the
- * CHU time code in raw mode, but this has disadvantages. In particular,
+ * A note about the line discipline. It is possible to receive the
+ * CHU time code in raw mode, but this has disadvantages. In particular,
* this puts a lot of code between the interrupt and the time you freeze
- * a time stamp, decreasing precision. It is also expensive in terms of
+ * a time stamp, decreasing precision. It is also expensive in terms of
* context switches, and made even more expensive by the way I do I/O.
* Worse, since you are listening directly to the output of your radio,
* CHU is noisy and will make you spend a lot of time receiving noise.
*
- * The line discipline fixes a lot of this. It knows that the CHU time
+ * The line discipline fixes a lot of this. It knows that the CHU time
* code consists of 10 bytes which arrive with an intercharacter
* spacing of about 37 ms, and that the data is BCD, and filters on this
- * basis. It delivers block of ten characters plus their associated time
- * stamps all at once. The time stamps are hence about as accurate as
+ * basis. It delivers block of ten characters plus their associated time
+ * stamps all at once. The time stamps are hence about as accurate as
* a Unix machine can get them, and much of the noise disappears in the
* kernel with no context switching cost.
*
@@ -112,13 +92,18 @@
*/
/*
- * Definitions
+ * CHU definitions
*/
-#define MAXUNITS 4 /* maximum number of CHU units permitted */
-#define CHUDEV "/dev/chu%d" /* device we open. %d is unit number */
-#define SPEED232 B300 /* uart speed (300 baud) */
+#define DEVICE "/dev/chu%d" /* device name and unit */
+#define SPEED232 B300 /* uart speed (300 baud) */
+#define PRECISION (-9) /* what the heck */
+#define REFID "CHU\0" /* reference ID */
+#define DESCRIPTION "Scratchbuilt CHU Receiver" /* WRU */
+
#define NCHUCODES 8 /* expect 8 CHU codes per minute */
+#ifndef CHULDISC
#define CHULDISC 10 /* XXX temp CHU line discipline */
+#endif
/*
* To compute a quality for the estimate (a pseudo dispersion) we add a
@@ -129,14 +114,6 @@
#define CHUDELAYPENALTY 0x0000028f
/*
- * Other constant stuff
- */
-#define CHUPRECISION (-9) /* what the heck */
-#define CHUREFID "CHU\0"
-#define CHUDESCRIPTION "Direct synchronized to CHU timecode"
-#define CHUHSREFID 0x7f7f070a /* 127.127.7.10 refid for hi strata */
-
-/*
* Default fudge factors
*/
#define DEFPROPDELAY 0x00624dd3 /* 0.0015 seconds, 1.5 ms */
@@ -160,37 +137,27 @@
static char hexstring[]="0123456789abcdef";
/*
- * CHU unit control structure.
+ * Unit control structure.
*/
struct chuunit {
- struct peer *peer; /* associated peer structure */
- struct event chutimer; /* timeout timer structure */
- struct refclockio chuio; /* given to the I/O handler */
- l_fp offsets[NCHUCODES]; /* offsets computed from each code */
- l_fp rectimes[NCHUCODES]; /* times we received this stuff */
- U_LONG reftimes[NCHUCODES]; /* time of last code received */
- u_char lastcode[NCHUCHARS*4]; /* last code we received */
- u_char asciicode[NCHUCHARS*4+1]; /* last code translated to ascii */
- u_char expect; /* the next offset expected */
- u_char unit; /* unit number for this guy */
- u_short haveoffset; /* flag word indicating valid offsets */
- u_short flags; /* operational flags */
- u_char status; /* clock status */
- u_char lastevent; /* last clock event */
- u_char unused[2];
- U_LONG lastupdate; /* last time data received */
- U_LONG responses; /* number of responses */
- U_LONG badformat; /* number of bad format responses */
- U_LONG baddata; /* number of invalid time codes */
- U_LONG timestarted; /* time we started this */
- u_char leap; /* leap status */
+ struct peer *peer; /* peer structure pointer */
+ struct event chutimer; /* timeout timer structure */
+ l_fp offsets[NCHUCODES]; /* offsets computed from each code */
+ l_fp rectimes[NCHUCODES]; /* times we received this stuff */
+ u_long reftimes[NCHUCODES]; /* time of last code received */
+ u_char lastcode[NCHUCHARS * 4]; /* last code we received */
+ u_char expect; /* the next offset expected */
+ u_short haveoffset; /* flag word indicating valid offsets */
+ u_short flags; /* operational flags */
+ u_long responses; /* number of responses */
+ int pollcnt; /* poll message counter */
};
-#define CHUTIMERSET 0x1 /* timer is set to fire */
+#define CHUTIMERSET 0x1 /* timer is set to fire */
/*
- * The CHU table. This gives the expected time of arrival of each
+ * The CHU table. This gives the expected time of arrival of each
* character after the on-time second and is computed as follows:
* The CHU time code is sent at 300 bps. Your average UART will
* synchronize at the edge of the start bit and will consider the
@@ -198,12 +165,11 @@ struct chuunit {
* 0.031667 ms later (some UARTS may complete the character at the
* end of the stop bit instead of the middle, but you can fudge this).
* Thus the expected time of each interrupt is the start bit time plus
- * 0.031667 seconds. These times are in chutable[]. To this we add
- * such things as propagation delay and delay fudge factor.
+ * 0.031667 seconds. These times are in chutable[].
*/
#define CHARDELAY 0x081b4e82
-static U_LONG chutable[NCHUCHARS] = {
+static u_long chutable[NCHUCHARS] = {
0x22222222 + CHARDELAY, /* 0.1333333333 */
0x2b851eb8 + CHARDELAY, /* 0.170 (exactly) */
0x34e81b4e + CHARDELAY, /* 0.2066666667 */
@@ -217,348 +183,110 @@ static U_LONG chutable[NCHUCHARS] = {
};
/*
- * Data space for the unit structures. Note that we allocate these on
- * the fly, but never give them back.
- */
-static struct chuunit *chuunits[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 propagation_delay[MAXUNITS];
-static l_fp fudgefactor[MAXUNITS];
-static l_fp offset_fudge[MAXUNITS];
-static u_char stratumtouse[MAXUNITS];
-static u_char sloppyclockflag[MAXUNITS];
-
-/*
- * We keep track of the start of the year, watching for changes.
- * We also keep track of whether the year is a leap year or not.
- * All because stupid CHU doesn't include the year in the time code.
- */
-static U_LONG yearstart;
-
-/*
* Imported from the timer module
*/
-extern U_LONG current_time;
+extern u_long current_time;
extern struct event timerqueue[];
/*
- * Imported from ntp_loopfilter module
- */
-extern int fdpps; /* pps file descriptor */
-
-/*
* Imported from ntpd module
*/
extern int debug; /* global debug flag */
/*
- * Event reporting. This optimizes things a little.
+ * Function prototypes
*/
-#define chu_event(chu, evcode) \
- do { \
- if ((chu)->status != (u_char)(evcode)) \
- chu_report_event((chu), (evcode)); \
- } while (0)
-
-static void chu_init P((void));
-static int chu_start P((u_int, struct peer *));
-static void chu_shutdown P((int));
-static void chu_report_event P((struct chuunit *, int));
+static int chu_start P((int, struct peer *));
+static void chu_shutdown P((int, struct peer *));
static void chu_receive P((struct recvbuf *));
static void chu_process P((struct chuunit *));
static void chu_poll P((int, struct peer *));
-static void chu_control P((u_int, struct refclockstat *, struct refclockstat *));
static void chu_timeout P((struct peer *));
/*
* Transfer vector
*/
struct refclock refclock_chu = {
- chu_start, chu_shutdown, chu_poll,
- chu_control, chu_init, noentry, NOFLAGS
+ chu_start, /* start up driver */
+ chu_shutdown, /* shut down driver */
+ chu_poll, /* transmit poll message */
+ noentry, /* not used (old chu_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old chu_buginfo) */
+ NOFLAGS /* not used */
};
-/*
- * chu_init - initialize internal chu driver data
- */
-static void
-chu_init()
-{
- register int i;
- /*
- * Just zero the data arrays
- */
- memset((char *)chuunits, 0, sizeof chuunits);
- memset((char *)unitinuse, 0, sizeof unitinuse);
-
- /*
- * Initialize fudge factors to default.
- */
- for (i = 0; i < MAXUNITS; i++) {
- propagation_delay[i].l_ui = 0;
- propagation_delay[i].l_uf = DEFPROPDELAY;
- fudgefactor[i].l_ui = 0;
- fudgefactor[i].l_uf = DEFFILTFUDGE;
- offset_fudge[i] = propagation_delay[i];
- L_ADD(&offset_fudge[i], &fudgefactor[i]);
- stratumtouse[i] = 0;
- sloppyclockflag[i] = 0;
- }
-}
-
/*
* chu_start - open the CHU device and initialize data for processing
*/
static int
chu_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register struct chuunit *chu;
- register int i;
- int fd232;
- char chudev[20];
- l_fp ts;
+ register struct chuunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
/*
- * Check configuration info
+ * Open serial port and set CHU line discipline
*/
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "chu_start: unit %d invalid", unit);
- return 0;
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "chu_start: unit %d in use", unit);
- return 0;
- }
+ (void) sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_CHU)))
+ return (0);
/*
- * Open serial port
+ * Allocate and initialize unit structure
*/
- (void) sprintf(chudev, CHUDEV, unit);
- fd232 = open(chudev, O_RDONLY, 0777);
- if (fd232 == -1) {
- syslog(LOG_ERR, "chu_start: open of %s: %m", chudev);
- return 0;
+ if (!(up = (struct chuunit *)
+ emalloc(sizeof(struct chuunit)))) {
+ (void) close(fd);
+ return (0);
}
-
-#if defined(HAVE_SYSV_TTYS)
- /*
- * System V serial line parameters (termio interface)
- */
- CHU SUPPORT NOT AVAILABLE IN TERMIO INTERFACE
-#endif /* HAVE_SYSV_TTYS */
-#if defined(HAVE_TERMIOS)
- /*
- * POSIX serial line parameters (termios interface)
- *
- * The CHUCLK support uses a 300-baud modem and level converter
- * (gadget box). It requires the chu_clk streams module and
- * SunOS 4.1.1 or later.
- *
- * The CHUPPS 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,
- "chu_start: tcgetattr(%s): %m", chudev);
- goto screwed;
- }
- ttyp->c_iflag = IGNBRK|IGNPAR;
- ttyp->c_oflag = 0;
- ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
- ttyp->c_lflag = 0;
- ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
- ttyp->c_cc[VMIN] = 1;
- ttyp->c_cc[VTIME] = 0;
- if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
- syslog(LOG_ERR,
- "chu_start: tcsetattr(%s): %m", chudev);
- goto screwed;
- }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- syslog(LOG_ERR,
- "chu_start: tcflush(%s): %m", chudev);
- goto screwed;
- }
- }
-#endif /* HAVE_TERMIOS */
-#ifdef STREAM
- while (ioctl(fd232, I_POP, 0 ) >= 0) ;
- if (ioctl(fd232, I_PUSH, "chu" ) < 0) {
- syslog(LOG_ERR,
- "chu_start: ioctl(%s, I_PUSH, chu): %m", chudev);
- goto screwed;
- }
-#if defined(CHUPPS)
- if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
- syslog(LOG_ERR,
- "chu_start: ioctl(%s, I_PUSH, ppsclock): %m", chudev);
- else
- fdpps = fd232;
-#endif /* CHUPPS */
-#endif /* STREAM */
-#if defined(HAVE_BSD_TTYS)
- /*
- * 4.3bsd serial line parameters (sgttyb interface)
- *
- * The CHUCLK support uses a 300-baud modem and level converter
- * (gadget box). It requires the chu_clk streams module and
- * 4.3bsd or later.
- */
- { struct sgttyb ttyb;
- int ldisc = CHULDISC;
-
- if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "chu_start: ioctl(%s, TIOCGETP): %m", chudev);
- goto screwed;
- }
- ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
- ttyb.sg_erase = ttyb.sg_kill = '\r';
- ttyb.sg_flags = RAW;
- if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "chu_start: ioctl(%s, TIOCSETP): %m", chudev);
- goto screwed;
+ memset((char *)up, 0, sizeof(struct chuunit));
+ up->chutimer.peer = (struct peer *)up;
+ up->chutimer.event_handler = chu_timeout;
+ up->peer = peer;
+ pp = peer->procptr;
+ pp->io.clock_recv = chu_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
}
- if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR,
- "chu_start: ioctl(%s, TIOCSETD): %m",chudev);
- goto screwed;
- }
- }
-#endif /* HAVE_BSD_TTYS */
-
- /*
- * Allocate unit structure
- */
- if (chuunits[unit] != 0) {
- chu = chuunits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < MAXUNITS; i++) {
- if (!unitinuse[i] && chuunits[i] != 0)
- break;
- }
- if (i < MAXUNITS) {
- /*
- * Reclaim this one
- */
- chu = chuunits[i];
- chuunits[i] = 0;
- } else {
- chu = (struct chuunit *)emalloc(sizeof(struct chuunit));
- }
- }
- memset((char *)chu, 0, sizeof(struct chuunit));
- chuunits[unit] = chu;
+ pp->unitptr = (caddr_t)up;
/*
- * Set up the structure
+ * Initialize miscellaneous variables
*/
- chu->peer = peer;
- chu->unit = (u_char)unit;
- chu->timestarted = current_time;
-
- chu->chutimer.peer = (struct peer *)chu;
- chu->chutimer.event_handler = chu_timeout;
-
- chu->chuio.clock_recv = chu_receive;
- chu->chuio.srcclock = (caddr_t)chu;
- chu->chuio.datalen = sizeof(struct chucode);
- chu->chuio.fd = fd232;
-
- /*
- * Initialize the year from the system time in case this is the
- * first open.
- */
- get_systime(&ts);
- yearstart = calyearstart(ts.l_ui);
- if (!io_addclock(&chu->chuio)) {
- goto screwed;
- }
-
- /*
- * All done. Initialize a few random peer variables, then
- * return success.
- */
- peer->precision = CHUPRECISION;
- peer->rootdelay = 0;
- peer->rootdispersion = 0;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, CHUREFID, 4);
- else
- peer->refid = htonl(CHUHSREFID);
- unitinuse[unit] = 1;
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
return (1);
-
- /*
- * Something broke; abandon ship.
- */
-screwed:
- (void) close(fd232);
- return (0);
}
/*
- * chu_shutdown - shut down a CHU clock
+ * chu_shutdown - shut down the clock
*/
static void
-chu_shutdown(unit)
+chu_shutdown(unit, peer)
int unit;
+ struct peer *peer;
{
- register struct chuunit *chu;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "chu_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "chu_shutdown: unit %d not in use", unit);
- return;
- }
+ register struct chuunit *up;
+ struct refclockproc *pp;
- /*
- * Tell the I/O module to turn us off, and dequeue timer
- * if any. We're history.
- */
- chu = chuunits[unit];
- if (chu->flags & CHUTIMERSET)
- TIMER_DEQUEUE(&chu->chutimer);
- io_closeclock(&chu->chuio);
- unitinuse[unit] = 0;
-}
-
-/*
- * chu_report_event - record an event and report it
- */
-static void
-chu_report_event(chu, code)
- struct chuunit *chu;
- int code;
-{
- /*
- * Trap support isn't up to handling this, so just
- * record it.
- */
- if (chu->status != (u_char)code) {
- chu->status = (u_char)code;
- if (code != CEVNT_NOMINAL)
- chu->lastevent = (u_char)code;
- }
+ pp = peer->procptr;
+ up = (struct chuunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
}
@@ -570,14 +298,16 @@ static void
chu_receive(rbufp)
struct recvbuf *rbufp;
{
- register int i;
- register U_LONG date_ui;
- register U_LONG tmp;
- register u_char *code;
- register struct chuunit *chu;
- register struct chucode *chuc;
+ register struct chuunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ int i;
+ u_long date_ui;
+ u_long tmp;
+ u_char *code;
+ struct chucode *chuc;
int isneg;
- U_LONG reftime;
+ u_long reftime;
l_fp off[NCHUCHARS];
int day, hour, minute, second;
@@ -585,7 +315,8 @@ chu_receive(rbufp)
* Do a length check on the data. Should be what we asked for.
*/
if (rbufp->recv_length != sizeof(struct chucode)) {
- syslog(LOG_ERR, "chu_receive: received %d bytes, expected %d",
+ syslog(LOG_ERR,
+ "chu_receive: received %d bytes, expected %d",
rbufp->recv_length, sizeof(struct chucode));
return;
}
@@ -593,27 +324,39 @@ chu_receive(rbufp)
/*
* Get the clock this applies to and a pointer to the data
*/
- chu = (struct chuunit *)rbufp->recv_srcclock;
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct chuunit *)pp->unitptr;
chuc = (struct chucode *)&rbufp->recv_space;
- chu->responses++;
- chu->lastupdate = current_time;
+ up->responses++;
/*
* 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);
+ for (i = 0; i < NCHUCHARS; i++) {
+ pp->lastcode[2 * i] = hexstring[chuc->codechars[i] &
+ 0xf];
+ pp->lastcode[2 * i + 1] = hexstring[chuc->codechars[i]
+ >> 4];
+ }
+ pp->lencode = 2 * i;
+ pp->lastcode[pp->lencode] = '\0';
+#ifdef DEBUG
+ if (debug > 3) {
+ printf("chu: %s packet\n", (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 \n */
+ printf("chu: %s .%06d\n", c,
+ chuc->codetimes[i].tv_usec);
+ }
}
#endif
@@ -633,7 +376,7 @@ chu_receive(rbufp)
* Break out the code into the BCD nibbles.
* Put it in the half of lastcode.
*/
- code = chu->lastcode;
+ code = up->lastcode;
code += 2*NCHUCHARS;
for (i = 0; i < NCHUCHARS; i++) {
*code++ = chuc->codechars[i] & 0xf;
@@ -651,8 +394,7 @@ chu_receive(rbufp)
parity = (parity ^ (parity>>1))&0x1;
if (parity)
{
- chu->badformat++;
- chu_event(chu, CEVNT_BADREPLY);
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
@@ -660,15 +402,14 @@ chu_receive(rbufp)
* This just happens to work. :-)
*/
- chu->leap = (leapbits >> 1) & 0x3;
+ pp->leap = (leapbits >> 1) & 0x3;
return;
}
if (chuc->chutype != CHU_TIME)
{
- chu->badformat++;
- chu_event(chu, CEVNT_BADREPLY);
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
@@ -677,7 +418,7 @@ chu_receive(rbufp)
* with the first half since both are identical. Note the first
* BCD character is the low order nibble, the second the high order.
*/
- code = chu->lastcode;
+ code = up->lastcode;
for (i = 0; i < NCHUCHARS; i++) {
*code++ = chuc->codechars[i] & 0xf;
*code++ = (chuc->codechars[i] >> 4) & 0xf;
@@ -688,19 +429,18 @@ chu_receive(rbufp)
* There's really no need for this, but it can't hurt.
*/
for (i = 0; i < NCHUCHARS/2; i++)
- if (chuc->codechars[i] != chuc->codechars[i+(NCHUCHARS/2)]) {
- chu->badformat++;
- chu_event(chu, CEVNT_BADREPLY);
+ if (chuc->codechars[i] !=
+ chuc->codechars[i+(NCHUCHARS/2)]) {
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
/*
* If the first nibble isn't a 6, we're up the creek
*/
- code = chu->lastcode;
+ code = up->lastcode;
if (*code++ != 6) {
- chu->badformat++;
- chu_event(chu, CEVNT_BADREPLY);
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
@@ -725,11 +465,11 @@ chu_receive(rbufp)
if (day < 1 || day > 366
|| hour > 23 || minute > 59
|| second < 32 || second > 39) {
- chu->baddata++;
+ pp->baddata++;
if (day < 1 || day > 366) {
- chu_event(chu, CEVNT_BADDATE);
+ refclock_report(peer, CEVNT_BADDATE);
} else {
- chu_event(chu, CEVNT_BADTIME);
+ refclock_report(peer, CEVNT_BADTIME);
}
return;
}
@@ -740,8 +480,8 @@ chu_receive(rbufp)
* date as bad and forget it.
*/
if (!clocktime(day, hour, minute, second, 0,
- rbufp->recv_time.l_ui, &yearstart, &reftime)) {
- chu_event(chu, CEVNT_BADDATE);
+ rbufp->recv_time.l_ui, &pp->yearstart, (U_LONG *)&reftime)) {
+ refclock_report(peer, CEVNT_BADDATE);
return;
}
date_ui = reftime;;
@@ -752,7 +492,7 @@ chu_receive(rbufp)
* the offsets for each character.
*/
for (i = 0; i < NCHUCHARS; i++) {
- register U_LONG tmp2;
+ register u_long tmp2;
off[i].l_ui = date_ui;
off[i].l_uf = chutable[i];
@@ -761,7 +501,7 @@ chu_receive(rbufp)
M_SUB(off[i].l_ui, off[i].l_uf, tmp, tmp2);
}
- if (!sloppyclockflag[chu->unit]) {
+ if (!pp->sloppyclockflag) {
u_short ord[NCHUCHARS];
/*
* In here we assume the clock has adequate bits
@@ -798,7 +538,7 @@ chu_receive(rbufp)
for (tmp = 0; tmp < (NCHUCHARS-1); tmp++) {
for (i = (int)tmp+1; i < NCHUCHARS; i++) {
if (!L_ISGEQ(&off[ord[i]], &off[ord[tmp]])) {
- date_ui = (U_LONG)ord[i];
+ date_ui = (u_long)ord[i];
ord[i] = ord[tmp];
ord[tmp] = (u_short)date_ui;
}
@@ -853,8 +593,8 @@ chu_receive(rbufp)
* out of a 64 bit product, even after rounding.
*/
if (date_ui < 9 || date_ui > 0xfffffff7) {
- register U_LONG prod_ui;
- register U_LONG prod_uf;
+ register u_long prod_ui;
+ register u_long prod_uf;
prod_ui = prod_uf = 0;
/*
@@ -881,10 +621,10 @@ chu_receive(rbufp)
* date_ui is integral part, tmp is fraction.
*/
} else {
- register U_LONG prod_ovr;
- register U_LONG prod_ui;
- register U_LONG prod_uf;
- register U_LONG highbits;
+ register u_long prod_ovr;
+ register u_long prod_ui;
+ register u_long prod_uf;
+ register u_long highbits;
prod_ovr = prod_ui = prod_uf = 0;
if (isneg)
@@ -902,7 +642,7 @@ chu_receive(rbufp)
}
if (prod_uf & 0x80000000)
- M_ADDUF(prod_ovr, prod_ui, (U_LONG)1);
+ M_ADDUF(prod_ovr, prod_ui, (u_long)1);
date_ui = prod_ovr;
tmp = prod_ui;
}
@@ -914,56 +654,50 @@ chu_receive(rbufp)
* it in the structure.
*/
i = second - 32; /* gives a value 0 through 8 */
- if (i < (int)chu->expect) {
+ if (i < (int)up->expect) {
/*
* This shouldn't actually happen, but might if a single
* bit error occurred in the code which fooled us.
* Throw away all previous data.
*/
- chu->expect = 0;
- chu->haveoffset = 0;
- if (chu->flags & CHUTIMERSET) {
- TIMER_DEQUEUE(&chu->chutimer);
- chu->flags &= ~CHUTIMERSET;
+ up->expect = 0;
+ up->haveoffset = 0;
+ if (up->flags & CHUTIMERSET) {
+ TIMER_DEQUEUE(&up->chutimer);
+ up->flags &= ~CHUTIMERSET;
}
}
- /*
- * Add in fudge factor.
- */
- M_ADD(date_ui, tmp, offset_fudge[chu->unit].l_ui,
- offset_fudge[chu->unit].l_uf);
-
- chu->offsets[i].l_ui = date_ui;
- chu->offsets[i].l_uf = tmp;
- chu->rectimes[i] = rbufp->recv_time;
- chu->reftimes[i] = reftime;
+ up->offsets[i].l_ui = date_ui;
+ up->offsets[i].l_uf = tmp;
+ up->rectimes[i] = rbufp->recv_time;
+ up->reftimes[i] = reftime;
- chu->expect = i + 1;
- chu->haveoffset |= (1<<i);
+ up->expect = i + 1;
+ up->haveoffset |= (1 << i);
- if (chu->expect >= NCHUCODES) {
+ if (up->expect >= NCHUCODES) {
/*
* Got a full second's worth. Dequeue timer and
* process this.
*/
- if (chu->flags & CHUTIMERSET) {
- TIMER_DEQUEUE(&chu->chutimer);
- chu->flags &= ~CHUTIMERSET;
+ if (up->flags & CHUTIMERSET) {
+ TIMER_DEQUEUE(&up->chutimer);
+ up->flags &= ~CHUTIMERSET;
}
- chu_process(chu);
- } else if (!(chu->flags & CHUTIMERSET)) {
+ chu_process(up);
+ } else if (!(up->flags & CHUTIMERSET)) {
/*
* Try to take an interrupt sometime after the
* 42 second mark (leaves an extra 2 seconds for
* slop). Round it up to an even multiple of
* 4 seconds.
*/
- chu->chutimer.event_time =
- current_time + (U_LONG)(10 - i) + (1<<EVENT_TIMEOUT);
- chu->chutimer.event_time &= ~((1<<EVENT_TIMEOUT) - 1);
- TIMER_INSERT(timerqueue, &chu->chutimer);
- chu->flags |= CHUTIMERSET;
+ up->chutimer.event_time =
+ current_time + (u_long)(10 - i) + (1<<EVENT_TIMEOUT);
+ up->chutimer.event_time &= ~((1<<EVENT_TIMEOUT) - 1);
+ TIMER_INSERT(timerqueue, &up->chutimer);
+ up->flags |= CHUTIMERSET;
}
}
@@ -990,62 +724,57 @@ chu_timeout(fakepeer)
* the results on to the NTP clock filters.
*/
static void
-chu_process(chu)
- register struct chuunit *chu;
+chu_process(up)
+ register struct chuunit *up;
{
- register int i;
- register s_fp bestoff;
- register s_fp tmpoff;
+ struct peer *peer;
+ struct refclockproc *pp;
+ int i;
+ s_fp bestoff;
+ s_fp tmpoff;
u_fp dispersion;
int imax;
- l_fp ts;
/*
* The most positive offset.
*/
+ peer = up->peer;
+ pp = peer->procptr;
imax = NCHUCODES;
for (i = 0; i < NCHUCODES; i++)
- if (chu->haveoffset & (1<<i))
- if (i < imax || L_ISGEQ(&chu->offsets[i],
- &chu->offsets[imax]))
+ if (up->haveoffset & (1<<i))
+ if (i < imax || L_ISGEQ(&up->offsets[i],
+ &up->offsets[imax]))
imax = i;
/*
* The most positive estimate is our best bet. Go through
* the list again computing the dispersion.
*/
- bestoff = LFPTOFP(&chu->offsets[imax]);
+ bestoff = LFPTOFP(&up->offsets[imax]);
dispersion = 0;
for (i = 0; i < NCHUCODES; i++) {
- if (chu->haveoffset & (1<<i)) {
- tmpoff = LFPTOFP(&chu->offsets[i]);
+ if (up->haveoffset & (1<<i)) {
+ tmpoff = LFPTOFP(&up->offsets[i]);
dispersion += (bestoff - tmpoff);
} else {
dispersion += CHUDELAYPENALTY;
}
}
- /*
- * Make up a reference time stamp, then give it to the
- * reference clock support code for further processing.
- */
- ts.l_ui = chu->reftimes[imax];
- ts.l_uf = chutable[NCHUCHARS-1];
-
- for (i = 0; i < NCHUCHARS*4; i++) {
- chu->asciicode[i] = hexstring[chu->lastcode[i]];
- }
- chu->asciicode[i] = '\0';
- record_clock_stats(&(chu->peer->srcadr), chu->asciicode);
- refclock_receive(chu->peer, &chu->offsets[imax], 0,
- dispersion, &ts, &chu->rectimes[imax], chu->leap);
+ pp->lasttime = current_time;
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
+ refclock_receive(peer, &up->offsets[imax], 0,
+ dispersion, &up->rectimes[imax], &up->rectimes[imax],
+ pp->leap);
/*
* Zero out unit for next code series
*/
- chu->haveoffset = 0;
- chu->expect = 0;
- chu_event(chu, CEVNT_NOMINAL);
+ up->haveoffset = 0;
+ up->expect = 0;
+ refclock_report(peer, CEVNT_NOMINAL);
}
@@ -1057,103 +786,15 @@ chu_poll(unit, peer)
int unit;
struct peer *peer;
{
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "chu_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "chu_poll: unit %d not in use", unit);
- return;
- }
+ register struct chuunit *up;
+ struct refclockproc *pp;
- if ((current_time - chuunits[unit]->lastupdate) > 150) {
- chu_event(chuunits[unit], CEVNT_PROP);
- }
+ pp = peer->procptr;
+ up = (struct chuunit *)pp->unitptr;
+ if (up->pollcnt == 0)
+ refclock_report(peer, CEVNT_TIMEOUT);
+ else
+ up->pollcnt--;
}
-
-
-/*
- * chu_control - set fudge factors, return statistics
- */
-static void
-chu_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- register struct chuunit *chu;
- U_LONG npolls;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "chu_control: unit %d invalid", unit);
- return;
- }
-
- if (in != 0) {
- if (in->haveflags & CLK_HAVETIME1)
- propagation_delay[unit] = in->fudgetime1;
- if (in->haveflags & CLK_HAVETIME2)
- fudgefactor[unit] = in->fudgetime2;
- offset_fudge[unit] = propagation_delay[unit];
- L_ADD(&offset_fudge[unit], &fudgefactor[unit]);
- 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
- */
- peer = chuunits[unit]->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid,
- CHUREFID, 4);
- else
- peer->refid = htonl(CHUHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
- sloppyclockflag[unit] = in->flags & CLK_FLAG1;
- }
- }
-
- if (out != 0) {
- out->type = REFCLK_CHU;
- out->flags = 0;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVETIME2|CLK_HAVEVAL1|
- CLK_HAVEVAL2|CLK_HAVEFLAG1;
- out->clockdesc = CHUDESCRIPTION;
- out->fudgetime1 = propagation_delay[unit];
- out->fudgetime2 = fudgefactor[unit];
- out->fudgeval1 = (long)stratumtouse[unit];
- out->flags = sloppyclockflag[unit];
- if (unitinuse[unit]) {
- chu = chuunits[unit];
- out->lencode = NCHUCHARS*4;
- out->fudgeval2 = chu->lastcode[2*NCHUCHARS+1];
- out->fudgeval2 *= (chu->lastcode[2*NCHUCHARS]&1)?-1:1;
- out->lastcode = chu->asciicode;
- out->timereset = current_time - chu->timestarted;
- npolls = out->timereset / 6; /* **divide** */
- out->polls = npolls;
- out->noresponse = (npolls - chu->responses);
- out->badformat = chu->badformat;
- out->baddata = chu->baddata;
- out->lastevent = chu->lastevent;
- out->currentstatus = chu->status;
- } else {
- out->fudgeval2 = 0;
- out->lencode = 0;
- out->lastcode = "";
- out->polls = out->noresponse = 0;
- out->badformat = out->baddata = 0;
- out->timereset = 0;
- out->currentstatus = out->lastevent = CEVNT_NOMINAL;
- }
- }
-}
#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_conf.c b/usr.sbin/xntpd/xntpd/refclock_conf.c
index 535ca27e9ebe..c0674d917311 100644
--- a/usr.sbin/xntpd/xntpd/refclock_conf.c
+++ b/usr.sbin/xntpd/xntpd/refclock_conf.c
@@ -15,95 +15,137 @@ static struct refclock refclock_none = {
};
#ifdef LOCAL_CLOCK
-extern struct refclock refclock_local;
+extern struct refclock refclock_local;
#else
#define refclock_local refclock_none
#endif
#if defined(TRAK) || defined(TRAKCLK) || defined(TRAKPPS)
-extern struct refclock refclock_trak;
+extern struct refclock refclock_trak;
#else
#define refclock_trak refclock_none
#endif
-#if defined(PST) || defined(PSTCLK) || defined(PSTPPS)
-extern struct refclock refclock_pst;
+#if defined(PST)
+extern struct refclock refclock_pst;
#else
#define refclock_pst refclock_none
#endif
-#if defined(CHU) || defined(CHUCLK) || defined(CHUPPS)
-extern struct refclock refclock_chu;
+#if defined(CHU)
+extern struct refclock refclock_chu;
#else
#define refclock_chu refclock_none
#endif
#if defined(GOES) || defined(GOESCLK) || defined(GOESPPS)
-extern struct refclock refclock_goes;
+extern struct refclock refclock_goes;
#else
#define refclock_goes refclock_none
#endif
-#if defined(WWVB) || defined(WWVBCLK) || defined(WWVBPPS)
-extern struct refclock refclock_wwvb;
+#if defined(WWVB)
+extern struct refclock refclock_wwvb;
#else
#define refclock_wwvb refclock_none
#endif
#if defined(PARSE) || defined(PARSEPPS)
-extern struct refclock refclock_parse;
+extern struct refclock refclock_parse;
#else
#define refclock_parse refclock_none
#endif
-#if defined(MX4200) || defined(MX4200CLK) || defined(MX4200PPS)
-extern struct refclock refclock_mx4200;
+#if defined(PPS) && (defined(MX4200) || defined(MX4200CLK) || defined(MX4200PPS))
+extern struct refclock refclock_mx4200;
#else
#define refclock_mx4200 refclock_none
#endif
-#if defined(AS2201) || defined(AS2201CLK) || defined(AS2201PPS)
-extern struct refclock refclock_as2201;
+#if defined(AS2201)
+extern struct refclock refclock_as2201;
#else
#define refclock_as2201 refclock_none
#endif
#if defined(OMEGA) || defined(OMEGACLK) || defined(OMEGAPPS)
-extern struct refclock refclock_omega;
+extern struct refclock refclock_omega;
#else
#define refclock_omega refclock_none
#endif
-#ifdef TPRO
-extern struct refclock refclock_tpro;
+#if defined(TPRO) && defined(sun) /* XXX sun only */
+extern struct refclock refclock_tpro;
#else
#define refclock_tpro refclock_none
#endif
#if defined(LEITCH) || defined(LEITCHCLK) || defined(LEITCHPPS)
-extern struct refclock refclock_leitch;
+extern struct refclock refclock_leitch;
#else
#define refclock_leitch refclock_none
#endif
-#ifdef IRIG
-extern struct refclock refclock_irig;
+#if defined(IRIG) && defined(sun) /* XXX sun only */
+extern struct refclock refclock_irig;
#else
#define refclock_irig refclock_none
#endif
#if defined(MSFEESPPS)
-extern struct refclock refclock_msfees;
+extern struct refclock refclock_msfees;
#else
#define refclock_msfees refclock_none
#endif
#if defined(GPSTM) || defined(GPSTMCLK) || defined(GPSTMPPS)
-extern struct refclock refclock_gpstm;
+extern struct refclock refclock_gpstm;
#else
#define refclock_gpstm refclock_none
#endif
+#if defined(BANC) || defined(BANCCLK) || defined(BANCPPS)
+extern struct refclock refclock_bancomm;
+#else
+#define refclock_bancomm refclock_none
+#endif
+
+#ifdef DATUM
+extern struct refclock refclock_datum;
+#else
+#define refclock_datum refclock_none
+#endif
+
+#ifdef ACTS
+extern struct refclock refclock_acts;
+#else
+#define refclock_acts refclock_none
+#endif
+
+#ifdef HEATH
+extern struct refclock refclock_heath;
+#else
+#define refclock_heath refclock_none
+#endif
+
+#ifdef NMEA
+extern struct refclock refclock_nmea;
+#else
+#define refclock_nmea refclock_none
+#endif
+
+#ifdef MOTO
+extern struct refclock refclock_moto;
+#else
+#define refclock_moto refclock_none
+#endif
+
+#ifdef ATOM
+extern struct refclock refclock_atom;
+#else
+#define refclock_atom refclock_none
+#endif
+
/*
* Order is clock_start(), clock_shutdown(), clock_poll(),
* clock_control(), clock_init(), clock_buginfo, clock_flags;
@@ -127,6 +169,15 @@ struct refclock *refclock_conf[] = {
&refclock_leitch, /* 13 REFCLK_ATOM_LEITCH */
&refclock_msfees, /* 14 REFCLK_MSF_EES */
&refclock_gpstm, /* 15 REFCLK_GPSTM_TRUETIME */
+ &refclock_bancomm, /* 16 REFCLK_IRIG_BANCOMM */
+ &refclock_datum, /* 17 REFCLK_GPS_DATUM */
+ &refclock_acts, /* 18 REFCLK_NIST_ACTS */
+ &refclock_heath, /* 19 REFCLK_WWV_HEATH */
+ &refclock_nmea, /* 20 REFCLK_GPS_NMEA */
+ &refclock_moto, /* 21 REFCLK_GPS_MOTO */
+ &refclock_atom, /* 22 REFCLK_ATOM_PPS */
+ &refclock_none, /* 23 reserved */
+ &refclock_none, /* 24 reserved */
};
u_char num_refclock_conf = sizeof(refclock_conf)/sizeof(struct refclock *);
diff --git a/usr.sbin/xntpd/xntpd/refclock_datum.c b/usr.sbin/xntpd/xntpd/refclock_datum.c
new file mode 100644
index 000000000000..825dee7ad7df
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_datum.c
@@ -0,0 +1,871 @@
+/*
+** refclock_datum - clock driver for the Datum Programmable Time Server
+**
+** Important note: This driver assumes that you have termios. If you have
+** a system that does not have termios, you will have to modify this driver.
+**
+** Sorry, I have only tested this driver on SUN and HP platforms.
+*/
+
+#if defined(REFCLOCK) && (defined(DATUM) || defined(DATUMCLK) || defined(DATUMPPS))
+
+/*
+** Include Files
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(WWVBCLK)
+#include <sys/clkdefs.h>
+#endif /* WWVBCLK */
+#endif /* STREAM */
+
+#if defined (WWVBPPS)
+#include <sys/ppsclock.h>
+#endif /* WWVBPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+** This driver supports the Datum Programmable Time System (PTS) clock.
+** The clock works in very straight forward manner. When it receives a
+** time code request (e.g., the ascii string "//k/mn"), it responds with
+** a seven byte BCD time code. This clock only responds with a
+** time code after it first receives the "//k/mn" message. It does not
+** periodically send time codes back at some rate once it is started.
+** the returned time code can be broken down into the following fields.
+**
+** _______________________________
+** Bit Index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+** ===============================
+** byte 0: | - - - - | H D |
+** ===============================
+** byte 1: | T D | U D |
+** ===============================
+** byte 2: | - - | T H | U H |
+** ===============================
+** byte 3: | - | T M | U M |
+** ===============================
+** byte 4: | - | T S | U S |
+** ===============================
+** byte 5: | t S | h S |
+** ===============================
+** byte 6: | m S | - - - - |
+** ===============================
+**
+** In the table above:
+**
+** "-" means don't care
+** "H D", "T D", and "U D" means Hundreds, Tens, and Units of Days
+** "T H", and "UH" means Tens and Units of Hours
+** "T M", and "U M" means Tens and Units of Minutes
+** "T S", and "U S" means Tens and Units of Seconds
+** "t S", "h S", and "m S" means tenths, hundredths, and thousandths
+** of seconds
+**
+** The Datum PTS communicates throught the RS232 port on your machine.
+** Right now, it assumes that you have termios. This driver has been tested
+** on SUN and HP workstations. The Datum PTS supports various IRIG and
+** NASA input codes. This driver assumes that the name of the device is
+** /dev/datum. You will need to make a soft link to your RS232 device or
+** create a new driver to use this refclock.
+*/
+
+/*
+** Datum PTS defines
+*/
+
+/*
+** Note that if GMT is defined, then the Datum PTS must use Greenwich
+** time. Otherwise, this driver allows the Datum PTS to use the current
+** wall clock for its time. It determines the time zone offset by minimizing
+** the error after trying several time zone offsets. If the Datum PTS
+** time is Greenwich time and GMT is not defined, everything should still
+** work since the time zone will be found to be 0. What this really means
+** is that your system time (at least to start with) must be within the
+** correct time by less than +- 30 minutes. The default is for GMT to not
+** defined. If you really want to force GMT without the funny +- 30 minute
+** stuff then you must define (uncomment) GMT below.
+*/
+
+/*
+#define GMT
+#define DEBUG_DATUM_PTC
+#define LOG_TIME_ERRORS
+*/
+
+
+#define PTSPRECISION (-10) /* precision assumed 1/1024 ms */
+#define DATMREFID "DATM" /* reference id */
+#define DATUM_DISPERSION 0 /* fixed dispersion = 0 ms */
+#define DATUM_MAX_ERROR 0.100 /* limits on sigma squared */
+
+#define DATUM_MAX_ERROR2 (DATUM_MAX_ERROR*DATUM_MAX_ERROR)
+
+/*
+** External Variables
+*/
+
+extern u_long current_time; /* current time (s) - not really used */
+extern int debug; /* global debug flag - not relly used */
+
+/*
+** The Datum PTS structure
+*/
+
+/*
+** I don't use a fixed array of MAXUNITS like everyone else just because
+** I don't like to program that way. Sorry if this bothers anyone. I assume
+** that you can use any id for your unit and I will search for it in a
+** dynamic array of units until I find it. I was worried that users might
+** enter a bad id in their configuration file (larger than MAXUNITS) and
+** besides, it is just cleaner not to have to assume that you have a fixed
+** number of anything in a program.
+*/
+
+struct datum_pts_unit {
+ struct peer *peer; /* peer used by xntp */
+ struct refclockio io; /* io structure used by xntp */
+ int PTS_fd; /* file descriptor for PTS */
+ u_int unit; /* id for unit */
+ u_long timestarted; /* time started */
+ l_fp lastrec; /* time tag for the receive time (system) */
+ l_fp lastref; /* reference time (Datum time) */
+ u_long yearstart; /* the year that this clock started */
+ int coderecv; /* number of time codes received */
+ int day; /* day */
+ int hour; /* hour */
+ int minute; /* minutes */
+ int second; /* seconds */
+ int msec; /* miliseconds */
+ int usec; /* miliseconds */
+ u_char leap; /* funny leap character code */
+ char retbuf[8]; /* returned time from the datum pts */
+ char nbytes; /* number of bytes received from datum pts */
+ double sigma2; /* average squared error (roughly) */
+ int tzoff; /* time zone offest from GMT */
+};
+
+/*
+** PTS static constant variables for internal use
+*/
+
+static char TIME_REQUEST[6]; /* request message sent to datum for time */
+static FILE *logfile; /* log file for logging information */
+static int nunits; /* number of active units */
+static struct datum_pts_unit
+ **datum_pts_unit; /* dynamic array of datum PTS structures */
+
+/*
+** Callback function prototypes that xntpd needs to know about.
+*/
+
+static int datum_pts_start P((int, struct peer *));
+static void datum_pts_shutdown P((int, struct peer *));
+static void datum_pts_poll P((int, struct peer *));
+static void datum_pts_control P((int, struct refclockstat *,
+ struct refclockstat *));
+static void datum_pts_init P((void));
+static void datum_pts_buginfo P((int, struct refclockbug *));
+
+/*
+** This is the call back function structure that xntpd actually uses for
+** this refclock.
+*/
+
+struct refclock refclock_datum = {
+ datum_pts_start, /* start up a new Datum refclock */
+ datum_pts_shutdown, /* shutdown a Datum refclock */
+ datum_pts_poll, /* sends out the time request */
+ datum_pts_control, /* not used */
+ datum_pts_init, /* initialization (called first) */
+ datum_pts_buginfo, /* not used */
+ NOFLAGS /* we are not setting any special flags */
+};
+
+/*
+** The datum_pts_receive callback function is handled differently from the
+** rest. It is passed to the xntpd io data structure. Basically, every
+** 64 seconds, the datum_pts_poll() routine is called. It sends out the time
+** request message to the Datum Programmable Time System. Then, xntpd
+** waits on a select() call to receive data back. The datum_pts_receive()
+** function is called as data comes back. We expect a seven byte time
+** code to be returned but the datum_pts_receive() function may only get
+** a few bytes passed to it at a time. In other words, this routine may
+** get called by the io stuff in xntpd a few times before we get all seven
+** bytes. Once the last byte is received, we process it and then pass the
+** new time measurement to xntpd for updating the system time. For now,
+** there is no 3 state filtering done on the time measurements. The
+** jitter may be a little high but at least for its current use, it is not
+** a problem. We have tried to keep things as simple as possible. This
+** clock should not jitter more than 1 or 2 mseconds at the most once
+** things settle down. It is important to get the right drift calibrated
+** in the xntpd.drift file as well as getting the right tick set up right
+** using tickadj for SUNs. Tickadj is not used for the HP but you need to
+** remember to bring up the adjtime daemon because HP does not support
+** the adjtime() call.
+*/
+
+static void datum_pts_receive P((struct recvbuf *));
+
+/*......................................................................*/
+/* datum_pts_start - start up the datum PTS. This means open the */
+/* RS232 device and set up the data structure for my unit. */
+/*......................................................................*/
+
+static int datum_pts_start(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct datum_pts_unit **temp_datum_pts_unit;
+ struct datum_pts_unit *datum_pts;
+
+#ifdef HAVE_TERMIOS
+ struct termios arg;
+#endif
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile, "Starting Datum PTS unit %d\n", unit);
+ fflush(logfile);
+#endif
+
+/*
+** Create the memory for the new unit
+*/
+
+ temp_datum_pts_unit = (struct datum_pts_unit **)
+ malloc((nunits+1)*sizeof(struct datum_pts_unit *));
+ if (nunits > 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
+ nunits*sizeof(struct datum_pts_unit *));
+ free(datum_pts_unit);
+ datum_pts_unit = temp_datum_pts_unit;
+ datum_pts_unit[nunits] = (struct datum_pts_unit *)
+ malloc(sizeof(struct datum_pts_unit));
+ datum_pts = datum_pts_unit[nunits];
+
+ datum_pts->unit = unit; /* set my unit id */
+ datum_pts->yearstart = 0; /* initialize the yearstart to 0 */
+ datum_pts->sigma2 = 0.0; /* initialize the sigma2 to 0 */
+
+/*
+** Open the Datum PTS device
+*/
+
+ datum_pts->PTS_fd = open("/dev/datum",O_RDWR);
+
+ fcntl(datum_pts->PTS_fd, F_SETFL, 0); /* clear the descriptor flags */
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Opening RS232 port with file descriptor %d\n",
+ datum_pts->PTS_fd);
+ fflush(logfile);
+#endif
+
+/*
+** Set up the RS232 terminal device information. Note that we assume that
+** we have termios. This code has only been tested on SUNs and HPs. If your
+** machine does not have termios then this program exits. You can change this
+** if you want by editing this source. Please give the changes back to the
+** xntp folks so that it can become part of their regular distribution.
+*/
+
+#ifdef HAVE_TERMIOS
+
+ arg.c_iflag = IGNBRK;
+ arg.c_oflag = 0;
+ arg.c_cflag = B9600 | CS8 | CREAD | PARENB | CLOCAL;
+ arg.c_lflag = 0;
+ arg.c_cc[VMIN] = 0; /* start timeout timer right away (not used) */
+ arg.c_cc[VTIME] = 30; /* 3 second timout on reads (not used) */
+
+ tcsetattr(datum_pts->PTS_fd, TCSANOW, &arg);
+
+#else
+
+ syslog(LOG_ERR, "Datum_PTS: Exiting - Termios not supported in this driver");
+ exit(1);
+
+#endif
+
+/*
+** Initialize the xntpd IO structure
+*/
+
+ datum_pts->peer = peer;
+ datum_pts->timestarted = current_time;
+
+ datum_pts->io.clock_recv = datum_pts_receive;
+ datum_pts->io.srcclock = (caddr_t)datum_pts;
+ datum_pts->io.datalen = 0;
+ datum_pts->io.fd = datum_pts->PTS_fd;
+
+ if (!io_addclock(&(datum_pts->io))) {
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Problem adding clock\n");
+ fflush(logfile);
+#endif
+
+ syslog(LOG_ERR, "Datum_PTS: Problem adding clock");
+
+ }
+
+ peer->precision = PTSPRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = 0;
+ memcpy((char *)&peer->refid, DATMREFID, 4);
+
+/*
+** Now add one to the number of units and return a successful code
+*/
+
+ nunits++;
+ return 1;
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_shutdown - this routine shuts doen the device and */
+/* removes the memory for the unit. */
+/*......................................................................*/
+
+static void datum_pts_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ int i,j;
+ struct datum_pts_unit **temp_datum_pts_unit;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Shutdown Datum PTS\n");
+ fflush(logfile);
+#endif
+
+ syslog(LOG_ERR, "Datum_PTS: Shutdown Datum PTS");
+
+/*
+** First we have to find the right unit (i.e., the one with the same id).
+** We do this by looping through the dynamic array of units intil we find
+** it. Note, that I don't simply use an array with a maximimum number of
+** Datum PTS units. Everything is completely dynamic.
+*/
+
+ for (i=0; i<nunits; i++) {
+ if (datum_pts_unit[i]->unit == unit) {
+
+/*
+** We found the unit so close the file descriptor and free up the memory used
+** by the structure.
+*/
+
+ io_closeclock(&datum_pts_unit[i]->io);
+ close(datum_pts_unit[i]->PTS_fd);
+ free(datum_pts_unit[i]);
+
+/*
+** Now clean up the datum_pts_unit dynamic array so that there are no holes.
+** This may mean moving pointers around, etc., to keep things compact.
+*/
+
+ if (nunits > 1) {
+
+ temp_datum_pts_unit = (struct datum_pts_unit **)
+ malloc((nunits-1)*sizeof(struct datum_pts_unit *));
+ if (i!= 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
+ i*sizeof(struct datum_pts_unit *));
+
+ for (j=i+1; j<nunits; j++) {
+ temp_datum_pts_unit[j-1] = datum_pts_unit[j];
+ }
+
+ free(datum_pts_unit);
+ datum_pts_unit = temp_datum_pts_unit;
+
+ }else{
+
+ free(datum_pts_unit);
+ datum_pts_unit = NULL;
+
+ }
+
+ return;
+
+ }
+ }
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Error, could not shut down unit %d\n",unit);
+ fflush(logfile);
+#endif
+
+ syslog(LOG_ERR, "Datum_PTS: Could not shut down Datum PTS unit %d",unit);
+
+}
+
+/*......................................................................*/
+/* datum_pts_poll - this routine sends out the time request to the */
+/* Datum PTS device. The time will be passed back in the */
+/* datum_pts_receive() routine. */
+/*......................................................................*/
+
+static void datum_pts_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ int i;
+ int index;
+ int error_code;
+ struct datum_pts_unit *datum_pts;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Poll Datum PTS\n");
+ fflush(logfile);
+#endif
+
+/*
+** Find the right unit and send out a time request once it is found.
+*/
+
+ index = -1;
+ for (i=0; i<nunits; i++) {
+ if (datum_pts_unit[i]->unit == unit) {
+ index = i;
+ datum_pts = datum_pts_unit[i];
+ error_code = write(datum_pts->PTS_fd, TIME_REQUEST, 6);
+ if (error_code != 6) perror("TIME_REQUEST");
+ datum_pts->nbytes = 0;
+ break;
+ }
+ }
+
+/*
+** Print out an error message if we could not find the right unit.
+*/
+
+ if (index == -1) {
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Error, could not poll unit %d\n",unit);
+ fflush(logfile);
+#endif
+
+ syslog(LOG_ERR, "Datum_PTS: Could not poll unit %d",unit);
+ return;
+
+ }
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_control - not used */
+/*......................................................................*/
+
+static void datum_pts_control(unit, in, out)
+ int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Control Datum PTS\n");
+ fflush(logfile);
+#endif
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_init - initializes things for all possible Datum */
+/* time code generators that might be used. In practice, this is */
+/* only called once at the beginning before anything else is */
+/* called. */
+/*......................................................................*/
+
+static void datum_pts_init()
+{
+
+/* */
+/*...... open up the log file if we are debugging ......................*/
+/* */
+
+/*
+** Open up the log file if we are debugging. For now, send data out to the
+** screen (stdout).
+*/
+
+#if defined(DEBUG_DATUM_PTC) || defined(LOG_TIME_ERRORS)
+/*
+ logfile = fopen("xntpd.log", "w");
+*/
+#endif
+
+ logfile = stdout;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Init Datum PTS\n");
+ fflush(logfile);
+#endif
+
+/*
+** Initialize the time request command string. This is the only message
+** that we ever have to send to the Datum PTS (although others are defined).
+*/
+
+ memcpy(TIME_REQUEST, "//k/mn",6);
+
+/*
+** Initialize the number of units to 0 and set the dynamic array of units to
+** NULL since there are no units defined yet.
+*/
+
+ datum_pts_unit = NULL;
+ nunits = 0;
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_buginfo - not used */
+/*......................................................................*/
+
+static void datum_pts_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Buginfo Datum PTS\n");
+ fflush(logfile);
+#endif
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_receive - receive the time buffer that was read in */
+/* by the xntpd io handling routines. When 7 bytes have been */
+/* received (it may take several tries before all 7 bytes are */
+/* received), then the time code must be unpacked and sent to */
+/* the xntpd clock_receive() routine which causes the systems */
+/* clock to be updated (several layers down). */
+/*......................................................................*/
+
+static void datum_pts_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ int i;
+ l_fp tstmp;
+ struct datum_pts_unit *datum_pts;
+ char *dpt;
+ int dpend;
+ int tzoff;
+ int timerr;
+ double ftimerr, abserr;
+ u_fp dispersion;
+ int goodtime;
+
+/*
+** Get the time code (maybe partial) message out of the rbufp buffer.
+*/
+
+ datum_pts = (struct datum_pts_unit *)rbufp->recv_srcclock;
+ dpt = (char *)&rbufp->recv_space;
+ dpend = rbufp->recv_length;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Receive Datum PTS: %d bytes\n", dpend);
+ fflush(logfile);
+#endif
+
+/* */
+/*...... save the ntp system time when the first byte is received ......*/
+/* */
+
+/*
+** Save the ntp system time when the first byte is received. Note that
+** because it may take several calls to this routine before all seven
+** bytes of our return message are finally received by the io handlers in
+** xntpd, we really do want to use the time tag when the first byte is
+** received to reduce the jitter.
+*/
+
+ if (datum_pts->nbytes == 0) {
+ datum_pts->lastrec = rbufp->recv_time;
+ }
+
+/*
+** Increment our count to the number of bytes received so far. Return if we
+** haven't gotten all seven bytes yet.
+*/
+
+ for (i=0; i<dpend; i++) {
+ datum_pts->retbuf[datum_pts->nbytes+i] = dpt[i];
+ }
+
+ datum_pts->nbytes += dpend;
+
+ if (datum_pts->nbytes != 7) {
+ return;
+ }
+
+/*
+** Convert the seven bytes received in our time buffer to day, hour, minute,
+** second, and msecond values. The usec value is not used for anything
+** currently. It is just the fractional part of the time stored in units
+** of microseconds.
+*/
+
+ datum_pts->day = 100*(datum_pts->retbuf[0] & 0x0f) +
+ 10*((datum_pts->retbuf[1] & 0xf0)>>4) +
+ (datum_pts->retbuf[1] & 0x0f);
+
+ datum_pts->hour = 10*((datum_pts->retbuf[2] & 0x30)>>4) +
+ (datum_pts->retbuf[2] & 0x0f);
+
+ datum_pts->minute = 10*((datum_pts->retbuf[3] & 0x70)>>4) +
+ (datum_pts->retbuf[3] & 0x0f);
+
+ datum_pts->second = 10*((datum_pts->retbuf[4] & 0x70)>>4) +
+ (datum_pts->retbuf[4] & 0x0f);
+
+ datum_pts->msec = 100*((datum_pts->retbuf[5] & 0xf0) >> 4) +
+ 10*(datum_pts->retbuf[5] & 0x0f) +
+ ((datum_pts->retbuf[6] & 0xf0)>>4);
+
+ datum_pts->usec = 1000*datum_pts->msec;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"day %d, hour %d, minute %d, second %d, msec %d\n",
+ datum_pts->day,
+ datum_pts->hour,
+ datum_pts->minute,
+ datum_pts->second,
+ datum_pts->msec);
+ fflush(logfile);
+#endif
+
+/*
+** Get the GMT time zone offset. Note that GMT should be zero if the Datum
+** reference time is using GMT as its time base. Otherwise we have to
+** determine the offset if the Datum PTS is using time of day as its time
+** base.
+*/
+
+ goodtime = 0; /* We are not sure about the time and offset yet */
+
+#ifdef GMT
+
+/*
+** This is the case where the Datum PTS is using GMT so there is no time
+** zone offset.
+*/
+
+ tzoff = 0; /* set time zone offset to 0 */
+
+#else
+
+/*
+** This is the case where the Datum PTS is using regular time of day for its
+** time so we must compute the time zone offset. The way we do it is kind of
+** funny but it works. We loop through different time zones (0 to 24) and
+** pick the one that gives the smallest error (+- one half hour). The time
+** zone offset is stored in the datum_pts structure for future use. Normally,
+** the clocktime() routine is only called once (unless the time zone offset
+** changes due to daylight savings) since the goodtime flag is set when a
+** good time is found (with a good offset). Note that even if the Datum
+** PTS is using GMT, this mechanism will still work since it should come up
+** with a value for tzoff = 0 (assuming that your system clock is within
+** a half hour of the Datum time (even with time zone differences).
+*/
+
+ for (tzoff=0; tzoff<24; tzoff++) {
+ if (clocktime( datum_pts->day,
+ datum_pts->hour,
+ datum_pts->minute,
+ datum_pts->second,
+ (tzoff + datum_pts->tzoff) % 24,
+ datum_pts->lastrec.l_ui,
+ &datum_pts->yearstart,
+ &datum_pts->lastref.l_ui) ) {
+
+ error = datum_pts->lastref.l_ui - datum_pts->lastrec.l_ui;
+
+#ifdef DEBUG_DATUM_PTC
+ printf("Time Zone (clocktime method) = %d, error = %d\n", tzoff, error);
+#endif
+
+ if ((error < 1799) && (error > -1799)) {
+ tzoff = (tzoff + datum_pts->tzoff) % 24;
+ datum_pts->tzoff = tzoff;
+ goodtime = 1;
+
+#ifdef DEBUG_DATUM_PTC
+ printf("Time Zone found (clocktime method) = %d\n",tzoff);
+#endif
+
+ break;
+ }
+
+ }
+ }
+
+#endif
+
+/*
+** Make sure that we have a good time from the Datum PTS. Clocktime() also
+** sets yearstart and lastref.l_ui. We will have to set astref.l_uf (i.e.,
+** the fraction of a second) stuff later.
+*/
+
+ if (!goodtime) {
+
+ if (!clocktime( datum_pts->day,
+ datum_pts->hour,
+ datum_pts->minute,
+ datum_pts->second,
+ tzoff,
+ datum_pts->lastrec.l_ui,
+ &datum_pts->yearstart,
+ &datum_pts->lastref.l_ui) ) {
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Error: bad clocktime\n");
+ fprintf(logfile,"GMT %d, lastrec %d, yearstart %d, lastref %d\n",
+ tzoff,
+ datum_pts->lastrec.l_ui,
+ datum_pts->yearstart,
+ datum_pts->lastref.l_ui);
+ fflush(logfile);
+#endif
+
+ syslog(LOG_ERR, "Datum_PTS: Bad clocktime");
+
+ return;
+
+ }else{
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Good clocktime\n");
+ fflush(logfile);
+#endif
+
+ }
+
+ }
+
+/*
+** We have datum_pts->lastref.l_ui set (which is the integer part of the
+** time. Now set the microseconds field.
+*/
+
+ TVUTOTSF(datum_pts->usec, datum_pts->lastref.l_uf);
+
+/*
+** Compute the time correction as the difference between the reference
+** time (i.e., the Datum time) minus the receive time (system time).
+*/
+
+ tstmp = datum_pts->lastref; /* tstmp is the datum ntp time */
+ L_SUB(&tstmp, &datum_pts->lastrec); /* tstmp is now the correction */
+ datum_pts->coderecv++; /* increment a counter */
+
+ dispersion = DATUM_DISPERSION; /* set the dispersion to 0 */
+
+#ifdef DEBUG_DATUM_PTC
+ ftimerr = dispersion;
+ ftimerr /= (1024.0 * 64.0);
+ fprintf(logfile,"dispersion = %d, %f\n", dispersion, ftimerr);
+ fflush(logfile);
+#endif
+
+/*
+** Pass the new time to xntpd through the refclock_receive function. Note
+** that we are not trying to make any corrections due to the time it takes
+** for the Datum PTS to send the message back. I am (erroneously) assuming
+** that the time for the Datum PTS to send the time back to us is negligable.
+** I suspect that this time delay may be as much as 15 ms or so (but probably
+** less). For our needs at JPL, this kind of error is ok so it is not
+** necessary to use fudge factors in the ntp.conf file. Maybe later we will.
+*/
+
+ refclock_receive( datum_pts->peer,
+ &tstmp,
+ tzoff,
+ dispersion,
+ &datum_pts->lastrec,
+ &datum_pts->lastrec,
+ datum_pts->leap );
+
+/*
+** Compute sigma squared (not used currently). Maybe later, this could be
+** used for the dispersion estimate. The problem is that xntpd does not link
+** in the math library so sqrt() is not available. Anyway, this is useful
+** for debugging. Maybe later I will just use absolute values for the time
+** error to come up with my dispersion estimate. Anyway, for now my dispersion
+** is set to 0.
+*/
+
+ timerr = tstmp.l_ui<<20;
+ timerr |= (tstmp.l_uf>>12) & 0x000fffff;
+ ftimerr = timerr;
+ ftimerr /= 1024*1024;
+ abserr = ftimerr;
+ if (ftimerr < 0.0) abserr = -ftimerr;
+
+ if (datum_pts->sigma2 == 0.0) {
+ if (abserr < DATUM_MAX_ERROR) {
+ datum_pts->sigma2 = abserr*abserr;
+ }else{
+ datum_pts->sigma2 = DATUM_MAX_ERROR2;
+ }
+ }else{
+ if (abserr < DATUM_MAX_ERROR) {
+ datum_pts->sigma2 = 0.95*datum_pts->sigma2 + 0.05*abserr*abserr;
+ }else{
+ datum_pts->sigma2 = 0.95*datum_pts->sigma2 + 0.05*DATUM_MAX_ERROR2;
+ }
+ }
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Time error = %f seconds\n", ftimerr);
+ fflush(logfile);
+#endif
+
+#if defined(DEBUG_DATUM_PTC) || defined(LOG_TIME_ERRORS)
+ fprintf(logfile,
+ "PTS: day %d, hour %d, minute %d, second %d, msec %d, Time Error %f\n",
+ datum_pts->day,
+ datum_pts->hour,
+ datum_pts->minute,
+ datum_pts->second,
+ datum_pts->msec,
+ ftimerr);
+ fflush(logfile);
+#endif
+
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_goes.c b/usr.sbin/xntpd/xntpd/refclock_goes.c
index 0b53326dc5d2..512131b8625d 100644
--- a/usr.sbin/xntpd/xntpd/refclock_goes.c
+++ b/usr.sbin/xntpd/xntpd/refclock_goes.c
@@ -1,9 +1,12 @@
/*
- * refclock_goes - clock driver for the Kinimetrics Truetime GOES receiver
- * Version 2.0
+ * refclock_goes - clock driver for the Kinemetrics Truetime GOES
+ * Receiver Version 3.0C - tested plain, with CLKLDISC
+ * Developement work being done:
+ * - Properly handle varying satellite positions (more acurately)
+ * - Integrate GPSTM and/or OMEGA and/or TRAK and/or ??? drivers
*/
-#if defined(REFCLOCK) && (defined(GOES) || defined(GOESCLK) || defined(GOESPPS))
+#if defined(REFCLOCK) && defined(GOES)
#include <stdio.h>
#include <ctype.h>
@@ -13,113 +16,102 @@
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
-
-#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(HAVE_TERMIOS)
-#include <termios.h>
-#endif
-#if defined(STREAM)
-#include <stropts.h>
-#if defined(GOESCLK)
-#include <clkdefs.h>
-#endif /* GOESCLK */
-#endif /* STREAM */
-
-#if defined (GOESPPS)
-#include <sys/ppsclock.h>
-#endif /* GOESPPS */
-
#include "ntp_stdlib.h"
/*
* Support for Kinemetrics Truetime 468-DC GOES Receiver
+ * OM-DC OMEGA and GPS-TM/TMD support in progress...
+ *
+ * Most of this code is originally from refclock_wwvb.c with thanks.
+ * It has been so mangled that wwvb is not a recognizable ancestor.
+ *
+ * Timcode format: ADDD:HH:MM:SSQCL
+ * A - control A
+ * Q Quality indication: indicates possible error of
+ * C - Carriage return
+ * L - Line feed
*
- * Most of this code is copied from refclock_goes.c with thanks.
+ * Quality codes indicate possible error of
+ * 468-DC GOES Receiver:
+ * GPS-TM/TMD Receiver:
+ * ? +/- 500 milliseconds # +/- 50 milliseconds
+ * * +/- 5 milliseconds . +/- 1 millisecond
+ * space less than 1 millisecond
+ * OM-DC OMEGA Receiver:
+ * > >+- 5 seconds
+ * ? >+/- 500 milliseconds # >+/- 50 milliseconds
+ * * >+/- 5 milliseconds . >+/- 1 millisecond
+ * A-H less than 1 millisecond. Character indicates which station
+ * is being received as follows:
+ * A = Norway, B = Liberia, C = Hawaii, D = North Dakota,
+ * E = La Reunion, F = Argentina, G = Australia, H = Japan.
*
- * the time code looks like follows; Send the clock a R or C and once per
- * second a timestamp will appear that looks like this:
- * ADDD:HH:MM:SSQCL
- * A - control A
- * Q Quality indication: indicates possible error of
- * ? +/- 500 milliseconds # +/- 50 milliseconds
- * * +/- 5 milliseconds . +/- 1 millisecond
- * space less than 1 millisecond
- * C - Carriage return
- * L - Line feed
- * The carriage return start bit begins on 0 seconds and extends to 1 bit time.
+ * The carriage return start bit begins on 0 seconds and extends to 1
+ * bit time
+ *
+ * Notes on 468-DC and OMEGA receiver:
+ *
+ * Send the clock a 'R' or 'C' and once per second a timestamp will
+ * appear. Send a 'P' to get the satellite position once.
+ *
+ * Notes on the 468-DC receiver:
+ *
+ * Unless you live on 125 degrees west longitude, you can't
+ * set your clock propagation delay settings correctly and still use
+ * automatic mode. The manual says to use a compromise when setting the
+ * switches. This results in significant errors. The solution; use fudge
+ * time1 and time2 to incorporate corrections. If your clock is set for
+ * 50 and it should be 58 for using the west and 46 for using the east,
+ * use the line
*
- * Unless you live on 125 degrees west longitude, you can't set your clock
- * propagation delay settings correctly and still use automatic mode.
- * The manual says to use a compromise when setting the switches. This
- * results in significant errors. The solution; use fudge time1 and time2
- * to incorporate corrections. If your clock is set for 50 and it should
- * be 58 for using the west and 46 for using the east, use the line
* fudge 127.127.5.0 time1 +0.008 time2 -0.004
- * This corrects the 4 milliseconds advance and 5 milliseconds retard needed.
- * The software will ask the clock which satellite it sees.
*
- * Flag1 set to 1 will silence the clock side of xntpd, just reading the
- * clock without trying to write to it. This is usefull if several
- * xntpds listen to the same clock. This has not been tested yet...
+ * This corrects the 4 milliseconds advance and 8 milliseconds retard
+ * needed. The software will ask the clock which satellite it sees.
+ *
+ * Ntp.conf parameters:
+ * time1 - offset applied to samples when reading WEST satellite (default = 0)
+ * time2 - offset applied to samples when reading EAST satellite (default = 0)
+ * val1 - stratum to assign to this clock (default = 0)
+ * val2 - refid assigned to this clock (default = "GOES", see below)
+ * flag1 - will silence the clock side of xntpd, just reading the clock
+ * without trying to write to it. (default = 0)
+ * flag2 - not assigned
+ * flag3 - enable ppsclock streams module
+ * flag4 - not assigned
+ *
*/
/*
* Definitions
*/
-#define MAXUNITS 4 /* max number of GOES units */
-#define GOES232 "/dev/goes%d"
+#define DEVICE "/dev/goes%d"
#define SPEED232 B9600 /* 9600 baud */
/*
* Radio interface parameters
*/
-#define GOESMAXDISPERSE (FP_SECOND>>1) /* max error for synchronized clock (0.5 s as an u_fp) */
-#define GOESSKEWFACTOR 17 /* skew factor (for about 32 ppm) */
-#define GOESPRECISION (-10) /* precision assumed (about 1 ms) */
-#define GOESREFID "GOES" /* reference id */
-#define GOESDESCRIPTION "Kinemetrics GOES Receiver" /* who we are */
-#define GOESHSREFID 0x7f7f050a /* 127.127.5.10 refid hi strata */
-#define GMT 0 /* hour offset from Greenwich */
-#define NCODES 3 /* stages of median filter */
-#define LENGOES0 13 /* format 0 timecode length */
-#define LENGOES2 21 /* format 2 timecode length */
-#define FMTGOESU 0 /* unknown format timecode id */
-#define FMTGOES0 1 /* format 0 timecode id */
-#define FMTGOES2 2 /* format 2 timecode id */
-#define DEFFUDGETIME 0 /* default fudge time (ms) */
-#define BMAX 50 /* timecode buffer length */
-#define CODEDIFF 0x20000000 /* 0.125 seconds as an l_fp fraction */
+#define MAXDISPERSE (FP_SECOND>>1) /* max error for synchronized clock (0.5 s as an u_fp) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define REFID "GOES" /* reference id */
+#define DESCRIPTION "TrueTime GPS/GOES Receivers" /* WRU */
+#define NSAMPLES 3 /* stages of median filter */
/*
- * Tag which satellite we see
+ * Tags which station (satellite) we see
*/
-#define GOES_SAT_NONE 0
-#define GOES_SAT_WEST 1
-#define GOES_SAT_EAST 2
-#define GOES_SAT_STAND 3
+#define GOES_WEST 0 /* Default to WEST satellite and apply time1 */
+#define GOES_EAST 1 /* until you discover otherwise */
/*
- * Hack to avoid excercising the multiplier. I have no pride.
+ * used by the state machine
*/
-#define MULBY10(x) (((x)<<3) + ((x)<<1))
+enum goes_event {e_Init, e_F18, e_F50, e_F51, e_TS};
/*
* Imported from the timer module
*/
-extern U_LONG current_time;
-extern struct event timerqueue[];
-
-/*
- * Imported from ntp_loopfilter module
- */
-extern int fdpps; /* pps file descriptor */
+extern u_long current_time;
/*
* Imported from ntpd module
@@ -127,634 +119,294 @@ extern int fdpps; /* pps file descriptor */
extern int debug; /* global debug flag */
/*
- * GOES unit control structure
+ * unit control structure
*/
struct goesunit {
- struct peer *peer; /* associated peer structure */
- struct refclockio io; /* given to the I/O handler */
- l_fp lastrec; /* last receive time */
- l_fp lastref; /* last timecode time */
- l_fp offset[NCODES]; /* recent sample offsets */
- char lastcode[BMAX]; /* last timecode received */
- u_short satellite; /* which satellite we saw */
- u_short polled; /* Hand in a time sample? */
- u_char format; /* timecode format */
- u_char lencode; /* length of last timecode */
- U_LONG lasttime; /* last time clock heard from */
- 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_char leap; /* leap indicators */
- u_short msec; /* millisecond of second */
- u_char quality; /* quality char from format 2 */
- 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 */
+ int pollcnt; /* poll message counter */
+ u_short station; /* which station we are on */
+ u_short polled; /* Hand in a time sample? */
+ enum {Base, Start, F18, F50, F51, F08}
+ State; /* State machine */
};
/*
- * Data space for the unit structures. Note that we allocate these on
- * the fly, but never give them back.
- */
-static struct goesunit *goesunits[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 fudgefactor1[MAXUNITS];
-static l_fp fudgefactor2[MAXUNITS];
-static u_char stratumtouse[MAXUNITS];
-static u_char readonlyclockflag[MAXUNITS];
-
-/*
* Function prototypes
*/
-static void goes_init P((void));
-static int goes_start P((u_int, struct peer *));
-static void goes_shutdown P((int));
-static void goes_report_event P((struct goesunit *, int));
+static int goes_start P((int, struct peer *));
+static void goes_shutdown P((int, struct peer *));
static void goes_receive P((struct recvbuf *));
-static char goes_process P((struct goesunit *, l_fp *, u_fp *));
static void goes_poll P((int, struct peer *));
-static void goes_control P((u_int, struct refclockstat *, struct refclockstat *));
-static void goes_buginfo P((int, struct refclockbug *));
-static void goes_send P((struct goesunit *, char *));
-
-struct refclock refclock_goes = {
- goes_start, goes_shutdown, goes_poll,
- goes_control, goes_init, goes_buginfo, NOFLAGS
-};
+static void goes_send P((struct peer *, char *));
+static void goes_initstate P((struct peer *));
+static void goes_doevent P((struct peer *, enum goes_event));
/*
- * goes_init - initialize internal goes driver data
+ * Transfer vector
*/
-static void
-goes_init()
-{
- register int i;
- /*
- * Just zero the data arrays
- */
- memset((char *)goesunits, 0, sizeof goesunits);
- memset((char *)unitinuse, 0, sizeof unitinuse);
-
- /*
- * Initialize fudge factors to default.
- */
- for (i = 0; i < MAXUNITS; i++) {
- fudgefactor1[i].l_ui = 0;
- fudgefactor1[i].l_uf = DEFFUDGETIME;
- fudgefactor2[i].l_ui = 0;
- fudgefactor2[i].l_uf = DEFFUDGETIME;
- stratumtouse[i] = 0;
- readonlyclockflag[i] = 0;
- }
-}
+struct refclock refclock_goes = {
+ goes_start, /* start up driver */
+ goes_shutdown, /* shut down driver */
+ goes_poll, /* transmit poll message */
+ noentry, /* not used (old goes_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old goes_buginfo) */
+ NOFLAGS /* not used */
+};
/*
- * goes_start - open the GOES devices and initialize data for processing
+ * goes_start - open the devices and initialize data for processing
*/
static int
goes_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register struct goesunit *goes;
- register int i;
- int fd232;
- char goesdev[20];
-
- /*
- * Check configuration info
- */
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "goes_start: unit %d invalid", unit);
- return 0;
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "goes_start: unit %d in use", unit);
- return 0;
- }
+ register struct goesunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
/*
* Open serial port
*/
- (void) sprintf(goesdev, GOES232, unit);
- fd232 = open(goesdev, O_RDWR, 0777);
- if (fd232 == -1) {
- syslog(LOG_ERR, "goes_start: open of %s: %m", goesdev);
- 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,
- "goes_start: ioctl(%s, TCGETA): %m", goesdev);
- 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,
- "goes_start: ioctl(%s, TCSETA): %m", goesdev);
- goto screwed;
- }
- }
-#endif /* HAVE_SYSV_TTYS */
-#if defined(HAVE_TERMIOS)
- /*
- * POSIX serial line parameters (termios interface)
- *
- * The GOESCLK option provides timestamping at the driver level.
- * It requires the tty_clk streams module.
- *
- * The GOESPPS 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,
- "goes_start: tcgetattr(%s): %m", goesdev);
- goto screwed;
- }
- ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
- 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,
- "goes_start: tcsetattr(%s): %m", goesdev);
- goto screwed;
- }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- syslog(LOG_ERR,
- "goes_start: tcflush(%s): %m", goesdev);
- goto screwed;
- }
- }
-#endif /* HAVE_TERMIOS */
-#ifdef STREAM
-#if defined(GOESCLK)
- if (ioctl(fd232, I_PUSH, "clk") < 0)
- syslog(LOG_ERR,
- "goes_start: ioctl(%s, I_PUSH, clk): %m", goesdev);
- if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
- syslog(LOG_ERR,
- "goes_start: ioctl(%s, CLK_SETSTR): %m", goesdev);
-#endif /* GOESCLK */
-#if defined(GOESPPS)
- if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
- syslog(LOG_ERR,
- "goes_start: ioctl(%s, I_PUSH, ppsclock): %m", goesdev);
- else
- fdpps = fd232;
-#endif /* GOESPPS */
-#endif /* STREAM */
-#if defined(HAVE_BSD_TTYS)
- /*
- * 4.3bsd serial line parameters (sgttyb interface)
- *
- * The GOESCLK option provides timestamping at the driver level.
- * It requires the tty_clk line discipline and 4.3bsd or later.
- */
- { struct sgttyb ttyb;
-#if defined(GOESCLK)
- int ldisc = CLKLDISC;
-#endif /* GOESCLK */
-
- if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "goes_start: ioctl(%s, TIOCGETP): %m", goesdev);
- goto screwed;
- }
- ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
-#if defined(GOESCLK)
- 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 /* GOESCLK */
- if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "goes_start: ioctl(%s, TIOCSETP): %m", goesdev);
- goto screwed;
- }
-#if defined(GOESCLK)
- if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR,
- "goes_start: ioctl(%s, TIOCSETD): %m",goesdev);
- goto screwed;
- }
-#endif /* GOESCLK */
- }
-#endif /* HAVE_BSD_TTYS */
-
- /*
- * Allocate unit structure
- */
- if (goesunits[unit] != 0) {
- goes = goesunits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < MAXUNITS; i++) {
- if (!unitinuse[i] && goesunits[i] != 0)
- break;
- }
- if (i < MAXUNITS) {
- /*
- * Reclaim this one
- */
- goes = goesunits[i];
- goesunits[i] = 0;
- } else {
- goes = (struct goesunit *)
- emalloc(sizeof(struct goesunit));
- }
- }
- memset((char *)goes, 0, sizeof(struct goesunit));
- goesunits[unit] = goes;
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
+ return (0);
/*
- * Set up the structures
+ * Allocate and initialize unit structure
*/
- goes->peer = peer;
- goes->unit = (u_char)unit;
- goes->timestarted = current_time;
- goes->satellite = GOES_SAT_NONE;
-
- goes->io.clock_recv = goes_receive;
- goes->io.srcclock = (caddr_t)goes;
- goes->io.datalen = 0;
- goes->io.fd = fd232;
- if (!io_addclock(&goes->io)) {
- goto screwed;
+ if (!(up = (struct goesunit *)
+ emalloc(sizeof(struct goesunit)))) {
+ (void) close(fd);
+ return (0);
}
-
- /*
- * All done. Initialize a few random peer variables, then
- * return success.
- */
- peer->precision = GOESPRECISION;
- peer->rootdelay = 0;
- peer->rootdispersion = 0;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, GOESREFID, 4);
- else
- peer->refid = htonl(GOESHSREFID);
- unitinuse[unit] = 1;
- return 1;
-
- /*
- * Something broke; abandon ship
- */
-screwed:
- (void) close(fd232);
- return 0;
-}
-
-/*
- * goes_shutdown - shut down a GOES clock
- */
-static void
-goes_shutdown(unit)
- int unit;
-{
- register struct goesunit *goes;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "goes_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "goes_shutdown: unit %d not in use", unit);
- return;
+ memset((char *)up, 0, sizeof(struct goesunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = goes_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
}
+ pp->unitptr = (caddr_t)up;
/*
- * Tell the I/O module to turn us off. We're history.
+ * Initialize miscellaneous variables
*/
- goes = goesunits[unit];
- io_closeclock(&goes->io);
- unitinuse[unit] = 0;
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
+/* goes_initstate(peer);*/
+ return (1);
}
/*
- * goes_report_event - note the occurance of an event
+ * goes_shutdown - shut down the clock
*/
static void
-goes_report_event(goes, code)
- struct goesunit *goes;
- int code;
-{
+goes_shutdown(unit, peer)
+ int unit;
struct peer *peer;
+{
+ register struct goesunit *up;
+ struct refclockproc *pp;
- peer = goes->peer;
- if (goes->status != (u_char)code) {
- goes->status = (u_char)code;
- if (code != CEVNT_NOMINAL)
- goes->lastevent = (u_char)code;
- syslog(LOG_INFO,
- "clock %s event %x\n", ntoa(&peer->srcadr), code);
-#ifdef DEBUG
- if (debug) {
- printf("goes_report_event(goes%d, code %d)\n",
- goes->unit, code);
- }
-#endif
- }
+ pp = peer->procptr;
+ up = (struct goesunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
}
/*
- * goes_receive - receive data from the serial interface on a Kinimetrics
- * clock
+ * goes_receive - receive data from the serial interface on a
+ * Kinimetrics clock
*/
static void
goes_receive(rbufp)
struct recvbuf *rbufp;
{
- register int i;
- register struct goesunit *goes;
- register u_char *dpt;
- register char *cp;
- register u_char *dpend;
- l_fp tstmp;
- u_fp dispersion;
+ register struct goesunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ l_fp tmp_l_fp;
+ u_short new_station;
+ char sync, c1, c2;
+ int i;
+ int lat, lon, off; /* GOES Satellite position */
/*
- * Get the clock this applies to and a pointers to the data
+ * Get the clock this applies to and pointers to the data
*/
- goes = (struct goesunit *)rbufp->recv_srcclock;
- dpt = (u_char *)&rbufp->recv_space;
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct goesunit *)pp->unitptr;
/*
- * Edit timecode to remove control chars
+ * Read clock output. Automatically handles STREAMS, CLKLDISC
*/
- dpend = dpt + rbufp->recv_length;
- cp = goes->lastcode;
- while (dpt < dpend) {
- if ((*cp = 0x7f & *dpt++) >= ' ') cp++;
-#ifdef GOESCLK
- else if (*cp == '\r') {
- if (dpend - dpt < 8) {
- /* short timestamp */
- return;
- }
- if (!buftvtots(dpt,&goes->lastrec)) {
- /* screwy timestamp */
- return;
- }
- dpt += 8;
- }
-#endif
- }
- *cp = '\0';
- goes->lencode = cp - goes->lastcode;
- if (goes->lencode == 0) return;
-#ifndef GOESCLK
- goes->lastrec = rbufp->recv_time;
-#endif /* GOESCLK */
- tstmp = goes->lastrec;
-
-#ifdef DEBUG
- if (debug)
- printf("goes: timecode %d %s\n",
- goes->lencode, goes->lastcode);
-#endif
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX,
+ &pp->lastrec);
/*
- * We get down to business, check the timecode format and decode
- * its contents. This code checks for and decodes both format 0
- * and format 2 and need not be told which in advance.
+ * There is a case where <cr><lf> generates 2 timestamps
*/
- cp = goes->lastcode;
- goes->leap = 0;
- goes->format = FMTGOESU;
- if (goes->lencode == LENGOES0) {
+ if (pp->lencode == 0)
+ return;
- /*
- * Check timecode format 0
- */
- if (!isdigit(cp[0]) || /* day of year */
- !isdigit(cp[1]) ||
- !isdigit(cp[2]) ||
- cp[3] != ':' || /* <sp> */
- !isdigit(cp[4]) || /* hours */
- !isdigit(cp[5]) ||
- cp[6] != ':' || /* : separator */
- !isdigit(cp[7]) || /* minutes */
- !isdigit(cp[8]) ||
- cp[9] != ':' || /* : separator */
- !isdigit(cp[10]) || /* seconds */
- !isdigit(cp[11])) {
- goes->badformat++;
- goes_report_event(goes, CEVNT_BADREPLY);
- return;
- }
- else goes->format = FMTGOES0;
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
- /*
- * Convert format 0 and check values
- */
- goes->year = 0; /* fake */
- goes->day = cp[0] - '0';
- goes->day = MULBY10(goes->day) + cp[1] - '0';
- goes->day = MULBY10(goes->day) + cp[2] - '0';
- goes->hour = MULBY10(cp[4] - '0') + cp[5] - '0';
- goes->minute = MULBY10(cp[7] - '0') + cp[8] - '0';
- goes->second = MULBY10(cp[10] - '0') + cp[11] - '0';
- goes->msec = 0;
-
- if (cp[12] != ' ' && cp[12] != '.' && cp[12] != '*')
- goes->leap = LEAP_NOTINSYNC;
- else
- goes->lasttime = current_time;
-
- if (goes->day < 1 || goes->day > 366) {
- goes->baddata++;
- goes_report_event(goes, CEVNT_BADDATE);
- return;
- }
- if (goes->hour > 23 || goes->minute > 59
- || goes->second > 59) {
- goes->baddata++;
- goes_report_event(goes, CEVNT_BADTIME);
- return;
- }
+ /*
+ * We get down to business, check the timecode format and decode
+ * its contents. This code decodes a multitude of different
+ * clock messages. Timecodes are processed if needed. All replies
+ * will be run through the state machine to tweak driver options
+ * and program the clock.
+ */
- } else if (goes->lencode == LENGOES2) {
+ /*
+ * Timecode: "nnnnn+nnn-nnn"
+ */
+ if (sscanf(pp->lastcode, "%5d%c%3d%c%3d",
+ &lon, &c1, &lat, &c2, &off) == 5 &&
+ (c1 == '+' || c1 == '-') &&
+ (c2 == '+' || c2 == '-')) {
/*
- * Extended precision satelite location info
+ * This is less than perfect. Call the (satellite)
+ * either EAST or WEST and adjust slop accodingly
+ * Perfectionists would recalcuted the exact delay
+ * and adjust accordingly...
*/
- if (!isdigit(cp[0]) || /* longitude */
- !isdigit(cp[1]) ||
- !isdigit(cp[2]) ||
- cp[3] != '.' ||
- !isdigit(cp[4]) ||
- !isdigit(cp[5]) ||
- !isdigit(cp[6]) ||
- !isdigit(cp[7]) ||
- (cp[8] != '+' && cp[8] != '-') ||
- !isdigit(cp[9]) || /*latitude */
- cp[10] != '.' ||
- !isdigit(cp[11]) ||
- !isdigit(cp[12]) ||
- !isdigit(cp[13]) ||
- !isdigit(cp[14]) ||
- (cp[15] != '+' && cp[15] != '-') ||
- !isdigit(cp[16]) || /* height */
- !isdigit(cp[17]) ||
- !isdigit(cp[18]) ||
- cp[19] != '.' ||
- !isdigit(cp[20])) {
- goes->badformat++;
- goes_report_event(goes, CEVNT_BADREPLY);
- return;
+ if (lon > 7000 && lon < 14000) {
+ if (lon < 10000)
+ new_station = GOES_EAST;
+ else
+ new_station = GOES_WEST;
+#ifdef DEBUG
+ if (debug) {
+ if (new_station == GOES_EAST)
+ printf("goes: station EAST\n");
+ if (new_station == GOES_WEST)
+ printf("goes: station WEST\n");
}
- else goes->format = FMTGOES2;
-
- /*
- * Figure out which satellite this is.
- * This allows +-5 degrees from nominal.
- */
- if (cp[0] == '1' && (cp[1] == '3' || cp[1] == '2'))
- goes->satellite = GOES_SAT_WEST;
- else if (cp[0] == '1' && cp[1] == '0')
- goes->satellite = GOES_SAT_STAND;
- else if (cp[0] == '0' && cp[1] == '7')
- goes->satellite = GOES_SAT_EAST;
- else
- goes->satellite = GOES_SAT_NONE;
-
+#endif
+ if (new_station != up->station) {
+ tmp_l_fp = pp->fudgetime1;
+ pp->fudgetime1 = pp->fudgetime2;
+ pp->fudgetime2 = tmp_l_fp;
+ up->station = new_station;
+ }
+ }
+ else {
+ refclock_report(peer, CEVNT_BADREPLY);
#ifdef DEBUG
- if (debug)
- printf("goes_receive: select satellite %d\n",
- goes->satellite);
+ if (debug)
+ printf("goes: station UNKNONW\n");
#endif
-
+ }
/*
- * Switch back to on-second time codes.
+ * Switch back to on-second time codes and return.
*/
- goes_send(goes,"C");
+ goes_send(peer, "C");
- /*
- * Since this is not a time code, just return...
- */
- return;
- } else {
- goes_report_event(goes, CEVNT_BADREPLY);
return;
}
/*
- * The clock will blurt a timecode every second but we only
- * want one when polled. If we havn't been polled, bail out.
+ * Timecode: "Fnn"
*/
- if (!goes->polled)
- return;
+ if (sscanf(pp->lastcode, "F%2d", &i) == 1 &&
+ i > 0 && i < 80) {
+ enum goes_event event = 0;
+
+ if (i == 50) event = e_F50;
+ if (i == 51) event = e_F51;
+ if (i == 50 || i == 51) {
+ goes_doevent(peer, event);
+ return;
+ }
+ }
/*
- * Now, compute the reference time value. Use the heavy
- * machinery for the seconds and the millisecond field for the
- * fraction when present.
- *
- * this code does not yet know how to do the years
+ * Timecode:" TRUETIME Mk III"
*/
- tstmp = goes->lastrec;
- if (!clocktime(goes->day, goes->hour, goes->minute,
- goes->second, GMT, tstmp.l_ui,
- &goes->yearstart, &goes->lastref.l_ui)) {
- goes->baddata++;
- goes_report_event(goes, CEVNT_BADTIME);
+ if (strcmp(pp->lastcode, " TRUETIME Mk III") == 0) {
+ enum goes_event event;
+
+ event = e_F18;
+ goes_doevent(peer, event);
return;
}
- MSUTOTSF(goes->msec, goes->lastref.l_uf);
-
/*
- * Slop the read value by fudgefactor1 or fudgefactor2 depending
- * on which satellite we are viewing last time we checked.
- */
+ * Timecode: "ddd:hh:mm:ssQ"
+ */
+ if (sscanf(pp->lastcode, "%3d:%2d:%2d:%2d%c",
+ &pp->day, &pp->hour, &pp->minute,
+ &pp->second, &sync) == 5) {
-#ifdef DEBUG
- if (debug)
- printf("GOES_RECEIVE: Slopping for satellite %d\n",
- goes->satellite);
-#endif
- if (goes->satellite == GOES_SAT_WEST)
- L_ADD(&goes->lastref, &fudgefactor1[goes->unit]);
- else if (goes->satellite == GOES_SAT_EAST)
- L_ADD(&goes->lastref, &fudgefactor2[goes->unit]);
-/* else if (goes->satellite == GOES_SAT_STAND)
- L_ADD(&goes->lastref, &((fudgefactor1[goes->unit] +
- fudgefactor2[goes->unit]) / 2)); */
-
- i = ((int)(goes->coderecv)) % NCODES;
- goes->offset[i] = goes->lastref;
- L_SUB(&goes->offset[i], &tstmp);
- if (goes->coderecv == 0)
- for (i = 1; i < NCODES; i++)
- goes->offset[i] = goes->offset[0];
-
- goes->coderecv++;
+ /*
+ * Adjust the synchronize indicator according to timecode
+ */
+ if (sync !=' ' && sync !='.' && sync !='*')
+ pp->leap = LEAP_NOTINSYNC;
+ else {
+ pp->leap = 0;
+ pp->lasttime = current_time;
+ }
- /*
- * Check the satellite position
- */
- goes_send(goes,"E");
+ /* goes_doevent(peer, e_TS); */
+
+ /*
+ * The clock will blurt a timecode every second but we only
+ * want one when polled. If we havn't been polled, bail out.
+ */
+ if (!up->polled)
+ return;
+
+ /*
+ * After each poll, check the station (satellite)
+ */
+ goes_send(peer, "P");
+
+ /*
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
+
+ /*
+ * We have succedded in answering the poll.
+ * Turn off the flag and return
+ */
+ up->polled = 0;
- /*
- * Process the median filter, add the fudge factor and pass the
- * offset and dispersion along. We use lastrec 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 (!goes_process(goes, &tstmp, &dispersion)) {
- goes->baddata++;
- goes_report_event(goes, CEVNT_BADTIME);
return;
}
- refclock_receive(goes->peer, &tstmp, GMT, dispersion,
- &goes->lastrec, &goes->lastrec, goes->leap);
/*
- * We have succedded in answering the poll. Turn off the flag
+ * No match to known timecodes, report failure and return
*/
- goes->polled = 0;
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
}
@@ -762,95 +414,89 @@ goes_receive(rbufp)
* goes_send - time to send the clock a signal to cough up a time sample
*/
static void
-goes_send(goes,cmd)
- struct goesunit *goes;
+goes_send(peer, cmd)
+ struct peer *peer;
char *cmd;
{
- if (!readonlyclockflag[goes->unit]) {
- /*
- * Send a command to the clock. C for on-second timecodes.
- * E for extended resolution satelite postion information.
- */
- if (write(goes->io.fd, cmd, 1) != 1) {
- syslog(LOG_ERR, "goes_send: unit %d: %m", goes->unit);
- goes_report_event(goes, CEVNT_FAULT);
- } else {
- goes->polls++;
- }
+ struct refclockproc *pp;
+ register int len = strlen(cmd);
+
+ pp = peer->procptr;
+ if (!pp->sloppyclockflag & CLK_FLAG1) {
+#ifdef DEBUG
+ if (debug)
+ printf("goes: Send '%s'\n", cmd);
+#endif
+ if (write(pp->io.fd, cmd, len) != len) {
+ refclock_report(peer, CEVNT_FAULT);
+ } else {
+ pp->polls++;
+ }
}
}
+
/*
- * goes_process - process a pile of samples from the clock
+ * state machine for initializing the clock
*/
-static char
-goes_process(goes, offset, dispersion)
- struct goesunit *goes;
- l_fp *offset;
- u_fp *dispersion;
+static void
+goes_doevent(peer, event)
+ struct peer *peer;
+ enum goes_event event;
{
- 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;
+ struct goesunit *up;
+ struct refclockproc *pp;
- /*
- * 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. We take the maximum
- * difference and use that as the sample dispersion. 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 = goes->offset[i].l_ui;
- tmp_uf = goes->offset[i].l_uf;
- M_SUB(tmp_ui, tmp_uf, goes->offset[j].l_ui,
- goes->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;
- }
- }
+ pp = peer->procptr;
+ up = (struct goesunit *)pp->unitptr;
+
+#ifdef DEBUG
+ if (debug) {
+ printf("goes_doevent: %d\n", (int)event);
+ }
+#endif
+ if (event == e_TS && up->State != F51 && up->State != F08) {
+ goes_send(peer, "\03\r");
}
- /*
- * It seems as if all are within 125 ms of each other.
- * Now to determine the median of the three. Whlie the
- * 125 ms check was going on, we also subtly catch the
- * dispersion and set-up for a very easy median calculation.
- * The largest difference between any two samples constitutes
- * the dispersion. The sample not involve in the dispersion is
- * the median sample. EASY!
- */
- if (goes->lasttime == 0 || disp_tmp2 > GOESMAXDISPERSE)
- disp_tmp2 = GOESMAXDISPERSE;
- if (not_median1 == 0) {
- if (not_median2 == 1)
- median = 2;
- else
- median = 1;
- } else {
- median = 0;
- }
- *offset = goes->offset[median];
- *dispersion = disp_tmp2;
- return 1;
+ switch (event) {
+ case e_Init:
+ goes_send(peer, "F18\r");
+ up->State = Start;
+ break;
+ case e_F18:
+ goes_send(peer, "F50\r");
+ up->State = F18;
+ break;
+ case e_F50:
+ goes_send(peer, "F51\r");
+ up->State = F50;
+ break;
+ case e_F51:
+ goes_send(peer, "F08\r");
+ up->State = F51;
+ break;
+ case e_TS:
+ /* nothing to send - we like this mode */
+ up->State = F08;
+ break;
+ }
+}
+
+static void
+goes_initstate(peer)
+ struct peer *peer;
+{
+ struct goesunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct goesunit *)pp->unitptr;
+ up->State = Base; /* just in case */
+ goes_doevent(peer, e_Init);
}
+
/*
* goes_poll - called by the transmit procedure
*/
@@ -859,155 +505,29 @@ goes_poll(unit, peer)
int unit;
struct peer *peer;
{
- struct goesunit *goes;
+ struct goesunit *up;
+ struct refclockproc *pp;
/*
* You don't need to poll this clock. It puts out timecodes
* once per second. If asked for a timestamp, take note.
* The next time a timecode comes in, it will be fed back.
*/
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "goes_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "goes_poll: unit %d not in use", unit);
- return;
- }
- goes = goesunits[unit];
- if ((current_time - goes->lasttime) > 150) {
- goes->noreply++;
- goes_report_event(goesunits[unit], CEVNT_TIMEOUT);
+ pp = peer->procptr;
+ up = (struct goesunit *)pp->unitptr;
+ if (up->pollcnt == 0) {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ goes_send(peer, "C");
}
+ else
+ up->pollcnt--;
/*
- * polled every 64 seconds. Ask GOES_RECEIVE to hand in a timestamp.
+ * polled every 64 seconds. Ask goes_receive to hand in a
+ * timestamp.
*/
- goes->polled = 1;
- goes->polls++;
-
- goes_send(goes,"C");
-}
-
-/*
- * goes_control - set fudge factors, return statistics
- */
-static void
-goes_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- register struct goesunit *goes;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "goes_control: unit %d invalid", unit);
- return;
- }
- goes = goesunits[unit];
-
- if (in != 0) {
- if (in->haveflags & CLK_HAVETIME1)
- fudgefactor1[unit] = in->fudgetime1;
- if (in->haveflags & CLK_HAVETIME2)
- fudgefactor2[unit] = in->fudgetime2;
- 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
- */
- peer = goes->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid,
- GOESREFID, 4);
- else
- peer->refid = htonl(GOESHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
- readonlyclockflag[unit] = in->flags & CLK_FLAG1;
- }
- }
-
- if (out != 0) {
- out->type = REFCLK_GOES_TRUETIME;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVETIME2|
- CLK_HAVEVAL1|CLK_HAVEVAL2|
- CLK_HAVEFLAG1|CLK_HAVEFLAG2;
- out->clockdesc = GOESDESCRIPTION;
- out->fudgetime1 = fudgefactor1[unit];
- out->fudgetime2 = fudgefactor2[unit];
- out->fudgeval1 = (LONG)stratumtouse[unit];
- out->fudgeval2 = 0;
- out->flags = readonlyclockflag[unit] |
- (goes->satellite << 1);
- if (unitinuse[unit]) {
- out->lencode = goes->lencode;
- out->lastcode = goes->lastcode;
- out->timereset = current_time - goes->timestarted;
- out->polls = goes->polls;
- out->noresponse = goes->noreply;
- out->badformat = goes->badformat;
- out->baddata = goes->baddata;
- out->lastevent = goes->lastevent;
- out->currentstatus = goes->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;
- }
- }
+ up->polled = 1;
+ pp->polls++;
}
-/*
- * goes_buginfo - return clock dependent debugging info
- */
-static void
-goes_buginfo(unit, bug)
- int unit;
- register struct refclockbug *bug;
-{
- register struct goesunit *goes;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "goes_buginfo: unit %d invalid", unit);
- return;
- }
-
- if (!unitinuse[unit])
- return;
- goes = goesunits[unit];
-
- bug->nvalues = 11;
- bug->ntimes = 5;
- if (goes->lasttime != 0)
- bug->values[0] = current_time - goes->lasttime;
- else
- bug->values[0] = 0;
- bug->values[1] = (U_LONG)goes->reason;
- bug->values[2] = (U_LONG)goes->year;
- bug->values[3] = (U_LONG)goes->day;
- bug->values[4] = (U_LONG)goes->hour;
- bug->values[5] = (U_LONG)goes->minute;
- bug->values[6] = (U_LONG)goes->second;
- bug->values[7] = (U_LONG)goes->msec;
- bug->values[8] = goes->noreply;
- bug->values[9] = goes->yearstart;
- bug->values[10] = goes->quality;
- bug->stimes = 0x1c;
- bug->times[0] = goes->lastref;
- bug->times[1] = goes->lastrec;
- bug->times[2] = goes->offset[0];
- bug->times[3] = goes->offset[1];
- bug->times[4] = goes->offset[2];
-}
#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_gpstm.c b/usr.sbin/xntpd/xntpd/refclock_gpstm.c
index 93abcf93773c..71eb015cb14b 100644
--- a/usr.sbin/xntpd/xntpd/refclock_gpstm.c
+++ b/usr.sbin/xntpd/xntpd/refclock_gpstm.c
@@ -78,13 +78,11 @@
* Radio interface parameters
*/
#define MAXDISPERSE (FP_SECOND>>1) /* max error for synchronized clock (0.5 s as an u_fp) */
-#define PRECISION (-20) /* precision assumed (about 1 ms) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
#define REFID "GPS\0" /* reference id */
#define DESCRIPTION "Kinemetrics GPS-TM/TMD Receiver" /* who we are */
-#define HSREFID 0x7f7f0f0a /* 127.127.15.10 refid hi strata */
#define GMT 0 /* hour offset from Greenwich */
#define NCODES 3 /* stages of median filter */
-#define BMAX 99 /* timecode buffer length */
#define CODEDIFF 0x20000000 /* 0.125 seconds as an l_fp fraction */
#define TIMEOUT 180 /* ping the clock if it's silent this long */
@@ -93,7 +91,6 @@
*/
enum gpstm_event {e_Init, e_F18, e_F50, e_F51, e_TS};
static enum {Base, Start, F18, F50, F51, F08} State[MAXUNITS];
-static time_t Last[MAXUNITS];
static void gpstm_doevent P((int, enum gpstm_event));
static void gpstm_initstate P((int));
@@ -143,7 +140,7 @@ struct gpstm_unit {
u_char leap; /* leap indicators */
u_short msec; /* millisecond of second */
u_char quality; /* quality character */
- U_LONG yearstart; /* start of current year */
+ u_long yearstart; /* start of current year */
/*
* Status tallies
*/
@@ -170,18 +167,19 @@ static l_fp fudgefactor1[MAXUNITS];
static l_fp fudgefactor2[MAXUNITS];
static u_char stratumtouse[MAXUNITS];
static u_char readonlyclockflag[MAXUNITS];
+static U_LONG refid[MAXUNITS];
/*
* Function prototypes
*/
static void gpstm_init P((void));
-static int gpstm_start P((u_int, struct peer *));
-static void gpstm_shutdown P((int));
+static int gpstm_start P((int, struct peer *));
+static void gpstm_shutdown P((int, struct peer *));
static void gpstm_rep_event P((struct gpstm_unit *, int));
static void gpstm_receive P((struct recvbuf *));
static char gpstm_process P((struct gpstm_unit *, l_fp *, u_fp *));
static void gpstm_poll P((int, struct peer *));
-static void gpstm_control P((u_int, struct refclockstat *,
+static void gpstm_control P((int, struct refclockstat *,
struct refclockstat *));
static void gpstm_buginfo P((int, struct refclockbug *));
static void gpstm_send P((struct gpstm_unit *, char *));
@@ -214,6 +212,7 @@ gpstm_init()
fudgefactor2[i].l_uf = 0;
stratumtouse[i] = 0;
readonlyclockflag[i] = 0;
+ memcpy((char *)&refid[i], REFID, 4);
}
}
@@ -223,7 +222,7 @@ gpstm_init()
*/
static int
gpstm_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
register struct gpstm_unit *gpstm;
@@ -417,10 +416,7 @@ gpstm_start(unit, peer)
peer->rootdelay = 0;
peer->rootdispersion = 0;
peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, REFID, 4);
- else
- peer->refid = htonl(HSREFID);
+ peer->refid = refid[unit];
unitinuse[unit] = 1;
gpstm_initstate(unit);
return 1;
@@ -437,8 +433,9 @@ screwed:
* gpstm_shutdown - shut down a clock
*/
static void
-gpstm_shutdown(unit)
+gpstm_shutdown(unit, peer)
int unit;
+ struct peer *peer;
{
register struct gpstm_unit *gpstm;
@@ -779,7 +776,9 @@ gpstm_doevent(unit, event)
}
static void
-gpstm_initstate(unit) {
+gpstm_initstate(unit)
+ int unit;
+ {
State[unit] = Base; /* just in case */
gpstm_doevent(unit, e_Init);
}
@@ -897,7 +896,7 @@ gpstm_poll(unit, peer)
*/
static void
gpstm_control(unit, in, out)
- u_int unit;
+ int unit;
struct refclockstat *in;
struct refclockstat *out;
{
@@ -907,48 +906,40 @@ gpstm_control(unit, in, out)
syslog(LOG_ERR, "gpstm_control: unit %d invalid", unit);
return;
}
- gpstm = gpstm_units[unit];
if (in != 0) {
if (in->haveflags & CLK_HAVETIME1)
fudgefactor1[unit] = in->fudgetime1;
if (in->haveflags & CLK_HAVETIME2)
fudgefactor2[unit] = in->fudgetime2;
- 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
- */
- peer = gpstm->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid,
- REFID, 4);
- else
- peer->refid = htonl(HSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
readonlyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = gpstm_units[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
}
}
if (out != 0) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
out->type = REFCLK_GPSTM_TRUETIME;
- out->haveflags = CLK_HAVETIME1 | CLK_HAVETIME2
- | CLK_HAVEVAL1 | CLK_HAVEVAL2
- | CLK_HAVEFLAG1;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVETIME2 | CLK_HAVEVAL1 |
+ CLK_HAVEVAL2 | CLK_HAVEFLAG1;
out->clockdesc = DESCRIPTION;
out->fudgetime1 = fudgefactor1[unit];
out->fudgetime2 = fudgefactor2[unit];
out->fudgeval1 = (LONG)stratumtouse[unit];
- out->fudgeval2 = 0;
+ out->fudgeval2 = refid[unit];
out->flags = readonlyclockflag[unit];
if (unitinuse[unit]) {
+ gpstm = gpstm_units[unit];
out->lencode = gpstm->lencode;
out->lastcode = gpstm->lastcode;
out->timereset = current_time - gpstm->timestarted;
@@ -958,13 +949,6 @@ gpstm_control(unit, in, out)
out->baddata = gpstm->baddata;
out->lastevent = gpstm->lastevent;
out->currentstatus = gpstm->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;
}
}
}
diff --git a/usr.sbin/xntpd/xntpd/refclock_heath.c b/usr.sbin/xntpd/xntpd/refclock_heath.c
new file mode 100644
index 000000000000..1fbb9b7e6876
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_heath.c
@@ -0,0 +1,393 @@
+/*
+ * refclock_heath - clock driver for Heath GC-1000 Most Accurate Clock
+ */
+#if defined(REFCLOCK) && defined(HEATH)
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the Heath GC-1000 Most Accurate Clock, with
+ * RS232C Output Accessory. This is a WWV/WWVH receiver somewhat less
+ * robust than other supported receivers. Its claimed accuracy is 100 ms
+ * when actually synchronized to the broadcast signal, but this doesn't
+ * happen even most of the time, due to propagation conditions, ambient
+ * noise sources, etc. When not synchronized, the accuracy is at the
+ * whim of the internal clock oscillator, which can wander into the
+ * sunset without warning. Since the indicated precision is 100 ms,
+ * expect a host synchronized only to this thing to wander to and fro,
+ * occasionally being rudely stepped when the offset exceeds the default
+ * CLOCK_MAX of 128 ms.
+ *
+ * The internal DIPswitches should be set to operate at 1200 baud in
+ * MANUAL mode and the current year. The external DIPswitches should be
+ * set to GMT and 24-hour format, or to the host local time zone (with
+ * DST) and 12-hour format. It is very important that the year be
+ * set correctly in the DIPswitches. Otherwise, the day of year will be
+ * incorrect after 28 April of a normal or leap year. In 12-hour mode
+ * with DST selected the clock will be incorrect by an hour for an
+ * indeterminate amount of time between 0000Z and 0200 on the day DST
+ * changes.
+ *
+ * In MANUAL mode the clock responds to a rising edge of the request to
+ * send (RTS) modem control line by sending the timecode. Therefore, it
+ * is necessary that the operating system implement the TIOCMBIC and
+ * TIOCMBIS ioctl system calls and TIOCM_RTS control bit. Present
+ * restrictions require the use of a POSIX-compatible programming
+ * interface, although other interfaces may work as well.
+ *
+ * A simple hardware modification to the clock can be made which
+ * prevents the clock hearing the request to send (RTS) if the HI SPEC
+ * lamp is out. Route the HISPEC signal to the tone decoder board pin
+ * 19, from the display, pin 19. Isolate pin 19 of the decoder board
+ * first, but maintain connection with pin 10. Also isolate pin 38 of
+ * the CPU on the tone board, and use half an added 7400 to gate the
+ * original signal to pin 38 with that from pin 19.
+ *
+ * The clock message consists of 23 ASCII printing characters in the
+ * following format:
+ *
+ * hh:mm:ss.f AM dd/mm/yr<cr>
+ *
+ * hh:mm:ss.f = hours, minutes, seconds
+ * f = deciseconds ('?' when out of spec)
+ * AM/PM/bb = blank in 24-hour mode
+ * dd/mm/yr = day, month, year
+ *
+ * The alarm condition is indicated by '?', rather than a digit, at f.
+ * Note that 0?:??:??.? is displayed before synchronization is first
+ * established and hh:mm:ss.? once synchronization is established and
+ * then lost again for about a day.
+ *
+ * Fudge Factors
+ *
+ * A fudge time1 value of .04 s appears to center the clock offset
+ * residuals. The fudge time2 parameter is the local time offset east of
+ * Greenwich, which depends on DST. Sorry about that, but the clock
+ * gives no hint on what the DIPswitches say.
+ */
+
+/*
+ * Interface definitions
+ */
+#define DEVICE "/dev/heath%d" /* device name and unit */
+#define SPEED232 B1200 /* uart speed (1200 baud) */
+#define PRECISION (-4) /* precision assumed (about 100 ms) */
+#define REFID "WWV\0" /* reference ID */
+#define DESCRIPTION "Heath GC-1000 Most Accurate Clock" /* WRU */
+
+#define NSAMPLES 3 /* stages of median filter */
+#define LENHEATH 23 /* min timecode length */
+
+/*
+ * Imported from ntp_timer module
+ */
+extern u_long current_time; /* current time (s) */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
+ * leap.
+ */
+static day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ * Unit control structure
+ */
+struct heathunit {
+ int pollcnt; /* poll message counter */
+ l_fp tstamp; /* timestamp of last poll */
+};
+
+/*
+ * Function prototypes
+ */
+static int heath_start P((int, struct peer *));
+static void heath_shutdown P((int, struct peer *));
+static void heath_receive P((struct recvbuf *));
+static void heath_poll P((int, struct peer *));
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_heath = {
+ heath_start, /* start up driver */
+ heath_shutdown, /* shut down driver */
+ heath_poll, /* transmit poll message */
+ noentry, /* not used (old heath_control) */
+ noentry, /* initialize driver */
+ noentry, /* not used (old heath_buginfo) */
+ NOFLAGS /* not used */
+};
+
+
+/*
+ * heath_start - open the devices and initialize data for processing
+ */
+static int
+heath_start(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct heathunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
+
+ /*
+ * Open serial port
+ */
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, 0)))
+ return (0);
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ if (!(up = (struct heathunit *)
+ emalloc(sizeof(struct heathunit)))) {
+ (void) close(fd);
+ return (0);
+ }
+ memset((char *)up, 0, sizeof(struct heathunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = heath_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+ pp->unitptr = (caddr_t)up;
+
+ /*
+ * Initialize miscellaneous variables
+ */
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
+ return (1);
+}
+
+
+/*
+ * heath_shutdown - shut down the clock
+ */
+static void
+heath_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct heathunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct heathunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
+}
+
+
+/*
+ * heath_receive - receive data from the serial interface
+ */
+static void
+heath_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register struct heathunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ l_fp trtmp;
+ int month, day;
+ int i;
+ char dsec, a[5];
+
+ /*
+ * Initialize pointers and read the timecode and timestamp
+ */
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct heathunit *)pp->unitptr;
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX, &trtmp);
+
+ /*
+ * We get a buffer and timestamp for each <cr>; however, we use
+ * the timestamp captured at the RTS modem control line toggle
+ * on the assumption that's what the radio bases the timecode
+ * on. Apparently, the radio takes about a second to make up its
+ * mind to send a timecode, so the receive timestamp is
+ * worthless.
+ */
+ pp->lastrec = up->tstamp;
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
+#ifdef DEBUG
+ if (debug)
+ printf("heath: timecode %d %s\n", pp->lencode,
+ pp->lastcode);
+#endif
+
+ /*
+ * We get down to business, check the timecode format and decode
+ * its contents. If the timecode has invalid length or is not in
+ * proper format, we declare bad format and exit.
+ */
+ if (pp->lencode < LENHEATH) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Timecode format: "hh:mm:ss.f AM mm/dd/yy"
+ */
+ if (sscanf(pp->lastcode, "%2d:%2d:%2d.%c%5c%2d/%2d/%2d",
+ &pp->hour, &pp->minute, &pp->second, &dsec, a, &month, &day,
+ &pp->year) != 8) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * If AM or PM is received, assume the clock is displaying local
+ * time. First, convert to 24-hour format, then add the local
+ * time correction (in hours east of Greenwich) from
+ * fudgetime2.
+ */
+ switch (a[1]) {
+ case 'P':
+ if (pp->hour < 12)
+ pp->hour += 12;
+ break;
+
+ case 'A':
+ if (pp->hour == 12)
+ pp->hour -= 12;
+ break;
+ }
+ i = (int)pp->hour - (int)pp->fudgetime2.l_ui;
+ if (i < 0)
+ i += 24;
+ pp->hour = i % 24;
+
+ /*
+ * We determine the day of the year from the DIPswitches. This
+ * should be fixed, since somebody might forget to set them.
+ * Someday this hazard will be fixed by a fiendish scheme that
+ * looks at the timecode and year the radio shows, then computes
+ * the residue of the seconds mod the seconds in a leap cycle.
+ * If in the third year of that cycle and the third and later
+ * months of that year, add one to the day. Then, correct the
+ * timecode accordingly. Icky pooh. This bit of nonsense could
+ * be avoided if the engineers had been required to write a
+ * device driver before finalizing the timecode format.
+ *
+ * Yes, I know this code incorrectly thinks that 2000 is a leap
+ * year; but, the latest year that can be set by the DIPswitches
+ * is 1997 anyay. Life is short.
+ */
+ if (month < 1 || month > 12 || day < 1) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ if (pp->year % 4) {
+ if (day > day1tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day1tab[i];
+ } else {
+ if (day > day2tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day2tab[i];
+ }
+ pp->day = day;
+
+ /*
+ * Determine synchronization and last update
+ */
+ if (!isdigit(dsec)) {
+ pp->leap = LEAP_NOTINSYNC;
+ } else {
+ pp->leap = 0;
+ pp->lasttime = current_time;
+ pp->msec = (dsec - '0') * 100;
+ }
+
+ /*
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
+}
+
+
+/*
+ * heath_poll - called by the transmit procedure
+ */
+static void
+heath_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct heathunit *up;
+ struct refclockproc *pp;
+ int bits = TIOCM_RTS;
+
+ /*
+ * At each poll we check for timeout and toggle the RTS modem
+ * control line, then take a timestamp. Presumably, this is the
+ * event the radio captures to generate the timecode.
+ */
+ pp = peer->procptr;
+ up = (struct heathunit *)pp->unitptr;
+ if (up->pollcnt == 0)
+ refclock_report(peer, CEVNT_TIMEOUT);
+ else
+ up->pollcnt--;
+ pp->polls++;
+
+ /*
+ * We toggle the RTS modem control lead to kick a timecode loose
+ * from the radio. This code works only for POSIX and SYSV
+ * interfaces. With bsd you are on your own. We take a timestamp
+ * between the up and down edges to lengthen the pulse, which
+ * should be about 50 usec on a Sun IPC. With hotshot CPUs, the
+ * pulse might get too short. Later.
+ */
+ if (ioctl(pp->io.fd, TIOCMBIC, (char *)&bits) < 0)
+ refclock_report(peer, CEVNT_FAULT);
+ gettstamp(&up->tstamp);
+ ioctl(pp->io.fd, TIOCMBIS, (char *)&bits);
+
+}
+
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_irig.c b/usr.sbin/xntpd/xntpd/refclock_irig.c
index 6167af2784ee..bc93fd74a918 100644
--- a/usr.sbin/xntpd/xntpd/refclock_irig.c
+++ b/usr.sbin/xntpd/xntpd/refclock_irig.c
@@ -1,8 +1,8 @@
/*
* refclock_irig - clock driver for the IRIG audio decoder
*/
+#if defined(REFCLOCK) && defined(IRIG) && defined(sun)
-#if defined(REFCLOCK) && defined(IRIG)
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
@@ -19,72 +19,72 @@
* 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 in the
+ * sys/bsd_audioirig.h header file:
*
* struct irig_time {
- * struct timeval stamp; timestamp
- * u_char bits[13]; 100 irig data bits
- * u_char status; status byte
- * char time[14]; time string (null terminated)
+ * struct timeval stamp; timestamp
+ * u_char bits[13]; 100 IRIG data bits
+ * u_char status; status byte
+ * char time[14]; time string (null terminated)
*
* where stamp represents a timestamp at the zero crossing of the index
* marker at the second's epoch, bits is a 13-octet, zero-padded binary-
* coded string representing code elements 1 through 100 in the IRIG-B
- * code format and status is a status bute, The decoded timestamp is a
+ * code format, and status is a status bute, The decoded timestamp is a
* 13-octet, null-terminated ASCII string "ddd hh:mm:ss*", where ddd is
- * the day of year, hh:mm:ss the time of day and * is a status indicator,
- * with " " indicating valid time and "?" indicating invalid time. The
- * timestamp is in unix timeval format, consisting of two 32-bit
- * longwords, the first of which is the seconds since 1970 and the second
- * is the fraction of the second in microseconds. The status byte is zero
+ * the day of year, hh:mm:ss the time of day and * is a status
+ * indicator, with " " indicating valid time and "?" indicating
+ * something wrong.
+ *
+ * The timestamp is in Unix timeval format, consisting of two 32-bit
+ * words, the first of which is the seconds since 1970 and the second is
+ * the fraction of the second in microseconds. The status byte is zero
* if (a) the input signal is within amplitude tolerances, (b) the raw
* binary timecode contains only valid code elements, (c) 11 position
- * identifiers have been found at the expected element positions, (d) the
- * clock status byte contained in the timecode is valid, and (e) a time
- * determination has been made since the last read() system call.
+ * identifiers have been found at the expected element positions, (d)
+ * the clock status byte contained in the timecode is valid, and (e) a
+ * time determination has been made since the last read() system call.
*
* The 100 elements of the IRIG-B timecode are numbered from 0 through
* 99. Position identifiers occur at elements 0, 9, 19 and every ten
- * thereafter to 99. The control function elements begin at element 50,
- * which is control-field element 1, and extend to element 78, which is
- * control-field element 27. The control functions have different
- * interpretations in various devices. The straight-binary-seconds(SBS)
- * field begins at element 80 and is 17 bits long.
+ * thereafter to 99. The control function (CF) elements begin at element
+ * 50 (CF 1) and extend to element 78 (CF 27). The straight-binary-
+ * seconds (SBS) field, which encodes the seconds of the UTC day, begins
+ * at element 80 (CF 28) and extends to element 97 (CF 44). The encoding
+ * of elements 50 (CF 1) through 78 (CF 27) is device dependent. This
+ * driver presently does not use the CF elements.
+ *
+ * Where feasible, the interface should be operated with signature
+ * control, so that, if the IRIG signal is lost or malformed, the
+ * interface produces an unmodulated signal, rather than possibly random
+ * digits. The driver will declare "unsynchronized" in this case.
*
* Spectracom Netclock/2 WWVB Synchronized Clock
- * 6 time sync status
- * 10-13 bcd year units
- * 15-18 bcd year tens
*
- * Austron 2201A GPS Receiver (speculative)
+ * Element CF Function
+ * -------------------------------------
+ * 55 6 time sync status
+ * 60-63 10-13 bcd year units
+ * 65-68 15-18 bcd year tens
+ *
*/
/*
- * Definitions
+ * IRIG interface definitions
*/
-#define MAXUNITS 1 /* max number of irig units */
-#define IRIGFD "/dev/irig" /* name of driver device */
+#define DEVICE "/dev/irig%d" /* device name and unit */
+#define PRECISION (-13) /* precision assumed (100 us) */
+#define REFID "IRIG" /* reference ID */
+#define DESCRIPTION "IRIG Audio Decoder" /* WRU */
-/*
- * IRIG interface parameters.
- */
-#define IRIGPRECISION (-20) /* precision assumed (1 us) */
-#define IRIGREFID "IRIG" /* reference id */
-#define IRIGDESCRIPTION "IRIG audio decoder" /* who we are */
-#define IRIGHSREFID 0x7f7f0c0a /* 127.127.6.10 refid hi strata */
-#define GMT 0 /* hour offset from Greenwich */
+#define NSAMPLES 3 /* stages of median filter */
#define IRIG_FORMAT 1 /* IRIG timestamp format */
-#define BMAX 40 /* length of decoded timecode */
-
-/*
- * 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) */
+extern u_long current_time; /* current time (s) */
/*
* Imported from ntpd module
@@ -92,282 +92,115 @@ extern U_LONG current_time; /* current time (s) */
extern int debug; /* global debug flag */
/*
- * irig unit control structure.
- */
-struct irigunit {
- struct peer *peer; /* associated peer structure */
- struct refclockio io; /* given to the I/O handler */
- l_fp lastrec; /* last local time */
- l_fp lastref; /* last timecode time */
- char lastcode[BMAX]; /* decoded timecode */
- char bincode[BMAX]; /* raw irig message */
- int lencode; /* lengthof last timecode */
- U_LONG lasttime; /* last time clock heard from */
- u_char unit; /* unit number for this guy */
- u_char status; /* clock status */
- u_char lastevent; /* last clock event */
- 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_LONG yearstart; /* start of current year */
- u_char leap; /* leap indicators */
- /*
- * 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 irigunit *irigunits[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 irig_init P(());
-static int irig_start P((u_int, struct peer *));
-static void irig_shutdown P((int));
-static void irig_report_event P((struct irigunit *, int));
-static void irig_poll P((int, struct peer *));
-static void irig_control P((u_int, struct refclockstat *, struct refclockstat *));
-static void irig_buginfo P((int, struct refclockbug *));
+static int irig_start P((int, struct peer *));
+static void irig_shutdown P((int, struct peer *));
+static void irig_poll P((int, struct peer *));
/*
* Transfer vector
*/
-struct refclock refclock_irig = {
- irig_start, irig_shutdown, irig_poll,
- irig_control, irig_init, irig_buginfo, NOFLAGS
+struct refclock refclock_irig = {
+ irig_start, /* start up driver */
+ irig_shutdown, /* shut down driver */
+ irig_poll, /* transmit poll message */
+ noentry, /* not used (old irig_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old irig_buginfo) */
+ NOFLAGS /* not used */
};
-/*
- * irig_init - initialize internal irig driver data
- */
-static void
-irig_init()
-{
- register int i;
-
- /*
- * Just zero the data arrays
- */
- memset((char *) irigunits, 0, sizeof irigunits);
- 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;
- }
-}
-
/*
- * irig_start - open the irig device and initialize data for processing
+ * irig_start - open the device and initialize data for processing
*/
static int
irig_start(unit, peer)
- u_int unit;
-struct peer *peer;
+ int unit;
+ struct peer *peer;
{
- register struct irigunit *irig;
- register int i;
- int fd_irig;
- int format = IRIG_FORMAT;
+ register struct refclockproc *pp;
+ char device[20];
+ int fd;
+ int format = IRIG_FORMAT;
/*
- * Check configuration info.
- */
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "irig_start: unit %d invalid", unit);
- return (0);
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "irig_start: unit %d in use", unit);
- return (0);
- }
- /*
- * Open IRIG device and set format
+ * Open audio device and set format
*/
- fd_irig = open(IRIGFD, O_RDONLY | O_NDELAY, 0777);
- if (fd_irig == -1) {
- syslog(LOG_ERR, "irig_start: open of %s: %m", IRIGFD);
+ (void)sprintf(device, DEVICE, unit);
+ fd = open(device, O_RDONLY | O_NDELAY, 0777);
+ if (fd == -1) {
+ syslog(LOG_ERR, "irig_start: open of %s: %m", device);
return (0);
}
- if (ioctl(fd_irig, AUDIO_IRIG_OPEN, 0) < 0) {
- syslog(LOG_ERR,
- "irig_start: ioctl(%s, AUDIO_IRIG_OPEN): %m", IRIGFD);
- close(fd_irig);
+ if (ioctl(fd, AUDIO_IRIG_OPEN, 0) < 0) {
+ syslog(LOG_ERR, "irig_start: AUDIO_IRIG_OPEN %m");
+ close(fd);
return (0);
}
- if (ioctl(fd_irig, AUDIO_IRIG_SETFORMAT, (char *) &format) < 0) {
- syslog(LOG_ERR,
- "irig_start: ioctl(%s, AUDIO_IRIG_SETFORMAT): %m", IRIGFD);
- close(fd_irig);
+ if (ioctl(fd, AUDIO_IRIG_SETFORMAT, (char *)&format) < 0) {
+ syslog(LOG_ERR, "irig_start: AUDIO_IRIG_SETFORMAT %m",
+ DEVICE);
+ close(fd);
return (0);
}
+ pp = peer->procptr;
+ pp->io.clock_recv = noentry;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
/*
- * Allocate unit structure
- */
- if (irigunits[unit] != 0) {
- irig = irigunits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < MAXUNITS; i++) {
- if (!unitinuse[i] && irigunits[i] != 0)
- break;
- }
- if (i < MAXUNITS) {
- /*
- * Reclaim this one
- */
- irig = irigunits[i];
- irigunits[i] = 0;
- } else {
- irig = (struct irigunit *)
- emalloc(sizeof(struct irigunit));
- }
- }
- memset((char *) irig, 0, sizeof(struct irigunit));
-
- irigunits[unit] = irig;
-
- /*
- * Set up the structures
- */
- irig->peer = peer;
- irig->unit = (u_char) unit;
- irig->timestarted = current_time;
-
- irig->io.clock_recv = noentry;
- irig->io.srcclock = (caddr_t) irig;
- irig->io.datalen = 0;
- irig->io.fd = fd_irig;
-
- /*
- * 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 = IRIGPRECISION;
- peer->rootdelay = 0;
- peer->rootdispersion = 0;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *) &peer->refid, IRIGREFID, 4);
- else
- peer->refid = htonl(IRIGHSREFID);
- unitinuse[unit] = 1;
+ * Initialize miscellaneous variables
+ */
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
return (1);
}
-/*
- * irig_shutdown - shut down a irig clock
- */
-static void
-irig_shutdown(unit)
- int unit;
-{
- register struct irigunit *irig;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "irig_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "irig_shutdown: unit %d not in use", unit);
- return;
- }
- /*
- * Tell the I/O module to turn us off. We're history.
- */
- irig = irigunits[unit];
- io_closeclock(&irig->io);
- unitinuse[unit] = 0;
-}
-
/*
- * irig_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.
+ * irig_shutdown - shut down the clock
*/
static void
-irig_report_event(irig, code)
- struct irigunit *irig;
-int code;
-{
+irig_shutdown(unit, peer)
+ int unit;
struct peer *peer;
+{
+ struct refclockproc *pp;
- peer = irig->peer;
- if (irig->status != (u_char) code) {
- irig->status = (u_char) code;
- if (code != CEVNT_NOMINAL)
- irig->lastevent = (u_char) code;
- syslog(LOG_INFO,
- "clock %s event %x", ntoa(&peer->srcadr), code);
- }
+ pp = peer->procptr;
+ io_closeclock(&pp->io);
}
+
/*
* irig_poll - called by the transmit procedure
*/
static void
irig_poll(unit, peer)
- int unit;
-struct peer *peer;
+ int unit;
+ struct peer *peer;
{
- struct irigunit *irig;
+ struct refclockproc *pp;
struct irig_time buf;
- register u_char *dpt;
- register char *cp, *dp;
- l_fp tstmp;
- int i;
+ char *cp, *dp;
+ u_char *dpt;
+ int i;
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "irig_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "irig_poll: unit %d not in use", unit);
- return;
- }
- irig = irigunits[unit];
- irig->polls++;
-
- if (read(irig->io.fd, (char *) &buf, sizeof(buf)) != sizeof(buf)) {
- syslog(LOG_ERR, "irig_poll: unit %d: %m", irig->unit);
- irig_report_event(irig, CEVNT_FAULT);
+ pp = peer->procptr;
+ if (read(pp->io.fd, (char *) &buf, sizeof(buf)) != sizeof(buf)) {
+ refclock_report(peer, CEVNT_FAULT);
return;
}
+ pp->polls++;
#ifdef DEBUG
if (debug) {
- dpt = (u_char *) & buf;
+ dpt = (u_char *)&buf;
printf("irig: ");
for (i = 0; i < sizeof(buf); i++)
printf("%02x", *dpt++);
@@ -375,194 +208,52 @@ struct peer *peer;
}
#endif
- buf.stamp.tv_sec += (U_LONG) JAN_1970;
- TVTOTS(&buf.stamp, &irig->lastrec);
- dpt = buf.bits;
- dp = irig->bincode;
- for (i = 0; i < sizeof(buf.bits); i++) {
- *dp++ = *dpt++;
- }
+ buf.stamp.tv_sec += JAN_1970;
+ TVTOTS(&buf.stamp, &pp->lastrec);
cp = buf.time;
- dp = irig->lastcode;
+ dp = pp->lastcode;
for (i = 0; i < sizeof(buf.time); i++)
*dp++ = *cp++;
- dp--;
- *dp = '\0';
- cp = irig->lastcode;
- irig->lencode = dp - cp;
+ *--dp = '\0';
+ pp->lencode = dp - pp->lastcode;
#ifdef DEBUG
if (debug)
- printf("irig: timecode %d %s %s\n",
- irig->lencode, ulfptoa(&irig->lastrec, 6), irig->lastcode);
+ printf("irig: time %s timecode %d %s\n",
+ ulfptoa(&pp->lastrec, 6), pp->lencode,
+ pp->lastcode);
#endif
-
- irig->lasttime = current_time;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
/*
- * Get irig time and convert to timestamp format.
+ * Get IRIG time and convert to timestamp format
*/
- if (irig->lencode < 13 || !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])) {
- irig->badformat++;
- irig_report_event(irig, CEVNT_BADREPLY);
- return;
- }
- record_clock_stats(&(irig->peer->srcadr), irig->lastcode);
- irig->day = cp[0] - '0';
- irig->day = MULBY10(irig->day) + cp[1] - '0';
- irig->day = MULBY10(irig->day) + cp[2] - '0';
- 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] = ' ')
- irig->leap = 0;
- else
- irig->leap = LEAP_NOTINSYNC;
- if (irig->day < 1 || irig->day > 366) {
- irig->baddata++;
- irig_report_event(irig, CEVNT_BADDATE);
+ if (sscanf(pp->lastcode, "%3d %2d:%2d:%2d",
+ &pp->day, &pp->hour, &pp->minute, &pp->second) != 4) {
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
- if (irig->hour > 23 || irig->minute > 59 || irig->second > 59) {
- irig->baddata++;
- irig_report_event(irig, CEVNT_BADTIME);
- return;
+ if (pp->lastcode[12] != ' ') {
+ pp->leap = LEAP_NOTINSYNC;
+ } else {
+ pp->leap = 0;
+ pp->lasttime = current_time;
}
/*
- * Now, compute the reference time value. Use the heavy
- * machinery for the seconds and the millisecond field for the
- * fraction when present. If an error in conversion to internal
- * format is found, the program declares bad data and exits.
- * Note that this code does not yet know how to do the years and
- * relies on the clock-calendar chip for sanity.
- */
- if (!clocktime(irig->day, irig->hour, irig->minute,
- irig->second, GMT, irig->lastrec.l_ui,
- &irig->yearstart, &irig->lastref.l_ui)) {
- irig->baddata++;
- irig_report_event(irig, CEVNT_BADTIME);
- return;
- }
- tstmp = irig->lastref;
- L_SUB(&tstmp, &irig->lastrec);
- irig->coderecv++;
- L_ADD(&tstmp, &(fudgefactor[irig->unit]));
- refclock_receive(irig->peer, &tstmp, GMT, 0,
- &irig->lastrec, &irig->lastrec, irig->leap);
-}
-
-/*
- * irig_control - set fudge factors, return statistics
- */
-static void
-irig_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- register struct irigunit *irig;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "irig_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
- */
- irig = irigunits[unit];
- peer = irig->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *) &peer->refid,
- IRIGREFID, 4);
- else
- peer->refid = htonl(IRIGHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
- sloppyclockflag[unit] = in->flags & CLK_FLAG1;
- }
- }
- if (out != 0) {
- out->type = REFCLK_IRIG_AUDIO;
- out->haveflags
- = CLK_HAVETIME1 | CLK_HAVEVAL1 | CLK_HAVEVAL2 | CLK_HAVEFLAG1;
- out->clockdesc = IRIGDESCRIPTION;
- 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]) {
- irig = irigunits[unit];
- out->lencode = irig->lencode;
- out->lastcode = irig->lastcode;
- out->timereset = current_time - irig->timestarted;
- out->polls = irig->polls;
- out->noresponse = irig->noreply;
- out->badformat = irig->badformat;
- out->baddata = irig->baddata;
- out->lastevent = irig->lastevent;
- out->currentstatus = irig->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;
- }
- }
-}
-
-/*
- * irig_buginfo - return clock dependent debugging info
- */
-static void
-irig_buginfo(unit, bug)
- int unit;
- register struct refclockbug *bug;
-{
- register struct irigunit *irig;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "irig_buginfo: unit %d invalid", unit);
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
return;
}
- if (!unitinuse[unit])
- return;
- irig = irigunits[unit];
-
- bug->nvalues = 8;
- bug->ntimes = 2;
- if (irig->lasttime != 0)
- bug->values[0] = current_time - irig->lasttime;
- else
- bug->values[0] = 0;
- bug->values[2] = (U_LONG) irig->year;
- bug->values[3] = (U_LONG) irig->day;
- bug->values[4] = (U_LONG) irig->hour;
- bug->values[5] = (U_LONG) irig->minute;
- bug->values[6] = (U_LONG) irig->second;
- bug->values[7] = irig->yearstart;
- bug->stimes = 0x1c;
- bug->times[0] = irig->lastref;
- bug->times[1] = irig->lastrec;
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
}
#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_leitch.c b/usr.sbin/xntpd/xntpd/refclock_leitch.c
index 330712997eba..753ad7673908 100644
--- a/usr.sbin/xntpd/xntpd/refclock_leitch.c
+++ b/usr.sbin/xntpd/xntpd/refclock_leitch.c
@@ -54,6 +54,7 @@
* P (last phone update failed)
*/
#define MAXUNITS 1 /* max number of LEITCH units */
+#define LEITCHREFID "ATOM" /* reference id */
#define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver"
#define LEITCH232 "/dev/leitch%d" /* name of radio device */
#define SPEED232 B300 /* uart speed (300 baud) */
@@ -106,17 +107,17 @@ struct leitchunit {
l_fp codetime1;
l_fp codetime2;
l_fp codetime3;
- U_LONG yearstart;
+ u_long yearstart;
};
/*
* Function prototypes
*/
static void leitch_init P((void));
-static int leitch_start P((u_int, struct peer *));
-static void leitch_shutdown P((int));
+static int leitch_start P((int, struct peer *));
+static void leitch_shutdown P((int, struct peer *));
static void leitch_poll P((int, struct peer *));
-static void leitch_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void leitch_control P((int, struct refclockstat *, struct refclockstat *));
#define leitch_buginfo noentry
static void leitch_receive P((struct recvbuf *));
static void leitch_process P((struct leitchunit *));
@@ -127,6 +128,8 @@ static int dysize P((int));
static struct leitchunit leitchunits[MAXUNITS];
static u_char unitinuse[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static U_LONG refid[MAXUNITS];
static char days_in_month [] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
@@ -144,16 +147,21 @@ struct refclock refclock_leitch = {
static void
leitch_init()
{
+ int i;
+
memset((char*)leitchunits, 0, sizeof(leitchunits));
memset((char*)unitinuse, 0, sizeof(unitinuse));
+ for (i = 0; i < MAXUNITS; i++)
+ memcpy((char *)&refid[i], LEITCHREFID, 4);
}
/*
* leitch_shutdown - shut down a LEITCH clock
*/
static void
-leitch_shutdown(unit)
-int unit;
+leitch_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
{
#ifdef DEBUG
if (debug)
@@ -196,40 +204,38 @@ leitch_poll(unit, peer)
static void
leitch_control(unit, in, out)
- u_int unit;
+ int unit;
struct refclockstat *in;
struct refclockstat *out;
{
-#if debug
- if (debug)
- fprintf(stderr, "leitch_control()\n");
-#endif
if (unit >= MAXUNITS) {
syslog(LOG_ERR,
"leitch_control: unit %d invalid", unit);
return;
}
+
if (in) {
- /* WE DONT SET ANY THING */
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = (&leitchunits[unit])->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
}
+
if (out) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
out->type = REFCLK_ATOM_LEITCH;
- out->flags = 0;
- out->haveflags = 0;
- out->lencode = 0;
+ out->haveflags = CLK_HAVEVAL1 | CLK_HAVEVAL2;
+ out->fudgeval1 = (LONG)stratumtouse[unit];
+ out->fudgeval2 = refid[unit];
out->lastcode = "";
- out->polls = 0;
- out->noresponse = 0;
- out->badformat = 0;
- out->baddata = 0;
- out->timereset = 0;
out->clockdesc = LEITCH_DESCRIPTION;
- out->fudgetime1.l_uf = 0;
- out->fudgetime1.l_ui = 0;
- out->fudgetime2.l_uf = 0;
- out->fudgetime2.l_ui = 0;
- out->currentstatus = 0;
- out->lastevent = 0;
}
}
@@ -238,7 +244,7 @@ leitch_control(unit, in, out)
*/
static int
leitch_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
struct leitchunit *leitch;
@@ -413,8 +419,8 @@ leitch_start(unit, peer)
peer->precision = 0;
peer->rootdelay = 0;
peer->rootdispersion = 0;
- peer->stratum = 0;
- peer->refid = htonl(0x41544f4d); /* ATOM */
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
unitinuse[unit] = 1;
return(1);
diff --git a/usr.sbin/xntpd/xntpd/refclock_local.c b/usr.sbin/xntpd/xntpd/refclock_local.c
index 1323ca91ed62..552e71272ab3 100644
--- a/usr.sbin/xntpd/xntpd/refclock_local.c
+++ b/usr.sbin/xntpd/xntpd/refclock_local.c
@@ -1,7 +1,8 @@
/*
* refclock_local - local pseudo-clock driver
*/
-#if defined(REFCLOCK) && defined(LOCAL_CLOCK)
+#if defined(REFCLOCK) && defined(LOCAL_CLOCK)
+
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
@@ -10,190 +11,129 @@
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
-static void local_init P((void));
-static int local_start P((u_int, struct peer *));
-static void local_shutdown P((int));
-static void local_poll P((int, struct peer *));
-static void local_control P((u_int, struct refclockstat *, struct refclockstat *));
-#define local_buginfo noentry
-
-struct refclock refclock_local = {
- local_start, local_shutdown, local_poll,
- local_control, local_init, local_buginfo, NOFLAGS
-};
-
/*
- * This is a hack to allow a machine to use its own system clock as
- * a "reference clock", i.e. to free run against its own clock at
- * a non-infinity stratum. This is certainly useful if you want to
- * use NTP in an isolated environment with no radio clock (not that
- * this is a good idea) to synchronize the machines together. Pick
- * a machine that you figure has a good clock and configure it with
- * a local reference clock running at stratum 0 (i.e. 127.127.1.0).
- * Then point all the other machines at the one you're using as the
- * reference.
+ * This is a hack to allow a machine to use its own system clock as a
+ * reference clock, i.e., to free-run using no outside clock discipline
+ * source. This is useful if you want to use NTP in an isolated
+ * environment with no radio clock or NIST modem available. Pick a
+ * machine that you figure has a good clock oscillator and configure it
+ * with this driver. Set the clock using the best means available, like
+ * eyeball-and-wristwatch. Then, point all the other machines at this
+ * one or use broadcast (not multicast) mode to distribute time.
*
- * The other thing this is good for is if you want to use a particular
- * server's clock as the last resort, when all radio time has gone
- * away. This is especially good if that server has an ovenized
- * oscillator or something which will keep the time stable for extended
- * periods, since then all the other machines can benefit from this.
- * For this you would configure a local clock at a higher stratum (say
- * 3 or 4) to prevent the server's stratum from falling below here.
- */
-
-/*
- * Definitions
+ * Another application for this driver is if you want to use a
+ * particular server's clock as the clock of last resort when all other
+ * normal synchronization sources have gone away. This is especially
+ * useful if that server has an ovenized oscillator. For this you would
+ * configure this driver at a higher stratum (say 3 or 4) to prevent the
+ * server's stratum from falling below that.
+ *
+ * A third application for this driver is when an external discipline
+ * source is available, such as the NIST "lockclock" program, which
+ * synchronizes the local clock via a telephone modem and the NIST
+ * Automated Computer Time Service (ACTS), or the Digital Time
+ * Synchronization Service (DTSS), which runs on DCE machines. In this
+ * case the stratum should be set at zero, indicating a bona fide
+ * stratum-1 source. Exercise some caution with this, since there is no
+ * easy way to telegraph via NTP that something might be wrong in the
+ * discipline source itself. In the case of DTSS, the local clock can
+ * have a rather large jitter, depending on the interval between
+ * corrections and the intrinsic frequency error of the clock
+ * oscillator. In extreme cases, this can cause clients to exceed the
+ * 128-ms slew window and drop off the NTP subnet.
+ *
+ * In the default mode the behavior of the clock selection algorithm is
+ * modified when this driver is in use. The algorithm is designed so
+ * that this driver will never be selected unless no other discipline
+ * source is available. This can be overriden with the prefer keyword of
+ * the server configuration command, in which case only this driver will
+ * be selected for synchronization and all other discipline sources will
+ * be ignored. This behavior is intended for use when an external
+ * discipline source controls the system clock.
+ *
+ * Fudge Factors
+ *
+ * The stratum for this driver LCLSTRATUM is set at 3 by default, but
+ * can be changed by the fudge command and/or the xntpdc utility. The
+ * reference ID is "LCL" by default, but can be changed using the same
+ * mechanisms. *NEVER* configure this driver to operate at a stratum
+ * which might possibly disrupt a client with access to a bona fide
+ * primary server, unless athe local clock oscillator is reliably
+ * disciplined by another source. *NEVER NEVER* configure a server which
+ * might devolve to an undisciplined local clock to use multicast mode.
+ *
+ * This driver provides a mechanism to trim the local clock in both time
+ * and frequency, as well as a way to manipulate the leap bits. The
+ * fudge time1 parameter adjusts the time, in seconds, and the fudge
+ * time2 parameter adjusts the frequency, in ppm. Both parameters are
+ * additive; that is, they add increments in time or frequency to the
+ * present values. The fudge flag1 and fudge flag2 bits set the
+ * corresponding leap bits; for example, setting flag1 causes a leap
+ * second to be added at the end of the UTC day. These bits are not
+ * reset automatically when the leap takes place; they must be turned
+ * off manually after the leap event.
*/
-#define NUMUNITS 16 /* 127.127.1.[0-15] */
/*
- * Some constant values we stick in the peer structure
+ * Local interface definitions
*/
-#define LCLDISPERSION (FP_SECOND/5) /* 200 ms dispersion */
-#define LCLROOTDISPERSION (FP_SECOND/5) /* 200 ms root dispersion */
-#define LCLPRECISION (-5) /* what the heck */
-#define LCLREFID "LCL\0"
-#define LCLREFOFFSET 20 /* reftime is 20s behind */
-#define LCLHSREFID 0x7f7f0101 /* 127.127.1.1 refid for hi stratum */
+#define PRECISION (-7) /* about 10 ms precision */
+#define REFID "LCL\0" /* reference ID */
+#define DESCRIPTION "Undisciplined local clock" /* WRU */
-/*
- * Description of clock
- */
-#define LCLDESCRIPTION "Free running against local system clock"
+#define STRATUM 3 /* default stratum */
+#define DISPERSION (FP_SECOND / 100) /* default dispersion (10 ms) */
/*
- * Local clock unit control structure.
+ * Imported from the timer module
*/
-struct lclunit {
- struct peer *peer; /* associated peer structure */
- u_char status; /* clock status */
- u_char lastevent; /* last clock event */
- u_char unit; /* unit number */
- u_char unused;
- U_LONG lastupdate; /* last time data received */
- U_LONG polls; /* number of polls */
- U_LONG timestarted; /* time we started this */
-};
-
+extern u_long current_time;
/*
- * Data space for the unit structures. Note that we allocate these on
- * the fly, but never give them back.
+ * Imported from ntp_proto
*/
-static struct lclunit *lclunits[NUMUNITS];
-static u_char unitinuse[NUMUNITS];
+extern s_char sys_precision;
/*
- * Imported from the timer module
+ * Function prototypes
*/
-extern U_LONG current_time;
-
-extern l_fp sys_clock_offset;
+static int local_start P((int, struct peer *));
+static void local_poll P((int, struct peer *));
/*
- * local_init - initialize internal local clock driver data
+ * Transfer vector
*/
-static void
-local_init()
-{
- /*
- * Just zero the data arrays
- */
- memset((char *)lclunits, 0, sizeof lclunits);
- memset((char *)unitinuse, 0, sizeof unitinuse);
-}
+struct refclock refclock_local = {
+ local_start, /* start up driver */
+ noentry, /* shut down driver (not used) */
+ local_poll, /* transmit poll message */
+ noentry, /* not used (old lcl_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old lcl_buginfo) */
+ NOFLAGS /* not used */
+};
/*
- * local_start - start up a local reference clock
+ * local_start - start up the clock
*/
static int
local_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register int i;
- register struct lclunit *lcl;
+ register struct refclockproc *pp;
- if (unit >= NUMUNITS) {
- syslog(LOG_ERR, "local clock: unit number %d invalid (max 15)",
- unit);
- return 0;
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "local clock: unit number %d in use", unit);
- return 0;
- }
+ pp = peer->procptr;
/*
- * Looks like this might succeed. Find memory for the structure.
- * Look to see if there are any unused ones, if not we malloc()
- * one.
+ * Initialize miscellaneous variables
*/
- if (lclunits[unit] != 0) {
- lcl = lclunits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < NUMUNITS; i++) {
- if (!unitinuse[i] && lclunits[i] != 0)
- break;
- }
- if (i < NUMUNITS) {
- /*
- * Reclaim this one
- */
- lcl = lclunits[i];
- lclunits[i] = 0;
- } else {
- lcl = (struct lclunit *)emalloc(sizeof(struct lclunit));
- }
- }
- memset((char *)lcl, 0, sizeof(struct lclunit));
- lclunits[unit] = lcl;
-
- /*
- * Set up the structure
- */
- lcl->peer = peer;
- lcl->unit = (u_char)unit;
- lcl->timestarted = lcl->lastupdate = current_time;
-
- /*
- * That was easy. Diddle the peer variables and return success.
- */
- peer->precision = LCLPRECISION;
- peer->rootdelay = 0;
- peer->rootdispersion = LCLROOTDISPERSION;
- peer->stratum = (u_char)unit;
- if (unit <= 1)
- memmove((char *)&peer->refid, LCLREFID, 4);
- else
- peer->refid = htonl(LCLHSREFID);
- unitinuse[unit] = 1;
- return 1;
-}
-
-
-/*
- * local_shutdown - shut down a local clock
- */
-static void
-local_shutdown(unit)
- int unit;
-{
- if (unit >= NUMUNITS) {
- syslog(LOG_ERR,
- "local clock: INTERNAL ERROR, unit number %d invalid (max 15)",
- unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR,
- "local clock: INTERNAL ERROR, unit number %d not in use", unit);
- return;
- }
-
- unitinuse[unit] = 0;
+ peer->precision = sys_precision;
+ pp->clockdesc = DESCRIPTION;
+ peer->stratum = STRATUM;
+ memcpy((char *)&pp->refid, REFID, 4);
+ return (1);
}
@@ -205,103 +145,26 @@ local_poll(unit, peer)
int unit;
struct peer *peer;
{
- l_fp off;
- l_fp ts;
+ struct refclockproc *pp;
- if (unit >= NUMUNITS) {
- syslog(LOG_ERR, "local clock poll: INTERNAL: unit %d invalid",
- unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "local clock poll: INTERNAL: unit %d unused",
- unit);
- return;
- }
- if (peer != lclunits[unit]->peer) {
- syslog(LOG_ERR,
- "local clock poll: INTERNAL: peer incorrect for unit %d",
- unit);
- return;
- }
+ pp = peer->procptr;
+ pp->polls++;
+ pp->lasttime = current_time;
/*
- * Update clock stat counters
+ * Ramble through the usual filtering and grooming code, which
+ * is essentially a no-op and included mostly for pretty
+ * billboards. We fudge flags as the leap indicators and allow a
+ * one-time adjustment in time using fudge time1 (s) and
+ * frequency using fudge time 2 (ppm).
*/
- lclunits[unit]->polls++;
- lclunits[unit]->lastupdate = current_time;
-
- /*
- * This is pretty easy. Give the reference clock support
- * a zero offset and our fixed dispersion. Use peer->xmt for
- * our receive time. Use peer->xmt - 20 seconds for our
- * reference time.
- */
- off.l_ui = off.l_uf = 0;
- ts = peer->xmt;
- ts.l_ui -= LCLREFOFFSET;
- refclock_receive(peer, &off, 0, LCLDISPERSION,
- &ts, &peer->xmt, 0);
+ pp->dispersion = DISPERSION;
+ gettstamp(&pp->lastrec);
+ refclock_receive(peer, &pp->fudgetime1, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->sloppyclockflag);
+ adj_frequency(LFPTOFP(&pp->fudgetime2));
+ L_CLR(&pp->fudgetime1);
+ L_CLR(&pp->fudgetime2);
}
-
-
-/*
- * local_control - set fudge factors, return statistics
- */
-static void
-local_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- extern s_fp drift_comp;
-
- if (unit >= NUMUNITS) {
- syslog(LOG_ERR, "local clock: unit %d invalid (max %d)",
- unit, NUMUNITS-1);
- return;
- }
-
- /*
- * The time1 fudge factor is the drift compensation register.
- * The time2 fudge factor is the offset of the system clock from
- * what the protocol has set it to be. Most useful when SLEWALWAYS
- * is defined.
- */
- if (in != 0) {
- if (in->haveflags & CLK_HAVETIME1)
- drift_comp = LFPTOFP(&in->fudgetime1);
- if (in->haveflags & CLK_HAVETIME2) {
- sys_clock_offset.l_ui = in->fudgetime2.l_ui;
- sys_clock_offset.l_uf = in->fudgetime2.l_uf;
- }
- }
- if (out != 0) {
- out->type = REFCLK_LOCALCLOCK;
- out->flags = 0;
- out->haveflags = CLK_HAVETIME1;
- out->clockdesc = LCLDESCRIPTION;
- FPTOLFP(drift_comp, &out->fudgetime1);
- out->fudgetime2.l_ui = sys_clock_offset.l_ui;
- out->fudgetime2.l_uf = sys_clock_offset.l_uf;
- out->fudgeval1 = out->fudgeval2 = 0;
- out->lencode = 0;
- out->lastcode = "";
- out->badformat = 0;
- out->baddata = 0;
- out->noresponse = 0;
- if (unitinuse[unit]) {
- out->polls = lclunits[unit]->polls;
- out->timereset =
- current_time - lclunits[unit]->timestarted;
- out->lastevent = lclunits[unit]->lastevent;
- out->currentstatus = lclunits[unit]->status;
- } else {
- out->polls = 0;
- out->timereset = 0;
- out->currentstatus = out->lastevent = CEVNT_NOMINAL;
- }
- }
-}
#endif /* REFCLOCK */
diff --git a/usr.sbin/xntpd/xntpd/refclock_moto.c b/usr.sbin/xntpd/xntpd/refclock_moto.c
new file mode 100644
index 000000000000..2e888bc40913
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_moto.c
@@ -0,0 +1,2 @@
+#if defined(REFCLOCK) && defined(NMEA)
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_msfees.c b/usr.sbin/xntpd/xntpd/refclock_msfees.c
index c2a882abb919..17e42351d472 100644
--- a/usr.sbin/xntpd/xntpd/refclock_msfees.c
+++ b/usr.sbin/xntpd/xntpd/refclock_msfees.c
@@ -87,7 +87,7 @@
* or 9.5uS/S then 3990.5uS at a 7min re-sync,
* at which point it may loose the "00" second time stamp.
* I assume that the most accurate time is just AFTER the re-sync.
- * Hence remember the last cycle interval,
+ * Hence remember the last cycle interval,
*
* Can run in any one of:
*
@@ -308,6 +308,8 @@ static l_fp onesec; /* = { 1, 0 }; */
/* Imported from the timer module */
extern u_long current_time;
+extern s_char sys_precision;
+
#ifdef DEBUG
static int debug;
#endif
@@ -328,33 +330,6 @@ static int debug;
#define USECS 1000000
#define MINSTEP 5 /* some systems increment uS on each call */
#define MAXLOOPS (USECS/9)
-static int ees_get_precision()
-{
- struct timeval tp;
- struct timezone tzp;
- long last;
- int i;
- long diff;
- long val;
- gettimeofday(&tp, &tzp);
-
- last = tp.tv_usec;
- for (i=0; i< 100000; i++) {
- gettimeofday(&tp, &tzp);
- diff = tp.tv_usec - last;
- if (diff < 0) diff += USECS;
- if (diff > MINSTEP) break;
- last = tp.tv_usec;
- }
- syslog(LOG_INFO,
- "I: ees: precision calculation given %duS after %d loop%s",
- diff, i, (i==1) ? "" : "s");
-
- if (i == 0) return -20 /* assume 1uS */;
- if (i >= MAXLOOPS) return EESPRECISION /* Lies ! */;
- for (i=0, val=USECS; val > 0; i--, val /= 2) if (diff > val) return i;
- return EESPRECISION /* Lies ! */;
-}
static void dump_buf(coffs, from, to, text)
l_fp *coffs;
@@ -407,18 +382,20 @@ static void msfees_init()
/* msfees_start - open the EES devices and initialize data for processing */
static int msfees_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
register struct eesunit *ees;
register int i;
int fd232 = -1;
char eesdev[20];
- struct termios ttyb, *ttyp;
+ struct termios ttyb, *ttyp;
static void ees_receive();
extern int io_addclock();
extern void io_closeclock();
extern char *emalloc();
+ struct refclockproc *pp;
+ pp = peer->procptr;
if (unit >= MAXUNITS) {
syslog(LOG_ERR, "ees clock: unit number %d invalid (max %d)",
@@ -462,24 +439,24 @@ static int msfees_start(unit, peer)
ttyp = &ttyb;
if (tcgetattr(fd232, ttyp) < 0) {
- syslog(LOG_ERR, "msfees_start: tcgetattr(%s): %m", eesdev);
- goto screwed;
- }
-
- ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
- ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
- ttyp->c_oflag = 0;
- ttyp->c_lflag = ICANON;
+ syslog(LOG_ERR, "msfees_start: tcgetattr(%s): %m", eesdev);
+ goto screwed;
+ }
+
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
+ ttyp->c_oflag = 0;
+ ttyp->c_lflag = ICANON;
ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
- if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
- syslog(LOG_ERR, "msfees_start: tcsetattr(%s): %m", eesdev);
- goto screwed;
- }
+ if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcsetattr(%s): %m", eesdev);
+ goto screwed;
+ }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- syslog(LOG_ERR, "msfees_start: tcflush(%s): %m", eesdev);
- goto screwed;
- }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcflush(%s): %m", eesdev);
+ goto screwed;
+ }
inherent_delay[unit].l_uf = INH_DELAY_PPS;
@@ -524,7 +501,7 @@ static int msfees_start(unit, peer)
* receiving stuff.
*/
- {
+ {
int rc1;
/* Pop any existing onews first ... */
while (ioctl(fd232, I_POP, 0 ) >= 0) ;
@@ -554,18 +531,21 @@ static int msfees_start(unit, peer)
/* All done. Initialize a few random peer variables, then
* return success. */
- peer->precision = ees_get_precision();
+ peer->precision = sys_precision;
peer->stratum = stratumtouse[unit];
peer->rootdelay = 0; /* ++++ */
peer->rootdispersion = 0; /* ++++ */
if (stratumtouse[unit] <= 1) {
- memmove((char *)&peer->refid, EESREFID, 4);
+ memcpy((char *)&pp->refid, EESREFID, 4);
if (unit > 0 && unit < 10)
- ((char *)&peer->refid)[3] = '0' + unit;
+ ((char *)&pp->refid)[3] = '0' + unit;
} else {
peer->refid = htonl(EESHSREFID);
}
unitinuse[unit] = 1;
+ pp->unitptr = (caddr_t) &eesunits[unit];
+ pp->clockdesc = EESDESCRIPTION;
+ pp->nstages = MAXSTAGE;
syslog(LOG_ERR, "ees clock: %s OK on %d", eesdev, unit);
return (1);
@@ -577,8 +557,9 @@ screwed:
/* msfees_shutdown - shut down a EES clock */
-static void msfees_shutdown(unit)
+static void msfees_shutdown(unit, peer)
int unit;
+ struct peer *peer;
{
register struct eesunit *ees;
extern void io_closeclock();
@@ -709,7 +690,7 @@ static void ees_receive(rbufp)
* continue on. */
cp = ees->lastcode;
break;
-
+
default:
syslog(LOG_ERR, "ees clock: INTERNAL ERROR: %d state %d",
ees->unit, ees->codestate);
@@ -818,7 +799,7 @@ static void ees_receive(rbufp)
ees->tz = istrue(cp[EESM_BST]) ? -1 : 0;
if (ees->day > 366 || ees->day < 1 ||
- ees->hour > 23 || ees->minute > 59 || ees->second > 59) {
+ ees->hour > 23 || ees->minute > 59 || ees->second > 59) {
ees->baddata++;
ees->reason = CODEREASON + 12;
ees_event(ees, CEVNT_BADDATE);
@@ -861,11 +842,11 @@ static void ees_receive(rbufp)
/* Number of seconds since the last step */
sincelast = this_uisec - ees->last_step;
- memset(&ppsclockev, 0, sizeof ppsclockev);
+ memset((char *) &ppsclockev, 0, sizeof ppsclockev);
rc = ioctl(ees->io.fd, CIOGETEV, (char *) &ppsclockev);
if (debug & DB_PRINT_EV) fprintf(stderr,
- "[%x] CIOGETEV u%d %d (%x %d) gave %d (%d): %08x %08x %d\n",
+ "[%x] CIOGETEV u%d %d (%lx %d) gave %d (%d): %08lx %08lx %ld\n",
DB_PRINT_EV, ees->unit, ees->io.fd, CIOGETEV, is_pps(ees),
rc, errno, ptr[0], ptr[1], ptr[2]);
@@ -881,7 +862,7 @@ static void ees_receive(rbufp)
/* allow for single loss of PPS only */
if (pps_step != 1 && pps_step != 2)
- fprintf(stderr, "PPS step: %d too far off %d (%d)\n",
+ fprintf(stderr, "PPS step: %d too far off %ld (%d)\n",
ppsclockev.serial, ees->last_pps_no, pps_step);
else if (!buftvtots((char *) &(ppsclockev.tv), &pps_arrvstamp))
fprintf(stderr, "buftvtots failed\n");
@@ -892,7 +873,7 @@ static void ees_receive(rbufp)
diff = pps_arrvstamp;
conv = 0;
L_SUB(&diff, &ees->arrvtime);
-if (debug & DB_PRINT_CDT) printf("[%x] Have %x.%08x and %x.%08x -> %x.%08x @ %s",
+if (debug & DB_PRINT_CDT) printf("[%x] Have %lx.%08lx and %lx.%08lx -> %lx.%08lx @ %s",
DB_PRINT_CDT, ees->arrvtime.l_ui, ees->arrvtime.l_uf,
pps_arrvstamp.l_ui, pps_arrvstamp.l_uf,
diff.l_ui, diff.l_uf,
@@ -929,7 +910,7 @@ syslog(LOG_ERR, "Have sec==1 slip %ds a=%08x-p=%08x -> %x.%08x (u=%d) %s",
}
ees->last_pps_no = ppsclockev.serial;
if (debug & DB_PRINT_CDTC) printf(
- "[%x] %08x %08x %d u%d (%d %d)\n",
+ "[%x] %08lx %08lx %d u%d (%d %d)\n",
DB_PRINT_CDTC, pps_arrvstamp.l_ui,
pps_arrvstamp.l_uf, conv, ees->unit,
call_pps_sample, pps_step);
@@ -951,7 +932,7 @@ syslog(LOG_ERR, "Have sec==1 slip %ds a=%08x-p=%08x -> %x.%08x (u=%d) %s",
/* Dump the deltas each minute */
if (debug & DB_DUMP_DELTAS)
- { if (0 <= ees->second &&
+ { if (/*0 <= ees->second && */
ees->second < ((sizeof deltas) / (sizeof deltas[0]))) deltas[ees->second] = delta_sfsec;
/* Dump on second 1, as second 0 sometimes missed */
if (ees->second == 1) {
@@ -964,8 +945,8 @@ syslog(LOG_ERR, "Have sec==1 slip %ds a=%08x-p=%08x -> %x.%08x (u=%d) %s",
while (*ptr) ptr++;
}
syslog(LOG_ERR, "Deltas: %d.%04d<->%d.%04d: %s",
- msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE),
- msec(EES_STEP_F + EES_STEP_F_GRACE), subms(EES_STEP_F + EES_STEP_F_GRACE),
+ msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE),
+ msec(EES_STEP_F + EES_STEP_F_GRACE), subms(EES_STEP_F + EES_STEP_F_GRACE),
text+1);
for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) deltas[i] = 0;
}
@@ -1056,7 +1037,7 @@ printf("MSF%d: steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
sum = 4 * 60;
}
ees->last_step = this_uisec;
-printf("MSF%d: d=%3d.%04d@%d :%d:%d:$%d:%d:%d\n",
+printf("MSF%d: d=%3ld.%04ld@%d :%d:%d:$%d:%d:%d\n",
ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs);
syslog(LOG_ERR, "MSF%d: d=%3d.%04d@%d :%d:%d:%d:%d:%d",
ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs);
@@ -1065,7 +1046,7 @@ ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ee
/* OK, so not a 4ms step at a minute boundry */
else {
if (suspect_4ms_step) syslog(LOG_ERR,
- "MSF%d: suspect = %x, but delta of %d.%04d [%d.%04d<%d.%04d<%d.%04d: %d %d]",
+ "MSF%d: suspect = %x, but delta of %d.%04d [%d.%04d<%d.%04d<%d.%04d: %d %d]",
ees->unit, suspect_4ms_step, msec(delta_sfsec), subms(delta_sfsec),
msec(EES_STEP_F - EES_STEP_F_GRACE),
subms(EES_STEP_F - EES_STEP_F_GRACE),
@@ -1079,7 +1060,7 @@ ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ee
static ees_step_notes = EES_STEP_NOTES;
if (ees_step_notes > 0) {
ees_step_notes--;
-printf("MSF%d: D=%3d.%04d@%02d :%d%s\n",
+printf("MSF%d: D=%3ld.%04ld@%02d :%d%s\n",
ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, sincelast, ees_step_notes ? "" : " -- NO MORE !");
syslog(LOG_ERR, "MSF%d: D=%3d.%04d@%02d :%d%s",
ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, (ees->last_step) ? sincelast : -1, ees_step_notes ? "" : " -- NO MORE !");
@@ -1114,7 +1095,7 @@ ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, (ees->last_step)
ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
if (debug & DB_PRINT_DELTAS) printf(
- "MSF%d: %3d/%03d -> d=%11d (%d|%d)\n",
+ "MSF%d: %3ld/%03d -> d=%11ld (%ld|%ld)\n",
ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
@@ -1150,7 +1131,7 @@ ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, (ees->last_step)
L_SUB(&ees->arrvtime, &offset_fudge[ees->unit]);
L_SUB(&pps_arrvstamp, &offset_fudge[ees->unit]);
- if (call_pps_sample && !(debug & DB_NO_PPS)) {
+ if (call_pps_sample && !(debug & DB_NO_PPS)) {
/* Sigh -- it expects its args negated */
L_NEG(&pps_arrvstamp);
(void) pps_sample(&pps_arrvstamp);
@@ -1202,7 +1183,7 @@ static void ees_process(ees)
u_fp dispersion; /* ++++ */
int lostsync, isinsync;
int samples = ees->nsamples;
- int samplelog;
+ int samplelog = 0; /* keep "gcc -Wall" happy ! */
int samplereduce = (samples + 1) / 2;
/* Reset things to zero so we don't have to worry later */
@@ -1238,7 +1219,7 @@ static void ees_process(ees)
* from the median. We work this out by doubling
* the median, subtracting off the end samples, and
* looking at the sign of the answer, using the
- * identity (c-b)-(b-a) == 2*b-a-c
+ * identity (c-b)-(b-a) == 2*b-a-c
*/
tmp = coffs[(noff + i)/2];
L_ADD(&tmp, &tmp);
@@ -1262,7 +1243,7 @@ static void ees_process(ees)
L_RSHIFTU(&offset);
}
else offset = coffs[i+BESTSAMPLE];
-
+
/* Compute the dispersion as the difference between the
* lowest and highest offsets that remain in the
* consideration list.
@@ -1416,7 +1397,7 @@ static void msfees_leap()
/* msfees_control - set fudge factors, return statistics */
static void msfees_control(unit, in, out)
- u_int unit;
+ int unit;
struct refclockstat *in;
struct refclockstat *out;
{
@@ -1443,19 +1424,20 @@ static void msfees_control(unit, in, out)
* will wait for the next timecode
*/
struct peer *peer = ees->peer;
+ struct refclockproc *pp = peer->procptr;
peer->stratum = stratumtouse[unit];
if (stratumtouse[unit] <= 1) {
- memmove((char *)&peer->refid,
+ memmove((char *)&pp->refid,
EESREFID, 4);
if (unit>0 && unit<10)
- ((char *)&peer->refid)[3] =
+ ((char *)&pp->refid)[3] =
'0' + unit;
}
else peer->refid = htonl(EESHSREFID);
}
}
if (in->haveflags & CLK_HAVEVAL2) {
- printf("Debug: %x -> %x\n", debug, in->fudgeval2);
+ printf("Debug: %x -> %lx\n", debug, in->fudgeval2);
syslog(LOG_ERR, "MSF%d: debug %x -> %x",
unit, debug, in->fudgeval2);
debug = in->fudgeval2;
@@ -1478,14 +1460,17 @@ static void msfees_control(unit, in, out)
}
if (out != 0) {
+ struct peer *peer = ees->peer;
+ struct refclockproc *pp = peer->procptr;
out->type = REFCLK_MSF_EES;
out->haveflags
= CLK_HAVETIME1|CLK_HAVETIME2|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1|CLK_HAVEFLAG3|CLK_HAVEFLAG4;
- out->clockdesc = EESDESCRIPTION;
+ out->clockdesc = pp->clockdesc;
out->fudgetime1 = fudgefactor[unit];
out->fudgetime2 = os_delay[unit];
out->fudgeval1 = (long)stratumtouse[unit];
- out->fudgeval2 = debug;
+ /*out->fudgeval2= debug*/;
+ memmove((char *)&out->fudgeval2, (char *)&pp->refid, 4);
out->flags = sloppyclockflag[unit];
if (unitinuse[unit]) {
out->flags |= ees->dump_vals | ees->usealldata;
diff --git a/usr.sbin/xntpd/xntpd/refclock_mx4200.c b/usr.sbin/xntpd/xntpd/refclock_mx4200.c
index 3c0d097a8d9e..2cfee5293c3e 100644
--- a/usr.sbin/xntpd/xntpd/refclock_mx4200.c
+++ b/usr.sbin/xntpd/xntpd/refclock_mx4200.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*/
-#if defined(REFCLOCK) && (defined(MX4200) || defined(MX4200CLK) || defined(MX4200PPS))
+#if defined(REFCLOCK) && defined(PPS) && (defined(MX4200) || defined(MX4200CLK) || defined(MX4200PPS))
#if !defined(lint) && !defined(__GNUC__)
static char rcsid[] =
@@ -102,7 +102,6 @@ static char rcsid[] =
#define MX4200PRECISION (-18) /* precision assumed (about 4 us) */
#define MX4200REFID "GPS" /* reference id */
#define MX4200DESCRIPTION "Magnavox MX4200 GPS Receiver" /* who we are */
-#define MX4200HSREFID 0x7f7f0a0a /* 127.127.10.10 refid for hi strata */
#define DEFFUDGETIME 0 /* default fudge time (ms) */
/* Leap stuff */
@@ -216,6 +215,7 @@ static u_char unitinuse[MAXUNITS];
static l_fp fudgefactor[MAXUNITS];
static u_char stratumtouse[MAXUNITS];
static u_char sloppyclockflag[MAXUNITS];
+static U_LONG refid[MAXUNITS];
static const char pmvxg[] = "PMVXG";
@@ -223,13 +223,13 @@ static const char pmvxg[] = "PMVXG";
* Function prototypes
*/
static void mx4200_init P((void));
-static int mx4200_start P((u_int, struct peer *));
-static void mx4200_shutdown P((int));
+static int mx4200_start P((int, struct peer *));
+static void mx4200_shutdown P((int, struct peer *));
static void mx4200_receive P((struct recvbuf *));
static void mx4200_process P((struct mx4200unit *));
static void mx4200_report_event P((struct mx4200unit *, int));
static void mx4200_poll P((int, struct peer *));
-static void mx4200_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void mx4200_control P((int, struct refclockstat *, struct refclockstat *));
static void mx4200_buginfo P((int, struct refclockbug *));
static char * mx4200_parse P((char *, struct calendar *, int *, int *));
@@ -273,6 +273,7 @@ mx4200_init()
fudgefactor[i].l_uf = DEFFUDGETIME;
stratumtouse[i] = 0;
sloppyclockflag[i] = 0;
+ memcpy((char *)&refid[i], MX4200REFID, 4);
}
}
@@ -316,7 +317,7 @@ checkdfile()
*/
static int
mx4200_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
register struct mx4200unit *mx4200;
@@ -511,10 +512,7 @@ mx4200_start(unit, peer)
peer->rootdelay = 0;
peer->rootdispersion = 0;
peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, MX4200REFID, 4);
- else
- peer->refid = htonl(MX4200HSREFID);
+ peer->refid = refid[unit];
unitinuse[unit] = 1;
/* Insure the receiver is properly configured */
@@ -537,8 +535,9 @@ screwed:
* mx4200_shutdown - shut down a MX4200 clock
*/
static void
-mx4200_shutdown(unit)
+mx4200_shutdown(unit, peer)
int unit;
+ struct peer *peer;
{
register struct mx4200unit *mx4200;
@@ -830,7 +829,7 @@ mx4200_receive(rbufp)
fprintf(df, "%s\t%s",
umfptoa(tmp_ui, tmp_uf, 6), mfptoa(t.l_ui, t.l_uf, 6));
if (debug > 3)
- fprintf(df, "\t(gps: %lu)", gpstime);
+ fprintf(df, "\t(gps: %lu)", (u_long)gpstime);
if (leapsec != 0)
fprintf(df, "\t(leap sec %+d)", leapsec);
if (!valid)
@@ -1024,7 +1023,7 @@ mx4200_process(mx4200)
*/
static void
mx4200_control(unit, in, out)
- u_int unit;
+ int unit;
struct refclockstat *in;
struct refclockstat *out;
{
@@ -1038,40 +1037,30 @@ mx4200_control(unit, in, out)
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
- */
- mx4200 = mx4200units[unit];
- peer = mx4200->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid,
- MX4200REFID, 4);
- else
- peer->refid = htonl(MX4200HSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
sloppyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = mx4200units[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
}
}
if (out != 0) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
out->type = REFCLK_GPS_MX4200;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 | CLK_HAVEVAL2 |
+ CLK_HAVEFLAG1;
out->clockdesc = MX4200DESCRIPTION;
out->fudgetime1 = fudgefactor[unit];
- out->fudgetime2.l_ui = 0;
- out->fudgetime2.l_uf = 0;
out->fudgeval1 = (LONG)stratumtouse[unit];
- out->fudgeval2 = 0;
+ out->fudgeval2 = refid[unit];;
out->flags = sloppyclockflag[unit];
if (unitinuse[unit]) {
mx4200 = mx4200units[unit];
@@ -1085,13 +1074,6 @@ mx4200_control(unit, in, out)
out->badformat = mx4200->badformat;
out->baddata = mx4200->baddata;
out->timereset = current_time - mx4200->timestarted;
- } 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;
}
}
}
diff --git a/usr.sbin/xntpd/xntpd/refclock_new/refclock_datum.c b/usr.sbin/xntpd/xntpd/refclock_new/refclock_datum.c
new file mode 100644
index 000000000000..2ce53a7d2c43
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_new/refclock_datum.c
@@ -0,0 +1,593 @@
+/*
+ * refclock_datum.c - clock driver for the Datum/Bancomm
+ * bc635VME Time and Frequency Processor.
+ * R. Schmidt, Time Service, US Naval Obs. May 94
+ * modelled after the TPRO NTP driver.
+ *
+ * This requires the Datum HP-UX V9.01 kernel driver and the HP-UX vme2
+ * driver subsystem. It has been tested on an HP9000/747i at HP-UX 9.03.
+ * There are no restrictions on release and use of the following code.
+ * The refclock type has been defined as 16.
+ */
+#if defined(REFCLOCK) && defined(DATUM)
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "/etc/conf/machine/vme2.h"
+#include "/etc/conf/h/io.h"
+#include "ntp_datum.h"
+#include "ntp_stdlib.h"
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 1 /* max number of VME units */
+#define BMAX 50 /* timecode buffer length */
+
+/*
+ * VME interface parameters. The "IRIG" can be changed to "GPS" for the
+ * VME-GPS.
+ */
+#define VMEPRECISION (-21) /* precision assumed (1 us) */
+#define VMEREFID "IRIG" /* reference id */
+#define VMEDESCRIPTION "Datum/ VME IRIG-B Reader" /* who we are */
+#define VMEHSREFID 0x7f7f1000 /* 127.127.16.00 refid hi strata */
+#define GMT 0 /* hour offset from Greenwich */
+
+/*
+ * Imported from ntp_timer module
+ */
+extern u_long current_time; /* current time (s) */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * VME unit control structure.
+ */
+struct vmeunit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ struct vmedate vmedata; /* data returned from vme read */
+ l_fp lastrec; /* last local time */
+ l_fp lastref; /* last timecode time */
+ char lastcode[BMAX]; /* last timecode received */
+ u_short lencode; /* length of last timecode */
+ u_long lasttime; /* last time clock heard from */
+ u_short unit; /* unit number for this guy */
+ u_short status; /* clock status */
+ u_short lastevent; /* last clock event */
+ u_short year; /* year of eternity */
+ u_short day; /* day of year */
+ u_short hour; /* hour of day */
+ u_short minute; /* minute of hour */
+ u_short second; /* seconds of minute */
+ u_long usec; /* microsecond of second */
+ u_long yearstart; /* start of current year */
+ u_short leap; /* leap indicators */
+ /*
+ * 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 vmeunit *vmeunits[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 vme_init P(());
+static int vme_start P((u_int, struct peer *));
+static void vme_shutdown P((int));
+static void vme_report_event P((struct vmeunit *, int));
+static void vme_receive P((struct recvbuf *));
+static void vme_poll P((int unit, struct peer *));
+static void vme_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void vme_buginfo P((int, struct refclockbug *));
+struct vmedate *get_datumtime();
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_vme = {
+ vme_start, vme_shutdown, vme_poll,
+ vme_control, vme_init, vme_buginfo, NOFLAGS
+};
+
+int fd_vme; /* file descriptor for ioctls */
+int regvalue;
+
+/*
+ * vme_init - initialize internal vme driver data
+ */
+static void
+vme_init()
+{
+ register int i;
+ /*
+ * Just zero the data arrays
+ */
+ /*
+ bzero((char *)vmeunits, sizeof vmeunits);
+ bzero((char *)unitinuse, 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;
+ }
+}
+
+/*
+ * vme_start - open the VME device and initialize data for processing
+ */
+static int
+vme_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct vmeunit *vme;
+ register int i;
+ int dummy;
+ char vmedev[20];
+
+ /*
+ * Check configuration info.
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "vme_start: unit %d invalid", unit);
+ return (0);
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "vme_start: unit %d in use", unit);
+ return (0);
+ }
+
+ /*
+ * Open VME device
+ */
+
+ if ( (fd_vme = open(VMEFD, O_RDWR)) < 0) {
+ syslog(LOG_ERR, "vme_start: failed open of %s: %m", vmedev);
+ return (0);
+ }
+ else { /* Release capture lockout in case it was set from before. */
+ if( ioctl( fd_vme, RUNLOCK, &dummy ) )
+ syslog(LOG_ERR, "vme_start: RUNLOCK failed %m");
+
+ regvalue = 0; /* More esoteric stuff to do... */
+ if( ioctl( fd_vme, WCR0, &regvalue ) )
+ syslog(LOG_ERR, "vme_start: WCR0 failed %m");
+ }
+
+ /*
+ * Allocate unit structure
+ */
+ if (vmeunits[unit] != 0) {
+ vme = vmeunits[unit]; /* The one we want is okay */
+ } else {
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && vmeunits[i] != 0)
+ break;
+ }
+ if (i < MAXUNITS) {
+ /*
+ * Reclaim this one
+ */
+ vme = vmeunits[i];
+ vmeunits[i] = 0;
+ } else {
+ vme = (struct vmeunit *)
+ emalloc(sizeof(struct vmeunit));
+ }
+ }
+ bzero((char *)vme, sizeof(struct vmeunit));
+ vmeunits[unit] = vme;
+
+ /*
+ * Set up the structures
+ */
+ vme->peer = peer;
+ vme->unit = (u_short)unit;
+ vme->timestarted = current_time;
+
+ vme->io.clock_recv = vme_receive;
+ vme->io.srcclock = (caddr_t)vme;
+ vme->io.datalen = 0;
+ vme->io.fd = fd_vme;
+
+ /*
+ * 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 = VMEPRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ if (stratumtouse[unit] <= 1)
+ bcopy(VMEREFID, (char *)&peer->refid, 4);
+ else
+ peer->refid = htonl(VMEHSREFID);
+ unitinuse[unit] = 1;
+ return (1);
+}
+
+
+/*
+ * vme_shutdown - shut down a VME clock
+ */
+static void
+vme_shutdown(unit)
+ int unit;
+{
+ register struct vmeunit *vme;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "vme_shutdown: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "vme_shutdown: unit %d not in use", unit);
+ return;
+ }
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ vme = vmeunits[unit];
+ io_closeclock(&vme->io);
+ unitinuse[unit] = 0;
+}
+
+/*
+ * vme_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
+vme_report_event(vme, code)
+ struct vmeunit *vme;
+ int code;
+{
+ struct peer *peer;
+
+ peer = vme->peer;
+ if (vme->status != (u_short)code) {
+ vme->status = (u_short)code;
+ if (code != CEVNT_NOMINAL)
+ vme->lastevent = (u_short)code;
+ syslog(LOG_INFO,
+ "clock %s event %x", ntoa(&peer->srcadr), code);
+ }
+}
+
+
+/*
+ * vme_receive - receive data from the VME device.
+ *
+ * Note: This interface would be interrupt-driven. We don't use that
+ * now, but include a dummy routine for possible future adventures.
+ */
+static void
+vme_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+}
+
+/*
+ * vme_poll - called by the transmit procedure
+ */
+static void
+vme_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct vmedate *tptr;
+ struct vmeunit *vme;
+ l_fp tstmp;
+ time_t tloc;
+ struct tm *tadr;
+
+
+ vme = (struct vmeunit *)emalloc(sizeof(struct vmeunit *));
+ tptr = (struct vmedate *)emalloc(sizeof(struct vmedate *));
+
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "vme_poll: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "vme_poll: unit %d not in use", unit);
+ return;
+ }
+ vme = vmeunits[unit]; /* Here is the structure */
+ vme->polls++;
+
+ tptr = &vme->vmedata;
+ if ((tptr = get_datumtime()) == NULL ) {
+ vme_report_event(vme, CEVNT_BADREPLY);
+ return;
+ }
+
+ gettstamp(&vme->lastrec);
+ vme->lasttime = current_time;
+
+ /*
+ * Get VME time and convert to timestamp format.
+ * The year must come from the system clock.
+ */
+
+ time(&tloc);
+ tadr = gmtime(&tloc);
+ tptr->year = (unsigned short)(tadr->tm_year + 1900);
+
+ sprintf(vme->lastcode,
+ "%3.3d %2.2d:%2.2d:%2.2d.%.6d %1d\0",
+ tptr->doy, tptr->hr, tptr->mn,
+ tptr->sec, tptr->frac, tptr->status);
+
+ record_clock_stats(&(vme->peer->srcadr), vme->lastcode);
+ vme->lencode = (u_short) strlen(vme->lastcode);
+
+ vme->day = tptr->doy;
+ vme->hour = tptr->hr;
+ vme->minute = tptr->mn;
+ vme->second = tptr->sec;
+ vme->usec = tptr->frac;
+
+#ifdef DEBUG
+ if (debug)
+ printf("vme: %3d %02d:%02d:%02d.%06ld %1x\n",
+ vme->day, vme->hour, vme->minute, vme->second,
+ vme->usec, tptr->status);
+#endif
+ if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */
+ vme_report_event(vme, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Now, compute the reference time value. Use the heavy
+ * machinery for the seconds and the millisecond field for the
+ * fraction when present. If an error in conversion to internal
+ * format is found, the program declares bad data and exits.
+ * Note that this code does not yet know how to do the years and
+ * relies on the clock-calendar chip for sanity.
+ */
+ if (!clocktime(vme->day, vme->hour, vme->minute,
+ vme->second, GMT, vme->lastrec.l_ui,
+ &vme->yearstart, &vme->lastref.l_ui)) {
+ vme->baddata++;
+ vme_report_event(vme, CEVNT_BADTIME);
+ syslog(LOG_ERR, "refclock_datum: bad data!!");
+ return;
+ }
+ TVUTOTSF(vme->usec, vme->lastref.l_uf);
+ tstmp = vme->lastref;
+
+ L_SUB(&tstmp, &vme->lastrec);
+ vme->coderecv++;
+
+ L_ADD(&tstmp, &(fudgefactor[vme->unit]));
+
+ refclock_receive(vme->peer, &tstmp, GMT, 0,
+ &vme->lastrec, &vme->lastrec, vme->leap);
+}
+
+/*
+ * vme_control - set fudge factors, return statistics
+ */
+static void
+vme_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct vmeunit *vme;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "vme_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
+ */
+ vme = vmeunits[unit];
+ peer = vme->peer;
+ peer->stratum = stratumtouse[unit];
+ if (stratumtouse[unit] <= 1)
+ bcopy(VMEREFID, (char *)&peer->refid,
+ 4);
+ else
+ peer->refid = htonl(VMEHSREFID);
+ }
+ }
+ if (in->haveflags & CLK_HAVEFLAG1) {
+ sloppyclockflag[unit] = in->flags & CLK_FLAG1;
+ }
+ }
+
+ if (out != 0) {
+/* out->type = REFCLK_IRIG_VME; */
+ out->type = 16; /* made up by RES */
+ out->haveflags
+ = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1;
+ out->clockdesc = VMEDESCRIPTION;
+ 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]) {
+ vme = vmeunits[unit];
+ out->lencode = vme->lencode;
+ out->lastcode = vme->lastcode;
+ out->timereset = current_time - vme->timestarted;
+ out->polls = vme->polls;
+ out->noresponse = vme->noreply;
+ out->badformat = vme->badformat;
+ out->baddata = vme->baddata;
+ out->lastevent = vme->lastevent;
+ out->currentstatus = vme->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;
+ }
+ }
+}
+
+/*
+ * vme_buginfo - return clock dependent debugging info
+ */
+static void
+vme_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct vmeunit *vme;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "vme_buginfo: unit %d invalid)", unit);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ vme = vmeunits[unit];
+
+ bug->nvalues = 11;
+ bug->ntimes = 5;
+ if (vme->lasttime != 0)
+ bug->values[0] = current_time - vme->lasttime;
+ else
+ bug->values[0] = 0;
+ bug->values[2] = (u_long)vme->year;
+ bug->values[3] = (u_long)vme->day;
+ bug->values[4] = (u_long)vme->hour;
+ bug->values[5] = (u_long)vme->minute;
+ bug->values[6] = (u_long)vme->second;
+ bug->values[7] = (u_long)vme->usec;
+ bug->values[9] = vme->yearstart;
+ bug->stimes = 0x1c;
+ bug->times[0] = vme->lastref;
+ bug->times[1] = vme->lastrec;
+}
+
+struct vmedate *get_datumtime()
+{
+ unsigned short status;
+ char cbuf[7];
+ struct vmedate *time_vme;
+ struct btfp_time vts;
+ time_vme = (struct vmedate *)malloc(sizeof(struct vmedate ));
+
+ if( ioctl(fd_vme, READTIME, &vts))
+ syslog(LOG_ERR, "get_datumtime error: %m");
+
+/* sprintf converts BCD to ASCII */
+/* Get doy */
+ sprintf(cbuf,"%3.3x\0", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
+ ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2]) )
+ time_vme->doy = (unsigned short)atoi(cbuf);
+ else
+ time_vme->doy = (unsigned short) 0;
+
+/* Get hour */
+ sprintf(cbuf,"%2.2x\0", vts.btfp_time[ 1 ] & 0x00ff);
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
+ time_vme->hr = (unsigned short)atoi(cbuf);
+ else
+ time_vme->hr = (unsigned short) 0;
+
+/* Get minutes */
+ sprintf(cbuf,"%2.2x\0", (vts.btfp_time[ 2 ] & 0xff00) >>8);
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
+ time_vme->mn = (unsigned short)atoi(cbuf);
+ else
+ time_vme->mn = (unsigned short) 0;
+
+/* Get seconds */
+ sprintf(cbuf,"%2.2x\0", vts.btfp_time[ 2 ] & 0x00ff);
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
+ time_vme->sec = (unsigned short)atoi(cbuf);
+ else
+ time_vme->sec = (unsigned short) 0;
+
+/* Get microseconds. Yes, we ignore the 0.1 microsecond digit so we can
+use the TVTOTSF function later on...*/
+
+ sprintf(cbuf,"%4.4x%2.2x\0", vts.btfp_time[ 3 ],
+ vts.btfp_time[ 4 ]>>8);
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2])
+ && isdigit(cbuf[3]) && isdigit(cbuf[4]) && isdigit(cbuf[5]))
+ time_vme->frac = (u_long) atoi(cbuf);
+ else
+ time_vme->frac = (u_long) 0;
+
+/* Get status bit */
+ status = (vts.btfp_time[0] & 0x0010) >>4;
+ time_vme->status = status; /* Status=0 if locked to ref. */
+ /* Status=1 if flywheeling */
+ if (status) { /* lost lock ? */
+ return ((void *)NULL);
+ }
+ else
+ return (time_vme);
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_new/refclock_gpstm.c b/usr.sbin/xntpd/xntpd/refclock_new/refclock_gpstm.c
new file mode 100644
index 000000000000..deab7f46ef6b
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_new/refclock_gpstm.c
@@ -0,0 +1,999 @@
+/*
+ * refclock_gpstm - clock driver for the Kinimetrics Truetime GPSTM/TMD rcvr
+ * Version 1.0 (from Version 2.0 of the GOES driver, as of 03Jan94)
+ */
+
+#if defined(REFCLOCK) && (defined(GPSTM) || defined(GPSTMCLK) \
+ || defined(GPSTMPPS))
+
+#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"
+
+#ifdef SYS_BSDI
+#undef HAVE_BSD_TTYS
+#include <sys/ioctl.h>
+#endif
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(GPSTMCLK)
+#include <clkdefs.h>
+#endif /* GPSTMCLK */
+#endif /* STREAM */
+
+#if defined(GPSTMPPS)
+#include <sys/ppsclock.h>
+#endif /* GPSTMPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+ * Support for Kinemetrics Truetime GPS-TM/TMD Receiver
+ *
+ * Most of this code is copied from refclock_goes.c with thanks.
+ *
+ * the time code looks like follows:
+ *
+ * ADDD:HH:MM:SSQCL
+ * A - control A
+ * Q Quality indication: indicates possible error of
+ * ? +/- 500 milliseconds # +/- 50 milliseconds
+ * * +/- 5 milliseconds . +/- 1 millisecond
+ * space less than 1 millisecond
+ * C - Carriage return
+ * L - Line feed
+ * The carriage return start bit begins on 0 seconds and extends to 1 bit time.
+ *
+ * Flag1 set to 1 will silence the clock side of xntpd, just reading the
+ * clock without trying to write to it. This is usefull if several
+ * xntpds listen to the same clock. This has not been tested yet...
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 4 /* max number of GPSTM units */
+#define GPSTM232 "/dev/gpstm%d"
+#define SPEED232 B9600 /* 9600 baud */
+
+/*
+ * Radio interface parameters
+ */
+#define MAXDISPERSE (FP_SECOND>>1) /* max error for synchronized clock (0.5 s as an u_fp) */
+#define PRECISION (-20) /* precision assumed (about 1 ms) */
+#define REFID "GPS\0" /* reference id */
+#define DESCRIPTION "Kinemetrics GPS-TM/TMD Receiver" /* who we are */
+#define GMT 0 /* hour offset from Greenwich */
+#define NCODES 3 /* stages of median filter */
+#define BMAX 99 /* timecode buffer length */
+#define CODEDIFF 0x20000000 /* 0.125 seconds as an l_fp fraction */
+#define TIMEOUT 180 /* ping the clock if it's silent this long */
+
+/*
+ * used by the state machine
+ */
+enum gpstm_event {e_Init, e_F18, e_F50, e_F51, e_TS};
+static enum {Base, Start, F18, F50, F51, F08} State[MAXUNITS];
+static void gpstm_doevent P((int, enum gpstm_event));
+static void gpstm_initstate P((int));
+
+/*
+ * Hack to avoid excercising the multiplier. I have no pride.
+ */
+#define MULBY10(x) (((x)<<3) + ((x)<<1))
+
+/*
+ * Imported from the timer module
+ */
+extern u_long current_time;
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * GPSTM unit control structure
+ */
+struct gpstm_unit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ l_fp lastrec; /* last receive time */
+ l_fp lastref; /* last timecode time */
+ l_fp offset[NCODES]; /* recent sample offsets */
+ char lastcode[BMAX]; /* last timecode received */
+ u_short polled; /* Hand in a time sample? */
+ u_char lencode; /* length of last timecode */
+ u_long lasttime; /* last time clock heard from */
+ 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_char leap; /* leap indicators */
+ u_short msec; /* millisecond of second */
+ u_char quality; /* quality character */
+ 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 gpstm_unit *gpstm_units[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 fudgefactor1[MAXUNITS];
+static l_fp fudgefactor2[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static u_char readonlyclockflag[MAXUNITS];
+static u_long refid[MAXUNITS];
+
+/*
+ * Function prototypes
+ */
+static void gpstm_init P((void));
+static int gpstm_start P((u_int, struct peer *));
+static void gpstm_shutdown P((int));
+static void gpstm_rep_event P((struct gpstm_unit *, int));
+static void gpstm_receive P((struct recvbuf *));
+static char gpstm_process P((struct gpstm_unit *, l_fp *, u_fp *));
+static void gpstm_poll P((int, struct peer *));
+static void gpstm_control P((u_int, struct refclockstat *,
+ struct refclockstat *));
+static void gpstm_buginfo P((int, struct refclockbug *));
+static void gpstm_send P((struct gpstm_unit *, char *));
+
+struct refclock refclock_gpstm = {
+ gpstm_start, gpstm_shutdown, gpstm_poll,
+ gpstm_control, gpstm_init, gpstm_buginfo, NOFLAGS
+};
+
+/*
+ * gpstm_init - initialize internal driver data
+ */
+static void
+gpstm_init()
+{
+ register int i;
+ /*
+ * Just zero the data arrays
+ */
+ memset((char *)gpstm_units, 0, sizeof gpstm_units);
+ memset((char *)unitinuse, 0, sizeof unitinuse);
+
+ /*
+ * Initialize fudge factors to default.
+ */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor1[i].l_ui = 0;
+ fudgefactor1[i].l_uf = 0;
+ fudgefactor2[i].l_ui = 0;
+ fudgefactor2[i].l_uf = 0;
+ stratumtouse[i] = 0;
+ readonlyclockflag[i] = 0;
+ memcpy((char *)&refid[i], REFID, 4);
+ }
+}
+
+
+/*
+ * gpstm_start - open the device and initialize data for processing
+ */
+static int
+gpstm_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct gpstm_unit *gpstm;
+ register int i;
+ int fd232;
+ char dev[20];
+
+ /*
+ * Check configuration info
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_start: unit %d invalid", unit);
+ return 0;
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "gpstm_start: unit %d in use", unit);
+ return 0;
+ }
+
+ /*
+ * Open serial port
+ */
+ (void) sprintf(dev, GPSTM232, unit);
+ fd232 = open(dev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR, "gpstm_start: open of %s: %m", dev);
+ 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,
+ "gpstm_start: ioctl(%s, TCGETA): %m", dev);
+ 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,
+ "gpstm_start: ioctl(%s, TCSETA): %m", dev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(HAVE_TERMIOS)
+ /*
+ * POSIX serial line parameters (termios interface)
+ *
+ * The GPSTMCLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The GPSTMPPS 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,
+ "gpstm_start: tcgetattr(%s): %m", dev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ 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,
+ "gpstm_start: tcsetattr(%s): %m", dev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: tcflush(%s): %m", dev);
+ goto screwed;
+ }
+#if defined(STREAM)
+#if defined(GPSTMCLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, I_PUSH, clk): %m", dev);
+ if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, CLK_SETSTR): %m", dev);
+#endif /* GPSTMCLK */
+#if defined(GPSTMPPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, I_PUSH, ppsclock): %m", dev);
+ else
+ fdpps = fd232;
+#endif /* GPSTMPPS */
+#endif /* STREAM */
+ }
+#endif /* HAVE_TERMIOS */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The GPSTMCLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(GPSTMCLK)
+ int ldisc = CLKLDISC;
+#endif /* GPSTMCLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, TIOCGETP): %m", dev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(GPSTMCLK)
+ 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 /* GPSTMCLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, TIOCSETP): %m", dev);
+ goto screwed;
+ }
+#if defined(GPSTMCLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, TIOCSETD): %m", dev);
+ goto screwed;
+ }
+#endif /* GPSTMCLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Allocate unit structure
+ */
+ if (gpstm_units[unit] != 0) {
+ gpstm = gpstm_units[unit]; /* The one we want is okay */
+ } else {
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && gpstm_units[i] != 0)
+ break;
+ }
+ if (i < MAXUNITS) {
+ /*
+ * Reclaim this one
+ */
+ gpstm = gpstm_units[i];
+ gpstm_units[i] = 0;
+ } else {
+ gpstm = (struct gpstm_unit *)
+ emalloc(sizeof(struct gpstm_unit));
+ }
+ }
+ memset((char *)gpstm, 0, sizeof(struct gpstm_unit));
+ gpstm_units[unit] = gpstm;
+
+ /*
+ * Set up the structures
+ */
+ gpstm->peer = peer;
+ gpstm->unit = (u_char)unit;
+ gpstm->timestarted = current_time;
+
+ gpstm->io.clock_recv = gpstm_receive;
+ gpstm->io.srcclock = (caddr_t)gpstm;
+ gpstm->io.datalen = 0;
+ gpstm->io.fd = fd232;
+ if (!io_addclock(&gpstm->io)) {
+ goto screwed;
+ }
+
+ /*
+ * All done. Initialize a few random peer variables, then
+ * return success.
+ */
+ peer->precision = PRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ unitinuse[unit] = 1;
+ gpstm_initstate(unit);
+ return 1;
+
+ /*
+ * Something broke; abandon ship
+ */
+screwed:
+ (void) close(fd232);
+ return 0;
+}
+
+/*
+ * gpstm_shutdown - shut down a clock
+ */
+static void
+gpstm_shutdown(unit)
+ int unit;
+{
+ register struct gpstm_unit *gpstm;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_shutdown: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "gpstm_shutdown: unit %d not in use", unit);
+ return;
+ }
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ gpstm = gpstm_units[unit];
+ io_closeclock(&gpstm->io);
+ unitinuse[unit] = 0;
+}
+
+
+/*
+ * gpstm_rep_event - note the occurance of an event
+ */
+static void
+gpstm_rep_event(gpstm, code)
+ struct gpstm_unit *gpstm;
+ int code;
+{
+ struct peer *peer;
+
+ peer = gpstm->peer;
+ if (gpstm->status != (u_char)code) {
+ gpstm->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ gpstm->lastevent = (u_char)code;
+ syslog(LOG_INFO,
+ "clock %s event %x\n", ntoa(&peer->srcadr), code);
+#ifdef DEBUG
+ if (debug) {
+ printf("gpstm_rep_event(gpstm%d, code %d)\n",
+ gpstm->unit, code);
+ }
+#endif
+ }
+ if (code == CEVNT_BADREPLY)
+ gpstm_initstate(gpstm->unit);
+}
+
+
+/*
+ * gpstm_receive - receive data from the serial interface on a clock
+ */
+static void
+gpstm_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register int i;
+ register struct gpstm_unit *gpstm;
+ register u_char *dpt;
+ register char *cp;
+ register u_char *dpend;
+ l_fp tstmp;
+ u_fp dispersion;
+
+ /*
+ * Get the clock this applies to and a pointers to the data
+ */
+ gpstm = (struct gpstm_unit *)rbufp->recv_srcclock;
+ dpt = (u_char *)&rbufp->recv_space;
+
+ /*
+ * Edit timecode to remove control chars
+ */
+ dpend = dpt + rbufp->recv_length;
+ cp = gpstm->lastcode;
+ while (dpt < dpend) {
+ if ((*cp = 0x7f & *dpt++) >= ' ') cp++;
+#ifdef GPSTMCLK
+ else if (*cp == '\r') {
+ if (dpend - dpt < 8) {
+ /* short timestamp */
+ return;
+ }
+ if (!buftvtots(dpt,&gpstm->lastrec)) {
+ /* screwy timestamp */
+ return;
+ }
+ dpt += 8;
+ }
+#endif
+ }
+ *cp = '\0';
+ gpstm->lencode = cp - gpstm->lastcode;
+ if (gpstm->lencode == 0)
+ return;
+#ifndef GPSTMCLK
+ gpstm->lastrec = rbufp->recv_time;
+#endif /* GPSTMCLK */
+#if !defined(GPSTMCLK) && !defined(GPSTMPPS) && defined(TIOCMODT)
+ do {
+ auto struct timeval cur, now;
+ register long usec;
+
+ if (ioctl(gpstm->io.fd, TIOCMODT, &cur) < 0) {
+ syslog(LOG_ERR, "TIOCMODT: %m");
+#ifdef DEBUG
+ if (debug) perror("TIOCMODT");
+ break;
+#endif
+ }
+ if (cur.tv_sec == 0) {
+ /* no timestamps yet */
+ if (debug) printf("MODT tv_sec == 0\n");
+ break;
+ }
+
+ gettimeofday(&now, NULL);
+ usec = 1000000 * (now.tv_sec - cur.tv_sec)
+ + (now.tv_usec - cur.tv_usec);
+#ifdef DEBUG
+ if (debug) printf("lastmodem: delay=%d us\n", usec);
+#endif
+ if (usec < 0 || usec > 10000) {
+ /* time warp or stale timestamp */
+ break;
+ }
+ if (!buftvtots((char *)&cur, &gpstm->lastrec)) {
+ /* screwy timestamp */
+ break;
+ }
+ } while (0);
+#endif /*TIOCMODT*/
+
+#ifdef DEBUG
+ if (debug)
+ printf("gpstm: timecode %d %s\n",
+ gpstm->lencode, gpstm->lastcode);
+#endif
+
+ cp = gpstm->lastcode;
+ gpstm->leap = 0;
+ if ((cp[0] == 'F' && isdigit(cp[1]) && isdigit(cp[2]))
+ || (cp[0] == ' ' && cp[1] == 'T' && cp[2] == 'R')) {
+ enum gpstm_event event;
+
+ syslog(LOG_NOTICE, "gpstm%d: \"%s\"", gpstm->unit, cp);
+ if (cp[1] == '5' && cp[2] == '0')
+ event = e_F50;
+ else if (cp[1] == '5' && cp[2] == '1')
+ event = e_F51;
+ else if (!strncmp(" TRUETIME Mk III", cp, 16))
+ event = e_F18;
+ else {
+ gpstm_rep_event(gpstm, CEVNT_BADREPLY);
+ return;
+ }
+ gpstm_doevent(gpstm->unit, event);
+ return;
+ } else if (gpstm->lencode == 13) {
+ /*
+ * Check timecode format 0
+ */
+ if (!isdigit(cp[0]) /* day of year */
+ || !isdigit(cp[1])
+ || !isdigit(cp[2])
+ || cp[3] != ':' /* : separator */
+ || !isdigit(cp[4]) /* hours */
+ || !isdigit(cp[5])
+ || cp[6] != ':' /* : separator */
+ || !isdigit(cp[7]) /* minutes */
+ || !isdigit(cp[8])
+ || cp[9] != ':' /* : separator */
+ || !isdigit(cp[10]) /* seconds */
+ || !isdigit(cp[11]))
+ {
+ gpstm->badformat++;
+ gpstm_rep_event(gpstm, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Convert format 0 and check values
+ */
+ gpstm->year = 0; /* fake */
+ gpstm->day = cp[0] - '0';
+ gpstm->day = MULBY10(gpstm->day) + cp[1] - '0';
+ gpstm->day = MULBY10(gpstm->day) + cp[2] - '0';
+ gpstm->hour = MULBY10(cp[4] - '0') + cp[5] - '0';
+ gpstm->minute = MULBY10(cp[7] - '0') + cp[8] - '0';
+ gpstm->second = MULBY10(cp[10] - '0') + cp[11] - '0';
+ gpstm->msec = 0;
+
+ if (cp[12] != ' ' && cp[12] != '.' && cp[12] != '*')
+ gpstm->leap = LEAP_NOTINSYNC;
+ else
+ gpstm->lasttime = current_time;
+
+ if (gpstm->day < 1 || gpstm->day > 366) {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADDATE);
+ return;
+ }
+ if (gpstm->hour > 23 || gpstm->minute > 59
+ || gpstm->second > 59) {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADTIME);
+ return;
+ }
+ gpstm_doevent(gpstm->unit, e_TS);
+ } else {
+ gpstm_rep_event(gpstm, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * The clock will blurt a timecode every second but we only
+ * want one when polled. If we havn't been polled, bail out.
+ */
+ if (!gpstm->polled)
+ return;
+
+ /*
+ * Now, compute the reference time value. Use the heavy
+ * machinery for the seconds and the millisecond field for the
+ * fraction when present.
+ *
+ * this code does not yet know how to do the years
+ */
+ tstmp = gpstm->lastrec;
+ if (!clocktime(gpstm->day, gpstm->hour, gpstm->minute,
+ gpstm->second, GMT, tstmp.l_ui,
+ &gpstm->yearstart, &gpstm->lastref.l_ui))
+ {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADTIME);
+ return;
+ }
+ MSUTOTSF(gpstm->msec, gpstm->lastref.l_uf);
+
+ i = ((int)(gpstm->coderecv)) % NCODES;
+ gpstm->offset[i] = gpstm->lastref;
+ L_SUB(&gpstm->offset[i], &tstmp);
+ if (gpstm->coderecv == 0)
+ for (i = 1; i < NCODES; i++)
+ gpstm->offset[i] = gpstm->offset[0];
+
+ gpstm->coderecv++;
+
+ /*
+ * Process the median filter, and pass the
+ * offset and dispersion along. We use lastrec 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 (!gpstm_process(gpstm, &tstmp, &dispersion)) {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADTIME);
+ return;
+ }
+ refclock_receive(gpstm->peer, &tstmp, GMT, dispersion,
+ &gpstm->lastrec, &gpstm->lastrec, gpstm->leap);
+
+ /*
+ * We have succedded in answering the poll. Turn off the flag
+ */
+ gpstm->polled = 0;
+}
+
+/*
+ * gpstm_send - time to send the clock a signal to cough up a time sample
+ */
+static void
+gpstm_send(gpstm, cmd)
+ struct gpstm_unit *gpstm;
+ char *cmd;
+{
+#ifdef DEBUG
+ if (debug) {
+ printf("gpstm_send(gpstm%d): %s\n", gpstm->unit, cmd);
+ }
+#endif
+ if (!readonlyclockflag[gpstm->unit]) {
+ register int len = strlen(cmd);
+
+ if (write(gpstm->io.fd, cmd, len) != len) {
+ syslog(LOG_ERR, "gpstm_send: unit %d: %m",
+ gpstm->unit);
+ gpstm_rep_event(gpstm, CEVNT_FAULT);
+ }
+ }
+}
+
+/*
+ * state machine for initializing the clock
+ */
+
+static void
+gpstm_doevent(unit, event)
+ int unit;
+ enum gpstm_event event;
+{
+ struct gpstm_unit *gpstm = gpstm_units[unit];
+
+#ifdef DEBUG
+ if (debug) {
+ printf("gpstm_doevent(gpstm%d, %d)\n", unit, (int)event);
+ }
+#endif
+ if (event == e_TS && State[unit] != F51 && State[unit] != F08) {
+ gpstm_send(gpstm, "\03\r");
+ }
+
+ switch (event) {
+ case e_Init:
+ gpstm_send(gpstm, "F18\r");
+ State[unit] = Start;
+ break;
+ case e_F18:
+ gpstm_send(gpstm, "F50\r");
+ State[unit] = F18;
+ break;
+ case e_F50:
+ gpstm_send(gpstm, "F51\r");
+ State[unit] = F50;
+ break;
+ case e_F51:
+ gpstm_send(gpstm, "F08\r");
+ State[unit] = F51;
+ break;
+ case e_TS:
+ /* nothing to send - we like this mode */
+ State[unit] = F08;
+ break;
+ }
+}
+
+static void
+gpstm_initstate(unit)
+ int unit;
+{
+ State[unit] = Base; /* just in case */
+ gpstm_doevent(unit, e_Init);
+}
+
+/*
+ * gpstm_process - process a pile of samples from the clock
+ */
+static char
+gpstm_process(gpstm, offset, dispersion)
+ struct gpstm_unit *gpstm;
+ 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. We take the maximum
+ * difference and use that as the sample dispersion. 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 = gpstm->offset[i].l_ui;
+ tmp_uf = gpstm->offset[i].l_uf;
+ M_SUB(tmp_ui, tmp_uf, gpstm->offset[j].l_ui,
+ gpstm->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;
+ }
+ }
+ }
+
+ /*
+ * It seems as if all are within 125 ms of each other.
+ * Now to determine the median of the three. Whlie the
+ * 125 ms check was going on, we also subtly catch the
+ * dispersion and set-up for a very easy median calculation.
+ * The largest difference between any two samples constitutes
+ * the dispersion. The sample not involve in the dispersion is
+ * the median sample. EASY!
+ */
+ if (gpstm->lasttime == 0 || disp_tmp2 > MAXDISPERSE)
+ disp_tmp2 = MAXDISPERSE;
+ if (not_median1 == 0) {
+ if (not_median2 == 1)
+ median = 2;
+ else
+ median = 1;
+ } else {
+ median = 0;
+ }
+ *offset = gpstm->offset[median];
+ *dispersion = disp_tmp2;
+ return 1;
+}
+
+/*
+ * gpstm_poll - called by the transmit procedure
+ */
+static void
+gpstm_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct gpstm_unit *gpstm;
+
+ /*
+ * You don't need to poll this clock. It puts out timecodes
+ * once per second. If asked for a timestamp, take note.
+ * The next time a timecode comes in, it will be fed back.
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_poll: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "gpstm_poll: unit %d not in use", unit);
+ return;
+ }
+ gpstm = gpstm_units[unit];
+ if ((current_time - gpstm->lasttime) > 150) {
+ gpstm->noreply++;
+ gpstm_rep_event(gpstm_units[unit], CEVNT_TIMEOUT);
+ gpstm_initstate(gpstm->unit);
+ }
+
+ /*
+ * polled every 64 seconds. Ask our receiver to hand in a timestamp.
+ */
+ gpstm->polled = 1;
+ gpstm->polls++;
+}
+
+/*
+ * gpstm_control - set fudge factors, return statistics
+ */
+static void
+gpstm_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct gpstm_unit *gpstm;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_control: unit %d invalid", unit);
+ return;
+ }
+
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ fudgefactor1[unit] = in->fudgetime1;
+ if (in->haveflags & CLK_HAVETIME2)
+ fudgefactor2[unit] = in->fudgetime2;
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
+ readonlyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = gpstm_units[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
+ }
+
+ if (out != 0) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
+ out->type = REFCLK_GPSTM_TRUETIME;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVETIME2 | CLK_HAVEVAL1 |
+ CLK_HAVEVAL2 | CLK_HAVEFLAG1;
+ out->clockdesc = DESCRIPTION;
+ out->fudgetime1 = fudgefactor1[unit];
+ out->fudgetime2 = fudgefactor2[unit];
+ out->fudgeval1 = stratumtouse[unit];
+ out->fudgeval2 = refid[unit];
+ out->flags = readonlyclockflag[unit];
+ if (unitinuse[unit]) {
+ gpstm = gpstm_units[unit];
+ out->lencode = gpstm->lencode;
+ out->lastcode = gpstm->lastcode;
+ out->timereset = current_time - gpstm->timestarted;
+ out->polls = gpstm->polls;
+ out->noresponse = gpstm->noreply;
+ out->badformat = gpstm->badformat;
+ out->baddata = gpstm->baddata;
+ out->lastevent = gpstm->lastevent;
+ out->currentstatus = gpstm->status;
+ }
+ }
+}
+
+/*
+ * gpstm_buginfo - return clock dependent debugging info
+ */
+static void
+gpstm_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct gpstm_unit *gpstm;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_buginfo: unit %d invalid", unit);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ gpstm = gpstm_units[unit];
+
+ bug->nvalues = 11;
+ bug->ntimes = 5;
+ if (gpstm->lasttime != 0)
+ bug->values[0] = current_time - gpstm->lasttime;
+ else
+ bug->values[0] = 0;
+ bug->values[1] = gpstm->reason;
+ bug->values[2] = gpstm->year;
+ bug->values[3] = gpstm->day;
+ bug->values[4] = gpstm->hour;
+ bug->values[5] = gpstm->minute;
+ bug->values[6] = gpstm->second;
+ bug->values[7] = gpstm->msec;
+ bug->values[8] = gpstm->noreply;
+ bug->values[9] = gpstm->yearstart;
+ bug->values[10] = gpstm->quality;
+ bug->stimes = 0x1c;
+ bug->times[0] = gpstm->lastref;
+ bug->times[1] = gpstm->lastrec;
+ bug->times[2] = gpstm->offset[0];
+ bug->times[3] = gpstm->offset[1];
+ bug->times[4] = gpstm->offset[2];
+}
+
+#endif /*GPSTM et al*/
diff --git a/usr.sbin/xntpd/xntpd/refclock_new/refclock_leitch.c b/usr.sbin/xntpd/xntpd/refclock_new/refclock_leitch.c
new file mode 100644
index 000000000000..b2a0e7fa76bf
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_new/refclock_leitch.c
@@ -0,0 +1,718 @@
+/*
+ * refclock_leitch - clock driver for the Leitch CSD-5300 Master Clock
+ */
+#if defined(REFCLOCK) && (defined(LEITCH) || defined(LEITCHCLK) || defined(LEITCHPPS))
+
+#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"
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+#ifdef STREAM
+#include <stropts.h>
+#if defined(LEITCHCLK)
+#include <sys/clkdefs.h>
+#endif /* LEITCHCLK */
+#endif /* STREAM */
+
+#if defined (LEITCHPPS)
+#include <sys/ppsclock.h>
+#endif /* LEITCHPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+ * Driver for Leitch CSD-5300 Master Clock System
+ *
+ * COMMANDS:
+ * DATE: D <CR>
+ * TIME: T <CR>
+ * STATUS: S <CR>
+ * LOOP: L <CR>
+ *
+ * FORMAT:
+ * DATE: YYMMDD<CR>
+ * TIME: <CR>/HHMMSS <CR>/HHMMSS <CR>/HHMMSS <CR>/
+ * second bondaried on the stop bit of the <CR>
+ * second boundaries at '/' above.
+ * STATUS: G (good), D (diag fail), T (time not provided) or
+ * P (last phone update failed)
+ */
+#define MAXUNITS 1 /* max number of LEITCH units */
+#define LEITCHREFID "ATOM" /* reference id */
+#define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver"
+#define LEITCH232 "/dev/leitch%d" /* name of radio device */
+#define SPEED232 B300 /* uart speed (300 baud) */
+#define leitch_send(A,M) \
+ if (debug) fprintf(stderr,"write leitch %s\n",M); \
+ if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
+ if (debug) \
+ fprintf(stderr, "leitch_send: unit %d send failed\n", A->unit); \
+ else \
+ syslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
+
+#define STATE_IDLE 0
+#define STATE_DATE 1
+#define STATE_TIME1 2
+#define STATE_TIME2 3
+#define STATE_TIME3 4
+
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * LEITCH unit control structure
+ */
+struct leitchunit {
+ struct peer *peer;
+ struct event leitchtimer;
+ struct refclockio leitchio;
+ u_char unit;
+ short year;
+ short yearday;
+ short month;
+ short day;
+ short hour;
+ short second;
+ short minute;
+ short state;
+ u_short fudge1;
+ l_fp reftime1;
+ l_fp reftime2;
+ l_fp reftime3;
+ l_fp codetime1;
+ l_fp codetime2;
+ l_fp codetime3;
+ u_long yearstart;
+};
+
+/*
+ * Function prototypes
+ */
+static void leitch_init P((void));
+static int leitch_start P((u_int, struct peer *));
+static void leitch_shutdown P((int));
+static void leitch_poll P((int, struct peer *));
+static void leitch_control P((u_int, struct refclockstat *, struct refclockstat *));
+#define leitch_buginfo noentry
+static void leitch_receive P((struct recvbuf *));
+static void leitch_process P((struct leitchunit *));
+static void leitch_timeout P((struct peer *));
+static int leitch_get_date P((struct recvbuf *, struct leitchunit *));
+static int leitch_get_time P((struct recvbuf *, struct leitchunit *, int));
+static int dysize P((int));
+
+static struct leitchunit leitchunits[MAXUNITS];
+static u_char unitinuse[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static u_long refid[MAXUNITS];
+
+static char days_in_month [] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_leitch = {
+ leitch_start, leitch_shutdown, leitch_poll,
+ leitch_control, leitch_init, leitch_buginfo, NOFLAGS
+};
+
+/*
+ * leitch_init - initialize internal leitch driver data
+ */
+static void
+leitch_init()
+{
+ int i;
+
+ memset((char*)leitchunits, 0, sizeof(leitchunits));
+ memset((char*)unitinuse, 0, sizeof(unitinuse));
+ for (i = 0; i < MAXUNITS; i++)
+ memcpy((char *)&refid[i], LEITCHREFID, 4);
+}
+
+/*
+ * leitch_shutdown - shut down a LEITCH clock
+ */
+static void
+leitch_shutdown(unit)
+int unit;
+{
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_shutdown()\n");
+#endif
+}
+
+/*
+ * leitch_poll - called by the transmit procedure
+ */
+static void
+leitch_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct leitchunit *leitch;
+
+ /* start the state machine rolling */
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_poll()\n");
+#endif
+ if (unit > MAXUNITS) {
+ /* XXXX syslog it */
+ return;
+ }
+
+ leitch = &leitchunits[unit];
+
+ if (leitch->state != STATE_IDLE) {
+ /* reset and wait for next poll */
+ /* XXXX syslog it */
+ leitch->state = STATE_IDLE;
+ } else {
+ leitch_send(leitch,"D\r");
+ leitch->state = STATE_DATE;
+ }
+}
+
+static void
+leitch_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,
+ "leitch_control: unit %d invalid", unit);
+ return;
+ }
+
+ if (in) {
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = (&leitchunits[unit])->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
+ }
+
+ if (out) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
+ out->type = REFCLK_ATOM_LEITCH;
+ out->haveflags = CLK_HAVEVAL1 | CLK_HAVEVAL2;
+ out->fudgeval1 = stratumtouse[unit];
+ out->fudgeval2 = refid[unit];
+ out->lastcode = "";
+ out->clockdesc = LEITCH_DESCRIPTION;
+ }
+}
+
+/*
+ * leitch_start - open the LEITCH devices and initialize data for processing
+ */
+static int
+leitch_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ struct leitchunit *leitch;
+ int fd232;
+ char leitchdev[20];
+
+ /*
+ * Check configuration info.
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "leitch_start: unit %d invalid", unit);
+ return (0);
+ }
+
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "leitch_start: unit %d in use", unit);
+ return (0);
+ }
+
+ /*
+ * Open serial port.
+ */
+ (void) sprintf(leitchdev, LEITCH232, unit);
+ fd232 = open(leitchdev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR,
+ "leitch_start: open of %s: %m", leitchdev);
+ return (0);
+ }
+
+ leitch = &leitchunits[unit];
+ memset((char*)leitch, 0, sizeof(*leitch));
+
+#if defined(HAVE_SYSV_TTYS)
+ /*
+ * System V serial line parameters (termio interface)
+ *
+ */
+ { struct termio ttyb;
+ if (ioctl(fd232, TCGETA, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TCGETA): %m", leitchdev);
+ 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,
+ "leitch_start: ioctl(%s, TCSETA): %m", leitchdev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(HAVE_TERMIOS)
+ /*
+ * POSIX serial line parameters (termios interface)
+ *
+ * The LEITCHCLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The LEITCHPPS 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,
+ "leitch_start: tcgetattr(%s): %m", leitchdev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ 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,
+ "leitch_start: tcsetattr(%s): %m", leitchdev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: tcflush(%s): %m", leitchdev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_TERMIOS */
+#ifdef STREAM
+#if defined(LEITCHCLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, I_PUSH, clk): %m", leitchdev);
+ if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, CLK_SETSTR): %m", leitchdev);
+#endif /* LEITCHCLK */
+#if defined(LEITCHPPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, I_PUSH, ppsclock): %m", leitchdev);
+ else
+ fdpps = fd232;
+#endif /* LEITCHPPS */
+#endif /* STREAM */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The LEITCHCLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(LEITCHCLK)
+ int ldisc = CLKLDISC;
+#endif /* LEITCHCLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TIOCGETP): %m", leitchdev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(LEITCHCLK)
+ 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 /* LEITCHCLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TIOCSETP): %m", leitchdev);
+ goto screwed;
+ }
+#if defined(LEITCHCLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TIOCSETD): %m",leitchdev);
+ goto screwed;
+ }
+#endif /* LEITCHCLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Set up the structures
+ */
+ leitch->peer = peer;
+ leitch->unit = unit;
+ leitch->state = STATE_IDLE;
+ leitch->fudge1 = 15; /* 15ms */
+
+ leitch->leitchio.clock_recv = leitch_receive;
+ leitch->leitchio.srcclock = (caddr_t) leitch;
+ leitch->leitchio.datalen = 0;
+ leitch->leitchio.fd = fd232;
+ if (!io_addclock(&leitch->leitchio)) {
+ 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 = 0;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ unitinuse[unit] = 1;
+ return(1);
+
+ /*
+ * Something broke; abandon ship.
+ */
+screwed:
+ close(fd232);
+ return(0);
+}
+
+/*
+ * leitch_receive - receive data from the serial interface on a leitch
+ * clock
+ */
+static void
+leitch_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ struct leitchunit *leitch = (struct leitchunit *)rbufp->recv_srcclock;
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_recieve(%*.*s)\n",
+ rbufp->recv_length, rbufp->recv_length,
+ rbufp->recv_buffer);
+#endif
+ if (rbufp->recv_length != 7)
+ return; /* The date is return with a trailing newline,
+ discard it. */
+
+ switch (leitch->state) {
+ case STATE_IDLE: /* unexpected, discard and resync */
+ return;
+ case STATE_DATE:
+ if (!leitch_get_date(rbufp,leitch)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+ leitch_send(leitch,"T\r");
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%u\n",leitch->yearday);
+#endif
+ leitch->state = STATE_TIME1;
+ break;
+ case STATE_TIME1:
+ if (!leitch_get_time(rbufp,leitch,1)) {
+ }
+ if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
+ leitch->second, 0, rbufp->recv_time.l_ui,
+ &leitch->yearstart, &leitch->reftime1.l_ui)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%lu\n", (u_long)leitch->reftime1.l_ui);
+#endif
+ MSUTOTSF(leitch->fudge1, leitch->reftime1.l_uf);
+ leitch->codetime1 = rbufp->recv_time;
+ leitch->state = STATE_TIME2;
+ break;
+ case STATE_TIME2:
+ if (!leitch_get_time(rbufp,leitch,2)) {
+ }
+ if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
+ leitch->second, 0, rbufp->recv_time.l_ui,
+ &leitch->yearstart, &leitch->reftime2.l_ui)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%lu\n", (u_long)leitch->reftime2.l_ui);
+#endif
+ MSUTOTSF(leitch->fudge1, leitch->reftime2.l_uf);
+ leitch->codetime2 = rbufp->recv_time;
+ leitch->state = STATE_TIME3;
+ break;
+ case STATE_TIME3:
+ if (!leitch_get_time(rbufp,leitch,3)) {
+ }
+ if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
+ leitch->second, 0, rbufp->recv_time.l_ui,
+ &leitch->yearstart, &leitch->reftime3.l_ui)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%lu\n", (u_long)leitch->reftime3.l_ui);
+#endif
+ MSUTOTSF(leitch->fudge1, leitch->reftime3.l_uf);
+ leitch->codetime3 = rbufp->recv_time;
+ leitch_process(leitch);
+ leitch->state = STATE_IDLE;
+ break;
+ default:
+ syslog(LOG_ERR,
+ "leitech_receive: invalid state %d unit %d",
+ leitch->state, leitch->unit);
+ }
+}
+
+/*
+ * leitch_process - process a pile of samples from the clock
+ *
+ * This routine uses a three-stage median filter to calculate offset and
+ * dispersion. reduce jitter. The dispersion is calculated as the span
+ * of the filter (max - min), unless the quality character (format 2) is
+ * non-blank, in which case the dispersion is calculated on the basis of
+ * the inherent tolerance of the internal radio oscillator, which is
+ * +-2e-5 according to the radio specifications.
+ */
+static void
+leitch_process(leitch)
+ struct leitchunit *leitch;
+{
+ l_fp off;
+ s_fp delay;
+ l_fp codetime;
+ l_fp tmp_fp;
+ int isinsync = 1;
+ u_fp dispersion = 10;
+
+ delay = 20;
+
+ codetime = leitch->codetime3;
+
+ off = leitch->reftime1;
+ L_SUB(&off,&leitch->codetime1);
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr,"%lu %lu %lu %lu %ld %ld\n",
+ (u_long)leitch->codetime1.l_ui,
+ (u_long)leitch->codetime1.l_uf,
+ (u_long)leitch->reftime1.l_ui,
+ (u_long)leitch->reftime1.l_uf,
+ (u_long)off.l_i,
+ (u_long)off.l_f);
+#endif
+ tmp_fp = leitch->reftime2;
+ L_SUB(&tmp_fp,&leitch->codetime2);
+ if (L_ISGEQ(&off,&tmp_fp))
+ off = tmp_fp;
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr,"%lu %lu %lu %lu %ld %ld\n",
+ (u_long)leitch->codetime2.l_ui,
+ (u_long)leitch->codetime2.l_uf,
+ (u_long)leitch->reftime2.l_ui,
+ (u_long)leitch->reftime2.l_uf,
+ (u_long)off.l_i,
+ (u_long)off.l_f);
+#endif
+ tmp_fp = leitch->reftime3;
+ L_SUB(&tmp_fp,&leitch->codetime3);
+
+ if (L_ISGEQ(&off,&tmp_fp))
+ off = tmp_fp;
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr,"%lu %lu %lu %lu %ld %ld\n",
+ (u_long)leitch->codetime3.l_ui,
+ (u_long)leitch->codetime3.l_uf,
+ (u_long)leitch->reftime3.l_ui,
+ (u_long)leitch->reftime3.l_uf,
+ (u_long)off.l_i,
+ (u_long)off.l_f);
+#endif
+ refclock_receive(leitch->peer, &off, 0, dispersion, &codetime,
+ &codetime, isinsync);
+}
+
+/*
+ * leitch_timeout
+ */
+static void
+leitch_timeout(fp)
+ struct peer *fp;
+{
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_timeout()\n");
+#endif
+
+#ifdef NOTYET
+ { struct leitchunit *leitch = (struct leitchunit *)fp;
+
+ switch(leitch->state) {
+ case STATE_IDLE:
+ leitch_send(leitch,"D\r");
+ leitch->state = STATE_DATE;
+ break;
+ case STATE_DATE:
+ leitch_send(leitch,"T\r");
+ leitch->state = STATE_TIME1;
+ break;
+ case STATE_TIME1:
+ case STATE_TIME2:
+ case STATE_TIME3:
+ default:
+ break;
+ }
+
+ leitch->leitchtimer.event_time += 30;
+ TIMER_ENQUEUE(timerqueue, &leitch->leitchtimer);
+ }
+#endif /* NOTYET */
+}
+
+/*
+ * dysize
+ */
+static int
+dysize(year)
+int year;
+{
+ if (year%4) { /* not a potential leap year */
+ return (365);
+ } else {
+ if (year % 100) { /* is a leap year */
+ return (366);
+ } else {
+ if (year % 400) {
+ return (365);
+ } else {
+ return (366);
+ }
+ }
+ }
+}
+
+static int
+leitch_get_date(rbufp,leitch)
+ struct recvbuf *rbufp;
+ struct leitchunit *leitch;
+{
+ int i;
+
+ if (rbufp->recv_length < 6)
+ return(0);
+#define BAD(A) (rbufp->recv_buffer[A] < '0') || (rbufp->recv_buffer[A] > '9')
+ if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
+ return(0);
+#define ATOB(A) ((rbufp->recv_buffer[A])-'0')
+ leitch->year = ATOB(0)*10 + ATOB(1);
+ leitch->month = ATOB(2)*10 + ATOB(3);
+ leitch->day = ATOB(4)*10 + ATOB(5);
+
+ /* sanity checks */
+ if (leitch->month > 12)
+ return(0);
+ if (leitch->day > days_in_month[leitch->month-1])
+ return(0);
+
+ /* calculate yearday */
+ i = 0;
+ leitch->yearday = leitch->day;
+
+ while ( i < (leitch->month-1) )
+ leitch->yearday += days_in_month[i++];
+
+ if ((dysize((leitch->year>90?1900:2000)+leitch->year)==365) &&
+ leitch->month > 2)
+ leitch->yearday--;
+
+ return(1);
+}
+
+/*
+ * leitch_get_time
+ */
+static int
+leitch_get_time(rbufp,leitch,which)
+ struct recvbuf *rbufp;
+ struct leitchunit *leitch;
+ int which;
+{
+ if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
+ return(0);
+ leitch->hour = ATOB(0)*10 +ATOB(1);
+ leitch->minute = ATOB(2)*10 +ATOB(3);
+ leitch->second = ATOB(4)*10 +ATOB(5);
+
+ if ((leitch->hour > 23) || (leitch->minute > 60) ||
+ (leitch->second > 60))
+ return(0);
+ return(1);
+}
+
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_new/refclock_msfees.c b/usr.sbin/xntpd/xntpd/refclock_new/refclock_msfees.c
new file mode 100644
index 000000000000..5a6307c3b6f6
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_new/refclock_msfees.c
@@ -0,0 +1,1575 @@
+/* refclock_ees - clock driver for the EES M201 receiver */
+
+#if defined(REFCLOCK) && defined(MSFEESPPS) && defined(STREAM)
+
+/* Currently REQUIRES STREAM and PPSCD. CLK and CBREAK modes
+ * were removed as the code was overly hairy, they weren't in use
+ * (hence probably didn't work). Still in RCS file at cl.cam.ac.uk
+ */
+
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_calendar.h"
+#if defined(HAVE_BSD_TTYS)
+#include <sgtty.h>
+#endif /* HAVE_BSD_TTYS */
+#if defined(HAVE_SYSV_TTYS)
+#include <termio.h>
+#endif /* HAVE_SYSV_TTYS */
+#include <termios.h>
+#include <stropts.h>
+#include <sys/ppsclock.h>
+#include "ntp_stdlib.h"
+
+ /*
+ fudgefactor = fudgetime1;
+ os_delay = fudgetime2;
+ offset_fudge = os_delay + fudgefactor + inherent_delay;
+ stratumtouse = fudgeval1 & 0xf
+ debug = fudgeval2;
+ sloppyclockflag = flags & CLK_FLAG1;
+ 1 log smoothing summary when processing sample
+ 4 dump the buffer from the clock
+ 8 EIOGETKD the last n uS time stamps
+ if (flags & CLK_FLAG2 && unitinuse) ees->leaphold = 0;
+ ees->dump_vals = flags & CLK_FLAG3;
+ ees->usealldata = flags & CLK_FLAG4;
+
+
+ bug->values[0] = (ees->lasttime) ? current_time - ees->lasttime : 0;
+ bug->values[1] = (ees->clocklastgood)?current_time-ees->clocklastgood:0;
+ bug->values[2] = ees->status;
+ bug->values[3] = ees->lastevent;
+ bug->values[4] = ees->reason;
+ bug->values[5] = ees->nsamples;
+ bug->values[6] = ees->codestate;
+ bug->values[7] = ees->day;
+ bug->values[8] = ees->hour;
+ bug->values[9] = ees->minute;
+ bug->values[10] = ees->second;
+ bug->values[11] = ees->tz;
+ bug->values[12] = ees->yearstart;
+ bug->values[13] = (ees->leaphold > current_time) ?
+ ees->leaphold - current_time : 0;
+ bug->values[14] = inherent_delay[unit].l_uf;
+ bug->values[15] = offset_fudge[unit].l_uf;
+
+ bug->times[0] = ees->reftime;
+ bug->times[1] = ees->arrvtime;
+ bug->times[2] = ees->lastsampletime;
+ bug->times[3] = ees->offset;
+ bug->times[4] = ees->lowoffset;
+ bug->times[5] = ees->highoffset;
+ bug->times[6] = inherent_delay[unit];
+ bug->times[8] = os_delay[unit];
+ bug->times[7] = fudgefactor[unit];
+ bug->times[9] = offset_fudge[unit];
+ bug->times[10]= ees->yearstart, 0;
+ */
+
+/* This should support the use of an EES M201 receiver with RS232
+ * output (modified to transmit time once per second).
+ *
+ * For the format of the message sent by the clock, see the EESM_
+ * definitions below.
+ *
+ * It appears to run free for an integral number of minutes, until the error
+ * reaches 4mS, at which point it steps at second = 01.
+ * It appears that sometimes it steps 4mS (say at 7 min interval),
+ * then the next minute it decides that it was an error, so steps back.
+ * On the next minute it steps forward again :-(
+ * This is typically 16.5uS/S then 3975uS at the 4min re-sync,
+ * or 9.5uS/S then 3990.5uS at a 7min re-sync,
+ * at which point it may loose the "00" second time stamp.
+ * I assume that the most accurate time is just AFTER the re-sync.
+ * Hence remember the last cycle interval,
+ *
+ * Can run in any one of:
+ *
+ * PPSCD PPS signal sets CD which interupts, and grabs the current TOD
+ * (sun) *in the interupt code*, so as to avoid problems with
+ * the STREAMS scheduling.
+ *
+ * It appears that it goes 16.5 uS slow each second, then every 4 mins it
+ * generates no "00" second tick, and gains 3975 uS. Ho Hum ! (93/2/7)
+ */
+
+/* Definitions */
+#ifndef MAXUNITS
+#define MAXUNITS 4 /* maximum number of EES units permitted */
+#endif
+
+#ifndef EES232
+#define EES232 "/dev/ees%d" /* Device to open to read the data */
+#endif
+
+/* Other constant stuff */
+#ifndef EESPRECISION
+#define EESPRECISION (-10) /* what the heck - 2**-10 = 1ms */
+#endif
+#ifndef EESREFID
+#define EESREFID "MSF\0" /* String to identify the clock */
+#endif
+#ifndef EESHSREFID
+#define EESHSREFID (0x7f7f0000 | ((REFCLK_MSF_EES) << 8)) /* Numeric refid */
+#endif
+
+/* Description of clock */
+#define EESDESCRIPTION "EES M201 MSF Receiver"
+
+/* Speed we run the clock port at. If this is changed the UARTDELAY
+ * value should be recomputed to suit.
+ */
+#ifndef SPEED232
+#define SPEED232 B9600 /* 9600 baud */
+#endif
+
+/* What is the inherent delay for this mode of working, i.e. when is the
+ * data time stamped.
+ */
+#define SAFETY_SHIFT 10 /* Split the shift to avoid overflow */
+#define BITS_TO_L_FP(bits, baud) \
+ (((((bits)*2 +1) << (FRACTION_PREC-SAFETY_SHIFT)) / (2*baud)) << SAFETY_SHIFT)
+#define INH_DELAY_CBREAK BITS_TO_L_FP(119, 9600)
+#define INH_DELAY_PPS BITS_TO_L_FP( 0, 9600)
+
+#ifndef STREAM_PP1
+#define STREAM_PP1 "ppsclocd\0<-- patch space for module name1 -->"
+#endif
+#ifndef STREAM_PP2
+#define STREAM_PP2 "ppsclock\0<-- patch space for module name2 -->"
+#endif
+
+/* Offsets of the bytes of the serial line code. The clock gives
+ * local time with a GMT/BST indication. The EESM_ definitions
+ * give offsets into ees->lastcode.
+ */
+#define EESM_CSEC 0 /* centiseconds - always zero in our clock */
+#define EESM_SEC 1 /* seconds in BCD */
+#define EESM_MIN 2 /* minutes in BCD */
+#define EESM_HOUR 3 /* hours in BCD */
+#define EESM_DAYWK 4 /* day of week (Sun = 0 etc) */
+#define EESM_DAY 5 /* day of month in BCD */
+#define EESM_MON 6 /* month in BCD */
+#define EESM_YEAR 7 /* year MOD 100 in BCD */
+#define EESM_LEAP 8 /* 0x0f if leap year, otherwise zero */
+#define EESM_BST 9 /* 0x03 if BST, 0x00 if GMT */
+#define EESM_MSFOK 10 /* 0x3f if radio good, otherwise zero */
+ /* followed by a frame alignment byte (0xff) /
+ / which is not put into the lastcode buffer*/
+
+/* Length of the serial time code, in characters. The first length
+ * is less the frame alignment byte.
+ */
+#define LENEESPRT (EESM_MSFOK+1)
+#define LENEESCODE (LENEESPRT+1)
+
+/* Code state. */
+#define EESCS_WAIT 0 /* waiting for start of timecode */
+#define EESCS_GOTSOME 1 /* have an incomplete time code buffered */
+
+/* Default fudge factor and character to receive */
+#define DEFFUDGETIME 0 /* Default user supplied fudge factor */
+#ifndef DEFOSTIME
+#define DEFOSTIME 0 /* Default OS delay -- passed by Make ? */
+#endif
+#define DEFINHTIME INH_DELAY_PPS /* inherent delay due to sample point*/
+
+/* Limits on things. Reduce the number of samples to SAMPLEREDUCE by median
+ * elimination. If we're running with an accurate clock, chose the BESTSAMPLE
+ * as the estimated offset, otherwise average the remainder.
+ */
+#define FULLSHIFT 6 /* NCODES root 2 */
+#define NCODES (1<< FULLSHIFT) /* 64 */
+#define REDUCESHIFT (FULLSHIFT -1) /* SAMPLEREDUCE root 2 */
+
+/* Towards the high ( Why ?) end of half */
+#define BESTSAMPLE ((samplereduce * 3) /4) /* 24 */
+
+/* Leap hold time. After a leap second the clock will no longer be
+ * reliable until it resynchronizes. Hope 40 minutes is enough. */
+#define EESLEAPHOLD (40 * 60)
+
+#define EES_STEP_F (1 << 24) /* the receiver steps in units of about 4ms */
+#define EES_STEP_F_GRACE (EES_STEP_F/8) /*Allow for slop of 1/8 which is .5ms*/
+#define EES_STEP_NOTE (1 << 21)/* Log any unexpected jumps, say .5 ms .... */
+#define EES_STEP_NOTES 50 /* Only do a limited number */
+#define MAX_STEP 16 /* Max number of steps to remember */
+
+/* debug is a bit mask of debugging that is wanted */
+#define DB_SYSLOG_SMPLI 0x0001
+#define DB_SYSLOG_SMPLE 0x0002
+#define DB_SYSLOG_SMTHI 0x0004
+#define DB_SYSLOG_NSMTHE 0x0008
+#define DB_SYSLOG_NSMTHI 0x0010
+#define DB_SYSLOG_SMTHE 0x0020
+#define DB_PRINT_EV 0x0040
+#define DB_PRINT_CDT 0x0080
+#define DB_PRINT_CDTC 0x0100
+#define DB_SYSLOG_KEEPD 0x0800
+#define DB_SYSLOG_KEEPE 0x1000
+#define DB_LOG_DELTAS 0x2000
+#define DB_PRINT_DELTAS 0x4000
+#define DB_LOG_AWAITMORE 0x8000
+#define DB_LOG_SAMPLES 0x10000
+#define DB_NO_PPS 0x20000
+#define DB_INC_PPS 0x40000
+#define DB_DUMP_DELTAS 0x80000
+
+struct eesunit { /* EES unit control structure. */
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ l_fp reftime; /* reference time */
+ l_fp lastsampletime; /* time as in txt from last EES msg */
+ l_fp arrvtime; /* Time at which pkt arrived */
+ l_fp codeoffsets[NCODES]; /* the time of arrival of 232 codes */
+ l_fp offset; /* chosen offset (for clkbug) */
+ l_fp lowoffset; /* lowest sample offset (for clkbug) */
+ l_fp highoffset; /* highest " " (for clkbug) */
+ char lastcode[LENEESCODE+6]; /* last time code we received */
+ u_long lasttime; /* last time clock heard from */
+ u_long clocklastgood; /* last time good radio seen */
+ u_char lencode; /* length of code in buffer */
+ u_char nsamples; /* number of samples we've collected */
+ u_char codestate; /* state of 232 code reception */
+ 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 hour; /* hour of day */
+ u_char minute; /* minute of hour */
+ u_char second; /* seconds of minute */
+ char tz; /* timezone from clock */
+ u_char ttytype; /* method used */
+ u_char dump_vals; /* Should clock values be dumped */
+ u_char usealldata; /* Use ALL samples */
+ u_short day; /* day of year from last code */
+ u_long yearstart; /* start of current year */
+ u_long leaphold; /* time of leap hold expiry */
+ u_long badformat; /* number of bad format codes */
+ u_long baddata; /* number of invalid time codes */
+ u_long timestarted; /* time we started this */
+ long last_pps_no; /* The serial # of the last PPS */
+ char fix_pending; /* Is a "sync to time" pending ? */
+ /* Fine tuning - compensate for 4 mS ramping .... */
+ l_fp last_l; /* last time stamp */
+ u_char last_steps[MAX_STEP]; /* Most recent n steps */
+ int best_av_step; /* Best guess at average step */
+ char best_av_step_count; /* # of steps over used above */
+ char this_step; /* Current pos in buffer */
+ int last_step_late; /* How late the last step was (0-59) */
+ long jump_fsecs; /* # of fractions of a sec last jump */
+ u_long last_step; /* time of last step */
+ int last_step_secs; /* Number of seconds in last step */
+ int using_ramp; /* 1 -> noemal, -1 -> over stepped */
+};
+#define last_sec last_l.l_ui
+#define last_sfsec last_l.l_f
+#define this_uisec ((ees->arrvtime).l_ui)
+#define this_sfsec ((ees->arrvtime).l_f)
+#define msec(x) ((x) / (1<<22))
+#define LAST_STEPS (sizeof ees->last_steps / sizeof ees->last_steps[0])
+#define subms(x) ((((((x < 0) ? (-(x)) : (x)) % (1<<22))/2) * 625) / (1<<(22 -5)))
+
+/* Bitmask for what methods to try to use -- currently only PPS enabled */
+#define T_CBREAK 1
+#define T_PPS 8
+/* macros to test above */
+#define is_cbreak(x) ((x)->ttytype & T_CBREAK)
+#define is_pps(x) ((x)->ttytype & T_PPS)
+#define is_any(x) ((x)->ttytype)
+
+#define CODEREASON 20 /* reason codes */
+
+/* Data space for the unit structures. Note that we allocate these on
+ * the fly, but never give them back. */
+static struct eesunit *eesunits[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 inherent_delay[MAXUNITS]; /* when time stamp is taken */
+static l_fp fudgefactor[MAXUNITS]; /* fudgetime1 */
+static l_fp os_delay[MAXUNITS]; /* fudgetime2 */
+static l_fp offset_fudge[MAXUNITS]; /* Sum of above */
+static u_char stratumtouse[MAXUNITS];
+static u_char sloppyclockflag[MAXUNITS];
+
+static int deltas[60];
+
+static l_fp acceptable_slop; /* = { 0, 1 << (FRACTION_PREC -2) }; */
+static l_fp onesec; /* = { 1, 0 }; */
+
+/* Imported from the timer module */
+extern u_long current_time;
+
+#ifdef DEBUG
+static int debug;
+#endif
+
+#ifndef DUMP_BUF_SIZE /* Size of buffer to be used by dump_buf */
+#define DUMP_BUF_SIZE 10112
+#endif
+
+/* ees_reset - reset the count back to zero */
+#define ees_reset(ees) (ees)->nsamples = 0; \
+ (ees)->codestate = EESCS_WAIT
+
+/* ees_event - record and report an event */
+#define ees_event(ees, evcode) if ((ees)->status != (u_char)(evcode)) \
+ ees_report_event((ees), (evcode))
+
+/* Find the precision of the system clock by reading it */
+#define USECS 1000000
+#define MINSTEP 5 /* some systems increment uS on each call */
+#define MAXLOOPS (USECS/9)
+static int ees_get_precision()
+{
+ struct timeval tp;
+ struct timezone tzp;
+ long last;
+ int i;
+ long diff;
+ long val;
+ gettimeofday(&tp, &tzp);
+
+ last = tp.tv_usec;
+ for (i=0; i< 100000; i++) {
+ gettimeofday(&tp, &tzp);
+ diff = tp.tv_usec - last;
+ if (diff < 0) diff += USECS;
+ if (diff > MINSTEP) break;
+ last = tp.tv_usec;
+ }
+ syslog(LOG_INFO,
+ "I: ees: precision calculation given %duS after %d loop%s",
+ diff, i, (i==1) ? "" : "s");
+
+ if (i == 0) return -20 /* assume 1uS */;
+ if (i >= MAXLOOPS) return EESPRECISION /* Lies ! */;
+ for (i=0, val=USECS; val > 0; i--, val /= 2) if (diff > val) return i;
+ return EESPRECISION /* Lies ! */;
+}
+
+static void dump_buf(coffs, from, to, text)
+l_fp *coffs;
+int from;
+int to;
+char *text;
+{
+ char buff[DUMP_BUF_SIZE + 80];
+ int i;
+ register char *ptr = buff;
+ sprintf(ptr, text);
+ for (i=from; i<to; i++)
+ { while (*ptr) ptr++;
+ if ((ptr-buff) > DUMP_BUF_SIZE) syslog(LOG_DEBUG, "D: %s", ptr=buff);
+ sprintf(ptr, " %06d", ((int)coffs[i].l_f) / 4295);
+ }
+ syslog(LOG_DEBUG, "D: %s", buff);
+}
+
+/* msfees_init - initialize internal ees driver data */
+static void msfees_init()
+{
+ register int i;
+ /* Just zero the data arrays */
+ memset((char *)eesunits, 0, sizeof eesunits);
+ memset((char *)unitinuse, 0, sizeof unitinuse);
+
+ acceptable_slop.l_ui = 0;
+ acceptable_slop.l_uf = 1 << (FRACTION_PREC -2);
+
+ onesec.l_ui = 1;
+ onesec.l_uf = 0;
+
+ /* Initialize fudge factors to default. */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor[i].l_ui = 0;
+ fudgefactor[i].l_uf = DEFFUDGETIME;
+ os_delay[i].l_ui = 0;
+ os_delay[i].l_uf = DEFOSTIME;
+ inherent_delay[i].l_ui = 0;
+ inherent_delay[i].l_uf = DEFINHTIME;
+ offset_fudge[i] = os_delay[i];
+ L_ADD(&offset_fudge[i], &fudgefactor[i]);
+ L_ADD(&offset_fudge[i], &inherent_delay[i]);
+ stratumtouse[i] = 0;
+ sloppyclockflag[i] = 0;
+ }
+}
+
+
+/* msfees_start - open the EES devices and initialize data for processing */
+static int msfees_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct eesunit *ees;
+ register int i;
+ int fd232 = -1;
+ char eesdev[20];
+ struct termios ttyb, *ttyp;
+ static void ees_receive();
+ extern int io_addclock();
+ extern void io_closeclock();
+ extern char *emalloc();
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock: unit number %d invalid (max %d)",
+ unit, MAXUNITS-1);
+ return 0;
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "ees clock: unit number %d in use", unit);
+ return 0;
+ }
+
+ /* Unit okay, attempt to open the devices. We do them both at
+ * once to make sure we can */
+ (void) sprintf(eesdev, EES232, unit);
+
+ fd232 = open(eesdev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR, "ees clock: open of %s failed: %m", eesdev);
+ return 0;
+ }
+
+#ifdef TIOCEXCL
+ /* Set for exclusive use */
+ if (ioctl(fd232, TIOCEXCL, (char *)0) < 0) {
+ syslog(LOG_ERR, "ees clock: ioctl(%s, TIOCEXCL): %m", eesdev);
+ goto screwed;
+ }
+#endif
+
+ /* STRIPPED DOWN VERSION: Only PPS CD is supported at the moment */
+
+ /* Set port characteristics. If we don't have a STREAMS module or
+ * a clock line discipline, cooked mode is just usable, even though it
+ * strips the top bit. The only EES byte which uses the top
+ * bit is the year, and we don't use that anyway. If we do
+ * have the line discipline, we choose raw mode, and the
+ * line discipline code will block up the messages.
+ */
+
+ /* STIPPED DOWN VERSION: Only PPS CD is supported at the moment */
+
+ ttyp = &ttyb;
+ if (tcgetattr(fd232, ttyp) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcgetattr(%s): %m", eesdev);
+ goto screwed;
+ }
+
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
+ ttyp->c_oflag = 0;
+ ttyp->c_lflag = ICANON;
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+ if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcsetattr(%s): %m", eesdev);
+ goto screwed;
+ }
+
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcflush(%s): %m", eesdev);
+ goto screwed;
+ }
+
+ inherent_delay[unit].l_uf = INH_DELAY_PPS;
+
+ /* offset fudge (how *late* the timestamp is) = fudge + os delays */
+ offset_fudge[unit] = os_delay[unit];
+ L_ADD(&offset_fudge[unit], &fudgefactor[unit]);
+ L_ADD(&offset_fudge[unit], &inherent_delay[unit]);
+
+ /* Looks like this might succeed. Find memory for the structure.
+ * Look to see if there are any unused ones, if not we malloc() one.
+ */
+ if (eesunits[unit] != 0) /* The one we want is okay */
+ ees = eesunits[unit];
+ else {
+ /* Look for an unused, but allocated struct */
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && eesunits[i] != 0)
+ break;
+ }
+
+ if (i < MAXUNITS) { /* Reclaim this one */
+ ees = eesunits[i];
+ eesunits[i] = 0;
+ } /* no spare -- make a new one */
+ else ees = (struct eesunit *) emalloc(sizeof(struct eesunit));
+ }
+ memset((char *)ees, 0, sizeof(struct eesunit));
+ eesunits[unit] = ees;
+
+ /* Set up the structures */
+ ees->peer = peer;
+ ees->unit = (u_char)unit;
+ ees->timestarted= current_time;
+ ees->ttytype = 0;
+ ees->io.clock_recv= ees_receive;
+ ees->io.srcclock= (caddr_t)ees;
+ ees->io.datalen = 0;
+ ees->io.fd = fd232;
+
+ /* Okay. Push one of the two (linked into the kernel, or dynamically
+ * loaded) STREAMS module, and give it to the I/O code to start
+ * receiving stuff.
+ */
+
+ {
+ int rc1;
+ /* Pop any existing onews first ... */
+ while (ioctl(fd232, I_POP, 0 ) >= 0) ;
+
+ /* Now try pushing either of the possible modules */
+ if ((rc1=ioctl(fd232, I_PUSH, STREAM_PP1)) < 0 &&
+ ioctl(fd232, I_PUSH, STREAM_PP2) < 0) {
+ syslog(LOG_ERR,
+ "ees clock: Push of `%s' and `%s' to %s failed %m",
+ STREAM_PP1, STREAM_PP2, eesdev);
+ goto screwed;
+ }
+ else {
+ syslog(LOG_INFO, "I: ees clock: PUSHed %s on %s",
+ (rc1 >= 0) ? STREAM_PP1 : STREAM_PP2, eesdev);
+ ees->ttytype |= T_PPS;
+ }
+ }
+
+ /* Add the clock */
+ if (!io_addclock(&ees->io)) {
+ /* Oh shit. Just close and return. */
+ syslog(LOG_ERR, "ees clock: io_addclock(%s): %m", eesdev);
+ goto screwed;
+ }
+
+
+ /* All done. Initialize a few random peer variables, then
+ * return success. */
+ peer->precision = ees_get_precision();
+ peer->stratum = stratumtouse[unit];
+ peer->rootdelay = 0; /* ++++ */
+ peer->rootdispersion = 0; /* ++++ */
+ if (stratumtouse[unit] <= 1) {
+ memmove((char *)&peer->refid, EESREFID, 4);
+ if (unit > 0 && unit < 10)
+ ((char *)&peer->refid)[3] = '0' + unit;
+ } else {
+ peer->refid = htonl(EESHSREFID);
+ }
+ unitinuse[unit] = 1;
+ syslog(LOG_ERR, "ees clock: %s OK on %d", eesdev, unit);
+ return (1);
+
+screwed:
+ if (fd232 != -1)
+ (void) close(fd232);
+ return (0);
+}
+
+
+/* msfees_shutdown - shut down a EES clock */
+static void msfees_shutdown(unit)
+ int unit;
+{
+ register struct eesunit *ees;
+ extern void io_closeclock();
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,
+ "ees clock: INTERNAL ERROR, unit number %d invalid (max %d)",
+ unit, MAXUNITS);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR,
+ "ees clock: INTERNAL ERROR, unit number %d not in use", unit);
+ return;
+ }
+
+ /* Tell the I/O module to turn us off. We're history. */
+ ees = eesunits[unit];
+ io_closeclock(&ees->io);
+ unitinuse[unit] = 0;
+}
+
+
+/* ees_report_event - note the occurance of an event */
+static void ees_report_event(ees, code)
+ struct eesunit *ees;
+ int code;
+{
+ if (ees->status != (u_char)code) {
+ ees->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ ees->lastevent = (u_char)code;
+ /* Should report event to trap handler in here.
+ * Soon...
+ */
+ }
+}
+
+
+/* ees_receive - receive data from the serial interface on an EES clock */
+static void ees_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register int n_sample;
+ register int day;
+ register struct eesunit *ees;
+ register u_char *dpt; /* Data PoinTeR: move along ... */
+ register u_char *dpend; /* Points just *after* last data char */
+ register char *cp;
+ l_fp tmp;
+ static void ees_process();
+ int call_pps_sample = 0;
+ l_fp pps_arrvstamp;
+ int sincelast;
+ int pps_step = 0;
+ int suspect_4ms_step = 0;
+ struct ppsclockev ppsclockev;
+ long *ptr = (long *) &ppsclockev;
+ extern errno;
+ int rc;
+
+ /* Get the clock this applies to and a pointer to the data */
+ ees = (struct eesunit *)rbufp->recv_srcclock;
+ dpt = (u_char *)&rbufp->recv_space;
+ dpend = dpt + rbufp->recv_length;
+ if ((debug & DB_LOG_AWAITMORE) && (rbufp->recv_length != LENEESCODE))
+ printf("[%d] ", rbufp->recv_length);
+
+ /* Check out our state and process appropriately */
+ switch (ees->codestate) {
+ case EESCS_WAIT:
+ /* Set an initial guess at the timestamp as the recv time.
+ * If just running in CBREAK mode, we can't improve this.
+ * If we have the CLOCK Line Discipline, PPSCD, or sime such,
+ * then we will do better later ....
+ */
+ ees->arrvtime = rbufp->recv_time;
+ ees->codestate = EESCS_GOTSOME;
+ ees->lencode = 0;
+ /*FALLSTHROUGH*/
+
+ case EESCS_GOTSOME:
+ cp = &(ees->lastcode[ees->lencode]);
+
+ /* Gobble the bytes until the final (possibly stripped) 0xff */
+ while (dpt < dpend && (*dpt & 0x7f) != 0x7f) {
+ *cp++ = (char)*dpt++;
+ ees->lencode++;
+ /* Oh dear -- too many bytes .. */
+ if (ees->lencode > LENEESPRT) {
+ syslog(LOG_INFO,
+"I: ees clock: %d + %d > %d [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
+ ees->lencode, dpend - dpt, LENEESPRT,
+#define D(x) (ees->lastcode[x])
+ D(0), D(1), D(2), D(3), D(4), D(5), D(6),
+ D(7), D(8), D(9), D(10), D(11), D(12));
+#undef D
+ ees->badformat++;
+ ees->reason = CODEREASON + 1;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+ }
+ /* Gave up because it was end of the buffer, rather than ff */
+ if (dpt == dpend) {
+ /* Incomplete. Wait for more. */
+ if (debug & DB_LOG_AWAITMORE) syslog(LOG_INFO,
+ "I: ees clock %d: %d == %d: await more",
+ ees->unit, dpt, dpend);
+ return;
+ }
+
+ /* This shouldn't happen ... ! */
+ if ((*dpt & 0x7f) != 0x7f) {
+ syslog(LOG_INFO, "I: ees clock: %0x & 0x7f != 0x7f", *dpt);
+ ees->badformat++;
+ ees->reason = CODEREASON + 2;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ /* Skip the 0xff */
+ dpt++;
+
+ /* Finally, got a complete buffer. Mainline code will
+ * continue on. */
+ cp = ees->lastcode;
+ break;
+
+ default:
+ syslog(LOG_ERR, "ees clock: INTERNAL ERROR: %d state %d",
+ ees->unit, ees->codestate);
+ ees->reason = CODEREASON + 5;
+ ees_event(ees, CEVNT_FAULT);
+ ees_reset(ees);
+ return;
+ }
+
+ /* Boy! After all that crap, the lastcode buffer now contains
+ * something we hope will be a valid time code. Do length
+ * checks and sanity checks on constant data.
+ */
+ ees->codestate = EESCS_WAIT;
+ ees->lasttime = current_time;
+ if (ees->lencode != LENEESPRT) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 6;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ cp = ees->lastcode;
+
+ /* Check that centisecond is zero */
+ if (cp[EESM_CSEC] != 0) {
+ ees->baddata++;
+ ees->reason = CODEREASON + 7;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ /* Check flag formats */
+ if (cp[EESM_LEAP] != 0 && cp[EESM_LEAP] != 0x0f) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 8;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ if (cp[EESM_BST] != 0 && cp[EESM_BST] != 0x03) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 9;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ if (cp[EESM_MSFOK] != 0 && cp[EESM_MSFOK] != 0x3f) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 10;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ /* So far, so good. Compute day, hours, minutes, seconds,
+ * time zone. Do range checks on these.
+ */
+
+#define bcdunpack(val) ( (((val)>>4) & 0x0f) * 10 + ((val) & 0x0f) )
+#define istrue(x) ((x)?1:0)
+
+ ees->second = bcdunpack(cp[EESM_SEC]); /* second */
+ ees->minute = bcdunpack(cp[EESM_MIN]); /* minute */
+ ees->hour = bcdunpack(cp[EESM_HOUR]); /* hour */
+
+ day = bcdunpack(cp[EESM_DAY]); /* day of month */
+
+ switch (bcdunpack(cp[EESM_MON])) { /* month */
+
+ /* Add in lengths of all previous months. Add one more
+ if it is a leap year and after February.
+ */
+ case 12: day += NOV; /*FALLSTHROUGH*/
+ case 11: day += OCT; /*FALLSTHROUGH*/
+ case 10: day += SEP; /*FALLSTHROUGH*/
+ case 9: day += AUG; /*FALLSTHROUGH*/
+ case 8: day += JUL; /*FALLSTHROUGH*/
+ case 7: day += JUN; /*FALLSTHROUGH*/
+ case 6: day += MAY; /*FALLSTHROUGH*/
+ case 5: day += APR; /*FALLSTHROUGH*/
+ case 4: day += MAR; /*FALLSTHROUGH*/
+ case 3: day += FEB;
+ if (istrue(cp[EESM_LEAP])) day++; /*FALLSTHROUGH*/
+ case 2: day += JAN; /*FALLSTHROUGH*/
+ case 1: break;
+ default: ees->baddata++;
+ ees->reason = CODEREASON + 11;
+ ees_event(ees, CEVNT_BADDATE);
+ ees_reset(ees);
+ return;
+ }
+
+ ees->day = day;
+
+ /* Get timezone. The clocktime routine wants the number
+ * of hours to add to the delivered time to get UT.
+ * Currently -1 if BST flag set, 0 otherwise. This
+ * is the place to tweak things if double summer time
+ * ever happens.
+ */
+ ees->tz = istrue(cp[EESM_BST]) ? -1 : 0;
+
+ if (ees->day > 366 || ees->day < 1 ||
+ ees->hour > 23 || ees->minute > 59 || ees->second > 59) {
+ ees->baddata++;
+ ees->reason = CODEREASON + 12;
+ ees_event(ees, CEVNT_BADDATE);
+ ees_reset(ees);
+ return;
+ }
+
+ n_sample = ees->nsamples;
+
+ /* Now, compute the reference time value: text -> tmp.l_ui */
+ if (!clocktime(ees->day, ees->hour, ees->minute, ees->second,
+ ees->tz, rbufp->recv_time.l_ui, &ees->yearstart,
+ &tmp.l_ui)) {
+ ees->baddata++;
+ ees->reason = CODEREASON + 13;
+ ees_event(ees, CEVNT_BADDATE);
+ ees_reset(ees);
+ return;
+ }
+ tmp.l_uf = 0;
+
+ /* DON'T use ees->arrvtime -- it may be < reftime */
+ ees->lastsampletime = tmp;
+
+ /* If we are synchronised to the radio, update the reference time.
+ * Also keep a note of when clock was last good.
+ */
+ if (istrue(cp[EESM_MSFOK])) {
+ ees->reftime = tmp;
+ ees->clocklastgood = current_time;
+ }
+
+
+ /* Compute the offset. For the fractional part of the
+ * offset we use the expected delay for the message.
+ */
+ ees->codeoffsets[n_sample].l_ui = tmp.l_ui;
+ ees->codeoffsets[n_sample].l_uf = 0;
+
+ /* Number of seconds since the last step */
+ sincelast = this_uisec - ees->last_step;
+
+ memset(&ppsclockev, 0, sizeof ppsclockev);
+
+ rc = ioctl(ees->io.fd, CIOGETEV, (char *) &ppsclockev);
+ if (debug & DB_PRINT_EV) fprintf(stderr,
+ "[%x] CIOGETEV u%d %d (%x %d) gave %d (%d): %08x %08x %d\n",
+ DB_PRINT_EV, ees->unit, ees->io.fd, CIOGETEV, is_pps(ees),
+ rc, errno, ptr[0], ptr[1], ptr[2]);
+
+ /* If we managed to get the time of arrival, process the info */
+ if (rc >= 0) {
+ int conv = -1;
+ pps_step = ppsclockev.serial - ees->last_pps_no;
+
+ /* Possible that PPS triggered, but text message didn't */
+ if (pps_step == 2) syslog(LOG_ERR, "pps step = 2 @ %02d", ees->second);
+ if (pps_step == 2 && ees->second == 1) suspect_4ms_step |= 1;
+ if (pps_step == 2 && ees->second == 2) suspect_4ms_step |= 4;
+
+ /* allow for single loss of PPS only */
+ if (pps_step != 1 && pps_step != 2)
+ fprintf(stderr, "PPS step: %d too far off %d (%d)\n",
+ ppsclockev.serial, ees->last_pps_no, pps_step);
+ else if (!buftvtots((char *) &(ppsclockev.tv), &pps_arrvstamp))
+ fprintf(stderr, "buftvtots failed\n");
+ else { /* if ((ABS(time difference) - 0.25) < 0)
+ * then believe it ...
+ */
+ l_fp diff;
+ diff = pps_arrvstamp;
+ conv = 0;
+ L_SUB(&diff, &ees->arrvtime);
+if (debug & DB_PRINT_CDT) printf("[%x] Have %x.%08x and %x.%08x -> %x.%08x @ %s",
+ DB_PRINT_CDT, ees->arrvtime.l_ui, ees->arrvtime.l_uf,
+ pps_arrvstamp.l_ui, pps_arrvstamp.l_uf,
+ diff.l_ui, diff.l_uf,
+ ctime(&(ppsclockev.tv.tv_sec)));
+ if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf);
+ L_SUB(&diff, &acceptable_slop);
+ if (L_ISNEG(&diff)) { /* AOK -- pps_sample */
+ ees->arrvtime = pps_arrvstamp;
+ conv++;
+ call_pps_sample++;
+ }
+ /* Some loss of some signals around sec = 1 */
+ else if (ees->second == 1) {
+ diff = pps_arrvstamp;
+ L_ADD(&diff, &onesec);
+ L_SUB(&diff, &ees->arrvtime);
+ if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf);
+ L_SUB(&diff, &acceptable_slop);
+syslog(LOG_ERR, "Have sec==1 slip %ds a=%08x-p=%08x -> %x.%08x (u=%d) %s",
+ pps_arrvstamp.l_ui - ees->arrvtime.l_ui,
+ pps_arrvstamp.l_uf,
+ ees->arrvtime.l_uf,
+ diff.l_ui, diff.l_uf,
+ ppsclockev.tv.tv_usec,
+ ctime(&(ppsclockev.tv.tv_sec)));
+ if (L_ISNEG(&diff)) { /* AOK -- pps_sample */
+ suspect_4ms_step |= 2;
+ ees->arrvtime = pps_arrvstamp;
+ L_ADD(&ees->arrvtime, &onesec);
+ conv++;
+ call_pps_sample++;
+ }
+ }
+ }
+ ees->last_pps_no = ppsclockev.serial;
+ if (debug & DB_PRINT_CDTC) printf(
+ "[%x] %08x %08x %d u%d (%d %d)\n",
+ DB_PRINT_CDTC, pps_arrvstamp.l_ui,
+ pps_arrvstamp.l_uf, conv, ees->unit,
+ call_pps_sample, pps_step);
+ }
+
+ /* See if there has been a 4ms jump at a minute boundry */
+ { l_fp delta;
+#define delta_isec delta.l_ui
+#define delta_ssec delta.l_i
+#define delta_sfsec delta.l_f
+ long delta_f_abs;
+
+ delta.l_i = ees->arrvtime.l_i;
+ delta.l_f = ees->arrvtime.l_f;
+
+ L_SUB(&delta, &ees->last_l);
+ delta_f_abs = delta_sfsec;
+ if (delta_f_abs < 0) delta_f_abs = -delta_f_abs;
+
+ /* Dump the deltas each minute */
+ if (debug & DB_DUMP_DELTAS)
+ { if (0 <= ees->second &&
+ ees->second < ((sizeof deltas) / (sizeof deltas[0]))) deltas[ees->second] = delta_sfsec;
+ /* Dump on second 1, as second 0 sometimes missed */
+ if (ees->second == 1) {
+ char text[16 * ((sizeof deltas) / (sizeof deltas[0]))];
+ char *ptr=text;
+ int i;
+ for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) {
+ sprintf(ptr, " %d.%04d",
+ msec(deltas[i]), subms(deltas[i]));
+ while (*ptr) ptr++;
+ }
+ syslog(LOG_ERR, "Deltas: %d.%04d<->%d.%04d: %s",
+ msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE),
+ msec(EES_STEP_F + EES_STEP_F_GRACE), subms(EES_STEP_F + EES_STEP_F_GRACE),
+ text+1);
+ for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) deltas[i] = 0;
+ }
+ }
+
+ /* Lets see if we have a 4 mS step at a minute boundaary */
+ if ( ((EES_STEP_F - EES_STEP_F_GRACE) < delta_f_abs) &&
+ (delta_f_abs < (EES_STEP_F + EES_STEP_F_GRACE)) &&
+ (ees->second == 0 || ees->second == 1 || ees->second == 2) &&
+ (sincelast < 0 || sincelast > 122)
+ ) { /* 4ms jump at min boundry */
+ int old_sincelast;
+ int count=0;
+ int sum = 0;
+ /* Yes -- so compute the ramp time */
+ if (ees->last_step == 0) sincelast = 0;
+ old_sincelast = sincelast;
+
+ /* First time in, just set "ees->last_step" */
+ if(ees->last_step) {
+ int other_step = 0;
+ int third_step = 0;
+ int this_step = (sincelast + (60 /2)) / 60;
+ int p_step = ees->this_step;
+ int p;
+ ees->last_steps[p_step] = this_step;
+ p= p_step;
+ p_step++;
+ if (p_step >= LAST_STEPS) p_step = 0;
+ ees->this_step = p_step;
+ /* Find the "average" interval */
+ while (p != p_step) {
+ int this = ees->last_steps[p];
+ if (this == 0) break;
+ if (this != this_step) {
+ if (other_step == 0 && (
+ this== (this_step +2) ||
+ this== (this_step -2) ||
+ this== (this_step +1) ||
+ this== (this_step -1)))
+ other_step = this;
+ if (other_step != this) {
+ int delta = (this_step - other_step);
+ if (delta < 0) delta = - delta;
+ if (third_step == 0 && (
+ (delta == 1) ? (
+ this == (other_step +1) ||
+ this == (other_step -1) ||
+ this == (this_step +1) ||
+ this == (this_step -1))
+ :
+ (
+ this == (this_step + other_step)/2
+ )
+ )) third_step = this;
+ if (third_step != this) break;
+ }
+ }
+ sum += this;
+ p--;
+ if (p < 0) p += LAST_STEPS;
+ count++;
+ }
+syslog(LOG_ERR, "MSF%d: %d: This=%d (%d), other=%d/%d, sum=%d, count=%d, pps_step=%d, suspect=%x", ees->unit, p, ees->last_steps[p], this_step, other_step, third_step, sum, count, pps_step, suspect_4ms_step);
+ if (count != 0) sum = ((sum * 60) + (count /2)) / count;
+#define SV(x) (ees->last_steps[(x + p_step) % LAST_STEPS])
+syslog(LOG_ERR, "MSF%d: %x steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ ees->unit, suspect_4ms_step, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6),
+ SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15));
+printf("MSF%d: steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ ees->unit, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6),
+ SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15));
+#undef SV
+ ees->jump_fsecs = delta_sfsec;
+ ees->using_ramp = 1;
+ if (sincelast > 170)
+ ees->last_step_late += sincelast - ((sum) ? sum : ees->last_step_secs);
+ else ees->last_step_late = 30;
+ if (ees->last_step_late < -60 || ees->last_step_late > 120) ees->last_step_late = 30;
+ if (ees->last_step_late < 0) ees->last_step_late = 0;
+ if (ees->last_step_late >= 60) ees->last_step_late = 59;
+ sincelast = 0;
+ }
+ else { /* First time in -- just save info */
+ ees->last_step_late = 30;
+ ees->jump_fsecs = delta_sfsec;
+ ees->using_ramp = 1;
+ sum = 4 * 60;
+ }
+ ees->last_step = this_uisec;
+printf("MSF%d: d=%3d.%04d@%d :%d:%d:$%d:%d:%d\n",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs);
+syslog(LOG_ERR, "MSF%d: d=%3d.%04d@%d :%d:%d:%d:%d:%d",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs);
+ if (sum) ees->last_step_secs = sum;
+ }
+ /* OK, so not a 4ms step at a minute boundry */
+ else {
+ if (suspect_4ms_step) syslog(LOG_ERR,
+ "MSF%d: suspect = %x, but delta of %d.%04d [%d.%04d<%d.%04d<%d.%04d: %d %d]",
+ ees->unit, suspect_4ms_step, msec(delta_sfsec), subms(delta_sfsec),
+ msec(EES_STEP_F - EES_STEP_F_GRACE),
+ subms(EES_STEP_F - EES_STEP_F_GRACE),
+ msec(delta_f_abs),
+ subms(delta_f_abs),
+ msec(EES_STEP_F + EES_STEP_F_GRACE),
+ subms(EES_STEP_F + EES_STEP_F_GRACE),
+ ees->second,
+ sincelast);
+ if ((delta_f_abs > EES_STEP_NOTE) && ees->last_l.l_i) {
+ static ees_step_notes = EES_STEP_NOTES;
+ if (ees_step_notes > 0) {
+ ees_step_notes--;
+printf("MSF%d: D=%3d.%04d@%02d :%d%s\n",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, sincelast, ees_step_notes ? "" : " -- NO MORE !");
+syslog(LOG_ERR, "MSF%d: D=%3d.%04d@%02d :%d%s",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, (ees->last_step) ? sincelast : -1, ees_step_notes ? "" : " -- NO MORE !");
+ }
+ }
+ }
+ }
+ ees->last_l = ees->arrvtime;
+
+ /* IF we have found that it's ramping
+ * && it's within twice the expected ramp period
+ * && there is a non zero step size (avoid /0 !)
+ * THEN we twiddle things
+ */
+ if (ees->using_ramp &&
+ sincelast < (ees->last_step_secs)*2 &&
+ ees->last_step_secs)
+ { long sec_of_ramp = sincelast + ees->last_step_late;
+ long fsecs;
+ l_fp inc;
+
+ /* Ramp time may vary, so may ramp for longer than last time */
+ if (sec_of_ramp > (ees->last_step_secs + 120))
+ sec_of_ramp = ees->last_step_secs;
+
+ /* sec_of_ramp * ees->jump_fsecs may overflow 2**32 */
+ fsecs = sec_of_ramp * (ees->jump_fsecs / ees->last_step_secs);
+
+ if (debug & DB_LOG_DELTAS) syslog(LOG_ERR,
+ "[%x] MSF%d: %3d/%03d -> d=%11d (%d|%d)",
+ DB_LOG_DELTAS,
+ ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
+ pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
+ if (debug & DB_PRINT_DELTAS) printf(
+ "MSF%d: %3d/%03d -> d=%11d (%d|%d)\n",
+ ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
+ pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
+
+ /* Must sign extend the result */
+ inc.l_i = (fsecs < 0) ? -1 : 0;
+ inc.l_f = fsecs;
+ if (debug & DB_INC_PPS)
+ { L_SUB(&pps_arrvstamp, &inc);
+ L_SUB(&ees->arrvtime, &inc);
+ }
+ else
+ { L_ADD(&pps_arrvstamp, &inc);
+ L_ADD(&ees->arrvtime, &inc);
+ }
+ }
+ else {
+ if (debug & DB_LOG_DELTAS) syslog(LOG_ERR,
+ "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x",
+ DB_LOG_DELTAS,
+ ees->unit, ees->using_ramp,
+ sincelast,
+ (ees->last_step_secs)*2,
+ ees->last_step_secs);
+ if (debug & DB_PRINT_DELTAS) printf(
+ "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x\n",
+ DB_LOG_DELTAS,
+ ees->unit, ees->using_ramp,
+ sincelast,
+ (ees->last_step_secs)*2,
+ ees->last_step_secs);
+ }
+
+ L_SUB(&ees->arrvtime, &offset_fudge[ees->unit]);
+ L_SUB(&pps_arrvstamp, &offset_fudge[ees->unit]);
+
+ if (call_pps_sample && !(debug & DB_NO_PPS)) {
+ /* Sigh -- it expects its args negated */
+ L_NEG(&pps_arrvstamp);
+ (void) pps_sample(&pps_arrvstamp);
+ }
+
+ /* Subtract off the local clock time stamp */
+ L_SUB(&ees->codeoffsets[n_sample], &ees->arrvtime);
+ if (debug & DB_LOG_SAMPLES) syslog(LOG_ERR,
+ "MSF%d: [%x] %d (ees: %d %d) (pps: %d %d)%s",
+ ees->unit, DB_LOG_DELTAS, n_sample,
+ ees->codeoffsets[n_sample].l_f,
+ ees->codeoffsets[n_sample].l_f / 4295,
+ pps_arrvstamp.l_f,
+ pps_arrvstamp.l_f /4295,
+ (debug & DB_NO_PPS) ? " [no PPS]" : "");
+
+ if (ees->nsamples++ == NCODES-1) ees_process(ees);
+
+ /* Done! */
+}
+
+
+static void set_x(fp_offset)
+l_fp *fp_offset;
+{
+ step_systime_real(fp_offset);
+}
+
+
+/* offcompare - auxiliary comparison routine for offset sort */
+
+static int
+offcompare(a, b)
+l_fp *a, *b;
+{
+ return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);
+}
+
+
+/* ees_process - process a pile of samples from the clock */
+static void ees_process(ees)
+ struct eesunit *ees;
+{
+ static last_samples = -1;
+ register int i, j;
+ register int noff;
+ register l_fp *coffs = ees->codeoffsets;
+ l_fp offset, tmp;
+ u_fp dispersion; /* ++++ */
+ int lostsync, isinsync;
+ int samples = ees->nsamples;
+ int samplelog;
+ int samplereduce = (samples + 1) / 2;
+
+ /* Reset things to zero so we don't have to worry later */
+ ees_reset(ees);
+
+ if (sloppyclockflag[ees->unit]) {
+ samplelog = (samples < 2) ? 0 :
+ (samples < 5) ? 1 :
+ (samples < 9) ? 2 :
+ (samples < 17) ? 3 :
+ (samples < 33) ? 4 : 5;
+ samplereduce = (1 << samplelog);
+ }
+
+ if (samples != last_samples &&
+ ((samples != (last_samples-1)) || samples < 3)) {
+ syslog(LOG_ERR, "Samples=%d (%d), samplereduce=%d ....",
+ samples, last_samples, samplereduce);
+ last_samples = samples;
+ }
+ if (samples < 1) return;
+
+ /* If requested, dump the raw data we have in the buffer */
+ if (ees->dump_vals) dump_buf(coffs, 0, samples, "Raw data is:");
+
+ /* Sort the offsets, trim off the extremes, then choose one. */
+ qsort((char *) coffs, samples, sizeof(l_fp), offcompare);
+
+ noff = samples;
+ i = 0;
+ while ((noff - i) > samplereduce) {
+ /* Trim off the sample which is further away
+ * from the median. We work this out by doubling
+ * the median, subtracting off the end samples, and
+ * looking at the sign of the answer, using the
+ * identity (c-b)-(b-a) == 2*b-a-c
+ */
+ tmp = coffs[(noff + i)/2];
+ L_ADD(&tmp, &tmp);
+ L_SUB(&tmp, &coffs[i]);
+ L_SUB(&tmp, &coffs[noff-1]);
+ if (L_ISNEG(&tmp)) noff--; else i++;
+ }
+
+ /* If requested, dump the reduce data we have in the buffer */
+ if (ees->dump_vals) dump_buf(coffs, i, noff, "Reduced to:");
+
+ /* What we do next depends on the setting of the sloppy clock flag.
+ * If it is on, average the remainder to derive our estimate.
+ * Otherwise, just pick a representative value from the remaining stuff
+ */
+ if (sloppyclockflag[ees->unit]) {
+ offset.l_ui = offset.l_uf = 0;
+ for (j = i; j < noff; j++)
+ L_ADD(&offset, &coffs[j]);
+ for (j = samplelog; j > 0; j--)
+ L_RSHIFTU(&offset);
+ }
+ else offset = coffs[i+BESTSAMPLE];
+
+ /* Compute the dispersion as the difference between the
+ * lowest and highest offsets that remain in the
+ * consideration list.
+ *
+ * It looks like MOST clocks have MOD (max error), so halve it !
+ */
+ tmp = coffs[noff-1];
+ L_SUB(&tmp, &coffs[i]);
+#define FRACT_SEC(n) ((1 << 30) / (n/2))
+ dispersion = LFPTOFP(&tmp) / 2; /* ++++ */
+ if (debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE)) syslog(
+ (debug & DB_SYSLOG_SMPLE) ? LOG_ERR : LOG_INFO,
+ "I: [%x] Offset=%06d (%d), disp=%06d%s [%d], %d %d=%d %d:%d %d=%d %d",
+ debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE),
+ offset.l_f / 4295, offset.l_f,
+ (dispersion * 1526) / 100,
+ (sloppyclockflag[ees->unit]) ? " by averaging" : "",
+ FRACT_SEC(10) / 4295,
+ (coffs[0].l_f) / 4295,
+ i,
+ (coffs[i].l_f) / 4295,
+ (coffs[samples/2].l_f) / 4295,
+ (coffs[i+BESTSAMPLE].l_f) / 4295,
+ noff-1,
+ (coffs[noff-1].l_f) / 4295,
+ (coffs[samples-1].l_f) / 4295);
+
+ /* Are we playing silly wotsits ?
+ * If we are using all data, see if there is a "small" delta,
+ * and if so, blurr this with 3/4 of the delta from the last value
+ */
+ if (ees->usealldata && ees->offset.l_uf) {
+ long diff = (long) (ees->offset.l_uf - offset.l_uf);
+
+ /* is the delta small enough ? */
+ if ((- FRACT_SEC(100)) < diff && diff < FRACT_SEC(100)) {
+ int samd = (64 * 4) / samples;
+ long new;
+ if (samd < 2) samd = 2;
+ new = offset.l_uf + ((diff * (samd -1)) / samd);
+
+ /* Sign change -> need to fix up int part */
+ if ((new & (1 << 31)) !=
+ (((long) offset.l_uf) & ( 1 << 31)))
+ { syslog(LOG_INFO, "I: %x != %x (%x %x), so add %d",
+ new & (1 << 31),
+ ((long) offset.l_uf) & ( 1 << 31),
+ new, (long) offset.l_uf,
+ (new < 0) ? -1 : 1);
+ offset.l_ui += (new < 0) ? -1 : 1;
+ }
+ dispersion /= 4;
+ if (debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE)) syslog(
+ (debug & DB_SYSLOG_SMTHE) ? LOG_ERR : LOG_INFO,
+ "I: [%x] Smooth data: %d -> %d, dispersion now %d",
+ debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE),
+ ((long) offset.l_uf) / 4295, new / 4295,
+ (dispersion * 1526) / 100);
+ offset.l_uf = new;
+ }
+ else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) syslog(
+ (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
+ "[%x] No smooth as delta not %d < %d < %d",
+ debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
+ - FRACT_SEC(100), diff, FRACT_SEC(100));
+ }
+ else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) syslog(
+ (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
+ "I: [%x] No smooth as flag=%x and old=%x=%d (%d:%d)",
+ debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
+ ees->usealldata, ees->offset.l_f, ees->offset.l_uf,
+ offset.l_f, ees->offset.l_f - offset.l_f);
+
+ /* Collect offset info for debugging info */
+ ees->offset = offset;
+ ees->lowoffset = coffs[i];
+ ees->highoffset = coffs[noff-1];
+
+ /* Determine synchronization status. Can be unsync'd either
+ * by a report from the clock or by a leap hold.
+ *
+ * Loss of the radio signal for a short time does not cause
+ * us to go unsynchronised, since the receiver keeps quite
+ * good time on its own. The spec says 20ms in 4 hours; the
+ * observed drift in our clock (Cambridge) is about a second
+ * a day, but even that keeps us within the inherent tolerance
+ * of the clock for about 15 minutes. Observation shows that
+ * the typical "short" outage is 3 minutes, so to allow us
+ * to ride out those, we will give it 5 minutes.
+ */
+ lostsync = current_time - ees->clocklastgood > 300 ? 1 : 0;
+ isinsync = (lostsync || ees->leaphold > current_time) ? 0 : 1;
+
+ /* Done. Use time of last good, synchronised code as the
+ * reference time, and lastsampletime as the receive time.
+ */
+ if (ees->fix_pending) {
+ syslog(LOG_ERR, "MSF%d: fix_pending=%d -> jump %x.%08x\n",
+ ees->fix_pending, ees->unit, offset.l_i, offset.l_f);
+ ees->fix_pending = 0;
+ set_x(&offset);
+ L_CLR(&offset);
+ }
+ refclock_receive(ees->peer,
+ &offset,
+ 0, /* delay */
+ dispersion,
+ &ees->reftime,
+ &ees->lastsampletime, /* receive time */
+ (isinsync) ? 0 : LEAP_NOTINSYNC);
+ ees_event(ees, lostsync ? CEVNT_PROP : CEVNT_NOMINAL);
+}
+
+/* msfees_poll - called by the transmit procedure */
+static void msfees_poll(unit, peer)
+ int unit;
+ char *peer;
+{
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d invalid",
+ unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d unused",
+ unit);
+ return;
+ }
+
+ ees_process(eesunits[unit]);
+
+ if ((current_time - eesunits[unit]->lasttime) > 150)
+ ees_event(eesunits[unit], CEVNT_FAULT);
+}
+
+/* msfees_leap - called when a leap second occurs */
+static void msfees_leap()
+{
+ register int i;
+
+ /* This routine should be entered a few seconds after
+ * midnight UTC when a leap second occurs. To ensure we
+ * don't believe foolish time from the clock(s) we set a
+ * 40 minute hold on them. It shouldn't take anywhere
+ * near this amount of time to adjust if the clock is getTING
+ * data, but doing anything else is complicated.
+ */
+ for (i = 0; i < MAXUNITS; i++) if (unitinuse[i])
+ eesunits[i]->leaphold = current_time + EESLEAPHOLD;
+}
+
+/* msfees_control - set fudge factors, return statistics */
+static void msfees_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct eesunit *ees = eesunits[unit];
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock: unit %d invalid (max %d)",
+ unit, MAXUNITS-1);
+ return;
+ }
+
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ fudgefactor[unit] = in->fudgetime1;
+ if (in->haveflags & CLK_HAVETIME2)
+ os_delay[unit] = in->fudgetime2;
+ offset_fudge[unit] = os_delay[unit];
+ L_ADD(&offset_fudge[unit], &fudgefactor[unit]);
+ L_ADD(&offset_fudge[unit], &inherent_delay[unit]);
+ if (in->haveflags & CLK_HAVEVAL1) {
+ stratumtouse[unit] = (u_char)(in->fudgeval1 & 0xf);
+ if (unitinuse[unit]) {
+ /* Should actually reselect clock, but
+ * will wait for the next timecode
+ */
+ struct peer *peer = ees->peer;
+ peer->stratum = stratumtouse[unit];
+ if (stratumtouse[unit] <= 1) {
+ memmove((char *)&peer->refid,
+ EESREFID, 4);
+ if (unit>0 && unit<10)
+ ((char *)&peer->refid)[3] =
+ '0' + unit;
+ }
+ else peer->refid = htonl(EESHSREFID);
+ }
+ }
+ if (in->haveflags & CLK_HAVEVAL2) {
+ printf("Debug: %x -> %x\n", debug, in->fudgeval2);
+ syslog(LOG_ERR, "MSF%d: debug %x -> %x",
+ unit, debug, in->fudgeval2);
+ debug = in->fudgeval2;
+ }
+ if (in->haveflags & CLK_HAVEFLAG1) {
+ sloppyclockflag[unit] = in->flags & CLK_FLAG1;
+ }
+ if (in->haveflags & CLK_HAVEFLAG2) {
+ ees->fix_pending++;
+ /* if (in->flags & CLK_FLAG2 && unitinuse[unit])
+ ees->leaphold = 0; */
+ }
+ if (in->haveflags & CLK_HAVEFLAG3 && unitinuse[unit]) {
+ printf("dump_vals: %x -> %x\n", ees->dump_vals, in->flags & CLK_FLAG3);
+ ees->dump_vals = in->flags & CLK_FLAG3;
+ }
+ if (in->haveflags & CLK_HAVEFLAG4 && unitinuse[unit]) {
+ ees->usealldata = in->flags & CLK_FLAG4;
+ }
+ }
+
+ if (out != 0) {
+ out->type = REFCLK_MSF_EES;
+ out->haveflags
+ = CLK_HAVETIME1|CLK_HAVETIME2|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1|CLK_HAVEFLAG3|CLK_HAVEFLAG4;
+ out->clockdesc = EESDESCRIPTION;
+ out->fudgetime1 = fudgefactor[unit];
+ out->fudgetime2 = os_delay[unit];
+ out->fudgeval1 = stratumtouse[unit];
+ /*out->fudgeval2= debug*/;
+ memmove((char *)&out->fudgeval2, EESREFID, 4);
+ if (unit > 0 && unit < 10)
+ ((char *)&out->fudgeval2)[3] = '0' + unit;
+ out->flags = sloppyclockflag[unit];
+ if (unitinuse[unit]) {
+ out->flags |= ees->dump_vals | ees->usealldata;
+ out->lencode = ees->lencode;
+ out->lastcode = ees->lastcode;
+ out->timereset = current_time - ees->timestarted;
+ out->polls = 0; /* we don't poll */
+ out->noresponse = 0; /* ditto */
+ out->badformat = ees->badformat;
+ out->baddata = ees->baddata;
+ out->lastevent = ees->lastevent;
+ out->currentstatus = ees->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;
+ }
+ }
+}
+
+
+/* msfees_buginfo - return clock dependent debugging info */
+static void msfees_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct eesunit *ees;
+
+ bug->nvalues = bug->ntimes = 0;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock: unit %d invalid (max %d)",
+ unit, MAXUNITS-1);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ ees = eesunits[unit];
+
+ bug->nvalues = 16;
+ bug->svalues = 0x0800;
+ bug->values[0] = (ees->lasttime) ? current_time - ees->lasttime : 0;
+ bug->values[1] = (ees->clocklastgood)?current_time-ees->clocklastgood:0;
+ bug->values[2] = ees->status;
+ bug->values[3] = ees->lastevent;
+ bug->values[4] = ees->reason;
+ bug->values[5] = ees->nsamples;
+ bug->values[6] = ees->codestate;
+ bug->values[7] = ees->day;
+ bug->values[8] = ees->hour;
+ bug->values[9] = ees->minute;
+ bug->values[10] = ees->second;
+ bug->values[11] = ees->tz;
+ bug->values[12] = ees->yearstart;
+ bug->values[13] = (ees->leaphold > current_time) ?
+ ees->leaphold - current_time : 0;
+ bug->values[14] = inherent_delay[unit].l_uf;
+ bug->values[15] = offset_fudge[unit].l_uf;
+
+ bug->ntimes = 11;
+ bug->stimes = 0x3f8;
+ bug->times[0] = ees->reftime;
+ bug->times[1] = ees->arrvtime;
+ bug->times[2] = ees->lastsampletime;
+ bug->times[3] = ees->offset;
+ bug->times[4] = ees->lowoffset;
+ bug->times[5] = ees->highoffset;
+ bug->times[6] = inherent_delay[unit];
+ bug->times[8] = os_delay[unit];
+ bug->times[7] = fudgefactor[unit];
+ bug->times[9] = offset_fudge[unit];
+ bug->times[10].l_ui = ees->yearstart;
+ bug->times[10].l_uf = 0;
+}
+
+struct refclock refclock_msfees = {
+ msfees_start, msfees_shutdown, msfees_poll,
+ msfees_control, msfees_init, msfees_buginfo, NOFLAGS
+};
+#endif /* defined(REFCLOCK) && defined(MSFEESPPS) && defined(STREAM) */
diff --git a/usr.sbin/xntpd/xntpd/refclock_new/refclock_mx4200.c b/usr.sbin/xntpd/xntpd/refclock_new/refclock_mx4200.c
new file mode 100644
index 000000000000..caf5951c55ed
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_new/refclock_mx4200.c
@@ -0,0 +1,977 @@
+/*
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66.
+ *
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(REFCLOCK) && defined(MX4200)
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_calendar.h"
+#include "ntp_unixtime.h"
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include <sys/ppsclock.h>
+
+#include "mx4200.h"
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the Magnavox Model MX4200 GPS Receiver.
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 2 /* max number of mx4200 units */
+#define MX4200FD "/dev/gps%d"
+#define SPEED232 B4800 /* baud */
+
+/*
+ * The number of raw samples which we acquire to derive a single estimate.
+ */
+#define NSTMPS 64
+
+/*
+ * Radio interface parameters
+ */
+#define MX4200PRECISION (-18) /* precision assumed (about 4 us) */
+#define MX4200REFID "GPS" /* reference id */
+#define MX4200DESCRIPTION "Magnavox MX4200 GPS Receiver" /* WRU */
+#define DEFFUDGETIME 0 /* default fudge time (ms) */
+
+/* Leap stuff */
+extern u_long leap_hoursfromleap;
+extern u_long leap_happened;
+static int leap_debug;
+
+/*
+ * mx4200_reset - reset the count back to zero
+ */
+#define mx4200_reset(up) \
+ do { \
+ (up)->nsamples = 0; \
+ } while (0)
+
+/*
+ * Imported from the timer module
+ */
+extern u_long current_time;
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * MX4200 unit control structure.
+ */
+struct mx4200unit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ u_long gpssamples[NSTMPS]; /* the GPS time samples */
+ l_fp unixsamples[NSTMPS]; /* the UNIX time samples */
+
+
+ l_fp lastsampletime; /* time of last estimate */
+ u_int lastserial; /* last pps serial number */
+#ifdef notdef
+ l_fp lastrec; /* last receive time */
+ l_fp lastref; /* last timecode time */
+#endif
+ char lastcode[RX_BUFF_SIZE]; /* last timecode received */
+ u_long lasttime; /* last time clock heard from */
+ u_char nsamples; /* number of samples we've collected */
+ 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 lencode; /* length of last timecode */
+ u_char year; /* year of eternity */
+ u_short monthday; /* day of month */
+ u_char hour; /* hour of day */
+ u_char minute; /* minute of hour */
+ u_char second; /* seconds of minute */
+ u_char leap; /* leap indicators */
+ /*
+ * Status tallies
+ */
+#ifdef notdef
+ u_long polls; /* polls sent */
+ u_long noresponse; /* number of nonresponses */
+#endif
+ u_long badformat; /* bad format */
+ u_long baddata; /* bad data */
+ u_long timestarted; /* time we started this */
+};
+
+/*
+ * We demand that consecutive PPS samples are more than 0.995 seconds
+ * and less than 1.005 seconds apart.
+ */
+#define PPSLODIFF_UI 0 /* 0.900 as an l_fp */
+#define PPSLODIFF_UF 0xe6666610
+
+#define PPSHIDIFF_UI 1 /* 1.100 as an l_fp */
+#define PPSHIDIFF_UF 0x19999990
+
+/*
+ * reason codes
+ */
+#define PPSREASON 20
+#define CODEREASON 40
+#define PROCREASON 60
+
+/*
+ * Data space for the unit structures. Note that we allocate these on
+ * the fly, but never give them back.
+ */
+static struct mx4200unit *mx4200units[MAXUNITS];
+
+static const char pmvxg[] = "PMVXG";
+
+/*
+ * Function prototypes
+ */
+static int mx4200_start P((int, struct peer *));
+static void mx4200_shutdown P((int, struct peer *));
+static void mx4200_receive P((struct recvbuf *));
+static void mx4200_process P((struct mx4200unit *));
+static void mx4200_poll P((int, struct peer *));
+
+static char * mx4200_parse P((char *, struct calendar *, int *, int *));
+static int mx4200_needconf P((char *));
+static void mx4200_config P((struct mx4200unit *));
+static void mx4200_send P((int, const char *, ...));
+static int mx4200_cmpl_fp P((void *, void *));
+static u_char cksum P((char *, u_int));
+
+#ifdef DEBUG
+static void opendfile P((int));
+static void checkdfile P((void));
+#endif /* DEBUG */
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_mx4200 = {
+ mx4200_start, /* start up driver */
+ mx4200_shutdown, /* shut down driver */
+ mx4200_poll, /* transmit poll message */
+ noentry, /* not used (old mx4200_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old mx4200_buginfo) */
+ NOFLAGS /* not used */
+};
+
+#ifdef DEBUG
+static char dfile[] = "/var/tmp/MX4200.debug";
+static FILE *df = NULL;
+
+static void
+opendfile(create)
+ int create;
+{
+ if (!create && access(dfile, F_OK) < 0) {
+ syslog(LOG_ERR, "mx4200: open %s: %m", dfile);
+ return;
+ }
+ df = fopen(dfile, "a");
+ if (df == NULL)
+ syslog(LOG_ERR, "mx4200: open %s: %m", dfile);
+ else if (setvbuf(df, NULL, _IOLBF, 0) < 0)
+ syslog(LOG_ERR, "mx4200: setvbuf %s: %m", dfile);
+}
+
+static void
+checkdfile()
+{
+
+ if (df == NULL)
+ return;
+
+ if (access(dfile, F_OK) < 0) {
+ fclose(df);
+ opendfile(1);
+ }
+}
+
+#endif
+
+
+/*
+ * mx4200_start - open the devices and initialize data for processing
+ */
+static int
+mx4200_start(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct mx4200unit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
+
+ /*
+ * Open serial port
+ */
+ (void)sprintf(device, MX4200FD, unit);
+ if (!(fd = refclock_open(device, SPEED232, 0)))
+ return (0);
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ if (!(up = (struct mx4200unit *)
+ emalloc(sizeof(struct mx4200unit)))) {
+ (void) close(fd);
+ return (0);
+ }
+ memset((char *)up, 0, sizeof(struct mx4200unit));
+ up->io.clock_recv = mx4200_receive;
+ up->io.srcclock = (caddr_t)up;
+ up->io.datalen = 0;
+ up->io.fd = fd;
+ if (!io_addclock(&up->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+ up->peer = peer;
+ pp = peer->procptr;
+ pp->unitptr = (caddr_t)up;
+
+ /*
+ * Initialize miscellaneous variables
+ */
+ peer->precision = MX4200PRECISION;
+ pp->clockdesc = MX4200DESCRIPTION;
+ memcpy((char *)&pp->refid, MX4200REFID, 4);
+
+ /* Insure the receiver is properly configured */
+ mx4200_config(up);
+
+#ifdef DEBUG
+ opendfile(0);
+#endif
+ return (1);
+}
+
+
+/*
+ * mx4200_shutdown - shut down the clock
+ */
+static void
+mx4200_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct mx4200unit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct mx4200unit *)pp->unitptr;
+ io_closeclock(&up->io);
+ free(up);
+}
+
+
+static void
+mx4200_config(up)
+ register struct mx4200unit *up;
+{
+ register int fd = up->io.fd;
+
+syslog(LOG_DEBUG, "mx4200_config");
+
+ /* Zero the output list (do it twice to flush possible junk) */
+ mx4200_send(fd, "%s,%03d,,%d,,,,,,", pmvxg, PMVXG_S_PORTCONF, 1);
+ mx4200_send(fd, "%s,%03d,,%d,,,,,,", pmvxg, PMVXG_S_PORTCONF, 1);
+
+ /* Switch to 2d mode */
+ mx4200_send(fd, "%s,%03d,%d,,%.1f,%.1f,,%d,%d,%c,%d",
+ pmvxg, PMVXG_S_INITMODEB,
+ 2, /* 2d mode */
+ 0.1, /* hor accel fact as per Steve */
+ 0.1, /* ver accel fact as per Steve */
+ 10, /* hdop limit as per Steve */
+ 5, /* elevation limit as per Steve */
+ 'U', /* time output mode */
+ 0); /* local time offset from gmt */
+
+ /* Configure time recovery */
+ mx4200_send(fd, "%s,%03d,%c,%c,%c,%d,%d,%d,",
+ pmvxg, PMVXG_S_TRECOVCONF,
+#ifdef notdef
+ 'K', /* known position */
+ 'D', /* dynamic position */
+#else
+ 'S', /* static position */
+#endif
+ 'U', /* steer clock to gps time */
+ 'A', /* always output time pulse */
+ 500, /* max time error in ns */
+ 0, /* user bias in ns */
+ 1); /* output to control port */
+}
+
+
+/*
+ * mx4200_poll - mx4200 watchdog routine
+ */
+static void
+mx4200_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct mx4200unit *up;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "mx4200_poll: unit %d invalid", unit);
+ return;
+ }
+
+ up = mx4200units[unit];
+ if ((current_time - up->lasttime) > 150) {
+ refclock_report(peer, CEVNT_FAULT);
+
+ /* Request a status message which should trigger a reconfig */
+ mx4200_send(up->io.fd, "%s,%03d", "CDGPQ", PMVXG_D_STATUS);
+ syslog(LOG_DEBUG, "mx4200_poll: request status");
+ }
+}
+
+static const char char2hex[] = "0123456789ABCDEF";
+
+
+/*
+ * mx4200_receive - receive gps data
+ */
+static void
+mx4200_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register struct mx4200unit *up;
+ struct peer *peer;
+ register char *dpt, *cp;
+ register u_long tmp_ui;
+ register u_long tmp_uf;
+ register u_long gpstime;
+ struct ppsclockev ev;
+ register struct calendar *jt;
+ struct calendar sjt;
+ register int n;
+ int valid, leapsec;
+ register u_char ck;
+
+ up = (struct mx4200unit *)rbufp->recv_srcclock;
+ peer = up->peer;
+#ifdef DEBUG
+ if (debug > 3)
+ printf("mx4200_receive: nsamples = %d\n", up->nsamples);
+#endif
+
+ /* Record the time of this event */
+ up->lasttime = current_time;
+
+ /* Get the pps value */
+ if (ioctl(up->io.fd, CIOGETEV, (char *)&ev) < 0) {
+ /* XXX Actually, if this fails, we're pretty much screwed */
+#ifdef DEBUG
+ if (debug) {
+ fprintf(stderr, "mx4200_receive: ");
+ perror("CIOGETEV");
+ }
+#endif
+ refclock_report(peer, CEVNT_FAULT);
+ mx4200_reset(up);
+ return;
+ }
+ tmp_ui = ev.tv.tv_sec + JAN_1970;
+ TVUTOTSF(ev.tv.tv_usec, tmp_uf);
+
+ /* Get buffer and length; sock away last timecode */
+ n = rbufp->recv_length;
+ dpt = rbufp->recv_buffer;
+ if (n <= 1)
+ return;
+ up->lencode = n;
+ memmove(up->lastcode, dpt, n);
+
+ /*
+ * We expect to see something like:
+ *
+ * $PMVXG,830,T,1992,07,09,04:18:34,U,S,-02154,00019,000000,00*1D\n
+ *
+ * Reject if any important landmarks are missing.
+ */
+ cp = dpt + n - 4;
+ if (cp < dpt || *dpt != '$' || cp[0] != '*' || cp[3] != '\n') {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: bad format\n");
+#endif
+ refclock_report(peer, CEVNT_BADREPLY);
+ mx4200_reset(up);
+ return;
+ }
+
+ /* Check checksum */
+ ck = cksum(&dpt[1], n - 5);
+ if (char2hex[ck >> 4] != cp[1] || char2hex[ck & 0xf] != cp[2]) {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: bad checksum\n");
+#endif
+ refclock_report(peer, CEVNT_BADREPLY);
+ mx4200_reset(up);
+ return;
+ }
+
+ /* Truncate checksum (and the buffer for that matter) */
+ *cp = '\0';
+
+ /* Leap second debugging stuff */
+ if ((leap_hoursfromleap && !leap_happened) || leap_debug > 0) {
+ /* generate reports for awhile after leap */
+ if (leap_hoursfromleap && !leap_happened)
+ leap_debug = 3600;
+ else
+ --leap_debug;
+ syslog(LOG_INFO, "mx4200 leap: %s \"%s\"",
+ umfptoa(tmp_ui, tmp_uf, 6), dpt);
+ }
+
+ /* Parse time recovery message */
+ jt = &sjt;
+ if ((cp = mx4200_parse(dpt, jt, &valid, &leapsec)) != NULL) {
+ /* Configure the receiver if necessary */
+ if (mx4200_needconf(dpt))
+ mx4200_config(up);
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: mx4200_parse: %s\n", cp);
+#endif
+ refclock_report(peer, CEVNT_BADREPLY);
+ mx4200_reset(up);
+ return;
+ }
+
+ /* Setup leap second indicator */
+ if (leapsec == 0)
+ up->leap = LEAP_NOWARNING;
+ else if (leapsec == 1)
+ up->leap = LEAP_ADDSECOND;
+ else if (leapsec == -1)
+ up->leap = LEAP_DELSECOND;
+ else
+ up->leap = LEAP_NOTINSYNC; /* shouldn't happen */
+
+ /* Check parsed time (allow for possible leap seconds) */
+ if (jt->second >= 61 || jt->minute >= 60 || jt->hour >= 24) {
+#ifdef DEBUG
+ if (debug) {
+ printf("mx4200_receive: bad time %d:%02d:%02d",
+ jt->hour, jt->minute, jt->second);
+ if (leapsec != 0)
+ printf(" (leap %+d)", leapsec);
+ putchar('\n');
+ }
+#endif
+ refclock_report(peer, CEVNT_BADTIME);
+ mx4200_reset(up);
+ /* Eat the next pulse which the clock claims will be bad */
+ up->nsamples = -1;
+ return;
+ }
+
+ /* Check parsed date */
+ if (jt->monthday > 31 || jt->month > 12 || jt->year < 1900) {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: bad date (%d/%d/%d)\n",
+ jt->monthday, jt->month, jt->year);
+#endif
+ refclock_report(peer, CEVNT_BADDATE);
+ mx4200_reset(up);
+ return;
+ }
+
+ /* Convert to ntp time */
+ gpstime = caltontp(jt);
+
+ /* The gps message describes the *next* pulse; pretend it's this one */
+ --gpstime;
+
+ /* Debugging */
+#ifdef DEBUG
+ checkdfile();
+ if (df != NULL) {
+ l_fp t;
+
+ t.l_ui = gpstime;
+ t.l_uf = 0;
+ M_SUB(t.l_ui, t.l_uf, tmp_ui, tmp_uf);
+ fprintf(df, "%s\t%s",
+ umfptoa(tmp_ui, tmp_uf, 6), mfptoa(t.l_ui, t.l_uf, 6));
+ if (debug > 3)
+ fprintf(df, "\t(gps: %lu)", gpstime);
+ if (leapsec != 0)
+ fprintf(df, "\t(leap sec %+d)", leapsec);
+ if (!valid)
+ fprintf(df, "\t(pulse not valid)");
+ fputc('\n', df);
+ }
+#endif
+
+ /* Check pps serial number against last one */
+ if (up->lastserial + 1 != ev.serial && up->lastserial != 0) {
+#ifdef DEBUG
+ if (debug) {
+ if (ev.serial == up->lastserial)
+ printf("mx4200_receive: no new pps event\n");
+ else
+ printf("mx4200_receive: missed %d pps events\n",
+ ev.serial - up->lastserial - 1);
+ }
+#endif
+ refclock_report(peer, CEVNT_FAULT);
+ mx4200_reset(up);
+ /* fall through and this one collect as first sample */
+ }
+ up->lastserial = ev.serial;
+
+/*
+ * XXX
+ * Since this message is for the next pulse, it's really the next pulse
+ * that the clock might be telling us will be invalid.
+ */
+ /* Toss if not designated "valid" by the gps */
+ if (!valid) {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: pps not valid\n");
+#endif
+ refclock_report(peer, CEVNT_BADTIME);
+ mx4200_reset(up);
+ return;
+ }
+
+ /* Copy time into mx4200unit struct */
+ /* XXX (why?) */
+ up->year = jt->year;
+ up->monthday = jt->monthday;
+ up->hour = jt->hour;
+ up->minute = jt->minute;
+ up->second = jt->second;
+
+ /* Sock away the GPS and UNIX timesamples */
+ n = up->nsamples++;
+ if (n < 0)
+ return; /* oops, this pulse is bad */
+ up->gpssamples[n] = gpstime;
+ up->unixsamples[n].l_ui = up->lastsampletime.l_ui = tmp_ui;
+ up->unixsamples[n].l_uf = up->lastsampletime.l_uf = tmp_uf;
+ if (up->nsamples >= NSTMPS) {
+ /*
+ * Here we've managed to complete an entire NSTMPS
+ * second cycle without major mishap. Process what has
+ * been received.
+ */
+ mx4200_process(up);
+ mx4200_reset(up);
+ }
+}
+
+/*
+ * Compare two l_fp's, used with qsort()
+ */
+static int
+mx4200_cmpl_fp(p1, p2)
+ register void *p1, *p2;
+{
+
+ if (!L_ISGEQ((l_fp *)p1, (l_fp *)p2))
+ return (-1);
+ if (L_ISEQU((l_fp *)p1, (l_fp *)p2))
+ return (0);
+ return (1);
+}
+
+/*
+ * mx4200_process - process a pile of samples from the clock
+ */
+static void
+mx4200_process(up)
+ struct mx4200unit *up;
+{
+ struct peer *peer;
+ struct refclockproc *pp;
+ register int i, n;
+ register l_fp *fp, *op;
+ register u_long *lp;
+ l_fp off[NSTMPS];
+ register u_long tmp_ui, tmp_uf;
+ register u_long date_ui, date_uf;
+ u_fp dispersion;
+
+ /* Compute offsets from the raw data. */
+ peer = up->peer;
+ pp = peer->procptr;
+ fp = up->unixsamples;
+ op = off;
+ lp = up->gpssamples;
+ for (i = 0; i < NSTMPS; ++i, ++lp, ++op, ++fp) {
+ op->l_ui = *lp;
+ op->l_uf = 0;
+ L_SUB(op, fp);
+ }
+
+ /* Sort offsets into ascending order. */
+ qsort((char *)off, NSTMPS, sizeof(l_fp), mx4200_cmpl_fp);
+
+ /*
+ * Reject the furthest from the median until 8 samples left
+ */
+ i = 0;
+ n = NSTMPS;
+ while ((n - i) > 8) {
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ date_ui = off[(n+i)/2].l_ui;
+ date_uf = off[(n+i)/2].l_uf;
+ M_SUB(tmp_ui, tmp_uf, date_ui, date_uf);
+ M_SUB(date_ui, date_uf, off[i].l_ui, off[i].l_uf);
+ if (M_ISHIS(date_ui, date_uf, tmp_ui, tmp_uf)) {
+ /*
+ * reject low end
+ */
+ i++;
+ } else {
+ /*
+ * reject high end
+ */
+ n--;
+ }
+ }
+
+ /*
+ * Compute the dispersion based on the difference between the
+ * extremes of the remaining offsets.
+ */
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ M_SUB(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
+ dispersion = MFPTOFP(tmp_ui, tmp_uf);
+
+ /*
+ * Now compute the offset estimate. If the sloppy clock
+ * flag is set, average the remainder, otherwise pick the
+ * median.
+ */
+ if (pp->sloppyclockflag) {
+ tmp_ui = tmp_uf = 0;
+ while (i < n) {
+ M_ADD(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
+ i++;
+ }
+ M_RSHIFT(tmp_ui, tmp_uf);
+ M_RSHIFT(tmp_ui, tmp_uf);
+ M_RSHIFT(tmp_ui, tmp_uf);
+ i = 0;
+ off[0].l_ui = tmp_ui;
+ off[0].l_uf = tmp_uf;
+ } else {
+ i = (n + i) / 2;
+ }
+
+ /*
+ * Add the default MX4200 QT delay into this.
+ */
+#ifdef notdef
+ L_ADDUF(&off[i], MX4200QTFUDGE);
+#endif
+
+ /*
+ * Done. Use lastref as the reference time and lastrec
+ * as the receive time. ** note this can result in tossing
+ * out the peer in the protocol module if lastref > lastrec,
+ * so last rec is used for both values - dlm ***
+ */
+ refclock_receive(up->peer, &off[i],
+ (s_fp)0, /* delay */
+ dispersion,
+ &up->unixsamples[NSTMPS-1], /* reftime */
+ &up->unixsamples[NSTMPS-1], /* rectime */
+ up->leap);
+
+ refclock_report(peer, CEVNT_NOMINAL);
+}
+
+
+/*
+ * Returns true if the this is a status message. We use this as
+ * an indication that the receiver needs to be initialized.
+ */
+static int
+mx4200_needconf(buf)
+ char *buf;
+{
+ register long v;
+ char *cp;
+
+ cp = buf;
+
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Record type */
+ v = strtol(cp, &cp, 10);
+ if (v != PMVXG_D_STATUS)
+ return (0);
+ /*
+ * XXX
+ * Since we configure the receiver to not give us status
+ * messages and since the receiver outputs status messages by
+ * default after being reset to factory defaults when sent the
+ * "$PMVXG,018,C\r\n" message, any status message we get
+ * indicates the reciever needs to be initialized; thus, it is
+ * not necessary to decode the status message.
+ */
+#ifdef notdef
+ ++cp;
+
+ /* Receiver status */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Number of satellites which should be visible */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Number of satellites being tracked */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Time since last NAV */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Initialization status */
+ v = strtol(cp, &cp, 10);
+ if (v == 0)
+#endif
+ return (1);
+}
+
+/* Parse a mx4200 time recovery message. Returns a string if error */
+static char *
+mx4200_parse(buf, jt, validp, leapsecp)
+ register char *buf;
+ register struct calendar *jt;
+ register int *validp, *leapsecp;
+{
+ register long v;
+ char *cp;
+
+ cp = buf;
+ memset((char *)jt, 0, sizeof(*jt));
+
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no rec-type");
+ ++cp;
+
+ /* Record type */
+ v = strtol(cp, &cp, 10);
+ if (v != PMVXG_D_TRECOVOUT)
+ return ("wrong rec-type");
+
+ /* Pulse valid indicator */
+ if (*cp++ != ',')
+ return ("no pulse-valid");
+ if (*cp == 'T')
+ *validp = 1;
+ else if (*cp == 'F')
+ *validp = 0;
+ else
+ return ("bad pulse-valid");
+ ++cp;
+
+ /* Year */
+ if (*cp++ != ',')
+ return ("no year");
+ jt->year = strtol(cp, &cp, 10);
+
+ /* Month of year */
+ if (*cp++ != ',')
+ return ("no month");
+ jt->month = strtol(cp, &cp, 10);
+
+ /* Day of month */
+ if (*cp++ != ',')
+ return ("no month day");
+ jt->monthday = strtol(cp, &cp, 10);
+
+ /* Hour */
+ if (*cp++ != ',')
+ return ("no hour");
+ jt->hour = strtol(cp, &cp, 10);
+
+ /* Minute */
+ if (*cp++ != ':')
+ return ("no minute");
+ jt->minute = strtol(cp, &cp, 10);
+
+ /* Second */
+ if (*cp++ != ':')
+ return ("no second");
+ jt->second = strtol(cp, &cp, 10);
+
+ /* Time indicator */
+ if (*cp++ != ',' || *cp++ == '\0')
+ return ("no time indicator");
+
+ /* Time recovery mode */
+ if (*cp++ != ',' || *cp++ == '\0')
+ return ("no time mode");
+
+ /* Oscillator offset */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no osc off");
+ ++cp;
+
+ /* Time mark error */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no time mark err");
+ ++cp;
+
+ /* User time bias */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no user bias");
+ ++cp;
+
+ /* Leap second flag */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no leap");
+ ++cp;
+ *leapsecp = strtol(cp, &cp, 10);
+
+ return (NULL);
+}
+
+/* Calculate the checksum */
+static u_char
+cksum(cp, n)
+ register char *cp;
+ register u_int n;
+{
+ register u_char ck;
+
+ for (ck = 0; n-- > 0; ++cp)
+ ck ^= *cp;
+ return (ck);
+}
+
+static void
+#if __STDC__
+mx4200_send(register int fd, const char *fmt, ...)
+#else
+mx4200_send(fd, fmt, va_alist)
+ register int fd;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ register char *cp;
+ register int n, m;
+ va_list ap;
+ char buf[1024];
+ u_char ck;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ cp = buf;
+ *cp++ = '$';
+#ifdef notdef
+ /* BSD is rational */
+ n = vsnprintf(cp, sizeof(buf) - 1, fmt, ap);
+#else
+ /* SunOS sucks */
+ (void)vsprintf(cp, fmt, ap);
+ n = strlen(cp);
+#endif
+ ck = cksum(cp, n);
+ cp += n;
+ ++n;
+#ifdef notdef
+ /* BSD is rational */
+ n += snprintf(cp, sizeof(buf) - n - 5, "*%02X\r\n", ck);
+#else
+ /* SunOS sucks */
+ sprintf(cp, "*%02X\r\n", ck);
+ n += strlen(cp);
+#endif
+
+ m = write(fd, buf, n);
+ if (m < 0)
+ syslog(LOG_ERR, "mx4200_send: write: %m (%s)", buf);
+ else if (m != n)
+ syslog(LOG_ERR, "mx4200_send: write: %d != %d (%s)", m, n, buf);
+ va_end(ap);
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_new/refclock_omega.c b/usr.sbin/xntpd/xntpd/refclock_new/refclock_omega.c
new file mode 100644
index 000000000000..e62b668956f3
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_new/refclock_omega.c
@@ -0,0 +1,999 @@
+/*
+ * refclock_omega - clock driver for the Kinemetrics Truetime OM-DC OMEGA
+ * receiver.
+ *
+ * Version 1.0 11-Dec-92 Steve Clift (clift@ml.csiro.au)
+ * Initial version, mostly lifted from refclock_goes.c.
+ *
+ * 1.1 03-May-93 Steve Clift
+ * Tarted up the sample filtering mechanism to give improved
+ * one-off measurements. Improved measurement dispersion code
+ * to account for accumulated drift when the clock loses lock.
+ *
+ */
+
+#if defined(REFCLOCK) && (defined(OMEGA) || defined(OMEGACLK) || defined(OMEGAPPS))
+
+#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"
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(OMEGACLK)
+#include <sys/clkdefs.h>
+#endif /* OMEGACLK */
+#endif /* STREAM */
+
+#if defined (OMEGAPPS)
+#include <sys/ppsclock.h>
+#endif /* OMEGAPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+ * Support for Kinemetrics Truetime OM-DC OMEGA Receiver
+ *
+ * Most of this code is copied from refclock_goes.c with thanks.
+ *
+ * the time code looks like follows; Send the clock a R or C and once per
+ * second a timestamp will appear that looks like this:
+ * ADDD:HH:MM:SSQCL
+ * A - control A
+ * Q Quality indication: indicates possible error of
+ * > >+- 5 seconds
+ * ? >+/- 500 milliseconds # >+/- 50 milliseconds
+ * * >+/- 5 milliseconds . >+/- 1 millisecond
+ * A-H less than 1 millisecond. Character indicates which station
+ * is being received as follows:
+ * A = Norway, B = Liberia, C = Hawaii, D = North Dakota,
+ * E = La Reunion, F = Argentina, G = Australia, H = Japan.
+ * C - Carriage return
+ * L - Line feed
+ * The carriage return start bit begins on 0 seconds and extends to 1 bit time.
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 4 /* max number of OMEGA units */
+#define OMEGA232 "/dev/omega%d"
+#define SPEED232 B9600 /* 9600 baud */
+
+/*
+ * Radio interface parameters
+ */
+#define OMEGADESCRIPTION "Kinemetrics OM-DC OMEGA Receiver" /* who we are */
+#define OMEGAMAXDISPERSE (FP_SECOND/32) /* max allowed sample dispersion */
+#define OMEGAPRECISION (-10) /* precision assumed (about 1 ms) */
+#define OMEGAREFID "VLF\0" /* reference id */
+#define LENOMEGA 13 /* length of standard response */
+#define GMT 0 /* hour offset from Greenwich */
+#define NSTAMPS 9 /* samples collected when polled */
+#define NSKEEP 5 /* samples to keep after discards */
+#define BMAX 50 /* timecode buffer length */
+
+/*
+ * The OM-DC puts out the start bit of the <CR> on the second, but
+ * we see the result after the <LF> is received, about 2ms later at
+ * 9600 baud. Use this as the default fudge time, and let the user
+ * fiddle it to account for driver latency etc.
+ */
+#define DEFFUDGETIME 0x00830000 /* default fudge time (~2ms) */
+
+/*
+ * Clock drift errors as u_fp values.
+ */
+#define U_FP5000MS (5*FP_SECOND) /* 5 seconds */
+#define U_FP500MS (FP_SECOND/2) /* 500 msec */
+#define U_FP50MS (FP_SECOND/20) /* 50 msec */
+#define U_FP5MS (FP_SECOND/200) /* 5 msec */
+
+/*
+ * Station codes
+ */
+#define STATION_NONE 0
+#define STATION_NORWAY 1
+#define STATION_LIBERIA 2
+#define STATION_HAWAII 3
+#define STATION_N_DAKOTA 4
+#define STATION_LA_REUNION 5
+#define STATION_ARGENTINA 6
+#define STATION_AUSTRALIA 7
+#define STATION_JAPAN 8
+
+/*
+ * Hack to avoid excercising the multiplier. I have no pride.
+ */
+#define MULBY10(x) (((x)<<3) + ((x)<<1))
+
+/*
+ * Imported from the timer module
+ */
+extern u_long current_time;
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * OMEGA unit control structure
+ */
+struct omegaunit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ l_fp lastrec; /* last receive time */
+ l_fp lastref; /* last timecode time */
+ l_fp offset[NSTAMPS]; /* recent sample offsets */
+ char lastcode[BMAX]; /* last timecode received */
+ u_short station; /* which station we're locked to */
+ u_short polled; /* Hand in a time sample? */
+ u_long coderecv; /* timecodes received */
+ u_char lencode; /* length of last timecode */
+ u_long lasttime; /* last time clock heard from */
+ 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 failure */
+ 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_char leap; /* leap indicators */
+ u_short msec; /* millisecond of second */
+ u_char quality; /* quality char from last timecode */
+ u_long yearstart; /* start of current year */
+ /*
+ * Status tallies
+ */
+ u_long polls; /* polls sent */
+ u_long noreply; /* no replies to polls */
+ 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 omegaunit *omegaunits[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 fudgefactor1[MAXUNITS];
+static l_fp fudgefactor2[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static u_char readonlyclockflag[MAXUNITS];
+static u_long refid[MAXUNITS];
+
+/*
+ * Function prototypes
+ */
+static void omega_init P((void));
+static int omega_start P((u_int, struct peer *));
+static void omega_shutdown P((int));
+static void omega_report_event P((struct omegaunit *, int));
+static void omega_receive P((struct recvbuf *));
+static char omega_process P((struct omegaunit *, l_fp *, u_fp *));
+static void omega_poll P((int, struct peer *));
+static void omega_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void omega_buginfo P((int, struct refclockbug *));
+static void omega_send P((struct omegaunit *, char *));
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_omega = {
+ omega_start, omega_shutdown, omega_poll,
+ omega_control, omega_init, omega_buginfo, NOFLAGS
+};
+
+/*
+ * omega_init - initialize internal omega driver data
+ */
+static void
+omega_init()
+{
+ register int i;
+ /*
+ * Just zero the data arrays
+ */
+ memset((char *)omegaunits, 0, sizeof omegaunits);
+ memset((char *)unitinuse, 0, sizeof unitinuse);
+
+ /*
+ * Initialize fudge factors to default.
+ */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor1[i].l_ui = 0;
+ fudgefactor1[i].l_uf = DEFFUDGETIME;
+ fudgefactor2[i].l_ui = 0;
+ fudgefactor2[i].l_uf = 0;
+ stratumtouse[i] = 0;
+ readonlyclockflag[i] = 0;
+ memcpy((char *)&refid[i], OMEGAREFID, 4);
+ }
+}
+
+
+/*
+ * omega_start - open the OMEGA devices and initialize data for processing
+ */
+static int
+omega_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct omegaunit *omega;
+ register int i;
+ int fd232;
+ char omegadev[20];
+
+ /*
+ * Check configuration info
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,"omega_start: unit %d invalid", unit);
+ return 0;
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "omega_start: unit %d in use", unit);
+ return 0;
+ }
+
+ /*
+ * Open serial port
+ */
+ (void) sprintf(omegadev, OMEGA232, unit);
+ fd232 = open(omegadev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR, "omega_start: open of %s: %m", omegadev);
+ 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,
+ "omega_start: ioctl(%s, TCGETA): %m", omegadev);
+ 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,
+ "omega_start: ioctl(%s, TCSETA): %m", omegadev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(HAVE_TERMIOS)
+ /*
+ * POSIX serial line parameters (termios interface)
+ *
+ * The OMEGACLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The OMEGAPPS 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,
+ "omega_start: tcgetattr(%s): %m", omegadev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ 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,
+ "omega_start: tcsetattr(%s): %m", omegadev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: tcflush(%s): %m", omegadev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_TERMIOS */
+#ifdef STREAM
+#if defined(OMEGACLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, I_PUSH, clk): %m", omegadev);
+ if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, CLK_SETSTR): %m", omegadev);
+#endif /* OMEGACLK */
+#if defined(OMEGAPPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, I_PUSH, ppsclock): %m", omegadev);
+ else
+ fdpps = fd232;
+#endif /* OMEGAPPS */
+#endif /* STREAM */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The OMEGACLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(OMEGACLK)
+ int ldisc = CLKLDISC;
+#endif /* OMEGACLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, TIOCGETP): %m", omegadev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(OMEGACLK)
+ 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 /* OMEGACLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, TIOCSETP): %m", omegadev);
+ goto screwed;
+ }
+#if defined(OMEGACLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, TIOCSETD): %m",omegadev);
+ goto screwed;
+ }
+#endif /* OMEGACLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Allocate unit structure
+ */
+ if (omegaunits[unit] != 0) {
+ omega = omegaunits[unit]; /* The one we want is okay */
+ } else {
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && omegaunits[i] != 0)
+ break;
+ }
+ if (i < MAXUNITS) {
+ /*
+ * Reclaim this one
+ */
+ omega = omegaunits[i];
+ omegaunits[i] = 0;
+ } else {
+ omega = (struct omegaunit *)
+ emalloc(sizeof(struct omegaunit));
+ }
+ }
+ memset((char *)omega, 0, sizeof(struct omegaunit));
+ omegaunits[unit] = omega;
+
+ /*
+ * Set up the structures
+ */
+ omega->peer = peer;
+ omega->unit = (u_char)unit;
+ omega->timestarted = current_time;
+ omega->station = STATION_NONE;
+
+ omega->io.clock_recv = omega_receive;
+ omega->io.srcclock = (caddr_t)omega;
+ omega->io.datalen = 0;
+ omega->io.fd = fd232;
+ if (!io_addclock(&omega->io)) {
+ goto screwed;
+ }
+
+ /*
+ * All done. Initialize a few random peer variables, then
+ * return success.
+ */
+ peer->precision = OMEGAPRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ unitinuse[unit] = 1;
+ return 1;
+
+ /*
+ * Something broke; abandon ship
+ */
+screwed:
+ (void) close(fd232);
+ return 0;
+}
+
+
+/*
+ * omega_shutdown - shut down a OMEGA clock
+ */
+static void
+omega_shutdown(unit)
+ int unit;
+{
+ register struct omegaunit *omega;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_shutdown: unit %d invalid",
+ unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "omega_shutdown: unit %d not in use", unit);
+ return;
+ }
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ omega = omegaunits[unit];
+ io_closeclock(&omega->io);
+ unitinuse[unit] = 0;
+}
+
+
+/*
+ * omega_report_event - note the occurance of an event
+ */
+static void
+omega_report_event(omega, code)
+ struct omegaunit *omega;
+ int code;
+{
+ struct peer *peer;
+
+ peer = omega->peer;
+ if (omega->status != (u_char)code) {
+ omega->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ omega->lastevent = (u_char)code;
+ syslog(LOG_INFO,
+ "omega clock %s event %x\n", ntoa(&peer->srcadr), code);
+ }
+}
+
+
+/*
+ * omega_receive - receive data from the serial interface on a
+ * Kinemetrics OM-DC OMEGA clock.
+ */
+static void
+omega_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register int i;
+ register struct omegaunit *omega;
+ register u_char *dpt;
+ register char *cp, *cpend;
+ register u_char *dpend;
+ l_fp tstmp;
+ u_fp dispersion, drift;
+
+ /*
+ * Get the clock this applies to and a pointers to the data
+ */
+ omega = (struct omegaunit *)rbufp->recv_srcclock;
+ dpt = (u_char *)&rbufp->recv_space;
+
+#ifndef PEDANTIC
+ /*
+ * The OM-DC outputs a timecode every second, but we only want
+ * a set of NSTAMPS timecodes when polled (every 64 seconds).
+ * Setting PEDANTIC causes a sanity check on every timecode.
+ */
+ if (!omega->polled)
+ return;
+#endif
+
+ /*
+ * Edit timecode to remove control chars
+ */
+ dpend = dpt + rbufp->recv_length;
+ cp = omega->lastcode;
+ cpend = omega->lastcode + BMAX - 1;
+ while (dpt < dpend && cp < cpend) {
+ if ((*cp = 0x7f & *dpt++) >= ' ') cp++;
+#ifdef OMEGACLK
+ else if (*cp == '\r') {
+ if (dpend - dpt < 8) {
+ /* short timestamp */
+ return;
+ }
+ if (!buftvtots(dpt,&omega->lastrec)) {
+ /* screwy timestamp */
+ return;
+ }
+ dpt += 8;
+ }
+#endif
+ }
+ *cp = '\0';
+ omega->lencode = cp - omega->lastcode;
+
+ if (omega->lencode == 0)
+ return;
+ else if (omega->lencode != LENOMEGA) {
+ omega->badformat++;
+ /* Sometimes get a lot of these, filling the log with noise */
+ /* omega_report_event(omega, CEVNT_BADREPLY); */
+ return;
+ }
+
+#ifndef OMEGACLK
+ omega->lastrec = rbufp->recv_time;
+#endif
+
+#ifdef DEBUG
+ if (debug)
+ printf("omega: timecode %d %s\n",
+ omega->lencode, omega->lastcode);
+#endif
+
+ /*
+ * We get down to business, check the timecode format
+ * and decode its contents.
+ */
+ cp = omega->lastcode;
+ omega->leap = 0;
+ /*
+ * Check timecode format.
+ */
+ if (!isdigit(cp[0]) || /* day of year */
+ !isdigit(cp[1]) ||
+ !isdigit(cp[2]) ||
+ cp[3] != ':' || /* <sp> */
+ !isdigit(cp[4]) || /* hours */
+ !isdigit(cp[5]) ||
+ cp[6] != ':' || /* : separator */
+ !isdigit(cp[7]) || /* minutes */
+ !isdigit(cp[8]) ||
+ cp[9] != ':' || /* : separator */
+ !isdigit(cp[10]) || /* seconds */
+ !isdigit(cp[11])) {
+ omega->badformat++;
+ omega_report_event(omega, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Convert and check values.
+ */
+ omega->year = 0; /* fake */
+ omega->day = cp[0] - '0';
+ omega->day = MULBY10(omega->day) + cp[1] - '0';
+ omega->day = MULBY10(omega->day) + cp[2] - '0';
+ omega->hour = MULBY10(cp[4] - '0') + cp[5] - '0';
+ omega->minute = MULBY10(cp[7] - '0') + cp[8] - '0';
+ omega->second = MULBY10(cp[10] - '0') + cp[11] - '0';
+ omega->msec = 0;
+
+ if (omega->day < 1 || omega->day > 366) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADDATE);
+ return;
+ }
+ if (omega->hour > 23 || omega->minute > 59 || omega->second > 59) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADTIME);
+ return;
+ }
+
+ /*
+ * Check quality/station-id flag. The OM-DC should normally stay
+ * permanently locked to a station, and its time error should be less
+ * than 1 msec. If it loses lock for any reason, it makes a worst
+ * case drift estimate based on the internally stored stability figure
+ * for its reference oscillator. The stability figure can be adjusted
+ * by the user based on experience. The default value is 1E05, which
+ * is pretty bad - 2E07 is about right for the unit I have.
+ *
+ * The following is arbitrary, change it if you're offended:
+ * For errors less than 50 msec, just clear the station indicator.
+ * For errors greater than 50 msec, flag loss of sync and report a
+ * propagation problem. If the error is greater than 500 msec,
+ * something is dreadfully wrong - report a clock fault.
+ *
+ * In each case, we set a drift estimate which is used below as an
+ * estimate of measurement accuracy.
+ */
+ omega->quality = cp[12];
+ if (cp[12] == '>' || cp[12] == '?') {
+ /* Error 500 to 5000 msec */
+ omega_report_event(omega, CEVNT_FAULT);
+ omega->leap = LEAP_NOTINSYNC;
+ omega->station = STATION_NONE;
+ drift = U_FP5000MS;
+ } else if (cp[12] == '#') {
+ /* Error 50 to 500 msec */
+ omega_report_event(omega, CEVNT_PROP);
+ omega->leap = LEAP_NOTINSYNC;
+ omega->station = STATION_NONE;
+ drift = U_FP500MS;
+ } else if (cp[12] == '*') {
+ /* Error 5 to 50 msec */
+ omega->lasttime = current_time;
+ omega->station = STATION_NONE;
+ drift = U_FP50MS;
+ } else if (cp[12] == '.') {
+ /* Error 1 to 5 msec */
+ omega->lasttime = current_time;
+ omega->station = STATION_NONE;
+ drift = U_FP5MS;
+ } else if ('A' <= cp[12] && cp[12] <= 'H') {
+ /* Error less than 1 msec */
+ omega->lasttime = current_time;
+ omega->station = cp[12] - 'A' + 1;
+ drift = 0;
+ } else {
+ omega->badformat++;
+ omega_report_event(omega, CEVNT_BADREPLY);
+ return;
+ }
+
+#ifdef PEDANTIC
+ /* If we haven't been polled, bail out. */
+ if (!omega->polled)
+ return;
+#endif
+
+ /*
+ * Now, compute the reference time value. Use the heavy
+ * machinery for the seconds and the millisecond field for the
+ * fraction when present.
+ *
+ * this code does not yet know how to do the years
+ */
+ tstmp = omega->lastrec;
+ if (!clocktime(omega->day, omega->hour, omega->minute,
+ omega->second, GMT, tstmp.l_ui,
+ &omega->yearstart, &omega->lastref.l_ui)) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADTIME);
+ return;
+ }
+ MSUTOTSF(omega->msec, omega->lastref.l_uf);
+
+ /*
+ * Adjust the read value by fudgefactor1 to correct RS232 delays.
+ */
+ L_ADD(&omega->lastref, &fudgefactor1[omega->unit]);
+
+ /* Carousel of NSTAMPS offsets. */
+ i = omega->coderecv % NSTAMPS;
+ omega->offset[i] = omega->lastref;
+ L_SUB(&omega->offset[i], &tstmp);
+ omega->coderecv++;
+
+ /* If we don't yet have a full set, return. */
+ if (omega->coderecv < NSTAMPS)
+ return;
+
+ /*
+ * Filter the samples, add the fudge factor and pass the
+ * offset and dispersion along. We use lastrec 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 the sample filter chokes because of excessive
+ * dispersion or whatever, get a new sample (omega->coderecv
+ * is still >= NSTAMPS) and try again.
+ */
+ if (!omega_process(omega, &tstmp, &dispersion)) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADTIME);
+ return;
+ }
+
+ /*
+ * Add accumulated clock drift to the dispersion to get
+ * a (hopefully) meaningful measurement accuracy estimate.
+ */
+ dispersion += drift;
+ refclock_receive(omega->peer, &tstmp, GMT, dispersion,
+ &omega->lastrec, &omega->lastrec, omega->leap);
+
+ /*
+ * We have succeeded in answering the poll. If the clock
+ * is locked, we're nominal.
+ */
+ omega->polled = 0;
+ omega->coderecv = 0;
+ if (omega->leap != LEAP_NOTINSYNC)
+ omega_report_event(omega, CEVNT_NOMINAL);
+}
+
+
+/*
+ * omega_send - time to send the clock a signal to cough up a time sample
+ */
+static void
+omega_send(omega,cmd)
+ struct omegaunit *omega;
+ char *cmd;
+{
+ if (!readonlyclockflag[omega->unit]) {
+ /*
+ * Send a command to the clock.
+ */
+ if (write(omega->io.fd, cmd, 1) != 1) {
+ syslog(LOG_ERR, "omega_send: unit %d: %m", omega->unit);
+ omega_report_event(omega, CEVNT_FAULT);
+ }
+ }
+}
+
+
+/*
+ * Compare two l_fp's, used with qsort()
+ */
+static int
+omega_cmpl_fp(p1, p2)
+ register void *p1, *p2;
+{
+
+ if (!L_ISGEQ((l_fp *)p1, (l_fp *)p2))
+ return (-1);
+ if (L_ISEQU((l_fp *)p1, (l_fp *)p2))
+ return (0);
+ return (1);
+}
+
+
+/*
+ * omega_process - process a pile of samples from the clock
+ */
+static char
+omega_process(omega, offset, dispersion)
+ struct omegaunit *omega;
+ l_fp *offset;
+ u_fp *dispersion;
+{
+ register int i, n;
+ register u_long med_ui, med_uf, tmp_ui, tmp_uf;
+ l_fp off[NSTAMPS];
+ u_fp disp;
+
+ /* Copy in offsets and sort into ascending order */
+ for (i = 0; i < NSTAMPS; i++)
+ off[i] = omega->offset[i];
+ qsort((char *)off, NSTAMPS, sizeof(l_fp), omega_cmpl_fp);
+ /*
+ * Reject the furthest from the median until NSKEEP samples remain
+ */
+ i = 0;
+ n = NSTAMPS;
+ while ((n - i) > NSKEEP) {
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ med_ui = off[(n+i)/2].l_ui;
+ med_uf = off[(n+i)/2].l_uf;
+ M_SUB(tmp_ui, tmp_uf, med_ui, med_uf);
+ M_SUB(med_ui, med_uf, off[i].l_ui, off[i].l_uf);
+ if (M_ISHIS(med_ui, med_uf, tmp_ui, tmp_uf)) {
+ /* reject low end */
+ i++;
+ } else {
+ /* reject high end */
+ n--;
+ }
+ }
+
+ /*
+ * Compute the dispersion based on the difference between the
+ * extremes of the remaining offsets. If this is greater than
+ * the allowed sample set dispersion, bail out. Otherwise,
+ * return the median offset and the dispersion.
+ */
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ M_SUB(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
+ disp = MFPTOFP(tmp_ui, tmp_uf);
+ if (disp > OMEGAMAXDISPERSE)
+ return 0;
+ *offset = off[(n+1)/2];
+ *dispersion = disp;
+ return 1;
+}
+
+
+/*
+ * omega_poll - called by the transmit procedure
+ */
+static void
+omega_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct omegaunit *omega;
+
+ /*
+ * You don't need to poll this clock. It puts out timecodes
+ * once per second. If asked for a timestamp, take note.
+ * The next time a timecode comes in, it will be fed back.
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_poll: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "omega_poll: unit %d not in use", unit);
+ return;
+ }
+ omega = omegaunits[unit];
+ if ((current_time - omega->lasttime) > 150) {
+ omega->noreply++;
+ omega_report_event(omegaunits[unit], CEVNT_TIMEOUT);
+ }
+
+ /*
+ * polled every 64 seconds. Ask OMEGA_RECEIVE to hand in a timestamp.
+ */
+ omega->polled = 1;
+ omega->polls++;
+ /*
+ * Ensure the clock is running in the correct mode - on-second
+ * timestamps.
+ */
+ omega_send(omega,"C");
+}
+
+
+/*
+ * omega_control - set fudge factors, return statistics
+ */
+static void
+omega_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct omegaunit *omega;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_control: unit %d invalid", unit);
+ return;
+ }
+
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ fudgefactor1[unit] = in->fudgetime1;
+ if (in->haveflags & CLK_HAVETIME2)
+ fudgefactor2[unit] = in->fudgetime2;
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
+ readonlyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = omegaunits[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
+ }
+
+ if (out != 0) {
+ out->type = REFCLK_OMEGA_TRUETIME;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVETIME2 | CLK_HAVEVAL1 |
+ CLK_HAVEVAL2| CLK_HAVEFLAG1;
+ out->clockdesc = OMEGADESCRIPTION;
+ out->fudgetime1 = fudgefactor1[unit];
+ out->fudgetime2 = fudgefactor2[unit];
+ out->fudgeval1 = stratumtouse[unit];
+ out->fudgeval2 = refid[unit];
+ out->flags = readonlyclockflag[unit];
+ if (unitinuse[unit]) {
+ omega = omegaunits[unit];
+ out->flags |= omega->station << 1;
+ out->lencode = omega->lencode;
+ out->lastcode = omega->lastcode;
+ out->timereset = current_time - omega->timestarted;
+ out->polls = omega->polls;
+ out->noresponse = omega->noreply;
+ out->badformat = omega->badformat;
+ out->baddata = omega->baddata;
+ out->lastevent = omega->lastevent;
+ out->currentstatus = omega->status;
+ }
+ }
+}
+
+
+/*
+ * omega_buginfo - return clock dependent debugging info
+ */
+static void
+omega_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct omegaunit *omega;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_buginfo: unit %d invalid", unit);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ omega = omegaunits[unit];
+
+ bug->nvalues = 11;
+ bug->ntimes = 5;
+ if (omega->lasttime != 0)
+ bug->values[0] = current_time - omega->lasttime;
+ else
+ bug->values[0] = 0;
+ bug->values[1] = omega->reason;
+ bug->values[2] = omega->year;
+ bug->values[3] = omega->day;
+ bug->values[4] = omega->hour;
+ bug->values[5] = omega->minute;
+ bug->values[6] = omega->second;
+ bug->values[7] = omega->msec;
+ bug->values[8] = omega->noreply;
+ bug->values[9] = omega->yearstart;
+ bug->values[10] = omega->quality;
+ bug->stimes = 0x1c;
+ bug->times[0] = omega->lastref;
+ bug->times[1] = omega->lastrec;
+ bug->times[2] = omega->offset[0];
+ bug->times[3] = omega->offset[1];
+ bug->times[4] = omega->offset[2];
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_new/refclock_parse.c b/usr.sbin/xntpd/xntpd/refclock_new/refclock_parse.c
new file mode 100644
index 000000000000..1b950a9b8e6f
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_new/refclock_parse.c
@@ -0,0 +1,3617 @@
+#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS))
+/*
+ * /src/NTP/REPOSITORY/v3/xntpd/refclock_parse.c,v 3.59 1994/05/23 16:29:27 kardel Exp
+ *
+ * refclock_parse.c,v 3.59 1994/05/23 16:29:27 kardel Exp
+ *
+ * generic reference clock driver for receivers
+ *
+ * make use of a STREAMS module for input processing where
+ * available and configured. Currently the STREAMS module
+ * is only available for Suns running SunOS 4.x and SunOS5.x (new - careful!)
+ *
+ * Copyright (c) 1989,1990,1991,1992,1993,1994
+ * Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/*
+ * Defines:
+ * REFCLOCK && (PARSE||PARSEPPS)
+ * - enable this mess
+ * STREAM - allow for STREAMS modules
+ * ("parse", "ppsclocd", "ppsclock")
+ * PARSEPPS - provide PPS information to loopfilter (for
+ * backward compatibilty only)
+ * PPS - supply loopfilter with PPS samples (if configured)
+ * PPSPPS - notify loopfilter of PPS file descriptor
+ *
+ * TTY defines:
+ * HAVE_BSD_TTYS - currently unsupported
+ * HAVE_SYSV_TTYS - will use termio.h
+ * HAVE_TERMIOS - will use termios.h
+ * STREAM - will use streams and implies HAVE_TERMIOS
+ */
+
+/*
+ * This driver currently provides the support for
+ * - Meinberg DCF77 receiver DCF77 PZF 535 (TCXO version) (DCF)
+ * - Meinberg DCF77 receiver DCF77 PZF 535 (OCXO version) (DCF)
+ * - Meinberg DCF77 receiver U/A 31 (DCF)
+ * - IGEL CLOCK (DCF)
+ * - ELV DCF7000 (DCF)
+ * - Schmid clock (DCF)
+ * - Conrad DCF77 receiver module (DCF)
+ * - FAU DCF77 NTP receiver (TimeBrick) (DCF)
+ * - Meinberg GPS166 (GPS)
+ * - Trimble SV6 (GPS)
+ *
+ */
+
+/*
+ * Meinberg receivers are connected via a 9600 baud serial line
+ *
+ * Receivers that do NOT support:
+ * - leap second indication
+ * DCF U/A 31
+ * DCF PZF535 (stock version)
+ *
+ * so...
+ * - for PZF535 please ask for revision PZFUERL4.6 or higher
+ * (support for leap second and alternate antenna)
+ *
+ * The Meinberg GPS receiver also has a special NTP time stamp
+ * format. The firmware release is Uni-Erlangen. Only this
+ * firmware release is supported by xntp3.
+ *
+ * Meinberg generic receiver setup:
+ * output time code every second
+ * Baud rate 9600 7E2S
+ */
+
+#include "ntpd.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_control.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+
+#include <sys/errno.h>
+extern int errno;
+
+#if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)
+/* #error NEED TO DEFINE ONE OF "STREAM" or "HAVE_SYSV_TTYS" */
+NEED TO DEFINE ONE OF "STREAM", "HAVE_SYSV_TTYS" or "HAVE_TERMIOS"
+#endif
+
+#ifdef STREAM
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#ifndef HAVE_TERMIOS
+#define HAVE_TERMIOS
+#endif
+#endif
+
+#ifdef HAVE_TERMIOS
+#include <termios.h>
+#define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
+#define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
+#undef HAVE_SYSV_TTYS
+#endif
+
+#ifdef HAVE_SYSV_TTYS
+#include <termio.h>
+#define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
+#define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
+#endif
+
+#ifdef HAVE_BSD_TTYS
+/* #error CURRENTLY NO BSD TTY SUPPORT */
+CURRENTLY NO BSD TTY SUPPORT
+#endif
+
+#if !defined(O_RDWR) /* XXX SOLARIS */
+#include <fcntl.h>
+#endif /* !def(O_RDWR) */
+
+#ifdef PPSPPS
+#include <sys/ppsclock.h>
+#endif
+
+#include "ntp_select.h"
+#include "ntp_stdlib.h"
+
+#include "parse.h"
+
+#if !defined(NO_SCCSID) && !defined(lint) && !defined(__GNUC__)
+static char rcsid[]="refclock_parse.c,v 3.59 1994/05/23 16:29:27 kardel Exp";
+#endif
+
+/**===========================================================================
+ ** external interface to xntp mechanism
+ **/
+
+static void parse_init P((void));
+static int parse_start P((u_int, struct peer *));
+static void parse_shutdown P((int));
+static void parse_poll P((int, struct peer *));
+static void parse_control P((u_int, struct refclockstat *, struct refclockstat *));
+
+#define parse_buginfo noentry
+
+struct refclock refclock_parse = {
+ parse_start,
+ parse_shutdown,
+ parse_poll,
+ parse_control,
+ parse_init,
+ parse_buginfo,
+ NOFLAGS
+};
+
+/*
+ * the unit field selects for one the prototype to be used (lower 4 bits)
+ * and for the other the clock type in case of different but similar
+ * receivers (bits 4-6)
+ * the most significant bit encodes PPS support
+ * when the most significant bit is set the pps telegrams will be used
+ * for controlling the local clock (ntp_loopfilter.c)
+ * receiver specific configration data is kept in the clockinfo field.
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 4 /* maximum number of "PARSE" units permitted */
+#define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */
+
+/**===========================================================================
+ ** function vector for dynamically binding io handling mechanism
+ **/
+
+typedef struct bind
+{
+ char *bd_description; /* name of type of binding */
+ int (*bd_init)(); /* initialize */
+ void (*bd_end)(); /* end */
+ int (*bd_setcs)(); /* set character size */
+ int (*bd_disable)(); /* disable */
+ int (*bd_enable)(); /* enable */
+ int (*bd_getfmt)(); /* get format */
+ int (*bd_setfmt)(); /* setfmt */
+ int (*bd_getstat)(); /* getstat */
+ int (*bd_setstat)(); /* setstat */
+ int (*bd_timecode)(); /* get time code */
+ void (*bd_receive)(); /* receive operation */
+ void (*bd_poll)(); /* poll operation */
+} bind_t;
+
+#define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_)
+#define PARSE_SETCS(_X_, _CS_) (*(_X_)->binding->bd_setcs)(_X_, _CS_)
+#define PARSE_ENABLE(_X_) (*(_X_)->binding->bd_enable)(_X_)
+#define PARSE_DISABLE(_X_) (*(_X_)->binding->bd_disable)(_X_)
+#define PARSE_GETFMT(_X_, _DCT_) (*(_X_)->binding->bd_getfmt)(_X_, _DCT_)
+#define PARSE_SETFMT(_X_, _DCT_) (*(_X_)->binding->bd_setfmt)(_X_, _DCT_)
+#define PARSE_GETSTAT(_X_, _DCT_) (*(_X_)->binding->bd_getstat)(_X_, _DCT_)
+#define PARSE_SETSTAT(_X_, _DCT_) (*(_X_)->binding->bd_setstat)(_X_, _DCT_)
+#define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)
+#define PARSE_POLL(_X_) (*(_X_)->binding->bd_poll)(_X_)
+
+/*
+ * io modes
+ */
+#define PARSE_F_NOPOLLONLY 0x0001 /* always do async io (possible PPS support via PARSE) */
+#define PARSE_F_POLLONLY 0x0002 /* never do async io (no PPS support via PARSE) */
+#define PARSE_F_PPSPPS 0x0004 /* use loopfilter PPS code (CIOGETEV) */
+#define PARSE_F_PPSONSECOND 0x0008 /* PPS pulses are on second */
+
+/**===========================================================================
+ ** refclock instance data
+ **/
+
+struct parseunit
+{
+ /*
+ * XNTP management
+ */
+ struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */
+ int fd; /* device file descriptor */
+ u_char unit; /* encoded unit/type/PPS */
+
+ /*
+ * XNTP io
+ */
+ struct refclockio io; /* io system structure (used in PPS mode) */
+ bind_t *binding; /* io handling binding */
+
+ /*
+ * parse state
+ */
+ parse_t parseio; /* io handling structure (user level parsing) */
+
+ /*
+ * type specific parameters
+ */
+ struct clockinfo *parse_type; /* link to clock description */
+
+ /*
+ * clock specific configuration
+ */
+ l_fp basedelay; /* clock local phase offset */
+ l_fp ppsdelay; /* clock local pps phase offset */
+
+ /*
+ * clock state handling/reporting
+ */
+ u_char flags; /* flags (leap_control) */
+ u_char status; /* current status */
+ u_char lastevent; /* last not NORMAL status */
+ u_long lastchange; /* time (xntp) when last state change accured */
+ u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */
+ struct event stattimer; /* statistics timer */
+ u_long polls; /* polls from NTP protocol machine */
+ u_long noresponse; /* number of expected but not seen datagrams */
+ u_long badformat; /* bad format (failed format conversions) */
+ u_long baddata; /* usually bad receive length, bad format */
+
+ u_char pollonly; /* 1 for polling only (no PPS mode) */
+ u_char pollneeddata; /* 1 for receive sample expected in PPS mode */
+ u_long laststatus; /* last packet status (error indication) */
+ u_short lastformat; /* last format used */
+ u_long lastsync; /* time (xntp) when clock was last seen fully synchronized */
+ u_long timestarted; /* time (xntp) when peer clock was instantiated */
+ u_long nosynctime; /* time (xntp) when last nosync message was posted */
+ u_long lastmissed; /* time (xntp) when poll didn't get data (powerup heuristic) */
+ u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
+ parsetime_t time; /* last (parse module) data */
+ void *localdata; /* optional local data */
+};
+
+
+/**===========================================================================
+ ** Clockinfo section all parameter for specific clock types
+ ** includes NTP paramaters, TTY parameters and IO handling parameters
+ **/
+
+static void poll_dpoll P((struct parseunit *));
+static void poll_poll P((struct parseunit *));
+static int poll_init P((struct parseunit *));
+static void poll_end P((struct parseunit *));
+
+typedef struct poll_info
+{
+ u_long rate; /* poll rate - once every "rate" seconds - 0 off */
+ char * string; /* string to send for polling */
+ u_long count; /* number of charcters in string */
+} poll_info_t;
+
+#define NO_FLAGS 0
+#define NO_POLL (void (*)())0
+#define NO_INIT (int (*)())0
+#define NO_END (void (*)())0
+#define NO_DATA (void *)0
+#define NO_FORMAT ""
+#define NO_PPSDELAY 0
+
+#define DCF_ID "DCF" /* generic DCF */
+#define DCF_A_ID "DCFa" /* AM demodulation */
+#define DCF_P_ID "DCFp" /* psuedo random phase shift */
+#define GPS_ID "GPS" /* GPS receiver */
+
+#define NOCLOCK_ROOTDELAY 0x00000000
+#define NOCLOCK_BASEDELAY 0x00000000
+#define NOCLOCK_DESCRIPTION ((char *)0)
+#define NOCLOCK_MAXUNSYNC 0
+#define NOCLOCK_CFLAG 0
+#define NOCLOCK_IFLAG 0
+#define NOCLOCK_OFLAG 0
+#define NOCLOCK_LFLAG 0
+#define NOCLOCK_ID "TILT"
+#define NOCLOCK_POLL NO_POLL
+#define NOCLOCK_INIT NO_INIT
+#define NOCLOCK_END NO_END
+#define NOCLOCK_DATA NO_DATA
+#define NOCLOCK_FORMAT NO_FORMAT
+#define NOCLOCK_TYPE CTL_SST_TS_UNSPEC
+
+#define DCF_TYPE CTL_SST_TS_LF
+#define GPS_TYPE CTL_SST_TS_UHF
+
+/*
+ * receiver specific constants
+ */
+#define MBG_CFLAG19200 (B19200|CS7|PARENB|CREAD|HUPCL)
+#define MBG_CFLAG (B9600|CS7|PARENB|CREAD|HUPCL)
+#define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)
+#define MBG_OFLAG 0
+#define MBG_LFLAG 0
+/*
+ * Meinberg DCF U/A 31 (AM) receiver
+ */
+#define DCFUA31_ROOTDELAY 0x00000D00 /* 50.78125ms */
+#define DCFUA31_BASEDELAY 0x02C00000 /* 10.7421875ms: 10 ms (+/- 3 ms) */
+#define DCFUA31_DESCRIPTION "Meinberg DCF U/A 31"
+#define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */
+#define DCFUA31_CFLAG MBG_CFLAG
+#define DCFUA31_IFLAG MBG_IFLAG
+#define DCFUA31_OFLAG MBG_OFLAG
+#define DCFUA31_LFLAG MBG_LFLAG
+
+/*
+ * Meinberg DCF PZF535/TCXO (FM/PZF) receiver
+ */
+#define DCFPZF535_ROOTDELAY 0x00000034 /* 800us */
+#define DCFPZF535_BASEDELAY 0x00800000 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
+#define DCFPZF535_DESCRIPTION "Meinberg DCF PZF 535/TCXO"
+#define DCFPZF535_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours
+ * @ 5e-8df/f we have accumulated
+ * at most 2.16 ms (thus we move to
+ * NTP synchronisation */
+#define DCFPZF535_CFLAG MBG_CFLAG
+#define DCFPZF535_IFLAG MBG_IFLAG
+#define DCFPZF535_OFLAG MBG_OFLAG
+#define DCFPZF535_LFLAG MBG_LFLAG
+
+
+/*
+ * Meinberg DCF PZF535/OCXO receiver
+ */
+#define DCFPZF535OCXO_ROOTDELAY 0x00000034 /* 800us (max error * 10) */
+#define DCFPZF535OCXO_BASEDELAY 0x00800000 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
+#define DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/OCXO"
+#define DCFPZF535OCXO_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
+ * @ 5e-9df/f we have accumulated
+ * at most an error of 1.73 ms
+ * (thus we move to NTP synchronisation) */
+#define DCFPZF535OCXO_CFLAG MBG_CFLAG
+#define DCFPZF535OCXO_IFLAG MBG_IFLAG
+#define DCFPZF535OCXO_OFLAG MBG_OFLAG
+#define DCFPZF535OCXO_LFLAG MBG_LFLAG
+
+/*
+ * Meinberg GPS166 receiver
+ */
+#define GPS166_ROOTDELAY 0x00000000 /* nothing here */
+#define GPS166_BASEDELAY 0x00800000 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
+#define GPS166_DESCRIPTION "Meinberg GPS166 receiver"
+#define GPS166_MAXUNSYNC 0 /* this clock is immediately lost */
+#define GPS166_CFLAG MBG_CFLAG
+#define GPS166_IFLAG MBG_IFLAG
+#define GPS166_OFLAG MBG_OFLAG
+#define GPS166_LFLAG MBG_LFLAG
+#define GPS166_POLL NO_POLL
+#define GPS166_INIT NO_INIT
+#define GPS166_END NO_END
+#define GPS166_DATA NO_DATA
+#define GPS166_ID GPS_ID
+#define GPS166_FORMAT NO_FORMAT
+
+/*
+ * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit)
+ *
+ * This is really not the hottest clock - but before you have nothing ...
+ */
+#define DCF7000_ROOTDELAY 0x00000364 /* 13 ms */
+#define DCF7000_BASEDELAY 0x67AE0000 /* 405 ms - slow blow */
+#define DCF7000_DESCRIPTION "ELV DCF7000"
+#define DCF7000_MAXUNSYNC (60*5) /* sorry - but it just was not build as a clock */
+#define DCF7000_CFLAG (B9600|CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL)
+#define DCF7000_IFLAG (IGNBRK)
+#define DCF7000_OFLAG 0
+#define DCF7000_LFLAG 0
+
+/*
+ * Schmid DCF Receiver Kit
+ *
+ * When the WSDCF clock is operating optimally we want the primary clock
+ * distance to come out at 300 ms. Thus, peer.distance in the WSDCF peer
+ * structure is set to 290 ms and we compute delays which are at least
+ * 10 ms long. The following are 290 ms and 10 ms expressed in u_fp format
+ */
+#define WS_POLLRATE 1 /* every second - watch interdependency with poll routine */
+#define WS_POLLCMD "\163"
+#define WS_CMDSIZE 1
+
+static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
+
+#define WSDCF_INIT poll_init
+#define WSDCF_POLL poll_dpoll
+#define WSDCF_END poll_end
+#define WSDCF_DATA ((void *)(&wsdcf_pollinfo))
+#define WSDCF_ROOTDELAY 0X00004A3D /* ~ 290ms */
+#define WSDCF_BASEDELAY 0x028F5C29 /* ~ 10ms */
+#define WSDCF_DESCRIPTION "WS/DCF Receiver"
+#define WSDCF_FORMAT "Schmid"
+#define WSDCF_MAXUNSYNC (60*60) /* assume this beast hold at 1 h better than 2 ms XXX-must verify */
+#define WSDCF_CFLAG (B1200|CS8|CREAD|CLOCAL)
+#define WSDCF_IFLAG 0
+#define WSDCF_OFLAG 0
+#define WSDCF_LFLAG 0
+
+/*
+ * RAW DCF77 - input of DCF marks via RS232 - many variants
+ */
+#define RAWDCF_FLAGS PARSE_F_NOPOLLONLY
+#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 */
+#define RAWDCF_CFLAG (B50|CS8|CREAD|CLOCAL|PARENB)
+#define RAWDCF_IFLAG (IGNPAR)
+#define RAWDCF_OFLAG 0
+#define RAWDCF_LFLAG 0
+
+/*
+ * RAW DCF variants
+ */
+/*
+ * Conrad receiver
+ *
+ * simplest (cheapest) DCF clock - e. g. DCF77 receiver by Conrad
+ * (~40DM - roughly $30 ) followed by a level converter for RS232
+ */
+#define CONRAD_BASEDELAY 0x420C49B0 /* ~258 ms - Conrad receiver @ 50 Baud on a Sun */
+#define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)"
+
+/*
+ * TimeBrick receiver
+ */
+#define TIMEBRICK_BASEDELAY 0x35C29000 /* ~210 ms - TimeBrick @ 50 Baud on a Sun */
+#define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)"
+
+/*
+ * IGEL:clock receiver
+ */
+#define IGELCLOCK_BASEDELAY 0x420C49B0 /* ~258 ms - IGEL:clock receiver */
+#define IGELCLOCK_DESCRIPTION "RAW DCF77 CODE (IGEL:clock)"
+#define IGELCLOCK_CFLAG (B1200|CS8|CREAD|HUPCL|CLOCAL)
+
+/*
+ * Trimble SV6 GPS receiver
+ */
+#ifndef TRIM_POLLRATE
+#define TRIM_POLLRATE 0 /* only true direct polling */
+#endif
+#define TRIM_POLLCMD ">SRM;FR_FLAG=F<>QTM<"
+#define TRIM_CMDSIZE 20
+
+static poll_info_t trimble_pollinfo = { TRIM_POLLRATE, TRIM_POLLCMD, TRIM_CMDSIZE };
+static int trimble_init P((struct parseunit *));
+
+#define TRIMBLESV6_CFLAG (B4800|CS8|CREAD)
+#define TRIMBLESV6_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
+#define TRIMBLESV6_OFLAG (OPOST|ONLCR)
+#define TRIMBLESV6_LFLAG (ICANON|ECHOK)
+#define TRIMBLESV6_FLAGS (PARSE_F_PPSPPS|PARSE_F_PPSONSECOND)
+#define TRIMBLESV6_POLL poll_dpoll
+#define TRIMBLESV6_INIT trimble_init
+#define TRIMBLESV6_END poll_end
+#define TRIMBLESV6_DATA ((void *)(&trimble_pollinfo))
+#define TRIMBLESV6_ID GPS_ID
+#define TRIMBLESV6_FORMAT NO_FORMAT
+#define TRIMBLESV6_ROOTDELAY 0x0
+#define TRIMBLESV6_BASEDELAY 0x0
+#define TRIMBLESV6_DESCRIPTION "Trimble SV6 GPS receiver"
+#define TRIMBLESV6_MAXUNSYNC 0
+#define TRIMBLESV6_EOL '<'
+
+static struct clockinfo
+{
+ u_long cl_flags; /* operation flags (io modes) */
+ void (*cl_poll)(); /* active poll routine */
+ int (*cl_init)(); /* active poll init routine */
+ void (*cl_end)(); /* active poll end routine */
+ void *cl_data; /* local data area for "poll" mechanism */
+ u_fp cl_rootdelay; /* rootdelay */
+ u_long cl_basedelay; /* current offset - unsigned l_fp fractional part */
+ u_long cl_ppsdelay; /* current PPS offset - unsigned l_fp fractional part */
+ char *cl_id; /* ID code (usually "DCF") */
+ char *cl_description; /* device name */
+ char *cl_format; /* fixed format */
+ u_char cl_type; /* clock type (ntp control) */
+ u_long cl_maxunsync; /* time to trust oscillator after loosing synch */
+ 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 */
+} clockinfo[] =
+{ /* 0. 0.0.128 - base offset for PPS support */
+ { /* 127.127.8.<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCFPZF535_ROOTDELAY,
+ DCFPZF535_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_P_ID,
+ DCFPZF535_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCFPZF535_MAXUNSYNC,
+ DCFPZF535_CFLAG,
+ DCFPZF535_IFLAG,
+ DCFPZF535_OFLAG,
+ DCFPZF535_LFLAG
+ },
+ { /* 127.127.8.4+<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCFPZF535OCXO_ROOTDELAY,
+ DCFPZF535OCXO_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_P_ID,
+ DCFPZF535OCXO_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCFPZF535OCXO_MAXUNSYNC,
+ DCFPZF535OCXO_CFLAG,
+ DCFPZF535OCXO_IFLAG,
+ DCFPZF535OCXO_OFLAG,
+ DCFPZF535OCXO_LFLAG
+ },
+ { /* 127.127.8.8+<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCFUA31_ROOTDELAY,
+ DCFUA31_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ DCFUA31_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCFUA31_MAXUNSYNC,
+ DCFUA31_CFLAG,
+ DCFUA31_IFLAG,
+ DCFUA31_OFLAG,
+ DCFUA31_LFLAG
+ },
+ { /* 127.127.8.12+<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCF7000_ROOTDELAY,
+ DCF7000_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ DCF7000_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCF7000_MAXUNSYNC,
+ DCF7000_CFLAG,
+ DCF7000_IFLAG,
+ DCF7000_OFLAG,
+ DCF7000_LFLAG
+ },
+ { /* 127.127.8.16+<device> */
+ NO_FLAGS,
+ WSDCF_POLL,
+ WSDCF_INIT,
+ WSDCF_END,
+ WSDCF_DATA,
+ WSDCF_ROOTDELAY,
+ WSDCF_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ WSDCF_DESCRIPTION,
+ WSDCF_FORMAT,
+ DCF_TYPE,
+ WSDCF_MAXUNSYNC,
+ WSDCF_CFLAG,
+ WSDCF_IFLAG,
+ WSDCF_OFLAG,
+ WSDCF_LFLAG
+ },
+ { /* 127.127.8.20+<device> */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ RAWDCF_ROOTDELAY,
+ CONRAD_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ CONRAD_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ RAWDCF_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG
+ },
+ { /* 127.127.8.24+<device> */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ RAWDCF_ROOTDELAY,
+ TIMEBRICK_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ TIMEBRICK_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ RAWDCF_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG
+ },
+ { /* 127.127.8.28+<device> */
+ NO_FLAGS,
+ GPS166_POLL,
+ GPS166_INIT,
+ GPS166_END,
+ GPS166_DATA,
+ GPS166_ROOTDELAY,
+ GPS166_BASEDELAY,
+ NO_PPSDELAY,
+ GPS166_ID,
+ GPS166_DESCRIPTION,
+ GPS166_FORMAT,
+ GPS_TYPE,
+ GPS166_MAXUNSYNC,
+ GPS166_CFLAG,
+ GPS166_IFLAG,
+ GPS166_OFLAG,
+ GPS166_LFLAG
+ },
+ { /* 127.127.8.32+<device> */
+ TRIMBLESV6_FLAGS,
+#if TRIM_POLLRATE /* DHD940515: Allow user config */
+ NO_POLL,
+#else
+ TRIMBLESV6_POLL,
+#endif
+ TRIMBLESV6_INIT,
+ TRIMBLESV6_END,
+ TRIMBLESV6_DATA,
+ TRIMBLESV6_ROOTDELAY,
+ TRIMBLESV6_BASEDELAY,
+ NO_PPSDELAY,
+ TRIMBLESV6_ID,
+ TRIMBLESV6_DESCRIPTION,
+ TRIMBLESV6_FORMAT,
+ GPS_TYPE,
+ TRIMBLESV6_MAXUNSYNC,
+ TRIMBLESV6_CFLAG,
+ TRIMBLESV6_IFLAG,
+ TRIMBLESV6_OFLAG,
+ TRIMBLESV6_LFLAG
+ },
+ { /* 127.127.8.36+<device> */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ RAWDCF_ROOTDELAY,
+ IGELCLOCK_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ IGELCLOCK_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ IGELCLOCK_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG
+ }
+};
+
+static int ncltypes = sizeof(clockinfo) / sizeof(struct clockinfo);
+
+#define CL_REALTYPE(x) (((x) >> 2) & 0x1F)
+#define CL_TYPE(x) ((CL_REALTYPE(x) >= ncltypes) ? ~0 : CL_REALTYPE(x))
+#define CL_PPS(x) ((x) & 0x80)
+#define CL_UNIT(x) ((x) & 0x3)
+
+/*
+ * Other constant stuff
+ */
+#define PARSEHSREFID 0x7f7f08ff /* 127.127.8.255 refid for hi strata */
+
+#define PARSENOSYNCREPEAT (10*60) /* mention uninitialized clocks all 10 minutes */
+#define PARSESTATISTICS (60*60) /* output state statistics every hour */
+
+static struct parseunit *parseunits[MAXUNITS];
+
+extern u_long current_time;
+extern s_char sys_precision;
+extern struct event timerqueue[];
+#ifdef PPSPPS
+extern int fdpps;
+#endif
+
+static int notice = 0;
+
+#define PARSE_STATETIME(parse, i) ((parse->status == i) ? parse->statetime[i] + current_time - parse->lastchange : parse->statetime[i])
+
+static void parse_event P((struct parseunit *, int));
+static void parse_process P((struct parseunit *, parsetime_t *));
+
+/**===========================================================================
+ ** implementation of i/o handling methods
+ ** (all STREAM, partial STREAM, user level)
+ **/
+
+/*
+ * define possible io handling methods
+ */
+#ifdef STREAM
+static int ppsclock_init P((struct parseunit *));
+static int stream_init P((struct parseunit *));
+static void stream_nop P((struct parseunit *));
+static int stream_enable P((struct parseunit *));
+static int stream_disable P((struct parseunit *));
+static int stream_setcs P((struct parseunit *, parsectl_t *));
+static int stream_getfmt P((struct parseunit *, parsectl_t *));
+static int stream_setfmt P((struct parseunit *, parsectl_t *));
+static int stream_getstat P((struct parseunit *, parsectl_t *));
+static int stream_setstat P((struct parseunit *, parsectl_t *));
+static int stream_timecode P((struct parseunit *, parsectl_t *));
+static void stream_receive P((struct recvbuf *));
+static void stream_poll P((struct parseunit *));
+#endif
+
+static int local_init P((struct parseunit *));
+static void local_end P((struct parseunit *));
+static int local_nop P((struct parseunit *));
+static int local_setcs P((struct parseunit *, parsectl_t *));
+static int local_getfmt P((struct parseunit *, parsectl_t *));
+static int local_setfmt P((struct parseunit *, parsectl_t *));
+static int local_getstat P((struct parseunit *, parsectl_t *));
+static int local_setstat P((struct parseunit *, parsectl_t *));
+static int local_timecode P((struct parseunit *, parsectl_t *));
+static void local_receive P((struct recvbuf *));
+static void local_poll P((struct parseunit *));
+
+static bind_t io_bindings[] =
+{
+#ifdef STREAM
+ {
+ "parse STREAM",
+ stream_init,
+ stream_nop,
+ stream_setcs,
+ stream_disable,
+ stream_enable,
+ stream_getfmt,
+ stream_setfmt,
+ stream_getstat,
+ stream_setstat,
+ stream_timecode,
+ stream_receive,
+ stream_poll
+ },
+ {
+ "ppsclock STREAM",
+ ppsclock_init,
+ local_end,
+ local_setcs,
+ local_nop,
+ local_nop,
+ local_getfmt,
+ local_setfmt,
+ local_getstat,
+ local_setstat,
+ local_timecode,
+ local_receive,
+ local_poll
+ },
+#endif
+ {
+ "normal",
+ local_init,
+ local_end,
+ local_setcs,
+ local_nop,
+ local_nop,
+ local_getfmt,
+ local_setfmt,
+ local_getstat,
+ local_setstat,
+ local_timecode,
+ local_receive,
+ local_poll
+ },
+ {
+ (char *)0,
+ }
+};
+
+#ifdef STREAM
+/*--------------------------------------------------
+ * ppsclock STREAM init
+ */
+static int
+ppsclock_init(parse)
+ struct parseunit *parse;
+{
+ /*
+ * now push the parse streams module
+ * it will ensure exclusive access to the device
+ */
+ if (ioctl(parse->fd, I_PUSH, (caddr_t)"ppsclocd") == -1 &&
+ ioctl(parse->fd, I_PUSH, (caddr_t)"ppsclock") == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m",
+ CL_UNIT(parse->unit));
+ return 0;
+ }
+ if (!local_init(parse))
+ {
+ (void)ioctl(parse->fd, I_POP, (caddr_t)0);
+ return 0;
+ }
+
+ parse->flags |= PARSE_PPSCLOCK;
+ return 1;
+}
+
+/*--------------------------------------------------
+ * parse STREAM init
+ */
+static int
+stream_init(parse)
+ struct parseunit *parse;
+{
+ /*
+ * now push the parse streams module
+ * to test whether it is there (Oh boy - neat kernel interface)
+ */
+ if (ioctl(parse->fd, I_PUSH, (caddr_t)"parse") == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ else
+ {
+ while(ioctl(parse->fd, I_POP, (caddr_t)0) == 0)
+ /* empty loop */;
+
+ /*
+ * now push it a second time after we have removed all
+ * module garbage
+ */
+ if (ioctl(parse->fd, I_PUSH, (caddr_t)"parse") == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+}
+
+ /*--------------------------------------------------
+ * STREAM setcs
+ */
+static int
+stream_setcs(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_SETCS;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_setcs: ioctl(fd, I_STR, PARSEIOC_SETCS): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM nop
+ */
+static void
+stream_nop(parse)
+ struct parseunit *parse;
+{
+}
+
+/*--------------------------------------------------
+ * STREAM enable
+ */
+static int
+stream_enable(parse)
+ struct parseunit *parse;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_ENABLE;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)0;
+ strioc.ic_len = 0;
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_enable: ioctl(fd, I_STR, PARSEIOC_ENABLE): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ parse->io.clock_recv = stream_receive; /* ok - parse input in kernel */
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM disable
+ */
+static int
+stream_disable(parse)
+ struct parseunit *parse;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_DISABLE;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)0;
+ strioc.ic_len = 0;
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_disable: ioctl(fd, I_STR, PARSEIOC_DISABLE): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ parse->io.clock_recv = local_receive; /* ok - parse input in daemon */
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM getfmt
+ */
+static int
+stream_getfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_GETFMT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: ioctl(fd, I_STR, PARSEIOC_GETFMT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM setfmt
+ */
+static int
+stream_setfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_SETFMT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_setfmt: ioctl(fd, I_STR, PARSEIOC_SETFMT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM getstat
+ */
+static int
+stream_getstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_GETSTAT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_getstat: ioctl(fd, I_STR, PARSEIOC_GETSTAT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM setstat
+ */
+static int
+stream_setstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_SETSTAT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_setstat: ioctl(fd, I_STR, PARSEIOC_SETSTAT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM timecode
+ */
+static int
+stream_timecode(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_TIMECODE;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_process: ioctl(fd, I_STR, PARSEIOC_TIMECODE): %m", CL_UNIT(parse->unit), parse->fd);
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM receive
+ */
+static void
+stream_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ struct parseunit *parse = (struct parseunit *)rbufp->recv_srcclock;
+ parsetime_t parsetime;
+
+ if (rbufp->recv_length != sizeof(parsetime_t))
+ {
+ syslog(LOG_ERR,"PARSE receiver #%d: parse_receive: bad size (got %d expected %d)",
+ CL_UNIT(parse->unit), rbufp->recv_length, sizeof(parsetime_t));
+ parse->baddata++;
+ parse_event(parse, CEVNT_BADREPLY);
+ return;
+ }
+ memmove((caddr_t)&parsetime,
+ (caddr_t)&rbufp->recv_space,
+ sizeof(parsetime_t));
+
+ /*
+ * switch time stamp world - be sure to normalize small usec field
+ * errors.
+ */
+
+#define fix_ts(_X_) \
+ if ((&(_X_))->tv.tv_usec >= 1000000) \
+ { \
+ (&(_X_))->tv.tv_usec -= 1000000; \
+ (&(_X_))->tv.tv_sec += 1; \
+ }
+
+#define cvt_ts(_X_, _Y_) \
+ { \
+ l_fp ts; \
+ \
+ fix_ts((_X_)); \
+ if (!buftvtots((const char *)&(&(_X_))->tv, &ts)) \
+ { \
+ syslog(LOG_ERR,"parse: stream_receive: timestamp conversion error (buftvtots) (%s) (%d.%06d) ", (_Y_), (&(_X_))->tv.tv_sec, (&(_X_))->tv.tv_usec);\
+ return; \
+ } \
+ else \
+ { \
+ (&(_X_))->fp = ts; \
+ } \
+ }
+
+ if (PARSE_TIMECODE(parsetime.parse_state))
+ {
+ cvt_ts(parsetime.parse_time, "parse_time");
+ cvt_ts(parsetime.parse_stime, "parse_stime");
+ }
+
+ if (PARSE_PPS(parsetime.parse_state))
+ cvt_ts(parsetime.parse_ptime, "parse_ptime");
+
+ parse_process(parse, &parsetime);
+}
+
+/*--------------------------------------------------
+ * STREAM poll
+ */
+static void
+stream_poll(parse)
+ struct parseunit *parse;
+{
+ register int fd, i, rtc;
+ fd_set fdmask;
+ struct timeval timeout, starttime, curtime, selecttime;
+ parsetime_t parsetime;
+
+ /*
+ * now we do the following:
+ * - read the first packet from the parse module (OLD !!!)
+ * - read the second packet from the parse module (fresh)
+ * - compute values for xntp
+ */
+
+ FD_ZERO(&fdmask);
+ fd = parse->fd;
+ FD_SET(fd, &fdmask);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000; /* 0.5 sec */
+
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+
+ if (GETTIMEOFDAY(&starttime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+
+ selecttime = timeout;
+
+ while ((rtc = select(fd + 1, &fdmask, 0, 0, &selecttime)) != 1)
+ {
+ /* no data from the radio clock */
+
+ if (rtc == -1)
+ {
+ if (errno == EINTR)
+ {
+ if (GETTIMEOFDAY(&curtime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+ selecttime.tv_sec = curtime.tv_sec - starttime.tv_sec;
+ if (curtime.tv_usec < starttime.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + curtime.tv_usec - starttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = curtime.tv_usec - starttime.tv_usec;
+ }
+
+
+ if (timercmp(&selecttime, &timeout, >))
+ {
+ /*
+ * elapsed real time passed timeout value - consider it timed out
+ */
+ break;
+ }
+
+ /*
+ * calculate residual timeout value
+ */
+ selecttime.tv_sec = timeout.tv_sec - selecttime.tv_sec;
+
+ if (selecttime.tv_usec > timeout.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + timeout.tv_usec - selecttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = timeout.tv_usec - selecttime.tv_usec;
+ }
+
+ FD_SET(fd, &fdmask);
+ continue;
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[old] from device (select() error: %m)", CL_UNIT(parse->unit));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[old] from device", CL_UNIT(parse->unit));
+ }
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+
+ return;
+ }
+
+ while (((i = read(fd, (char *)&parsetime, sizeof(parsetime))) < sizeof(parsetime)))
+ {
+ /* bad packet */
+ if ( i == -1)
+ {
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[old] from streams module (read() error: %m)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[old] from streams module (got %d bytes - expected %d bytes)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ parse->baddata++;
+ parse_event(parse, CEVNT_BADREPLY);
+
+ return;
+ }
+
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 500000; /* 1.500 sec */
+ FD_ZERO(&fdmask);
+ FD_SET(fd, &fdmask);
+
+ if (GETTIMEOFDAY(&starttime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+
+ selecttime = timeout;
+
+ while ((rtc = select(fd + 1, &fdmask, 0, 0, &selecttime)) != 1)
+ {
+ /* no data from the radio clock */
+
+ if (rtc == -1)
+ {
+ if (errno == EINTR)
+ {
+ if (GETTIMEOFDAY(&curtime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+ selecttime.tv_sec = curtime.tv_sec - starttime.tv_sec;
+ if (curtime.tv_usec < starttime.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + curtime.tv_usec - starttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = curtime.tv_usec - starttime.tv_usec;
+ }
+
+
+ if (timercmp(&selecttime, &timeout, >))
+ {
+ /*
+ * elapsed real time passed timeout value - consider it timed out
+ */
+ break;
+ }
+
+ /*
+ * calculate residual timeout value
+ */
+ selecttime.tv_sec = timeout.tv_sec - selecttime.tv_sec;
+
+ if (selecttime.tv_usec > timeout.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + timeout.tv_usec - selecttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = timeout.tv_usec - selecttime.tv_usec;
+ }
+
+ FD_SET(fd, &fdmask);
+ continue;
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[new] from device (select() error: %m)", CL_UNIT(parse->unit));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[new] from device", CL_UNIT(parse->unit));
+ }
+
+ /*
+ * we will return here iff we got a good old sample as this would
+ * be misinterpreted. bad samples are passed on to be logged into the
+ * state statistics
+ */
+ if ((parsetime.parse_status & CVT_MASK) == CVT_OK)
+ {
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+ return;
+ }
+ }
+
+ /*
+ * we get here either by a possible read() (rtc == 1 - while assertion)
+ * or by a timeout or a system call error. when a read() is possible we
+ * get the new data, otherwise we stick with the old
+ */
+ if ((rtc == 1) && ((i = read(fd, (char *)&parsetime, sizeof(parsetime))) < sizeof(parsetime)))
+ {
+ /* bad packet */
+ if ( i== -1)
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[new] from streams module (read() error: %m)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[new] from streams module (got %d bytes - expected %d bytes)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ parse->baddata++;
+ parse_event(parse, CEVNT_BADREPLY);
+
+ return;
+ }
+
+ /*
+ * process what we got
+ */
+ parse_process(parse, &parsetime);
+}
+#endif
+
+/*--------------------------------------------------
+ * local init
+ */
+static int
+local_init(parse)
+ struct parseunit *parse;
+{
+ return parse_ioinit(&parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local end
+ */
+static void
+local_end(parse)
+ struct parseunit *parse;
+{
+ parse_ioend(&parse->parseio);
+}
+
+
+/*--------------------------------------------------
+ * local nop
+ */
+static int
+local_nop(parse)
+ struct parseunit *parse;
+{
+ return 1;
+}
+
+/*--------------------------------------------------
+ * local setcs
+ */
+static int
+local_setcs(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_setcs(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local getfmt
+ */
+static int
+local_getfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_getfmt(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local setfmt
+ */
+static int
+local_setfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_setfmt(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local getstat
+ */
+static int
+local_getstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_getstat(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local setstat
+ */
+static int
+local_setstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_setstat(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local timecode
+ */
+static int
+local_timecode(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_timecode(tcl, &parse->parseio);
+}
+
+
+/*--------------------------------------------------
+ * local receive
+ */
+static void
+local_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ struct parseunit *parse = (struct parseunit *)rbufp->recv_srcclock;
+ register int count;
+ register char *s;
+ /*
+ * eat all characters, parsing then and feeding complete samples
+ */
+ count = rbufp->recv_length;
+ s = rbufp->recv_buffer;
+
+ while (count--)
+ {
+ if (parse_ioread(&parse->parseio, *s++, &rbufp->recv_time))
+ {
+ /*
+ * got something good to eat
+ */
+#ifdef PPSPPS
+ if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state) &&
+ (parse->flags & PARSE_PPSCLOCK))
+ {
+ l_fp ts;
+ struct ppsclockev ev;
+
+ if (ioctl(parse->fd, CIOGETEV, (caddr_t)&ev) == 0)
+ {
+ if (ev.serial != parse->ppsserial)
+ {
+ /*
+ * add PPS time stamp if available via ppsclock module
+ * and not supplied already.
+ */
+ if (!buftvtots((const char *)&ev.tv, &ts))
+ {
+ syslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
+ }
+ else
+ {
+ parse->parseio.parse_dtime.parse_ptime.fp = ts;
+ parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
+ }
+ }
+ parse->ppsserial = ev.serial;
+ }
+ }
+#endif
+ parse_process(parse, &parse->parseio.parse_dtime);
+ parse_iodone(&parse->parseio);
+ }
+ }
+}
+
+/*--------------------------------------------------
+ * local poll
+ */
+static void
+local_poll(parse)
+ struct parseunit *parse;
+{
+ register int fd, i, rtc;
+ fd_set fdmask;
+ struct timeval timeout, starttime, curtime, selecttime;
+ static struct timeval null_time = { 0, 0};
+ timestamp_t ts;
+
+ FD_ZERO(&fdmask);
+ fd = parse->fd;
+ FD_SET(fd, &fdmask);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 500000; /* 1.5 sec */
+
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+
+ if (GETTIMEOFDAY(&starttime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+
+ selecttime = timeout;
+
+ do
+ {
+ while ((rtc = select(fd + 1, &fdmask, 0, 0, &selecttime)) != 1)
+ {
+ /* no data from the radio clock */
+
+ if (rtc == -1)
+ {
+ if (errno == EINTR)
+ {
+ if (GETTIMEOFDAY(&curtime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+ selecttime.tv_sec = curtime.tv_sec - starttime.tv_sec;
+ if (curtime.tv_usec < starttime.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + curtime.tv_usec - starttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = curtime.tv_usec - starttime.tv_usec;
+ }
+
+
+ if (!timercmp(&selecttime, &timeout, >))
+ {
+ /*
+ * calculate residual timeout value
+ */
+ selecttime.tv_sec = timeout.tv_sec - selecttime.tv_sec;
+
+ if (selecttime.tv_usec > timeout.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + timeout.tv_usec - selecttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = timeout.tv_usec - selecttime.tv_usec;
+ }
+
+ FD_SET(fd, &fdmask);
+ continue;
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data from device (select() error: %m)", CL_UNIT(parse->unit));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data from device", CL_UNIT(parse->unit));
+ }
+
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+
+ return;
+ }
+
+ /*
+ * at least 1 character is available - gobble everthing up that is available
+ */
+ do
+ {
+ char inbuf[256];
+
+ register char *s = inbuf;
+
+ rtc = i = read(fd, inbuf, sizeof(inbuf));
+
+ get_systime(&ts.fp);
+
+ while (i-- > 0)
+ {
+ if (parse_ioread(&parse->parseio, *s++, &ts))
+ {
+ /*
+ * got something good to eat
+ */
+ parse_process(parse, &parse->parseio.parse_dtime);
+ parse_iodone(&parse->parseio);
+ /*
+ * done if no more characters are available
+ */
+ FD_SET(fd, &fdmask);
+ if ((i == 0) &&
+ (select(fd + 1, &fdmask, 0, 0, &null_time) == 0))
+ return;
+ }
+ }
+ FD_SET(fd, &fdmask);
+ } while ((rtc = select(fd + 1, &fdmask, 0, 0, &null_time)) == 1);
+ FD_SET(fd, &fdmask);
+ } while (1);
+}
+
+/*--------------------------------------------------
+ * init_iobinding - find and initialize lower layers
+ */
+static bind_t *
+init_iobinding(parse)
+ struct parseunit *parse;
+{
+ register bind_t *b = io_bindings;
+
+ while (b->bd_description != (char *)0)
+ {
+ if ((*b->bd_init)(parse))
+ {
+ return b;
+ }
+ b++;
+ }
+ return (bind_t *)0;
+}
+
+/**===========================================================================
+ ** support routines
+ **/
+
+/*--------------------------------------------------
+ * convert a flag field to a string
+ */
+static char *
+parsestate(state, buffer)
+ u_long state;
+ char *buffer;
+{
+ static struct bits
+ {
+ u_long bit;
+ char *name;
+ } flagstrings[] =
+ {
+ { PARSEB_ANNOUNCE, "DST SWITCH WARNING" },
+ { PARSEB_POWERUP, "NOT SYNCHRONIZED" },
+ { PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" },
+ { PARSEB_DST, "DST" },
+ { PARSEB_UTC, "UTC DISPLAY" },
+ { PARSEB_LEAPADD, "LEAP ADD WARNING" },
+ { PARSEB_LEAPDEL, "LEAP DELETE WARNING" },
+ { PARSEB_LEAPSECOND, "LEAP SECOND" },
+ { PARSEB_ALTERNATE,"ALTERNATE ANTENNA" },
+ { PARSEB_TIMECODE, "TIME CODE" },
+ { PARSEB_PPS, "PPS" },
+ { PARSEB_POSITION, "POSITION" },
+ { 0 }
+ };
+
+ static struct sbits
+ {
+ u_long bit;
+ char *name;
+ } sflagstrings[] =
+ {
+ { PARSEB_S_LEAP, "LEAP INDICATION" },
+ { PARSEB_S_PPS, "PPS SIGNAL" },
+ { PARSEB_S_ANTENNA, "ANTENNA" },
+ { PARSEB_S_POSITION, "POSITION" },
+ { 0 }
+ };
+ int i;
+
+ *buffer = '\0';
+
+ i = 0;
+ while (flagstrings[i].bit)
+ {
+ if (flagstrings[i].bit & state)
+ {
+ if (buffer[0])
+ strcat(buffer, "; ");
+ strcat(buffer, flagstrings[i].name);
+ }
+ i++;
+ }
+
+ if (state & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
+ {
+ register char *s, *t;
+
+ if (buffer[0])
+ strcat(buffer, "; ");
+
+ strcat(buffer, "(");
+
+ t = s = buffer + strlen(buffer);
+
+ i = 0;
+ while (sflagstrings[i].bit)
+ {
+ if (sflagstrings[i].bit & state)
+ {
+ if (t != s)
+ {
+ strcpy(t, "; ");
+ t += 2;
+ }
+
+ strcpy(t, sflagstrings[i].name);
+ t += strlen(t);
+ }
+ i++;
+ }
+ strcpy(t, ")");
+ }
+ return buffer;
+}
+
+/*--------------------------------------------------
+ * convert a status flag field to a string
+ */
+static char *
+parsestatus(state, buffer)
+ u_long state;
+ char *buffer;
+{
+ static struct bits
+ {
+ u_long bit;
+ char *name;
+ } flagstrings[] =
+ {
+ { CVT_OK, "CONVERSION SUCCESSFUL" },
+ { CVT_NONE, "NO CONVERSION" },
+ { CVT_FAIL, "CONVERSION FAILED" },
+ { CVT_BADFMT, "ILLEGAL FORMAT" },
+ { CVT_BADDATE, "DATE ILLEGAL" },
+ { CVT_BADTIME, "TIME ILLEGAL" },
+ { 0 }
+ };
+ int i;
+
+ *buffer = '\0';
+
+ i = 0;
+ while (flagstrings[i].bit)
+ {
+ if (flagstrings[i].bit & state)
+ {
+ if (buffer[0])
+ strcat(buffer, "; ");
+ strcat(buffer, flagstrings[i].name);
+ }
+ i++;
+ }
+
+ return buffer;
+}
+
+/*--------------------------------------------------
+ * convert a clock status flag field to a string
+ */
+static char *
+clockstatus(state)
+ u_long state;
+{
+ static char buffer[20];
+ static struct status
+ {
+ u_long value;
+ char *name;
+ } flagstrings[] =
+ {
+ { CEVNT_NOMINAL, "NOMINAL" },
+ { CEVNT_TIMEOUT, "NO RESPONSE" },
+ { CEVNT_BADREPLY,"BAD FORMAT" },
+ { CEVNT_FAULT, "FAULT" },
+ { CEVNT_PROP, "PROPAGATION DELAY" },
+ { CEVNT_BADDATE, "ILLEGAL DATE" },
+ { CEVNT_BADTIME, "ILLEGAL TIME" },
+ { ~0 }
+ };
+ int i;
+
+ i = 0;
+ while (flagstrings[i].value != ~0)
+ {
+ if (flagstrings[i].value == state)
+ {
+ return flagstrings[i].name;
+ }
+ i++;
+ }
+
+ sprintf(buffer, "unknown #%ld", (u_long)state);
+
+ return buffer;
+}
+
+/*--------------------------------------------------
+ * mkascii - make a printable ascii string
+ * assumes (unless defined better) 7-bit ASCII
+ */
+#ifndef isprint
+#define isprint(_X_) (((_X_) > 0x1F) && ((_X_) < 0x7F))
+#endif
+
+static char *
+mkascii(buffer, blen, src, srclen)
+ register char *buffer;
+ register long blen;
+ register char *src;
+ register long srclen;
+{
+ register char *b = buffer;
+ register char *endb = (char *)0;
+
+ if (blen < 4)
+ return (char *)0; /* don't bother with mini buffers */
+
+ endb = buffer + blen - 4;
+
+ blen--; /* account for '\0' */
+
+ while (blen && srclen--)
+ {
+ if ((*src != '\\') && isprint(*src))
+ { /* printables are easy... */
+ *buffer++ = *src++;
+ blen--;
+ }
+ else
+ {
+ if (blen < 4)
+ {
+ while (blen--)
+ {
+ *buffer++ = '.';
+ }
+ *buffer = '\0';
+ return b;
+ }
+ else
+ {
+ if (*src == '\\')
+ {
+ strcpy(buffer,"\\\\");
+ buffer += 2;
+ blen -= 2;
+ }
+ else
+ {
+ sprintf(buffer, "\\x%02x", *src++);
+ blen -= 4;
+ buffer += 4;
+ }
+ }
+ }
+ if (srclen && !blen && endb) /* overflow - set last chars to ... */
+ strcpy(endb, "...");
+ }
+
+ *buffer = '\0';
+ return b;
+}
+
+
+/*--------------------------------------------------
+ * l_mktime - make representation of a relative time
+ */
+static char *
+l_mktime(delta)
+ u_long delta;
+{
+ u_long tmp, m, s;
+ static char buffer[40];
+
+ buffer[0] = '\0';
+
+ if ((tmp = delta / (60*60*24)) != 0)
+ {
+ sprintf(buffer, "%ldd+", (u_long)tmp);
+ delta -= tmp * 60*60*24;
+ }
+
+ s = delta % 60;
+ delta /= 60;
+ m = delta % 60;
+ delta /= 60;
+
+ sprintf(buffer+strlen(buffer), "%02d:%02d:%02d",
+ (int)delta, (int)m, (int)s);
+
+ return buffer;
+}
+
+
+/*--------------------------------------------------
+ * parse_statistics - list summary of clock states
+ */
+static void
+parse_statistics(parse)
+ register struct parseunit *parse;
+{
+ register int i;
+
+ syslog(LOG_INFO, "PARSE receiver #%d: running time: %s",
+ CL_UNIT(parse->unit),
+ l_mktime(current_time - parse->timestarted));
+
+ syslog(LOG_INFO, "PARSE receiver #%d: current status: %s",
+ CL_UNIT(parse->unit),
+ clockstatus(parse->status));
+
+ for (i = 0; i <= CEVNT_MAX; i++)
+ {
+ register u_long stime;
+ register u_long percent, div = current_time - parse->timestarted;
+
+ percent = stime = PARSE_STATETIME(parse, i);
+
+ while (((u_long)(~0) / 10000) < percent)
+ {
+ percent /= 10;
+ div /= 10;
+ }
+
+ if (div)
+ percent = (percent * 10000) / div;
+ else
+ percent = 10000;
+
+ if (stime)
+ syslog(LOG_INFO, "PARSE receiver #%d: state %18s: %13s (%3d.%02d%%)",
+ CL_UNIT(parse->unit),
+ clockstatus(i),
+ l_mktime(stime),
+ percent / 100, percent % 100);
+ }
+}
+
+/*--------------------------------------------------
+ * cparse_statistics - wrapper for statistics call
+ */
+static void
+cparse_statistics(peer)
+ register struct peer *peer;
+{
+ register struct parseunit *parse = (struct parseunit *)peer;
+
+ parse_statistics(parse);
+ parse->stattimer.event_time = current_time + PARSESTATISTICS;
+ TIMER_ENQUEUE(timerqueue, &parse->stattimer);
+}
+
+/**===========================================================================
+ ** xntp interface routines
+ **/
+
+/*--------------------------------------------------
+ * parse_init - initialize internal parse driver data
+ */
+static void
+parse_init()
+{
+ memset((caddr_t)parseunits, 0, sizeof parseunits);
+}
+
+
+/*--------------------------------------------------
+ * parse_shutdown - shut down a PARSE clock
+ */
+static void
+parse_shutdown(unit)
+ int unit;
+{
+ register struct parseunit *parse;
+
+ unit = CL_UNIT(unit);
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_shutdown: INTERNAL ERROR, unit invalid (max %d)",
+ unit,MAXUNITS);
+ return;
+ }
+
+ parse = parseunits[unit];
+
+ if (parse && !parse->peer) {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_shutdown: INTERNAL ERROR, unit not in use", unit);
+ return;
+ }
+
+ /*
+ * print statistics a last time and
+ * stop statistics machine
+ */
+ parse_statistics(parse);
+ TIMER_DEQUEUE(&parse->stattimer);
+
+#if PPSPPS
+ {
+ /*
+ * kill possible PPS association
+ */
+ if (fdpps == parse->fd)
+ fdpps = -1;
+ }
+#endif
+
+ if (parse->parse_type->cl_end)
+ {
+ parse->parse_type->cl_end(parse);
+ }
+
+ if (parse->binding)
+ PARSE_END(parse);
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ if (!parse->pollonly)
+ io_closeclock(&parse->io);
+ else
+ (void) close(parse->fd);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" removed",
+ CL_UNIT(parse->unit), parse->parse_type->cl_description);
+
+ parse->peer = (struct peer *)0; /* unused now */
+}
+
+/*--------------------------------------------------
+ * parse_start - open the PARSE devices and initialize data for processing
+ */
+static int
+parse_start(sysunit, peer)
+ u_int sysunit;
+ struct peer *peer;
+{
+ u_int unit;
+ int fd232, i;
+#ifdef HAVE_TERMIOS
+ struct termios tm; /* NEEDED FOR A LONG TIME ! */
+#endif
+#ifdef HAVE_SYSV_TTYS
+ struct termio tm; /* NEEDED FOR A LONG TIME ! */
+#endif
+ struct parseunit * parse;
+ char parsedev[sizeof(PARSEDEVICE)+20];
+ parsectl_t tmp_ctl;
+ u_int type;
+
+ type = CL_TYPE(sysunit);
+ unit = CL_UNIT(sysunit);
+
+ if (unit >= MAXUNITS)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: unit number invalid (max %d)",
+ unit, MAXUNITS-1);
+ return 0;
+ }
+
+ if ((type == ~0) || (clockinfo[type].cl_description == (char *)0))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: unsupported clock type %d (max %d)",
+ unit, CL_REALTYPE(sysunit), ncltypes-1);
+ return 0;
+ }
+
+ if (parseunits[unit] && parseunits[unit]->peer)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: unit in use", unit);
+ return 0;
+ }
+
+ /*
+ * Unit okay, attempt to open the device.
+ */
+ (void) sprintf(parsedev, PARSEDEVICE, unit);
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
+ fd232 = open(parsedev, O_RDWR|O_NOCTTY, 0777);
+ if (fd232 == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: open of %s failed: %m", unit, parsedev);
+ return 0;
+ }
+
+ /*
+ * Looks like this might succeed. Find memory for the structure.
+ * Look to see if there are any unused ones, if not we malloc()
+ * one.
+ */
+ if (parseunits[unit])
+ {
+ parse = parseunits[unit]; /* The one we want is okay - and free */
+ }
+ else
+ {
+ for (i = 0; i < MAXUNITS; i++)
+ {
+ if (parseunits[i] && !parseunits[i]->peer)
+ break;
+ }
+ if (i < MAXUNITS)
+ {
+ /*
+ * Reclaim this one
+ */
+ parse = parseunits[i];
+ parseunits[i] = (struct parseunit *)0;
+ }
+ else
+ {
+ parse = (struct parseunit *)
+ emalloc(sizeof(struct parseunit));
+ }
+ }
+
+ memset((char *)parse, 0, sizeof(struct parseunit));
+ parseunits[unit] = parse;
+
+ /*
+ * Set up the structures
+ */
+ parse->unit = (u_char)sysunit;
+ parse->timestarted = current_time;
+ parse->lastchange = current_time;
+ /*
+ * we want to filter input for the sake of
+ * getting an impression on dispersion
+ * also we like to average the median range
+ */
+ parse->flags = PARSE_STAT_FILTER|PARSE_STAT_AVG;
+ parse->pollneeddata = 0;
+ parse->pollonly = 1; /* go for default polling mode */
+ parse->lastformat = ~0; /* assume no format known */
+ parse->status = CEVNT_TIMEOUT; /* expect the worst */
+ parse->laststatus = ~0; /* be sure to mark initial status change */
+ parse->nosynctime = 0; /* assume clock reasonable */
+ parse->lastmissed = 0; /* assume got everything */
+ parse->ppsserial = 0;
+ parse->localdata = (void *)0;
+
+ parse->parse_type = &clockinfo[type];
+
+ parse->basedelay.l_ui = 0; /* we can only pre-configure delays less than 1 second */
+ parse->basedelay.l_uf = parse->parse_type->cl_basedelay;
+
+ parse->ppsdelay.l_ui = 0; /* we can only pre-configure delays less than 1 second */
+ parse->ppsdelay.l_uf = parse->parse_type->cl_ppsdelay;
+
+ peer->rootdelay = parse->parse_type->cl_rootdelay;
+ peer->sstclktype = parse->parse_type->cl_type;
+ peer->precision = sys_precision;
+ peer->stratum = STRATUM_REFCLOCK;
+ if (peer->stratum <= 1)
+ memmove((char *)&peer->refid, parse->parse_type->cl_id, 4);
+ else
+ peer->refid = htonl(PARSEHSREFID);
+
+ parse->fd = fd232;
+
+ parse->peer = peer; /* marks it also as busy */
+
+ parse->binding = init_iobinding(parse);
+
+ if (parse->binding == (bind_t *)0)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: io sub system initialisation failed.");
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+
+ /*
+ * configure terminal line
+ */
+ if (TTY_GETATTR(fd232, &tm) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcgetattr(%d, &tm): %m", unit, fd232);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ else
+ {
+#ifndef _PC_VDISABLE
+ memset((char *)tm.c_cc, 0, sizeof(tm.c_cc));
+#else
+ int disablec;
+ errno = 0; /* pathconf can deliver -1 without changing errno ! */
+
+ disablec = fpathconf(parse->fd, _PC_VDISABLE);
+ if (disablec == -1 && errno)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: fpathconf(fd, _PC_VDISABLE): %m", CL_UNIT(parse->unit));
+ memset((char *)tm.c_cc, 0, sizeof(tm.c_cc)); /* best guess */
+ }
+ else
+ if (disablec != -1)
+ memset((char *)tm.c_cc, disablec, sizeof(tm.c_cc));
+#endif
+
+ tm.c_cflag = clockinfo[type].cl_cflag;
+ tm.c_iflag = clockinfo[type].cl_iflag;
+ tm.c_oflag = clockinfo[type].cl_oflag;
+ tm.c_lflag = clockinfo[type].cl_lflag;
+
+ if (TTY_SETATTR(fd232, &tm) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcsetattr(%d, &tm): %m", unit, fd232);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ }
+
+ /*
+ * as we always(?) get 8 bit chars we want to be
+ * sure, that the upper bits are zero for less
+ * than 8 bit I/O - so we pass that information on.
+ * note that there can be only one bit count format
+ * per file descriptor
+ */
+
+ switch (tm.c_cflag & CSIZE)
+ {
+ case CS5:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS5;
+ break;
+
+ case CS6:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS6;
+ break;
+
+ case CS7:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS7;
+ break;
+
+ case CS8:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS8;
+ break;
+ }
+
+ if (!PARSE_SETCS(parse, &tmp_ctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setcs() FAILED.", unit);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+
+ strcpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format);
+ tmp_ctl.parseformat.parse_count = strlen(tmp_ctl.parseformat.parse_buffer);
+
+ if (!PARSE_SETFMT(parse, &tmp_ctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+
+#ifdef TCFLSH
+ /*
+ * get rid of all IO accumulated so far
+ */
+ {
+#ifndef TCIOFLUSH
+#define TCIOFLUSH 2
+#endif
+ int flshcmd = TCIOFLUSH;
+
+ (void) ioctl(parse->fd, TCFLSH, (caddr_t)&flshcmd);
+ }
+#endif
+
+ tmp_ctl.parsestatus.flags = parse->flags & PARSE_STAT_FLAGS;
+
+ if (!PARSE_SETSTAT(parse, &tmp_ctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setstat() FAILED.", unit);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+
+ /*
+ * try to do any special initializations
+ */
+ if (parse->parse_type->cl_init)
+ {
+ if (parse->parse_type->cl_init(parse))
+ {
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+ }
+
+ if (!(parse->parse_type->cl_flags & PARSE_F_POLLONLY) &&
+ (CL_PPS(parse->unit) || (parse->parse_type->cl_flags & PARSE_F_NOPOLLONLY)))
+ {
+ /*
+ * Insert in async io device list.
+ */
+ parse->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
+ parse->io.srcclock = (caddr_t)parse;
+ parse->io.datalen = 0;
+ parse->io.fd = parse->fd; /* replicated, but what the heck */
+ if (!io_addclock(&parse->io))
+ {
+ if (parse->parse_type->cl_flags & PARSE_F_NOPOLLONLY)
+ {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CL_UNIT(parse->unit), parsedev);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ else
+ {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_start: addclock %s fails (switching to polling mode)", CL_UNIT(parse->unit), parsedev);
+ }
+ }
+ else
+ {
+ parse->pollonly = 0; /*
+ * update at receipt of time_stamp - also
+ * supports PPS processing
+ */
+ }
+ }
+
+#ifdef PPSPPS
+ if (parse->pollonly && (parse->parse_type->cl_flags & PARSE_F_PPSPPS))
+ {
+ if (fdpps == -1)
+ {
+ fdpps = parse->fd;
+ if (!PARSE_DISABLE(parse))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_disable() FAILED", CL_UNIT(parse->unit));
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ }
+ else
+ {
+ syslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: loopfilter PPS already active - no PPS via CIOGETEV", CL_UNIT(parse->unit));
+ }
+ }
+#endif
+
+ /*
+ * wind up statistics timer
+ */
+ parse->stattimer.peer = (struct peer *)parse; /* we know better, but what the heck */
+ parse->stattimer.event_handler = cparse_statistics;
+ parse->stattimer.event_time = current_time + PARSESTATISTICS;
+ TIMER_ENQUEUE(timerqueue, &parse->stattimer);
+
+ /*
+ * get out Copyright information once
+ */
+ if (!notice)
+ {
+ syslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-1993, Frank Kardel");
+ notice = 1;
+ }
+
+ /*
+ * print out configuration
+ */
+ syslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (device %s) added",
+ CL_UNIT(parse->unit),
+ parse->parse_type->cl_description, parsedev);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, %sPPS support, trust time %s, precision %d",
+ CL_UNIT(parse->unit),
+ parse->peer->stratum, (parse->pollonly || !CL_PPS(parse->unit)) ? "no " : "",
+ l_mktime(parse->parse_type->cl_maxunsync), parse->peer->precision);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: rootdelay %s s, phaseadjust %s s, %s IO handling",
+ CL_UNIT(parse->unit),
+ ufptoa(parse->parse_type->cl_rootdelay, 6),
+ lfptoa(&parse->basedelay, 8),
+ parse->binding->bd_description);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CL_UNIT(parse->unit),
+ !(*parse->parse_type->cl_format) ? "<AUTOMATIC>" : parse->parse_type->cl_format);
+
+#ifdef PPSPPS
+ syslog(LOG_INFO, "PARSE receiver #%d: %sCD PPS support",
+ CL_UNIT(parse->unit),
+ (fdpps == parse->fd) ? "" : "NO ");
+#endif
+
+ return 1;
+}
+
+/*--------------------------------------------------
+ * parse_poll - called by the transmit procedure
+ */
+static void
+parse_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct parseunit *parse;
+
+ unit = CL_UNIT(unit);
+
+ if (unit >= MAXUNITS)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll: INTERNAL: unit invalid",
+ unit);
+ return;
+ }
+
+ parse = parseunits[unit];
+
+ if (!parse->peer)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll: INTERNAL: unit unused",
+ unit);
+ return;
+ }
+
+ if (peer != parse->peer)
+ {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: poll: INTERNAL: peer incorrect",
+ unit);
+ return;
+ }
+
+ /*
+ * Update clock stat counters
+ */
+ parse->polls++;
+
+ /*
+ * in PPS mode we just mark that we want the next sample
+ * for the clock filter
+ */
+ if (!parse->pollonly)
+ {
+ if (parse->pollneeddata)
+ {
+ /*
+ * bad news - didn't get a response last time
+ */
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval", CL_UNIT(parse->unit));
+ }
+ parse->pollneeddata = 1;
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+ return;
+ }
+
+ /*
+ * the following code is only executed only when polling is used
+ */
+
+ PARSE_POLL(parse);
+}
+
+/*--------------------------------------------------
+ * parse_leap - called when a leap second occurs
+ */
+
+static void
+parse_leap()
+{
+ /*
+ * 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).
+ */
+}
+
+
+/*--------------------------------------------------
+ * parse_control - set fudge factors, return statistics
+ */
+static void
+parse_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct parseunit *parse;
+ parsectl_t tmpctl;
+ u_long type;
+ static char outstatus[400]; /* status output buffer */
+
+ type = CL_TYPE(unit);
+ unit = CL_UNIT(unit);
+
+ if (out)
+ {
+ out->lencode = 0;
+ out->lastcode = 0;
+ out->polls = out->noresponse = 0;
+ out->badformat = out->baddata = 0;
+ out->timereset = 0;
+ out->currentstatus = out->lastevent = CEVNT_NOMINAL;
+ out->kv_list = (struct ctl_var *)0;
+ }
+
+ if (unit >= MAXUNITS)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (max %d)",
+ unit, MAXUNITS-1);
+ return;
+ }
+
+ parse = parseunits[unit];
+
+ if (!parse || !parse->peer)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
+ unit);
+ return;
+ }
+
+ if (in)
+ {
+ if (in->haveflags & CLK_HAVETIME1)
+ parse->basedelay = in->fudgetime1;
+
+ if (in->haveflags & CLK_HAVETIME2)
+ {
+ parse->ppsdelay = in->fudgetime2;
+ }
+
+ if (in->haveflags & CLK_HAVEVAL1)
+ {
+ parse->peer->stratum = (u_char)(in->fudgeval1 & 0xf);
+ if (parse->peer->stratum <= 1)
+ memmove((char *)&parse->peer->refid,
+ parse->parse_type->cl_id,
+ 4);
+ else
+ parse->peer->refid = htonl(PARSEHSREFID);
+ }
+
+ if (in->haveflags & CLK_HAVEVAL2)
+ {
+ parse->peer->refid = in->fudgeval2;
+ }
+
+ if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
+ {
+ parse->flags = (in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4)) |
+ (parse->flags & ~PARSE_STAT_FLAGS);
+ }
+
+ if (in->haveflags & (CLK_HAVEVAL2|CLK_HAVETIME2|CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
+ {
+ parsectl_t tmpctl;
+ tmpctl.parsestatus.flags = parse->flags & PARSE_STAT_FLAGS;
+
+ if (!PARSE_SETSTAT(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_setstat() FAILED", unit);
+ }
+ }
+ }
+
+ if (out)
+ {
+ register u_long sum = 0;
+ register char *t, *tt;
+ register struct tm *tm;
+ register short utcoff;
+ register char sign;
+ register int i;
+ time_t tim;
+
+ outstatus[0] = '\0';
+
+ out->haveflags = CLK_HAVETIME1|CLK_HAVETIME2|CLK_HAVEVAL1|CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3;
+ out->clockdesc = parse->parse_type->cl_description;
+
+ out->fudgetime1 = parse->basedelay;
+
+ out->fudgetime2 = parse->ppsdelay;
+
+ out->fudgeval1 = parse->peer->stratum;
+
+ out->fudgeval2 = parse->peer->refid;
+
+ out->flags = parse->flags & PARSE_STAT_FLAGS;
+
+ out->type = REFCLK_PARSE;
+
+ /*
+ * figure out skew between PPS and RS232 - just for informational
+ * purposes - returned in time2 value
+ */
+ if (PARSE_SYNC(parse->time.parse_state))
+ {
+ if (PARSE_PPS(parse->time.parse_state) && PARSE_TIMECODE(parse->time.parse_state))
+ {
+ l_fp off;
+
+ /*
+ * we have a PPS and RS232 signal - calculate the skew
+ * WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
+ */
+ off = parse->time.parse_stime.fp;
+ L_SUB(&off, &parse->time.parse_ptime.fp); /* true offset */
+ tt = add_var(&out->kv_list, 40, RO);
+ sprintf(tt, "refclock_ppsskew=%s", lfptoms(&off, 6));
+ }
+ }
+
+ if (PARSE_PPS(parse->time.parse_state))
+ {
+ tt = add_var(&out->kv_list, 80, RO|DEF);
+ sprintf(tt, "refclock_ppstime=\"%s\"", prettydate(&parse->time.parse_ptime.fp));
+ }
+
+ /*
+ * all this for just finding out the +-xxxx part (there are always
+ * new and changing fields in the standards 8-().
+ *
+ * but we do it for the human user...
+ */
+ tim = parse->time.parse_time.fp.l_ui - JAN_1970;
+ tm = gmtime(&tim);
+ utcoff = tm->tm_hour * 60 + tm->tm_min;
+ tm = localtime(&tim);
+ utcoff = tm->tm_hour * 60 + tm->tm_min - utcoff + 12 * 60;
+ utcoff += 24 * 60;
+ utcoff %= 24 * 60;
+ utcoff -= 12 * 60;
+ if (utcoff < 0)
+ {
+ utcoff = -utcoff;
+ sign = '-';
+ }
+ else
+ {
+ sign = '+';
+ }
+
+ tt = add_var(&out->kv_list, 128, RO|DEF);
+ sprintf(tt, "refclock_time=\"");
+ tt += strlen(tt);
+
+ if (parse->time.parse_time.fp.l_ui == 0)
+ {
+ strcpy(tt, "<UNDEFINED>\"");
+ }
+ else
+ {
+ strcpy(tt, prettydate(&parse->time.parse_time.fp));
+ t = tt + strlen(tt);
+
+ sprintf(t, " (%c%02d%02d)\"", sign, utcoff / 60, utcoff % 60);
+ }
+
+ if (!PARSE_GETTIMECODE(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
+ }
+ else
+ {
+ tt = add_var(&out->kv_list, 128, RO|DEF);
+ sprintf(tt, "refclock_status=\"");
+ tt += strlen(tt);
+
+ /*
+ * copy PPS flags from last read transaction (informational only)
+ */
+ tmpctl.parsegettc.parse_state |= parse->time.parse_state &
+ (PARSEB_PPS|PARSEB_S_PPS);
+
+ (void) parsestate(tmpctl.parsegettc.parse_state, tt);
+
+ strcat(tt, "\"");
+
+ if (tmpctl.parsegettc.parse_count)
+ mkascii(outstatus+strlen(outstatus), sizeof(outstatus)- strlen(outstatus) - 1,
+ tmpctl.parsegettc.parse_buffer, tmpctl.parsegettc.parse_count - 1);
+
+ parse->badformat += tmpctl.parsegettc.parse_badformat;
+ }
+
+ tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
+
+ if (!PARSE_GETFMT(parse, &tmpctl))
+ {
+ syslog (LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit);
+ }
+ else
+ {
+ tt = add_var(&out->kv_list, 80, RO|DEF);
+ sprintf(tt, "refclock_format=\"");
+
+ strncat(tt, tmpctl.parseformat.parse_buffer, tmpctl.parseformat.parse_count);
+ strcat(tt,"\"");
+ }
+
+ /*
+ * gather state statistics
+ */
+
+ tt = add_var(&out->kv_list, 200, RO|DEF);
+ strcpy(tt, "refclock_states=\"");
+ tt += strlen(tt);
+
+ for (i = 0; i <= CEVNT_MAX; i++)
+ {
+ register u_long stime;
+ register u_long div = current_time - parse->timestarted;
+ register u_long percent;
+
+ percent = stime = PARSE_STATETIME(parse, i);
+
+ while (((u_long)(~0) / 10000) < percent)
+ {
+ percent /= 10;
+ div /= 10;
+ }
+
+ if (div)
+ percent = (percent * 10000) / div;
+ else
+ percent = 10000;
+
+ if (stime)
+ {
+ sprintf(tt, "%s%s%s: %s (%d.%02d%%)",
+ sum ? "; " : "",
+ (parse->status == i) ? "*" : "",
+ clockstatus(i),
+ l_mktime(stime),
+ (int)(percent / 100), (int)(percent % 100));
+ sum += stime;
+ tt += strlen(tt);
+ }
+ }
+
+ sprintf(tt, "; running time: %s\"", l_mktime(sum));
+
+ tt = add_var(&out->kv_list, 32, RO);
+ sprintf(tt, "refclock_id=\"%s\"", parse->parse_type->cl_id);
+
+ tt = add_var(&out->kv_list, 80, RO);
+ 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.59 1994/05/23 16:29:27 kardel Exp\"");
+
+ out->lencode = strlen(outstatus);
+ out->lastcode = outstatus;
+ out->timereset = parse->timestarted;
+ out->polls = parse->polls;
+ out->noresponse = parse->noresponse;
+ out->badformat = parse->badformat;
+ out->baddata = parse->baddata;
+ out->lastevent = parse->lastevent;
+ out->currentstatus = parse->status;
+ }
+}
+
+/**===========================================================================
+ ** processing routines
+ **/
+
+/*--------------------------------------------------
+ * event handling - note that nominal events will also be posted
+ */
+static void
+parse_event(parse, event)
+ struct parseunit *parse;
+ int event;
+{
+ if (parse->status != (u_char) event)
+ {
+ parse->statetime[parse->status] += current_time - parse->lastchange;
+ parse->lastchange = current_time;
+
+ parse->status = (u_char)event;
+ if (event != CEVNT_NOMINAL)
+ parse->lastevent = parse->status;
+
+ report_event(EVNT_PEERCLOCK, parse->peer);
+ }
+}
+
+/*--------------------------------------------------
+ * process a PARSE time sample
+ */
+static void
+parse_process(parse, parsetime)
+ struct parseunit *parse;
+ parsetime_t *parsetime;
+{
+ unsigned char leap;
+ struct timeval usecdisp;
+ l_fp off, rectime, reftime, dispersion;
+
+ /*
+ * check for changes in conversion status
+ * (only one for each new status !)
+ */
+ if (parse->laststatus != parsetime->parse_status)
+ {
+ char buffer[200];
+
+ syslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
+ CL_UNIT(parse->unit), parsestatus(parsetime->parse_status, buffer));
+
+ if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
+ {
+ /*
+ * tell more about the story - list time code
+ * there is a slight change for a race condition and
+ * the time code might be overwritten by the next packet
+ */
+ parsectl_t tmpctl;
+
+ if (!PARSE_GETTIMECODE(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CL_UNIT(parse->unit));
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\"",
+ CL_UNIT(parse->unit), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, tmpctl.parsegettc.parse_count - 1));
+ parse->badformat += tmpctl.parsegettc.parse_badformat;
+ }
+ }
+
+ parse->laststatus = parsetime->parse_status;
+ }
+
+ /*
+ * examine status and post appropriate events
+ */
+ if ((parsetime->parse_status & CVT_MASK) != CVT_OK)
+ {
+ /*
+ * got bad data - tell the rest of the system
+ */
+ switch (parsetime->parse_status & CVT_MASK)
+ {
+ case CVT_NONE:
+ break; /* well, still waiting - timeout is handled at higher levels */
+
+ case CVT_FAIL:
+ parse->badformat++;
+ if (parsetime->parse_status & CVT_BADFMT)
+ {
+ parse_event(parse, CEVNT_BADREPLY);
+ }
+ else
+ if (parsetime->parse_status & CVT_BADDATE)
+ {
+ parse_event(parse, CEVNT_BADDATE);
+ }
+ else
+ if (parsetime->parse_status & CVT_BADTIME)
+ {
+ parse_event(parse, CEVNT_BADTIME);
+ }
+ else
+ {
+ parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */
+ }
+ }
+ return; /* skip the rest - useless */
+ }
+
+ /*
+ * check for format changes
+ * (in case somebody has swapped clocks 8-)
+ */
+ if (parse->lastformat != parsetime->parse_format)
+ {
+ parsectl_t tmpctl;
+
+ tmpctl.parseformat.parse_format = parsetime->parse_format;
+
+ if (!PARSE_GETFMT(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CL_UNIT(parse->unit));
+ }
+ else
+ {
+ syslog(LOG_INFO, "PARSE receiver #%d: new packet format \"%s\"",
+ CL_UNIT(parse->unit), tmpctl.parseformat.parse_buffer);
+ }
+ parse->lastformat = parsetime->parse_format;
+ }
+
+ /*
+ * now, any changes ?
+ */
+ if (parse->time.parse_state != parsetime->parse_state)
+ {
+ char tmp1[200];
+ char tmp2[200];
+ /*
+ * something happend
+ */
+
+ (void) parsestate(parsetime->parse_state, tmp1);
+ (void) parsestate(parse->time.parse_state, tmp2);
+
+ syslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
+ CL_UNIT(parse->unit), tmp2, tmp1);
+ }
+
+ /*
+ * remember for future
+ */
+ parse->time = *parsetime;
+
+ /*
+ * check to see, whether the clock did a complete powerup or lost PZF signal
+ * and post correct events for current condition
+ */
+ if (PARSE_POWERUP(parsetime->parse_state))
+ {
+ /*
+ * this is bad, as we have completely lost synchronisation
+ * well this is a problem with the receiver here
+ * for PARSE U/A 31 the lost synchronisation ist true
+ * as it is the powerup state and the time is taken
+ * from a crude real time clock chip
+ * for the PZF series this is only partly true, as
+ * PARSE_POWERUP only means that the pseudo random
+ * phase shift sequence cannot be found. this is only
+ * bad, if we have never seen the clock in the SYNC
+ * state, where the PHASE and EPOCH are correct.
+ * for reporting events the above business does not
+ * really matter, but we can use the time code
+ * even in the POWERUP state after having seen
+ * the clock in the synchronized state (PZF class
+ * receivers) unless we have had a telegram disruption
+ * after having seen the clock in the SYNC state. we
+ * thus require having seen the clock in SYNC state
+ * *after* having missed telegrams (noresponse) from
+ * the clock. one problem remains: we might use erroneously
+ * POWERUP data if the disruption is shorter than 1 polling
+ * interval. fortunately powerdowns last usually longer than 64
+ * seconds and the receiver is at least 2 minutes in the
+ * POWERUP or NOSYNC state before switching to SYNC
+ */
+ parse_event(parse, CEVNT_FAULT);
+ if (parse->nosynctime)
+ {
+ /*
+ * repeated POWERUP/NOSYNC state - look whether
+ * the message should be repeated
+ */
+ if (current_time - parse->nosynctime > PARSENOSYNCREPEAT)
+ {
+ syslog(LOG_ERR,"PARSE receiver #%d: *STILL* NOT SYNCHRONIZED (POWERUP or no PZF signal)",
+ CL_UNIT(parse->unit));
+ parse->nosynctime = current_time;
+ }
+ }
+ else
+ {
+ syslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED",
+ CL_UNIT(parse->unit));
+ parse->nosynctime = current_time;
+ }
+ }
+ else
+ {
+ /*
+ * we have two states left
+ *
+ * SYNC:
+ * this state means that the EPOCH (timecode) and PHASE
+ * information has be read correctly (at least two
+ * successive PARSE timecodes were received correctly)
+ * this is the best possible state - full trust
+ *
+ * NOSYNC:
+ * The clock should be on phase with respect to the second
+ * signal, but the timecode has not been received correctly within
+ * at least the last two minutes. this is a sort of half baked state
+ * for PARSE U/A 31 this is bad news (clock running without timecode
+ * confirmation)
+ * PZF 535 has also no time confirmation, but the phase should be
+ * very precise as the PZF signal can be decoded
+ */
+ parse->nosynctime = 0; /* current state is better than worst state */
+
+ if (PARSE_SYNC(parsetime->parse_state))
+ {
+ /*
+ * currently completely synchronized - best possible state
+ */
+ parse->lastsync = current_time;
+ /*
+ * log OK status
+ */
+ parse_event(parse, CEVNT_NOMINAL);
+ }
+ else
+ {
+ /*
+ * we have had some problems receiving the time code
+ */
+ parse_event(parse, CEVNT_PROP);
+ }
+ }
+
+ if (PARSE_TIMECODE(parsetime->parse_state))
+ {
+ l_fp offset;
+
+ /*
+ * calculate time offset including systematic delays
+ * off = PARSE-timestamp + propagation delay - kernel time stamp
+ */
+ offset = parse->basedelay;
+
+ off = parsetime->parse_time.fp;
+
+ reftime = off;
+
+ L_ADD(&off, &offset);
+ rectime = off; /* this makes org time and xmt time somewhat artificial */
+
+ 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;
+ /*
+ * offset is already calculated
+ */
+ usecerror.tv_sec = parsetime->parse_usecerror / 1000000;
+ usecerror.tv_usec = parsetime->parse_usecerror % 1000000;
+
+ sTVTOTS(&usecerror, &off);
+ L_ADD(&off, &offset);
+ }
+ }
+
+ if (PARSE_PPS(parsetime->parse_state) && CL_PPS(parse->unit))
+ {
+ l_fp offset;
+
+ /*
+ * we have a PPS signal - much better than the RS232 stuff (we hope)
+ */
+ offset = parsetime->parse_ptime.fp;
+
+ L_ADD(&offset, &parse->ppsdelay);
+
+ if (PARSE_TIMECODE(parsetime->parse_state))
+ {
+ if (M_ISGEQ(off.l_i, off.l_f, -1, 0x80000000) &&
+ M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_f))
+ {
+ /*
+ * RS232 offsets within [-0.5..0.5[ - take PPS offsets
+ */
+
+ if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
+ {
+ reftime = off = offset;
+ rectime = offset;
+ /*
+ * implied on second offset
+ */
+ off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
+ off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
+ }
+ else
+ {
+ /*
+ * time code describes pulse
+ */
+ off = parsetime->parse_time.fp;
+
+ rectime = reftime = off; /* take reference time - fake rectime */
+
+ L_SUB(&off, &offset); /* true offset */
+ }
+ }
+ /*
+ * take RS232 offset when PPS when out of bounds
+ */
+ }
+ else
+ {
+ /*
+ * Well, no time code to guide us - assume on second pulse
+ * and pray, that we are within [-0.5..0.5[
+ */
+ reftime = off = offset;
+ rectime = offset;
+ /*
+ * implied on second offset
+ */
+ off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
+ off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
+ }
+ }
+ else
+ {
+ if (!PARSE_TIMECODE(parsetime->parse_state))
+ {
+ /*
+ * Well, no PPS, no TIMECODE, no more work ...
+ */
+ return;
+ }
+ }
+
+
+#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS) || defined(PARSEPPS)
+ if (CL_PPS(parse->unit) && !parse->pollonly && PARSE_SYNC(parsetime->parse_state))
+ {
+ /*
+ * only provide PPS information when clock
+ * is in sync
+ * thus PHASE and EPOCH are correct and PPS is not
+ * done via the CIOGETEV loopfilter mechanism
+ */
+#ifdef PPSPPS
+ if (fdpps != parse->fd)
+#endif
+ (void) pps_sample(&off);
+ }
+#endif /* PPS || PPSCLK || PPSPPS || PARSEPPS */
+
+ /*
+ * ready, unless the machine wants a sample
+ */
+ if (!parse->pollonly && !parse->pollneeddata)
+ return;
+
+ parse->pollneeddata = 0;
+
+ if (PARSE_PPS(parsetime->parse_state))
+ {
+ L_CLR(&dispersion);
+ }
+ else
+ {
+ /*
+ * convert usec dispersion into NTP TS world
+ */
+
+ usecdisp.tv_sec = parsetime->parse_usecdisp / 1000000;
+ usecdisp.tv_usec = parsetime->parse_usecdisp % 1000000;
+
+ TVTOTS(&usecdisp, &dispersion);
+ }
+
+ /*
+ * and now stick it into the clock machine
+ * samples are only valid iff lastsync is not too old and
+ * we have seen the clock in sync at least once
+ * after the last time we didn't see an expected data telegram
+ * see the clock states section above for more reasoning
+ */
+ if (((current_time - parse->lastsync) > parse->parse_type->cl_maxunsync) ||
+ (parse->lastsync <= parse->lastmissed))
+ {
+ leap = LEAP_NOTINSYNC;
+ }
+ else
+ {
+ 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
+ if (PARSE_LEAPDEL(parsetime->parse_state))
+ {
+ leap = LEAP_DELSECOND;
+ }
+ else
+ {
+ leap = LEAP_NOWARNING;
+ }
+ }
+
+ refclock_receive(parse->peer, &off, 0, LFPTOFP(&dispersion), &reftime, &rectime, leap);
+}
+
+/**===========================================================================
+ ** clock polling support
+ **/
+
+struct poll_timer
+{
+ struct event timer; /* we'd like to poll a a higher rate than 1/64s */
+};
+
+typedef struct poll_timer poll_timer_t;
+
+/*--------------------------------------------------
+ * direct poll routine
+ */
+static void
+poll_dpoll(parse)
+ struct parseunit *parse;
+{
+ register int rtc;
+ register char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
+ register int ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
+
+ rtc = write(parse->fd, ps, ct);
+ if (rtc < 0)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CL_UNIT(parse->unit));
+ }
+ else
+ if (rtc != ct)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%d of %d bytes sent)", CL_UNIT(parse->unit), rtc, ct);
+ }
+}
+
+/*--------------------------------------------------
+ * periodic poll routine
+ */
+static void
+poll_poll(parse)
+ struct parseunit *parse;
+{
+ register poll_timer_t *pt = (poll_timer_t *)parse->localdata;
+
+ poll_dpoll(parse);
+
+ if (pt != (poll_timer_t *)0)
+ {
+ pt->timer.event_time = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
+ TIMER_ENQUEUE(timerqueue, &pt->timer);
+ }
+}
+
+/*--------------------------------------------------
+ * init routine - setup timer
+ */
+static int
+poll_init(parse)
+ struct parseunit *parse;
+{
+ register poll_timer_t *pt;
+
+ if (((poll_info_t *)parse->parse_type->cl_data)->rate)
+ {
+ parse->localdata = (void *)malloc(sizeof(poll_timer_t));
+ memset((char *)parse->localdata, 0, sizeof(poll_timer_t));
+
+ pt = (poll_timer_t *)parse->localdata;
+
+ pt->timer.peer = (struct peer *)parse; /* well, only we know what it is */
+ pt->timer.event_handler = poll_poll;
+ poll_poll(parse);
+ }
+ else
+ {
+ parse->localdata = (void *)0;
+ }
+
+ return 0;
+}
+
+/*--------------------------------------------------
+ * end routine - clean up timer
+ */
+static void
+poll_end(parse)
+ struct parseunit *parse;
+{
+ if (parse->localdata != (void *)0)
+ {
+ TIMER_DEQUEUE(&((poll_timer_t *)parse->localdata)->timer);
+ free((char *)parse->localdata);
+ parse->localdata = (void *)0;
+ }
+}
+
+/**===========================================================================
+ ** special code for special clocks
+ **/
+
+/*--------------------------------------------------
+ * trimble init routine - setup EOL and then do poll_init.
+ */
+static int
+trimble_init(parse)
+ struct parseunit *parse;
+{
+#ifdef HAVE_TERMIOS
+ struct termios tm;
+#endif
+#ifdef HAVE_SYSV_TTYS
+ struct termio tm;
+#endif
+ /*
+ * configure terminal line for trimble receiver
+ */
+ if (TTY_GETATTR(parse->fd, &tm) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: trimble_init: tcgetattr(fd, &tm): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ else
+ {
+ tm.c_cc[VEOL] = TRIMBLESV6_EOL;
+
+ if (TTY_SETATTR(parse->fd, &tm) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: trimble_init: tcsetattr(fd, &tm): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ }
+ return poll_init(parse);
+}
+#endif /* defined(REFCLOCK) && defined(PARSE) */
+
+/*
+ * History:
+ *
+ * refclock_parse.c,v
+ * Revision 3.59 1994/05/23 16:29:27 kardel
+ * IGEL clock - Trimble update
+ *
+ * Revision 3.58 1994/05/12 21:03:39 kardel
+ * adhere to new standard that fudgeval2 is refid
+ *
+ * Revision 3.57 1994/05/12 12:50:47 kardel
+ * printf fmt/arg cleanup
+ *
+ * Revision 3.56 1994/05/10 21:15:51 kardel
+ * var reference level bug, kernel disable fix
+ *
+ * Revision 3.55 1994/05/02 00:37:01 kardel
+ * 3.3t reconcilation + bug fixes (PPS simulation - old kpll)
+ *
+ * Revision 3.54 1994/04/11 19:34:42 kardel
+ * longer input characters for DCF77 raw input (8Bit+parity ignored)
+ *
+ * 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
+ *
+ * Revision 3.44 1994/01/25 17:32:23 kardel
+ * settable extended variables
+ *
+ * Revision 3.43 1994/01/23 16:28:39 kardel
+ * HAVE_TERMIOS introduced
+ *
+ * Revision 3.42 1994/01/22 11:35:04 kardel
+ * added HAVE_TERMIOS
+ *
+ * Revision 3.41 1993/11/27 18:44:37 kardel
+ * can't trust GPS166 on unsync
+ *
+ * Revision 3.40 1993/11/21 18:03:36 kardel
+ * useless declaration deleted
+ *
+ * Revision 3.39 1993/11/21 15:30:15 kardel
+ * static funcitions may be declared only at outer level
+ *
+ * Revision 3.38 1993/11/15 21:26:49 kardel
+ * conditional define comments fixed
+ *
+ * Revision 3.37 1993/11/11 11:20:49 kardel
+ * declaration fixes
+ *
+ * Revision 3.36 1993/11/10 12:17:14 kardel
+ * #ifdef glitch
+ *
+ * Revision 3.35 1993/11/01 21:15:06 kardel
+ * comments updated
+ *
+ * Revision 3.34 1993/11/01 20:01:08 kardel
+ * parse Solaris support (initial version)
+ *
+ * Revision 3.33 1993/10/30 09:44:58 kardel
+ * conditional compilation flag cleanup
+ *
+ * Revision 3.32 1993/10/22 14:28:43 kardel
+ * Oct. 22nd 1993 reconcilation
+ *
+ * Revision 3.31 1993/10/10 21:19:10 kardel
+ * compilation cleanup - (minimal porting tests)
+ *
+ * Revision 3.30 1993/10/09 21:44:35 kardel
+ * syslog strings fixed
+ *
+ * Revision 3.29 1993/10/09 14:40:15 kardel
+ * default precision setting fixed
+ *
+ * Revision 3.28 1993/10/08 14:48:22 kardel
+ * Changed offset determination logic:
+ * Take the PPS offset if it is available and the time
+ * code offset is within [-0.5..0.5[, otherwise stick
+ * to the time code offset
+ *
+ * Revision 3.27 1993/10/08 00:53:17 kardel
+ * announce also simulated PPS via CIOGETEV in ntpq cl
+ *
+ * Revision 3.26 1993/10/07 23:29:35 kardel
+ * trimble fixes
+ *
+ * Revision 3.25 1993/10/06 21:13:35 kardel
+ * test reversed (CIOGETEV support)
+ *
+ * Revision 3.24 1993/10/03 20:18:26 kardel
+ * Well, values > 999999 in the usec field from uniqtime() timestamps
+ * can prove harmful.
+ *
+ * Revision 3.23 1993/10/03 19:49:54 kardel
+ * buftvtots where failing on uninitialized time stamps
+ *
+ * Revision 3.22 1993/10/03 19:11:09 kardel
+ * restructured I/O handling
+ *
+ * Revision 3.21 1993/09/29 11:30:18 kardel
+ * special init for trimble to set EOL
+ *
+ * Revision 3.20 1993/09/27 22:46:28 kardel
+ * preserve module stack if I_PUSH parse fails
+ *
+ * Revision 3.19 1993/09/27 21:10:11 kardel
+ * wrong structure member
+ *
+ * Revision 3.18 1993/09/27 13:05:06 kardel
+ * Trimble is true polling only
+ *
+ * Revision 3.17 1993/09/27 12:47:10 kardel
+ * poll string support generalized
+ *
+ * Revision 3.16 1993/09/26 23:40:56 kardel
+ * new parse driver logic
+ *
+ * Revision 3.15 1993/09/24 15:00:51 kardel
+ * Sep 23rd distribution...
+ *
+ * Revision 3.14 1993/09/22 18:21:15 kardel
+ * support ppsclock streams module (-DSTREAM -DPPSPPS -DPARSEPPS -UPARSESTREAM)
+ *
+ * Revision 3.13 1993/09/05 15:38:33 kardel
+ * not every cpp understands #error...
+ *
+ * Revision 3.12 1993/09/02 20:04:19 kardel
+ * TTY cleanup
+ *
+ * Revision 3.11 1993/09/01 21:48:47 kardel
+ * conditional cleanup
+ *
+ * Revision 3.10 1993/09/01 11:32:45 kardel
+ * assuming HAVE_POSIX_TTYS when STREAM defined
+ *
+ * Revision 3.9 1993/08/31 22:31:46 kardel
+ * SINIX-M SysVR4 integration
+ *
+ * Revision 3.8 1993/08/27 00:29:50 kardel
+ * compilation cleanup
+ *
+ * Revision 3.7 1993/08/24 22:27:30 kardel
+ * cleaned up AUTOCONF DCF77 mess 8-) - wasn't too bad
+ *
+ * Revision 3.6 1993/08/24 21:36:23 kardel
+ * casting and ifdefs
+ *
+ * Revision 3.5 1993/07/09 23:36:59 kardel
+ * HAVE_POSIX_TTYS used to produce errors 8-( - BSD driver support still lacking
+ *
+ * Revision 3.4 1993/07/09 12:42:29 kardel
+ * RAW DCF now officially released
+ *
+ * Revision 3.3 1993/07/09 11:50:37 kardel
+ * running GPS also on 960 to be able to switch GPS/DCF77
+ *
+ * Revision 3.2 1993/07/09 11:37:34 kardel
+ * Initial restructured version + GPS support
+ *
+ * Revision 3.1 1993/07/06 10:01:07 kardel
+ * DCF77 driver goes generic...
+ *
+ */
diff --git a/usr.sbin/xntpd/xntpd/refclock_nmea.c b/usr.sbin/xntpd/xntpd/refclock_nmea.c
new file mode 100644
index 000000000000..3058956df516
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_nmea.c
@@ -0,0 +1,391 @@
+/*
+ * refclock_nmea.c - clock driver for an NMEA GPS CLOCK
+ * Michael Petry Jun 20, 1994
+ * based on refclock_heath.c
+ */
+#if defined(REFCLOCK) && defined(NMEA)
+
+#define DEBUG 1
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the NMEA GPS Receiver with
+ *
+ * Protype was refclock_trak.c, Thanks a lot.
+ *
+ * The reciever used spits out the NMEA sentences for boat navigation.
+ * And you thought it was an information superhighway. Try a raging river
+ * filled with rapids and whirlpools that rip away your data and warp time.
+ */
+
+/*
+ * Definitions
+ */
+#define DEVICE "/dev/gps%d" /* name of radio device */
+#define SPEED232 B4800 /* uart speed (4800 bps) */
+#define PRECISION (-9) /* precision assumed (about 2 ms) */
+#define REFID "GPS\0" /* reference id */
+#define DESCRIPTION "NMEA GPS Clock" /* who we are */
+
+#define NSAMPLES 3 /* stages of median filter */
+#define LENNMEA 75 /* min timecode length */
+
+/*
+ * 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 */
+
+/*
+ * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
+ * leap.
+ */
+static day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ * Unit control structure
+ */
+struct nmeaunit {
+ int pollcnt; /* poll message counter */
+ l_fp tstamp; /* timestamp of last poll */
+};
+
+/*
+ * Function prototypes
+ */
+static int nmea_start P((int, struct peer *));
+static void nmea_shutdown P((int, struct peer *));
+static void nmea_receive P((struct recvbuf *));
+static void nmea_poll P((int, struct peer *));
+static void gps_send P((int, char *, struct peer *));
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_nmea = {
+ nmea_start, /* start up driver */
+ nmea_shutdown, /* shut down driver */
+ nmea_poll, /* transmit poll message */
+ noentry, /* handle control */
+ noentry, /* initialize driver */
+ noentry, /* buginfo */
+ NOFLAGS /* not used */
+};
+
+/*
+ * nmea_start - open the GPS devices and initialize data for processing
+ */
+static int
+nmea_start(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct nmeaunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
+
+ /*
+ * Open serial port. Use CLK line discipline, if available.
+ */
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
+ return (0);
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ if (!(up = (struct nmeaunit *)
+ emalloc(sizeof(struct nmeaunit)))) {
+ (void) close(fd);
+ return (0);
+ }
+ memset((char *)up, 0, sizeof(struct nmeaunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = nmea_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+ pp->unitptr = (caddr_t)up;
+
+ /*
+ * Initialize miscellaneous variables
+ */
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
+ gps_send(pp->io.fd,"$PMOTG,RMC,0000\n", peer);
+ return (1);
+}
+
+/*
+ * nmea_shutdown - shut down a GPS clock
+ */
+static void
+nmea_shutdown(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct nmeaunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct nmeaunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
+}
+
+/*
+ * nmea_receive - receive data from the serial interface
+ */
+static void
+nmea_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register struct nmeaunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ l_fp trtmp;
+ int month, day;
+ int i;
+ char *cp, *dp;
+ int cmdtype;
+ char *field_parse();
+
+ /*
+ * Initialize pointers and read the timecode and timestamp
+ */
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct nmeaunit *)pp->unitptr;
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX, &trtmp);
+
+ /*
+ * There is a case that a <CR><LF> gives back a "blank" line
+ */
+ if (pp->lencode == 0)
+ return;
+
+ /*
+ * We get a buffer and timestamp for each <cr>; however, we use
+ * the timestamp of "now" since this may be a broadcast instead
+ * of a poll. This needs to be checked empeerically
+ */
+ gettstamp(&up->tstamp); /* HACK */
+ pp->lastrec = up->tstamp;
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
+#ifdef DEBUG
+ if (debug)
+ printf("nmea: timecode %d %s\n", pp->lencode,
+ pp->lastcode);
+#endif
+
+ /*
+ * We check the timecode format and decode its contents. The
+ * we only care about a few of them. The most important being
+ * the $GPRMC format
+ * $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
+ */
+#define GPRMC 0
+#define GPXXX 1
+ cp = pp->lastcode;
+ pp->leap = 0;
+ cmdtype=0;
+ if(strncmp(cp,"$GPRMC",6)==0) {
+ cmdtype=GPRMC;
+ }
+ else if(strncmp(cp,"$GPXXX",6)==0) {
+ cmdtype=GPXXX;
+ }
+ else
+ return;
+
+ switch( cmdtype ) {
+ case GPRMC:
+ /*
+ * Check time code format of NMEA
+ */
+
+ dp = field_parse(cp,1);
+ if( !isdigit(dp[0]) ||
+ !isdigit(dp[1]) ||
+ !isdigit(dp[2]) ||
+ !isdigit(dp[3]) ||
+ !isdigit(dp[4]) ||
+ !isdigit(dp[5])
+ ) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+ break;
+ case GPXXX:
+ return;
+ default:
+ return;
+
+ }
+
+ dp = field_parse(cp,9);
+ /*
+ * Convert date and check values.
+ */
+ day = dp[0] - '0';
+ day = (day * 10) + dp[1] - '0';
+ month = dp[2] - '0';
+ month = (month * 10) + dp[3] - '0';
+ pp->year = dp[4] - '0';
+ pp->year = (pp->year * 10) + dp[5] - '0';
+
+ if (month < 1 || month > 12 || day < 1) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+
+ if (pp->year % 4) {
+ if (day > day1tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day1tab[i];
+ } else {
+ if (day > day2tab[month - 1]) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ for (i = 0; i < month - 1; i++)
+ day += day2tab[i];
+ }
+ pp->day = day;
+
+ dp = field_parse(cp,1);
+ /*
+ * Convert time and check values.
+ */
+ pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
+ pp->minute = ((dp[2] - '0') * 10) + dp[3] - '0';
+ pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
+ pp->msec = 0;
+
+ if (pp->hour > 23 || pp->minute > 59 || pp->second > 59) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+
+ /*
+ * Test for synchronization Check for quality byte. (soon)
+ */
+ pp->leap = 0;
+ pp->lasttime = current_time;
+
+ /*
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
+}
+
+/*
+ * nmea_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
+nmea_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct nmeaunit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct nmeaunit *)pp->unitptr;
+ if (up->pollcnt == 0)
+ refclock_report(peer, CEVNT_TIMEOUT);
+ else
+ up->pollcnt--;
+ pp->polls++;
+
+ /*
+ * usually nmea_receive can get a timestamp every second
+ */
+
+ gps_send(pp->io.fd,"$PMOTG,RMC,0\n", peer);
+}
+
+/*
+ *
+ * gps_send(fd,cmd, peer) Sends a command to the GPS receiver.
+ * as gps_send(fd,"rqts,u\r", peer);
+ *
+ * We don't currently send any data, but would like to send
+ * RTCM SC104 messages for differential positioning. It should
+ * also give us better time. Without a PPS output, we're
+ * Just fooling ourselves because of the serial code paths
+ *
+ */
+static void
+gps_send(fd, cmd, peer)
+ int fd;
+ char *cmd;
+ struct peer *peer;
+{
+
+ if (write(fd, cmd, strlen(cmd)) == -1) {
+ refclock_report(peer, CEVNT_FAULT);
+ }
+}
+
+char *
+field_parse(cp, fn)
+ char *cp;
+ int fn;
+{
+ char *tp;
+ int i = fn;
+
+ for (tp = cp; *tp != '\0'; tp++) {
+ if (*tp == ',')
+ i--;
+ if (i == 0)
+ break;
+ }
+ return (++tp);
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_old/refclock_datum.c b/usr.sbin/xntpd/xntpd/refclock_old/refclock_datum.c
new file mode 100644
index 000000000000..680f104568bf
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_old/refclock_datum.c
@@ -0,0 +1,645 @@
+/*
+ * refclock_datum - clock driver for the Datum watchayamacallit
+ */
+#if defined(REFCLOCK) && (defined(DATUM) || defined(DATUMCLK) || defined(DATUMPPS))
+/* */
+/*...... Include Files .................................................*/
+/* */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(WWVBCLK)
+#include <sys/clkdefs.h>
+#endif /* WWVBCLK */
+#endif /* STREAM */
+
+#if defined (WWVBPPS)
+#include <sys/ppsclock.h>
+#endif /* WWVBPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+#include "temp.c"
+void set_logfile();
+*/
+
+
+#define DEBUG_DATUM_PTC
+
+
+/* */
+/*...... #defines ......................................................*/
+/* */
+
+/*
+#define refclock_datum_pts refclock_wwvb
+*/
+
+#define MAXUNITS 4
+#define PTSPRECISION (-13) /* precision assumed (about 100 us) */
+#define GMT 7
+#define DATUM_MAX_ERROR 0.100
+#define DATUM_MAX_ERROR2 DATUM_MAX_ERROR*DATUM_MAX_ERROR
+
+/* */
+/*...... externals .....................................................*/
+/* */
+
+extern U_LONG current_time; /* current time (s) */
+extern int debug; /* global debug flag */
+
+
+/* */
+/*...... My structure ..................................................*/
+/* */
+
+struct datum_pts_unit {
+ struct peer *peer; /* peer used by xntp */
+ struct refclockio io; /* io structure used by xntp */
+ int PTS_fd; /* file descriptor for PTS */
+ int PTS_START; /* ? */
+ u_int unit; /* id for unit */
+ U_LONG timestarted; /* time started */
+ int inuse; /* in use flag */
+ l_fp lastrec;
+ l_fp lastref;
+ int yearstart;
+ int coderecv;
+ int day; /* day */
+ int hour; /* hour */
+ int minute; /* minutes */
+ int second; /* seconds */
+ int msec; /* miliseconds */
+ int usec; /* miliseconds */
+ u_char leap;
+ char retbuf[8]; /* returned time from the datum pts */
+ char nbytes; /* number of bytes received from datum pts */
+ double sigma2; /* average squared error (roughly) */
+};
+
+
+/* */
+/*...... pts static constant variables for internal use ................*/
+/* */
+
+static char STOP_GENERATOR[6];
+static char START_GENERATOR[6];
+static char TIME_REQUEST[6];
+
+static int nunits;
+static struct datum_pts_unit **datum_pts_unit;
+static u_char stratumtouse[MAXUNITS];
+static l_fp fudgefactor[MAXUNITS];
+
+static FILE *logfile;
+
+/* */
+/*...... callback functions that xntp knows about ......................*/
+/* */
+
+static int datum_pts_start P((u_int, struct peer *));
+static void datum_pts_shutdown P((int));
+static void datum_pts_poll P((int, struct peer *));
+static void datum_pts_control P((u_int, struct refclockstat *,
+ struct refclockstat *));
+static void datum_pts_init P((void));
+static void datum_pts_buginfo P((int, struct refclockbug *));
+
+struct refclock refclock_datum = {
+ datum_pts_start,
+ datum_pts_shutdown,
+ datum_pts_poll,
+ datum_pts_control,
+ datum_pts_init,
+ datum_pts_buginfo,
+ NOFLAGS
+};
+
+/*
+struct refclock refclock_wvvb = {
+ datum_pts_start,
+ datum_pts_shutdown,
+ datum_pts_poll,
+ datum_pts_control,
+ datum_pts_init,
+ datum_pts_buginfo,
+ NOFLAGS
+};
+*/
+
+/* */
+/*...... receive callback functions for xntp ..........................*/
+/* */
+
+static void datum_pts_receive P((struct recvbuf *));
+
+
+/*......................................................................*/
+/* datum_pts_start */
+/*......................................................................*/
+
+static int datum_pts_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ struct datum_pts_unit **temp_datum_pts_unit;
+ struct datum_pts_unit *datum_pts;
+ struct termios arg;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile, "Starting Datum PTS unit %d\n", unit);
+ fflush(logfile);
+#endif
+
+/* */
+/*...... create the memory for the new unit ............................*/
+/* */
+
+ temp_datum_pts_unit = (struct datum_pts_unit **)
+ malloc((nunits+1)*sizeof(struct datum_pts_unit *));
+ if (nunits > 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
+ nunits*sizeof(struct datum_pts_unit *));
+ free(datum_pts_unit);
+ datum_pts_unit = temp_datum_pts_unit;
+ datum_pts_unit[nunits] = (struct datum_pts_unit *)
+ malloc(sizeof(struct datum_pts_unit));
+ datum_pts = datum_pts_unit[nunits];
+
+ datum_pts->unit = unit;
+ datum_pts->yearstart = 0;
+ datum_pts->sigma2 = 0.0;
+
+/* */
+/*...... open the datum pts device .....................................*/
+/* */
+
+ datum_pts->PTS_fd = open("/dev/ttya",O_RDWR);
+
+ fcntl(datum_pts->PTS_fd, F_SETFL, 0);
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Opening RS232 port ttya with file descriptor %d\n",
+ datum_pts->PTS_fd);
+ fflush(logfile);
+#endif
+
+/* */
+/*...... set up the RS232 terminal device information ..................*/
+/* */
+
+ arg.c_iflag = IGNBRK;
+ arg.c_oflag = 0;
+ arg.c_cflag = B9600 | CS8 | CREAD | PARENB | CLOCAL;
+ arg.c_lflag = 0;
+ arg.c_line = 0;
+ arg.c_cc[VMIN] = 0; /* start timeout timer right away */
+ arg.c_cc[VTIME] = 30; /* this is a 3 second timout on reads */
+
+ tcsetattr(datum_pts->PTS_fd, TCSANOW, &arg);
+
+/* */
+/*...... initialize the io structure ...................................*/
+/* */
+
+ datum_pts->peer = peer;
+ datum_pts->timestarted = current_time;
+
+ datum_pts->io.clock_recv = datum_pts_receive;
+ datum_pts->io.srcclock = (caddr_t)datum_pts;
+ datum_pts->io.datalen = 0;
+ datum_pts->io.fd = datum_pts->PTS_fd;
+
+ if (!io_addclock(&(datum_pts->io))) {
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Problem adding clock\n");
+ fflush(logfile);
+#endif
+ syslog(LOG_ERR, "Datum_PTS: Problem adding clock");
+ }
+
+ peer->precision = PTSPRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+
+/* */
+/*...... now add one to the number of units ............................*/
+/* */
+
+ nunits++;
+
+/* */
+/*...... return successful code ........................................*/
+/* */
+
+ return 1;
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_shutdown */
+/*......................................................................*/
+
+static void datum_pts_shutdown(unit)
+ int unit;
+{
+ int i,j;
+ struct datum_pts_unit **temp_datum_pts_unit;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Shutdown Datum PTS\n");
+ fflush(logfile);
+#endif
+ syslog(LOG_ERR, "Datum_PTS: Shutdown Datum PTS");
+
+/* */
+/*...... loop until the right unit is found ............................*/
+/* */
+
+ for (i=0; i<nunits; i++) {
+ if (datum_pts_unit[i]->unit == unit) {
+
+/* */
+/*...... found it so close the file descriptor and free up memory .....*/
+/* */
+
+ io_closeclock(&datum_pts_unit[i]->io);
+ close(datum_pts_unit[i]->PTS_fd);
+ free(datum_pts_unit[i]);
+
+/* */
+/*...... clean up the datum_pts_unit array (no holes) ..................*/
+/* */
+
+ if (nunits > 1) {
+
+ temp_datum_pts_unit = (struct datum_pts_unit **)
+ malloc((nunits-1)*sizeof(struct datum_pts_unit *));
+ if (i!= 0) memcpy(temp_datum_pts_unit, datum_pts_unit,
+ i*sizeof(struct datum_pts_unit *));
+
+ for (j=i+1; j<nunits; j++) {
+ temp_datum_pts_unit[j-1] = datum_pts_unit[j];
+ }
+
+ free(datum_pts_unit);
+ datum_pts_unit = temp_datum_pts_unit;
+
+ }else{
+
+ free(datum_pts_unit);
+ datum_pts_unit = NULL;
+
+ }
+
+ return;
+
+ }
+ }
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Error, could not shut down unit %d\n",unit);
+ fflush(logfile);
+#endif
+ syslog(LOG_ERR, "Datum_PTS: Could not shut down Datum PTS unit %d",unit);
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_poll */
+/*......................................................................*/
+
+static void datum_pts_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ int i;
+ int index;
+ int error_code;
+ l_fp tstmp;
+ struct datum_pts_unit *datum_pts;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Poll Datum PTS\n");
+ fflush(logfile);
+#endif
+
+/* */
+/*...... find the unit and send out a time request .....................*/
+/* */
+
+ index = -1;
+ for (i=0; i<nunits; i++) {
+ if (datum_pts_unit[i]->unit == unit) {
+ index = i;
+ datum_pts = datum_pts_unit[i];
+ error_code = write(datum_pts->PTS_fd, TIME_REQUEST, 6);
+ if (error_code != 6) perror("TIME_REQUEST");
+ datum_pts->nbytes = 0;
+ break;
+ }
+ }
+
+ if (index == -1) {
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Error, could not poll unit %d\n",unit);
+ fflush(logfile);
+#endif
+ syslog(LOG_ERR, "Datum_PTS: Could not poll unit %d",unit);
+ return;
+ }
+
+}
+
+
+/*......................................................................*/
+/* datum_pts_control */
+/*......................................................................*/
+
+static void datum_pts_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Control Datum PTS\n");
+ fflush(logfile);
+#endif
+}
+
+
+/*......................................................................*/
+/* datum_pts_init */
+/*......................................................................*/
+
+static void datum_pts_init()
+{
+
+#ifdef DEBUG_DATUM_PTC
+ logfile = fopen("xntpd.log", "w");
+ fprintf(logfile,"Init Datum PTS\n");
+ fflush(logfile);
+#endif
+
+ memcpy(START_GENERATOR, "//kk01",6);
+ memcpy(STOP_GENERATOR, "//kk00",6);
+ memcpy(TIME_REQUEST, "//k/mn",6);
+
+ datum_pts_unit = NULL;
+ nunits = 0;
+}
+
+
+/*......................................................................*/
+/* datum_pts_buginfo */
+/*......................................................................*/
+
+static void datum_pts_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Buginfo Datum PTS\n");
+ fflush(logfile);
+#endif
+}
+
+
+/*......................................................................*/
+/* datum_pts_receive */
+/*......................................................................*/
+
+static void datum_pts_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ int i;
+ l_fp tstmp, trtmp, tstmp1;
+ struct datum_pts_unit *datum_pts;
+ char *dpt;
+ int dpend;
+ time_t tim;
+ struct tm *loctm;
+ int tzoff;
+ int timerr;
+ double ftimerr, abserr;
+
+ datum_pts = (struct datum_pts_unit *)rbufp->recv_srcclock;
+ dpt = (char *)&rbufp->recv_space;
+ dpend = rbufp->recv_length;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Receive Datum PTS: %d bytes\n", dpend);
+ fflush(logfile);
+#endif
+
+ for (i=0; i<dpend; i++) {
+ datum_pts->retbuf[datum_pts->nbytes+i] = dpt[i];
+ }
+ datum_pts->nbytes += dpend;
+
+ if (datum_pts->nbytes != 7) {
+ return;
+ }
+
+
+/* */
+/*...... save the ntp system time ......................................*/
+/* */
+
+ trtmp = rbufp->recv_time;
+ datum_pts->lastrec = trtmp;
+
+/* */
+/*...... convert the time from the buffer ..............................*/
+/* */
+
+ datum_pts->day = 100*(datum_pts->retbuf[0] & 0x0f) +
+ 10*((datum_pts->retbuf[1] & 0xf0)>>4) +
+ (datum_pts->retbuf[1] & 0x0f);
+
+ datum_pts->hour = 10*((datum_pts->retbuf[2] & 0x30)>>4) +
+ (datum_pts->retbuf[2] & 0x0f);
+
+ datum_pts->minute = 10*((datum_pts->retbuf[3] & 0x70)>>4) +
+ (datum_pts->retbuf[3] & 0x0f);
+
+ datum_pts->second = 10*((datum_pts->retbuf[4] & 0x70)>>4) +
+ (datum_pts->retbuf[4] & 0x0f);
+
+ datum_pts->msec = 100*((datum_pts->retbuf[5] & 0xf0) >> 4) +
+ 10*(datum_pts->retbuf[5] & 0x0f) +
+ ((datum_pts->retbuf[6] & 0xf0)>>4);
+
+ datum_pts->usec = 1000*datum_pts->msec;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"day %d, hour %d, minute %d, second %d, msec %d\n",
+ datum_pts->day,
+ datum_pts->hour,
+ datum_pts->minute,
+ datum_pts->second,
+ datum_pts->msec);
+ fflush(logfile);
+#endif
+
+/* */
+/*...... get the GMT time zone offset ..................................*/
+/* */
+
+ tim = trtmp.l_ui - JAN_1970;
+ loctm = localtime(&tim);
+ tzoff = -loctm->tm_gmtoff/3600;
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Time Zone = %d, time (sec) since 1970 = %d\n",tzoff, tim);
+ fflush(logfile);
+#endif
+
+/* */
+/*...... make sure that we have a good time from the Datum PTS .........*/
+/* */
+
+ if (!clocktime( datum_pts->day,
+ datum_pts->hour,
+ datum_pts->minute,
+ datum_pts->second,
+ tzoff,
+ datum_pts->lastrec.l_ui,
+ &datum_pts->yearstart,
+ &datum_pts->lastref.l_ui) ) {
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Error: bad clocktime\n");
+ fprintf(logfile,"GMT %d, lastrec %d, yearstart %d, lastref %d\n",
+ tzoff,
+ datum_pts->lastrec.l_ui,
+ datum_pts->yearstart,
+ datum_pts->lastref.l_ui);
+ fflush(logfile);
+#endif
+ syslog(LOG_ERR, "Datum_PTS: Bad clocktime");
+
+ return;
+
+ }else{
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Good clocktime\n");
+ fflush(logfile);
+#endif
+
+ }
+
+/* */
+/*...... we have datum_pts->lastref.l_ui set, get useconds now .........*/
+/* */
+
+ TVUTOTSF(datum_pts->usec, datum_pts->lastref.l_uf);
+
+/* */
+/*...... pass the new time to xntpd ....................................*/
+/* */
+
+ tstmp = datum_pts->lastref;
+ L_SUB(&tstmp, &datum_pts->lastrec); /* tstmp is the time correction */
+ datum_pts->coderecv++;
+
+/*
+ set_logfile(logfile);
+*/
+
+ refclock_receive( datum_pts->peer,
+ &tstmp,
+ tzoff,
+ 0,
+ &datum_pts->lastrec,
+ &datum_pts->lastrec,
+ datum_pts->leap );
+ timerr = tstmp.l_ui<<20;
+ timerr |= (tstmp.l_uf>>12) & 0x000fffff;
+ ftimerr = timerr;
+ ftimerr /= 1024*1024;
+ abserr = ftimerr;
+ if (ftimerr < 0.0) abserr = -ftimerr;
+
+ if (datum_pts->sigma2 == 0.0) {
+ if (abserr < DATUM_MAX_ERROR) {
+ datum_pts->sigma2 = abserr*abserr;
+ }else{
+ datum_pts->sigma2 = DATUM_MAX_ERROR2;
+ }
+ }else{
+ if (abserr < DATUM_MAX_ERROR) {
+ datum_pts->sigma2 = 0.95*datum_pts->sigma2 + 0.05*abserr*abserr;
+ }else{
+ datum_pts->sigma2 = 0.95*datum_pts->sigma2 + 0.05*DATUM_MAX_ERROR2;
+ }
+ }
+
+#ifdef DEBUG_DATUM_PTC
+ fprintf(logfile,"Time error = %f seconds, Sigma Squared = %f\n",
+ ftimerr, datum_pts->sigma2);
+ fflush(logfile);
+#endif
+
+/* */
+/*...... make sure that we understand the format for xntp time .........*/
+/* */
+
+#ifdef DEBUG_DATUM_PTC
+ tstmp.l_ui = 2;
+ TVUTOTSF(123456, tstmp.l_uf);
+
+ timerr = tstmp.l_ui<<20;
+ timerr |= (tstmp.l_uf>>12) & 0x000fffff;
+ ftimerr = timerr;
+ ftimerr /= 1024*1024;
+ fprintf(logfile,"Test1 2.123456 = %f\n",ftimerr);
+ fflush(logfile);
+
+ tstmp1.l_ui = 3;
+ TVUTOTSF(223456, tstmp1.l_uf);
+ timerr = tstmp1.l_ui<<20;
+ timerr |= (tstmp1.l_uf>>12) & 0x000fffff;
+ ftimerr = timerr;
+ ftimerr /= 1024*1024;
+ fprintf(logfile,"Test2 3.223456 = %f\n",ftimerr);
+ fflush(logfile);
+
+ L_SUB(&tstmp, &tstmp1);
+ timerr = tstmp.l_ui<<20;
+ timerr |= (tstmp.l_uf>>12) & 0x000fffff;
+ ftimerr = timerr;
+ ftimerr /= 1024*1024;
+ fprintf(logfile,"Test3 -1.100000 = %f\n",ftimerr);
+ fflush(logfile);
+#endif
+
+
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_old/refclock_gpstm.c b/usr.sbin/xntpd/xntpd/refclock_old/refclock_gpstm.c
new file mode 100644
index 000000000000..2e81e52c8dae
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_old/refclock_gpstm.c
@@ -0,0 +1,998 @@
+/*
+ * refclock_gpstm - clock driver for the Kinimetrics Truetime GPSTM/TMD rcvr
+ * Version 1.0 (from Version 2.0 of the GOES driver, as of 03Jan94)
+ */
+
+#if defined(REFCLOCK) && (defined(GPSTM) || defined(GPSTMCLK) \
+ || defined(GPSTMPPS))
+
+#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"
+
+#ifdef SYS_BSDI
+#undef HAVE_BSD_TTYS
+#include <sys/ioctl.h>
+#endif
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(GPSTMCLK)
+#include <clkdefs.h>
+#endif /* GPSTMCLK */
+#endif /* STREAM */
+
+#if defined(GPSTMPPS)
+#include <sys/ppsclock.h>
+#endif /* GPSTMPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+ * Support for Kinemetrics Truetime GPS-TM/TMD Receiver
+ *
+ * Most of this code is copied from refclock_goes.c with thanks.
+ *
+ * the time code looks like follows:
+ *
+ * ADDD:HH:MM:SSQCL
+ * A - control A
+ * Q Quality indication: indicates possible error of
+ * ? +/- 500 milliseconds # +/- 50 milliseconds
+ * * +/- 5 milliseconds . +/- 1 millisecond
+ * space less than 1 millisecond
+ * C - Carriage return
+ * L - Line feed
+ * The carriage return start bit begins on 0 seconds and extends to 1 bit time.
+ *
+ * Flag1 set to 1 will silence the clock side of xntpd, just reading the
+ * clock without trying to write to it. This is usefull if several
+ * xntpds listen to the same clock. This has not been tested yet...
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 4 /* max number of GPSTM units */
+#define GPSTM232 "/dev/gpstm%d"
+#define SPEED232 B9600 /* 9600 baud */
+
+/*
+ * Radio interface parameters
+ */
+#define MAXDISPERSE (FP_SECOND>>1) /* max error for synchronized clock (0.5 s as an u_fp) */
+#define PRECISION (-20) /* precision assumed (about 1 ms) */
+#define REFID "GPS\0" /* reference id */
+#define DESCRIPTION "Kinemetrics GPS-TM/TMD Receiver" /* who we are */
+#define GMT 0 /* hour offset from Greenwich */
+#define NCODES 3 /* stages of median filter */
+#define BMAX 99 /* timecode buffer length */
+#define CODEDIFF 0x20000000 /* 0.125 seconds as an l_fp fraction */
+#define TIMEOUT 180 /* ping the clock if it's silent this long */
+
+/*
+ * used by the state machine
+ */
+enum gpstm_event {e_Init, e_F18, e_F50, e_F51, e_TS};
+static enum {Base, Start, F18, F50, F51, F08} State[MAXUNITS];
+static time_t Last[MAXUNITS];
+static void gpstm_doevent P((int, enum gpstm_event));
+static void gpstm_initstate P((int));
+
+/*
+ * Hack to avoid excercising the multiplier. I have no pride.
+ */
+#define MULBY10(x) (((x)<<3) + ((x)<<1))
+
+/*
+ * Imported from the timer module
+ */
+extern U_LONG current_time;
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * GPSTM unit control structure
+ */
+struct gpstm_unit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ l_fp lastrec; /* last receive time */
+ l_fp lastref; /* last timecode time */
+ l_fp offset[NCODES]; /* recent sample offsets */
+ char lastcode[BMAX]; /* last timecode received */
+ u_short polled; /* Hand in a time sample? */
+ u_char lencode; /* length of last timecode */
+ U_LONG lasttime; /* last time clock heard from */
+ 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_char leap; /* leap indicators */
+ u_short msec; /* millisecond of second */
+ u_char quality; /* quality character */
+ 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 gpstm_unit *gpstm_units[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 fudgefactor1[MAXUNITS];
+static l_fp fudgefactor2[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static u_char readonlyclockflag[MAXUNITS];
+static U_LONG refid[MAXUNITS];
+
+/*
+ * Function prototypes
+ */
+static void gpstm_init P((void));
+static int gpstm_start P((u_int, struct peer *));
+static void gpstm_shutdown P((int));
+static void gpstm_rep_event P((struct gpstm_unit *, int));
+static void gpstm_receive P((struct recvbuf *));
+static char gpstm_process P((struct gpstm_unit *, l_fp *, u_fp *));
+static void gpstm_poll P((int, struct peer *));
+static void gpstm_control P((u_int, struct refclockstat *,
+ struct refclockstat *));
+static void gpstm_buginfo P((int, struct refclockbug *));
+static void gpstm_send P((struct gpstm_unit *, char *));
+
+struct refclock refclock_gpstm = {
+ gpstm_start, gpstm_shutdown, gpstm_poll,
+ gpstm_control, gpstm_init, gpstm_buginfo, NOFLAGS
+};
+
+/*
+ * gpstm_init - initialize internal driver data
+ */
+static void
+gpstm_init()
+{
+ register int i;
+ /*
+ * Just zero the data arrays
+ */
+ memset((char *)gpstm_units, 0, sizeof gpstm_units);
+ memset((char *)unitinuse, 0, sizeof unitinuse);
+
+ /*
+ * Initialize fudge factors to default.
+ */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor1[i].l_ui = 0;
+ fudgefactor1[i].l_uf = 0;
+ fudgefactor2[i].l_ui = 0;
+ fudgefactor2[i].l_uf = 0;
+ stratumtouse[i] = 0;
+ readonlyclockflag[i] = 0;
+ memcpy((char *)&refid[i], REFID, 4);
+ }
+}
+
+
+/*
+ * gpstm_start - open the device and initialize data for processing
+ */
+static int
+gpstm_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct gpstm_unit *gpstm;
+ register int i;
+ int fd232;
+ char dev[20];
+
+ /*
+ * Check configuration info
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_start: unit %d invalid", unit);
+ return 0;
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "gpstm_start: unit %d in use", unit);
+ return 0;
+ }
+
+ /*
+ * Open serial port
+ */
+ (void) sprintf(dev, GPSTM232, unit);
+ fd232 = open(dev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR, "gpstm_start: open of %s: %m", dev);
+ 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,
+ "gpstm_start: ioctl(%s, TCGETA): %m", dev);
+ 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,
+ "gpstm_start: ioctl(%s, TCSETA): %m", dev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(HAVE_TERMIOS)
+ /*
+ * POSIX serial line parameters (termios interface)
+ *
+ * The GPSTMCLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The GPSTMPPS 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,
+ "gpstm_start: tcgetattr(%s): %m", dev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ 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,
+ "gpstm_start: tcsetattr(%s): %m", dev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: tcflush(%s): %m", dev);
+ goto screwed;
+ }
+#if defined(STREAM)
+#if defined(GPSTMCLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, I_PUSH, clk): %m", dev);
+ if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, CLK_SETSTR): %m", dev);
+#endif /* GPSTMCLK */
+#if defined(GPSTMPPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, I_PUSH, ppsclock): %m", dev);
+ else
+ fdpps = fd232;
+#endif /* GPSTMPPS */
+#endif /* STREAM */
+ }
+#endif /* HAVE_TERMIOS */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The GPSTMCLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(GPSTMCLK)
+ int ldisc = CLKLDISC;
+#endif /* GPSTMCLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, TIOCGETP): %m", dev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(GPSTMCLK)
+ 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 /* GPSTMCLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, TIOCSETP): %m", dev);
+ goto screwed;
+ }
+#if defined(GPSTMCLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "gpstm_start: ioctl(%s, TIOCSETD): %m", dev);
+ goto screwed;
+ }
+#endif /* GPSTMCLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Allocate unit structure
+ */
+ if (gpstm_units[unit] != 0) {
+ gpstm = gpstm_units[unit]; /* The one we want is okay */
+ } else {
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && gpstm_units[i] != 0)
+ break;
+ }
+ if (i < MAXUNITS) {
+ /*
+ * Reclaim this one
+ */
+ gpstm = gpstm_units[i];
+ gpstm_units[i] = 0;
+ } else {
+ gpstm = (struct gpstm_unit *)
+ emalloc(sizeof(struct gpstm_unit));
+ }
+ }
+ memset((char *)gpstm, 0, sizeof(struct gpstm_unit));
+ gpstm_units[unit] = gpstm;
+
+ /*
+ * Set up the structures
+ */
+ gpstm->peer = peer;
+ gpstm->unit = (u_char)unit;
+ gpstm->timestarted = current_time;
+
+ gpstm->io.clock_recv = gpstm_receive;
+ gpstm->io.srcclock = (caddr_t)gpstm;
+ gpstm->io.datalen = 0;
+ gpstm->io.fd = fd232;
+ if (!io_addclock(&gpstm->io)) {
+ goto screwed;
+ }
+
+ /*
+ * All done. Initialize a few random peer variables, then
+ * return success.
+ */
+ peer->precision = PRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ unitinuse[unit] = 1;
+ gpstm_initstate(unit);
+ return 1;
+
+ /*
+ * Something broke; abandon ship
+ */
+screwed:
+ (void) close(fd232);
+ return 0;
+}
+
+/*
+ * gpstm_shutdown - shut down a clock
+ */
+static void
+gpstm_shutdown(unit)
+ int unit;
+{
+ register struct gpstm_unit *gpstm;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_shutdown: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "gpstm_shutdown: unit %d not in use", unit);
+ return;
+ }
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ gpstm = gpstm_units[unit];
+ io_closeclock(&gpstm->io);
+ unitinuse[unit] = 0;
+}
+
+
+/*
+ * gpstm_rep_event - note the occurance of an event
+ */
+static void
+gpstm_rep_event(gpstm, code)
+ struct gpstm_unit *gpstm;
+ int code;
+{
+ struct peer *peer;
+
+ peer = gpstm->peer;
+ if (gpstm->status != (u_char)code) {
+ gpstm->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ gpstm->lastevent = (u_char)code;
+ syslog(LOG_INFO,
+ "clock %s event %x\n", ntoa(&peer->srcadr), code);
+#ifdef DEBUG
+ if (debug) {
+ printf("gpstm_rep_event(gpstm%d, code %d)\n",
+ gpstm->unit, code);
+ }
+#endif
+ }
+ if (code == CEVNT_BADREPLY)
+ gpstm_initstate(gpstm->unit);
+}
+
+
+/*
+ * gpstm_receive - receive data from the serial interface on a clock
+ */
+static void
+gpstm_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register int i;
+ register struct gpstm_unit *gpstm;
+ register u_char *dpt;
+ register char *cp;
+ register u_char *dpend;
+ l_fp tstmp;
+ u_fp dispersion;
+
+ /*
+ * Get the clock this applies to and a pointers to the data
+ */
+ gpstm = (struct gpstm_unit *)rbufp->recv_srcclock;
+ dpt = (u_char *)&rbufp->recv_space;
+
+ /*
+ * Edit timecode to remove control chars
+ */
+ dpend = dpt + rbufp->recv_length;
+ cp = gpstm->lastcode;
+ while (dpt < dpend) {
+ if ((*cp = 0x7f & *dpt++) >= ' ') cp++;
+#ifdef GPSTMCLK
+ else if (*cp == '\r') {
+ if (dpend - dpt < 8) {
+ /* short timestamp */
+ return;
+ }
+ if (!buftvtots(dpt,&gpstm->lastrec)) {
+ /* screwy timestamp */
+ return;
+ }
+ dpt += 8;
+ }
+#endif
+ }
+ *cp = '\0';
+ gpstm->lencode = cp - gpstm->lastcode;
+ if (gpstm->lencode == 0)
+ return;
+#ifndef GPSTMCLK
+ gpstm->lastrec = rbufp->recv_time;
+#endif /* GPSTMCLK */
+#if !defined(GPSTMCLK) && !defined(GPSTMPPS) && defined(TIOCMODT)
+ do {
+ auto struct timeval cur, now;
+ register long usec;
+
+ if (ioctl(gpstm->io.fd, TIOCMODT, &cur) < 0) {
+ syslog(LOG_ERR, "TIOCMODT: %m");
+#ifdef DEBUG
+ if (debug) perror("TIOCMODT");
+ break;
+#endif
+ }
+ if (cur.tv_sec == 0) {
+ /* no timestamps yet */
+ if (debug) printf("MODT tv_sec == 0\n");
+ break;
+ }
+
+ gettimeofday(&now, NULL);
+ usec = 1000000 * (now.tv_sec - cur.tv_sec)
+ + (now.tv_usec - cur.tv_usec);
+#ifdef DEBUG
+ if (debug) printf("lastmodem: delay=%d us\n", usec);
+#endif
+ if (usec < 0 || usec > 10000) {
+ /* time warp or stale timestamp */
+ break;
+ }
+ if (!buftvtots((char *)&cur, &gpstm->lastrec)) {
+ /* screwy timestamp */
+ break;
+ }
+ } while (0);
+#endif /*TIOCMODT*/
+
+#ifdef DEBUG
+ if (debug)
+ printf("gpstm: timecode %d %s\n",
+ gpstm->lencode, gpstm->lastcode);
+#endif
+
+ cp = gpstm->lastcode;
+ gpstm->leap = 0;
+ if ((cp[0] == 'F' && isdigit(cp[1]) && isdigit(cp[2]))
+ || (cp[0] == ' ' && cp[1] == 'T' && cp[2] == 'R')) {
+ enum gpstm_event event;
+
+ syslog(LOG_NOTICE, "gpstm%d: \"%s\"", gpstm->unit, cp);
+ if (cp[1] == '5' && cp[2] == '0')
+ event = e_F50;
+ else if (cp[1] == '5' && cp[2] == '1')
+ event = e_F51;
+ else if (!strncmp(" TRUETIME Mk III", cp, 16))
+ event = e_F18;
+ else {
+ gpstm_rep_event(gpstm, CEVNT_BADREPLY);
+ return;
+ }
+ gpstm_doevent(gpstm->unit, event);
+ return;
+ } else if (gpstm->lencode == 13) {
+ /*
+ * Check timecode format 0
+ */
+ if (!isdigit(cp[0]) /* day of year */
+ || !isdigit(cp[1])
+ || !isdigit(cp[2])
+ || cp[3] != ':' /* : separator */
+ || !isdigit(cp[4]) /* hours */
+ || !isdigit(cp[5])
+ || cp[6] != ':' /* : separator */
+ || !isdigit(cp[7]) /* minutes */
+ || !isdigit(cp[8])
+ || cp[9] != ':' /* : separator */
+ || !isdigit(cp[10]) /* seconds */
+ || !isdigit(cp[11]))
+ {
+ gpstm->badformat++;
+ gpstm_rep_event(gpstm, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Convert format 0 and check values
+ */
+ gpstm->year = 0; /* fake */
+ gpstm->day = cp[0] - '0';
+ gpstm->day = MULBY10(gpstm->day) + cp[1] - '0';
+ gpstm->day = MULBY10(gpstm->day) + cp[2] - '0';
+ gpstm->hour = MULBY10(cp[4] - '0') + cp[5] - '0';
+ gpstm->minute = MULBY10(cp[7] - '0') + cp[8] - '0';
+ gpstm->second = MULBY10(cp[10] - '0') + cp[11] - '0';
+ gpstm->msec = 0;
+
+ if (cp[12] != ' ' && cp[12] != '.' && cp[12] != '*')
+ gpstm->leap = LEAP_NOTINSYNC;
+ else
+ gpstm->lasttime = current_time;
+
+ if (gpstm->day < 1 || gpstm->day > 366) {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADDATE);
+ return;
+ }
+ if (gpstm->hour > 23 || gpstm->minute > 59
+ || gpstm->second > 59) {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADTIME);
+ return;
+ }
+ gpstm_doevent(gpstm->unit, e_TS);
+ } else {
+ gpstm_rep_event(gpstm, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * The clock will blurt a timecode every second but we only
+ * want one when polled. If we havn't been polled, bail out.
+ */
+ if (!gpstm->polled)
+ return;
+
+ /*
+ * Now, compute the reference time value. Use the heavy
+ * machinery for the seconds and the millisecond field for the
+ * fraction when present.
+ *
+ * this code does not yet know how to do the years
+ */
+ tstmp = gpstm->lastrec;
+ if (!clocktime(gpstm->day, gpstm->hour, gpstm->minute,
+ gpstm->second, GMT, tstmp.l_ui,
+ &gpstm->yearstart, &gpstm->lastref.l_ui))
+ {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADTIME);
+ return;
+ }
+ MSUTOTSF(gpstm->msec, gpstm->lastref.l_uf);
+
+ i = ((int)(gpstm->coderecv)) % NCODES;
+ gpstm->offset[i] = gpstm->lastref;
+ L_SUB(&gpstm->offset[i], &tstmp);
+ if (gpstm->coderecv == 0)
+ for (i = 1; i < NCODES; i++)
+ gpstm->offset[i] = gpstm->offset[0];
+
+ gpstm->coderecv++;
+
+ /*
+ * Process the median filter, and pass the
+ * offset and dispersion along. We use lastrec 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 (!gpstm_process(gpstm, &tstmp, &dispersion)) {
+ gpstm->baddata++;
+ gpstm_rep_event(gpstm, CEVNT_BADTIME);
+ return;
+ }
+ refclock_receive(gpstm->peer, &tstmp, GMT, dispersion,
+ &gpstm->lastrec, &gpstm->lastrec, gpstm->leap);
+
+ /*
+ * We have succedded in answering the poll. Turn off the flag
+ */
+ gpstm->polled = 0;
+}
+
+/*
+ * gpstm_send - time to send the clock a signal to cough up a time sample
+ */
+static void
+gpstm_send(gpstm, cmd)
+ struct gpstm_unit *gpstm;
+ char *cmd;
+{
+#ifdef DEBUG
+ if (debug) {
+ printf("gpstm_send(gpstm%d): %s\n", gpstm->unit, cmd);
+ }
+#endif
+ if (!readonlyclockflag[gpstm->unit]) {
+ register int len = strlen(cmd);
+
+ if (write(gpstm->io.fd, cmd, len) != len) {
+ syslog(LOG_ERR, "gpstm_send: unit %d: %m",
+ gpstm->unit);
+ gpstm_rep_event(gpstm, CEVNT_FAULT);
+ }
+ }
+}
+
+/*
+ * state machine for initializing the clock
+ */
+
+static void
+gpstm_doevent(unit, event)
+ int unit;
+ enum gpstm_event event;
+{
+ struct gpstm_unit *gpstm = gpstm_units[unit];
+
+#ifdef DEBUG
+ if (debug) {
+ printf("gpstm_doevent(gpstm%d, %d)\n", unit, (int)event);
+ }
+#endif
+ if (event == e_TS && State[unit] != F51 && State[unit] != F08) {
+ gpstm_send(gpstm, "\03\r");
+ }
+
+ switch (event) {
+ case e_Init:
+ gpstm_send(gpstm, "F18\r");
+ State[unit] = Start;
+ break;
+ case e_F18:
+ gpstm_send(gpstm, "F50\r");
+ State[unit] = F18;
+ break;
+ case e_F50:
+ gpstm_send(gpstm, "F51\r");
+ State[unit] = F50;
+ break;
+ case e_F51:
+ gpstm_send(gpstm, "F08\r");
+ State[unit] = F51;
+ break;
+ case e_TS:
+ /* nothing to send - we like this mode */
+ State[unit] = F08;
+ break;
+ }
+}
+
+static void
+gpstm_initstate(unit) {
+ State[unit] = Base; /* just in case */
+ gpstm_doevent(unit, e_Init);
+}
+
+/*
+ * gpstm_process - process a pile of samples from the clock
+ */
+static char
+gpstm_process(gpstm, offset, dispersion)
+ struct gpstm_unit *gpstm;
+ 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. We take the maximum
+ * difference and use that as the sample dispersion. 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 = gpstm->offset[i].l_ui;
+ tmp_uf = gpstm->offset[i].l_uf;
+ M_SUB(tmp_ui, tmp_uf, gpstm->offset[j].l_ui,
+ gpstm->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;
+ }
+ }
+ }
+
+ /*
+ * It seems as if all are within 125 ms of each other.
+ * Now to determine the median of the three. Whlie the
+ * 125 ms check was going on, we also subtly catch the
+ * dispersion and set-up for a very easy median calculation.
+ * The largest difference between any two samples constitutes
+ * the dispersion. The sample not involve in the dispersion is
+ * the median sample. EASY!
+ */
+ if (gpstm->lasttime == 0 || disp_tmp2 > MAXDISPERSE)
+ disp_tmp2 = MAXDISPERSE;
+ if (not_median1 == 0) {
+ if (not_median2 == 1)
+ median = 2;
+ else
+ median = 1;
+ } else {
+ median = 0;
+ }
+ *offset = gpstm->offset[median];
+ *dispersion = disp_tmp2;
+ return 1;
+}
+
+/*
+ * gpstm_poll - called by the transmit procedure
+ */
+static void
+gpstm_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct gpstm_unit *gpstm;
+
+ /*
+ * You don't need to poll this clock. It puts out timecodes
+ * once per second. If asked for a timestamp, take note.
+ * The next time a timecode comes in, it will be fed back.
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_poll: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "gpstm_poll: unit %d not in use", unit);
+ return;
+ }
+ gpstm = gpstm_units[unit];
+ if ((current_time - gpstm->lasttime) > 150) {
+ gpstm->noreply++;
+ gpstm_rep_event(gpstm_units[unit], CEVNT_TIMEOUT);
+ gpstm_initstate(gpstm->unit);
+ }
+
+ /*
+ * polled every 64 seconds. Ask our receiver to hand in a timestamp.
+ */
+ gpstm->polled = 1;
+ gpstm->polls++;
+}
+
+/*
+ * gpstm_control - set fudge factors, return statistics
+ */
+static void
+gpstm_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct gpstm_unit *gpstm;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_control: unit %d invalid", unit);
+ return;
+ }
+
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ fudgefactor1[unit] = in->fudgetime1;
+ if (in->haveflags & CLK_HAVETIME2)
+ fudgefactor2[unit] = in->fudgetime2;
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
+ readonlyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = gpstm_units[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
+ }
+
+ if (out != 0) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
+ out->type = REFCLK_GPSTM_TRUETIME;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVETIME2 | CLK_HAVEVAL1 |
+ CLK_HAVEVAL2 | CLK_HAVEFLAG1;
+ out->clockdesc = DESCRIPTION;
+ out->fudgetime1 = fudgefactor1[unit];
+ out->fudgetime2 = fudgefactor2[unit];
+ out->fudgeval1 = (LONG)stratumtouse[unit];
+ out->fudgeval2 = refid[unit];
+ out->flags = readonlyclockflag[unit];
+ if (unitinuse[unit]) {
+ gpstm = gpstm_units[unit];
+ out->lencode = gpstm->lencode;
+ out->lastcode = gpstm->lastcode;
+ out->timereset = current_time - gpstm->timestarted;
+ out->polls = gpstm->polls;
+ out->noresponse = gpstm->noreply;
+ out->badformat = gpstm->badformat;
+ out->baddata = gpstm->baddata;
+ out->lastevent = gpstm->lastevent;
+ out->currentstatus = gpstm->status;
+ }
+ }
+}
+
+/*
+ * gpstm_buginfo - return clock dependent debugging info
+ */
+static void
+gpstm_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct gpstm_unit *gpstm;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "gpstm_buginfo: unit %d invalid", unit);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ gpstm = gpstm_units[unit];
+
+ bug->nvalues = 11;
+ bug->ntimes = 5;
+ if (gpstm->lasttime != 0)
+ bug->values[0] = current_time - gpstm->lasttime;
+ else
+ bug->values[0] = 0;
+ bug->values[1] = (U_LONG)gpstm->reason;
+ bug->values[2] = (U_LONG)gpstm->year;
+ bug->values[3] = (U_LONG)gpstm->day;
+ bug->values[4] = (U_LONG)gpstm->hour;
+ bug->values[5] = (U_LONG)gpstm->minute;
+ bug->values[6] = (U_LONG)gpstm->second;
+ bug->values[7] = (U_LONG)gpstm->msec;
+ bug->values[8] = gpstm->noreply;
+ bug->values[9] = gpstm->yearstart;
+ bug->values[10] = gpstm->quality;
+ bug->stimes = 0x1c;
+ bug->times[0] = gpstm->lastref;
+ bug->times[1] = gpstm->lastrec;
+ bug->times[2] = gpstm->offset[0];
+ bug->times[3] = gpstm->offset[1];
+ bug->times[4] = gpstm->offset[2];
+}
+
+#endif /*GPSTM et al*/
diff --git a/usr.sbin/xntpd/xntpd/refclock_old/refclock_leitch.c b/usr.sbin/xntpd/xntpd/refclock_old/refclock_leitch.c
new file mode 100644
index 000000000000..808f65bb4b89
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_old/refclock_leitch.c
@@ -0,0 +1,709 @@
+/*
+ * refclock_leitch - clock driver for the Leitch CSD-5300 Master Clock
+ */
+#if defined(REFCLOCK) && (defined(LEITCH) || defined(LEITCHCLK) || defined(LEITCHPPS))
+
+#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"
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+#ifdef STREAM
+#include <stropts.h>
+#if defined(LEITCHCLK)
+#include <sys/clkdefs.h>
+#endif /* LEITCHCLK */
+#endif /* STREAM */
+
+#if defined (LEITCHPPS)
+#include <sys/ppsclock.h>
+#endif /* LEITCHPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+ * Driver for Leitch CSD-5300 Master Clock System
+ *
+ * COMMANDS:
+ * DATE: D <CR>
+ * TIME: T <CR>
+ * STATUS: S <CR>
+ * LOOP: L <CR>
+ *
+ * FORMAT:
+ * DATE: YYMMDD<CR>
+ * TIME: <CR>/HHMMSS <CR>/HHMMSS <CR>/HHMMSS <CR>/
+ * second bondaried on the stop bit of the <CR>
+ * second boundaries at '/' above.
+ * STATUS: G (good), D (diag fail), T (time not provided) or
+ * P (last phone update failed)
+ */
+#define MAXUNITS 1 /* max number of LEITCH units */
+#define LEITCHREFID "ATOM" /* reference id */
+#define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver"
+#define LEITCH232 "/dev/leitch%d" /* name of radio device */
+#define SPEED232 B300 /* uart speed (300 baud) */
+#define leitch_send(A,M) \
+ if (debug) fprintf(stderr,"write leitch %s\n",M); \
+ if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
+ if (debug) \
+ fprintf(stderr, "leitch_send: unit %d send failed\n", A->unit); \
+ else \
+ syslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
+
+#define STATE_IDLE 0
+#define STATE_DATE 1
+#define STATE_TIME1 2
+#define STATE_TIME2 3
+#define STATE_TIME3 4
+
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * LEITCH unit control structure
+ */
+struct leitchunit {
+ struct peer *peer;
+ struct event leitchtimer;
+ struct refclockio leitchio;
+ u_char unit;
+ short year;
+ short yearday;
+ short month;
+ short day;
+ short hour;
+ short second;
+ short minute;
+ short state;
+ u_short fudge1;
+ l_fp reftime1;
+ l_fp reftime2;
+ l_fp reftime3;
+ l_fp codetime1;
+ l_fp codetime2;
+ l_fp codetime3;
+ U_LONG yearstart;
+};
+
+/*
+ * Function prototypes
+ */
+static void leitch_init P((void));
+static int leitch_start P((u_int, struct peer *));
+static void leitch_shutdown P((int));
+static void leitch_poll P((int, struct peer *));
+static void leitch_control P((u_int, struct refclockstat *, struct refclockstat *));
+#define leitch_buginfo noentry
+static void leitch_receive P((struct recvbuf *));
+static void leitch_process P((struct leitchunit *));
+static void leitch_timeout P((struct peer *));
+static int leitch_get_date P((struct recvbuf *, struct leitchunit *));
+static int leitch_get_time P((struct recvbuf *, struct leitchunit *, int));
+static int dysize P((int));
+
+static struct leitchunit leitchunits[MAXUNITS];
+static u_char unitinuse[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static U_LONG refid[MAXUNITS];
+
+static char days_in_month [] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_leitch = {
+ leitch_start, leitch_shutdown, leitch_poll,
+ leitch_control, leitch_init, leitch_buginfo, NOFLAGS
+};
+
+/*
+ * leitch_init - initialize internal leitch driver data
+ */
+static void
+leitch_init()
+{
+ int i;
+
+ memset((char*)leitchunits, 0, sizeof(leitchunits));
+ memset((char*)unitinuse, 0, sizeof(unitinuse));
+ for (i = 0; i < MAXUNITS; i++)
+ memcpy((char *)&refid[i], LEITCHREFID, 4);
+}
+
+/*
+ * leitch_shutdown - shut down a LEITCH clock
+ */
+static void
+leitch_shutdown(unit)
+int unit;
+{
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_shutdown()\n");
+#endif
+}
+
+/*
+ * leitch_poll - called by the transmit procedure
+ */
+static void
+leitch_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct leitchunit *leitch;
+
+ /* start the state machine rolling */
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_poll()\n");
+#endif
+ if (unit > MAXUNITS) {
+ /* XXXX syslog it */
+ return;
+ }
+
+ leitch = &leitchunits[unit];
+
+ if (leitch->state != STATE_IDLE) {
+ /* reset and wait for next poll */
+ /* XXXX syslog it */
+ leitch->state = STATE_IDLE;
+ } else {
+ leitch_send(leitch,"D\r");
+ leitch->state = STATE_DATE;
+ }
+}
+
+static void
+leitch_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,
+ "leitch_control: unit %d invalid", unit);
+ return;
+ }
+
+ if (in) {
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = (&leitchunits[unit])->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
+ }
+
+ if (out) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
+ out->type = REFCLK_ATOM_LEITCH;
+ out->haveflags = CLK_HAVEVAL1 | CLK_HAVEVAL2;
+ out->fudgeval1 = (LONG)stratumtouse[unit];
+ out->fudgeval2 = refid[unit];
+ out->lastcode = "";
+ out->clockdesc = LEITCH_DESCRIPTION;
+ }
+}
+
+/*
+ * leitch_start - open the LEITCH devices and initialize data for processing
+ */
+static int
+leitch_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ struct leitchunit *leitch;
+ int fd232;
+ char leitchdev[20];
+
+ /*
+ * Check configuration info.
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "leitch_start: unit %d invalid", unit);
+ return (0);
+ }
+
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "leitch_start: unit %d in use", unit);
+ return (0);
+ }
+
+ /*
+ * Open serial port.
+ */
+ (void) sprintf(leitchdev, LEITCH232, unit);
+ fd232 = open(leitchdev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR,
+ "leitch_start: open of %s: %m", leitchdev);
+ return (0);
+ }
+
+ leitch = &leitchunits[unit];
+ memset((char*)leitch, 0, sizeof(*leitch));
+
+#if defined(HAVE_SYSV_TTYS)
+ /*
+ * System V serial line parameters (termio interface)
+ *
+ */
+ { struct termio ttyb;
+ if (ioctl(fd232, TCGETA, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TCGETA): %m", leitchdev);
+ 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,
+ "leitch_start: ioctl(%s, TCSETA): %m", leitchdev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(HAVE_TERMIOS)
+ /*
+ * POSIX serial line parameters (termios interface)
+ *
+ * The LEITCHCLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The LEITCHPPS 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,
+ "leitch_start: tcgetattr(%s): %m", leitchdev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ 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,
+ "leitch_start: tcsetattr(%s): %m", leitchdev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: tcflush(%s): %m", leitchdev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_TERMIOS */
+#ifdef STREAM
+#if defined(LEITCHCLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, I_PUSH, clk): %m", leitchdev);
+ if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, CLK_SETSTR): %m", leitchdev);
+#endif /* LEITCHCLK */
+#if defined(LEITCHPPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, I_PUSH, ppsclock): %m", leitchdev);
+ else
+ fdpps = fd232;
+#endif /* LEITCHPPS */
+#endif /* STREAM */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The LEITCHCLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(LEITCHCLK)
+ int ldisc = CLKLDISC;
+#endif /* LEITCHCLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TIOCGETP): %m", leitchdev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(LEITCHCLK)
+ 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 /* LEITCHCLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TIOCSETP): %m", leitchdev);
+ goto screwed;
+ }
+#if defined(LEITCHCLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "leitch_start: ioctl(%s, TIOCSETD): %m",leitchdev);
+ goto screwed;
+ }
+#endif /* LEITCHCLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Set up the structures
+ */
+ leitch->peer = peer;
+ leitch->unit = unit;
+ leitch->state = STATE_IDLE;
+ leitch->fudge1 = 15; /* 15ms */
+
+ leitch->leitchio.clock_recv = leitch_receive;
+ leitch->leitchio.srcclock = (caddr_t) leitch;
+ leitch->leitchio.datalen = 0;
+ leitch->leitchio.fd = fd232;
+ if (!io_addclock(&leitch->leitchio)) {
+ 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 = 0;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ unitinuse[unit] = 1;
+ return(1);
+
+ /*
+ * Something broke; abandon ship.
+ */
+screwed:
+ close(fd232);
+ return(0);
+}
+
+/*
+ * leitch_receive - receive data from the serial interface on a leitch
+ * clock
+ */
+static void
+leitch_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ struct leitchunit *leitch = (struct leitchunit *)rbufp->recv_srcclock;
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_recieve(%*.*s)\n",
+ rbufp->recv_length, rbufp->recv_length,
+ rbufp->recv_buffer);
+#endif
+ if (rbufp->recv_length != 7)
+ return; /* The date is return with a trailing newline,
+ discard it. */
+
+ switch (leitch->state) {
+ case STATE_IDLE: /* unexpected, discard and resync */
+ return;
+ case STATE_DATE:
+ if (!leitch_get_date(rbufp,leitch)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+ leitch_send(leitch,"T\r");
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%u\n",leitch->yearday);
+#endif
+ leitch->state = STATE_TIME1;
+ break;
+ case STATE_TIME1:
+ if (!leitch_get_time(rbufp,leitch,1)) {
+ }
+ if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
+ leitch->second, 0, rbufp->recv_time.l_ui,
+ &leitch->yearstart, &leitch->reftime1.l_ui)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%u\n", leitch->reftime1.l_ui);
+#endif
+ MSUTOTSF(leitch->fudge1, leitch->reftime1.l_uf);
+ leitch->codetime1 = rbufp->recv_time;
+ leitch->state = STATE_TIME2;
+ break;
+ case STATE_TIME2:
+ if (!leitch_get_time(rbufp,leitch,2)) {
+ }
+ if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
+ leitch->second, 0, rbufp->recv_time.l_ui,
+ &leitch->yearstart, &leitch->reftime2.l_ui)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%u\n", leitch->reftime2.l_ui);
+#endif
+ MSUTOTSF(leitch->fudge1, leitch->reftime2.l_uf);
+ leitch->codetime2 = rbufp->recv_time;
+ leitch->state = STATE_TIME3;
+ break;
+ case STATE_TIME3:
+ if (!leitch_get_time(rbufp,leitch,3)) {
+ }
+ if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
+ leitch->second, 0, rbufp->recv_time.l_ui,
+ &leitch->yearstart, &leitch->reftime3.l_ui)) {
+ leitch->state = STATE_IDLE;
+ break;
+ }
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "%u\n", leitch->reftime3.l_ui);
+#endif
+ MSUTOTSF(leitch->fudge1, leitch->reftime3.l_uf);
+ leitch->codetime3 = rbufp->recv_time;
+ leitch_process(leitch);
+ leitch->state = STATE_IDLE;
+ break;
+ default:
+ syslog(LOG_ERR,
+ "leitech_receive: invalid state %d unit %d",
+ leitch->state, leitch->unit);
+ }
+}
+
+/*
+ * leitch_process - process a pile of samples from the clock
+ *
+ * This routine uses a three-stage median filter to calculate offset and
+ * dispersion. reduce jitter. The dispersion is calculated as the span
+ * of the filter (max - min), unless the quality character (format 2) is
+ * non-blank, in which case the dispersion is calculated on the basis of
+ * the inherent tolerance of the internal radio oscillator, which is
+ * +-2e-5 according to the radio specifications.
+ */
+static void
+leitch_process(leitch)
+ struct leitchunit *leitch;
+{
+ l_fp off;
+ s_fp delay;
+ l_fp codetime;
+ l_fp tmp_fp;
+ int isinsync = 1;
+ u_fp dispersion = 10;
+
+ delay = 20;
+
+ codetime = leitch->codetime3;
+
+ off = leitch->reftime1;
+ L_SUB(&off,&leitch->codetime1);
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr,"%u %u %u %u %d %d\n",
+ leitch->codetime1.l_ui, leitch->codetime1.l_uf,
+ leitch->reftime1.l_ui, leitch->reftime1.l_uf,
+ off.l_ui, off.l_uf);
+#endif
+ tmp_fp = leitch->reftime2;
+ L_SUB(&tmp_fp,&leitch->codetime2);
+ if (L_ISGEQ(&off,&tmp_fp))
+ off = tmp_fp;
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr,"%u %u %u %u %d %d\n",
+ leitch->codetime2.l_ui, leitch->codetime2.l_uf,
+ leitch->reftime2.l_ui, leitch->reftime2.l_uf,
+ off.l_ui, off.l_uf);
+#endif
+ tmp_fp = leitch->reftime3;
+ L_SUB(&tmp_fp,&leitch->codetime3);
+
+ if (L_ISGEQ(&off,&tmp_fp))
+ off = tmp_fp;
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr,"%u %u %u %u %d %d\n",
+ leitch->codetime3.l_ui, leitch->codetime3.l_uf,
+ leitch->reftime3.l_ui, leitch->reftime3.l_uf,
+ off.l_ui, off.l_uf);
+#endif
+ refclock_receive(leitch->peer, &off, 0, dispersion, &codetime,
+ &codetime, isinsync);
+}
+
+/*
+ * leitch_timeout
+ */
+static void
+leitch_timeout(fp)
+ struct peer *fp;
+{
+
+#ifdef DEBUG
+ if (debug)
+ fprintf(stderr, "leitch_timeout()\n");
+#endif
+
+#ifdef NOTYET
+ { struct leitchunit *leitch = (struct leitchunit *)fp;
+
+ switch(leitch->state) {
+ case STATE_IDLE:
+ leitch_send(leitch,"D\r");
+ leitch->state = STATE_DATE;
+ break;
+ case STATE_DATE:
+ leitch_send(leitch,"T\r");
+ leitch->state = STATE_TIME1;
+ break;
+ case STATE_TIME1:
+ case STATE_TIME2:
+ case STATE_TIME3:
+ default:
+ break;
+ }
+
+ leitch->leitchtimer.event_time += 30;
+ TIMER_ENQUEUE(timerqueue, &leitch->leitchtimer);
+ }
+#endif /* NOTYET */
+}
+
+/*
+ * dysize
+ */
+static int
+dysize(year)
+int year;
+{
+ if (year%4) { /* not a potential leap year */
+ return (365);
+ } else {
+ if (year % 100) { /* is a leap year */
+ return (366);
+ } else {
+ if (year % 400) {
+ return (365);
+ } else {
+ return (366);
+ }
+ }
+ }
+}
+
+static int
+leitch_get_date(rbufp,leitch)
+ struct recvbuf *rbufp;
+ struct leitchunit *leitch;
+{
+ int i;
+
+ if (rbufp->recv_length < 6)
+ return(0);
+#define BAD(A) (rbufp->recv_buffer[A] < '0') || (rbufp->recv_buffer[A] > '9')
+ if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
+ return(0);
+#define ATOB(A) ((rbufp->recv_buffer[A])-'0')
+ leitch->year = ATOB(0)*10 + ATOB(1);
+ leitch->month = ATOB(2)*10 + ATOB(3);
+ leitch->day = ATOB(4)*10 + ATOB(5);
+
+ /* sanity checks */
+ if (leitch->month > 12)
+ return(0);
+ if (leitch->day > days_in_month[leitch->month-1])
+ return(0);
+
+ /* calculate yearday */
+ i = 0;
+ leitch->yearday = leitch->day;
+
+ while ( i < (leitch->month-1) )
+ leitch->yearday += days_in_month[i++];
+
+ if ((dysize((leitch->year>90?1900:2000)+leitch->year)==365) &&
+ leitch->month > 2)
+ leitch->yearday--;
+
+ return(1);
+}
+
+/*
+ * leitch_get_time
+ */
+static int
+leitch_get_time(rbufp,leitch,which)
+ struct recvbuf *rbufp;
+ struct leitchunit *leitch;
+ int which;
+{
+ if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
+ return(0);
+ leitch->hour = ATOB(0)*10 +ATOB(1);
+ leitch->minute = ATOB(2)*10 +ATOB(3);
+ leitch->second = ATOB(4)*10 +ATOB(5);
+
+ if ((leitch->hour > 23) || (leitch->minute > 60) ||
+ (leitch->second > 60))
+ return(0);
+ return(1);
+}
+
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_old/refclock_msfees.c b/usr.sbin/xntpd/xntpd/refclock_old/refclock_msfees.c
new file mode 100644
index 000000000000..255d74f285de
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_old/refclock_msfees.c
@@ -0,0 +1,1575 @@
+/* refclock_ees - clock driver for the EES M201 receiver */
+
+#if defined(REFCLOCK) && defined(MSFEESPPS) && defined(STREAM)
+
+/* Currently REQUIRES STREAM and PPSCD. CLK and CBREAK modes
+ * were removed as the code was overly hairy, they weren't in use
+ * (hence probably didn't work). Still in RCS file at cl.cam.ac.uk
+ */
+
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_calendar.h"
+#if defined(HAVE_BSD_TTYS)
+#include <sgtty.h>
+#endif /* HAVE_BSD_TTYS */
+#if defined(HAVE_SYSV_TTYS)
+#include <termio.h>
+#endif /* HAVE_SYSV_TTYS */
+#include <termios.h>
+#include <stropts.h>
+#include <sys/ppsclock.h>
+#include "ntp_stdlib.h"
+
+ /*
+ fudgefactor = fudgetime1;
+ os_delay = fudgetime2;
+ offset_fudge = os_delay + fudgefactor + inherent_delay;
+ stratumtouse = fudgeval1 & 0xf
+ debug = fudgeval2;
+ sloppyclockflag = flags & CLK_FLAG1;
+ 1 log smoothing summary when processing sample
+ 4 dump the buffer from the clock
+ 8 EIOGETKD the last n uS time stamps
+ if (flags & CLK_FLAG2 && unitinuse) ees->leaphold = 0;
+ ees->dump_vals = flags & CLK_FLAG3;
+ ees->usealldata = flags & CLK_FLAG4;
+
+
+ bug->values[0] = (ees->lasttime) ? current_time - ees->lasttime : 0;
+ bug->values[1] = (ees->clocklastgood)?current_time-ees->clocklastgood:0;
+ bug->values[2] = (u_long)ees->status;
+ bug->values[3] = (u_long)ees->lastevent;
+ bug->values[4] = (u_long)ees->reason;
+ bug->values[5] = (u_long)ees->nsamples;
+ bug->values[6] = (u_long)ees->codestate;
+ bug->values[7] = (u_long)ees->day;
+ bug->values[8] = (u_long)ees->hour;
+ bug->values[9] = (u_long)ees->minute;
+ bug->values[10] = (u_long)ees->second;
+ bug->values[11] = (u_long)ees->tz;
+ bug->values[12] = ees->yearstart;
+ bug->values[13] = (ees->leaphold > current_time) ?
+ ees->leaphold - current_time : 0;
+ bug->values[14] = inherent_delay[unit].l_uf;
+ bug->values[15] = offset_fudge[unit].l_uf;
+
+ bug->times[0] = ees->reftime;
+ bug->times[1] = ees->arrvtime;
+ bug->times[2] = ees->lastsampletime;
+ bug->times[3] = ees->offset;
+ bug->times[4] = ees->lowoffset;
+ bug->times[5] = ees->highoffset;
+ bug->times[6] = inherent_delay[unit];
+ bug->times[8] = os_delay[unit];
+ bug->times[7] = fudgefactor[unit];
+ bug->times[9] = offset_fudge[unit];
+ bug->times[10]= ees->yearstart, 0;
+ */
+
+/* This should support the use of an EES M201 receiver with RS232
+ * output (modified to transmit time once per second).
+ *
+ * For the format of the message sent by the clock, see the EESM_
+ * definitions below.
+ *
+ * It appears to run free for an integral number of minutes, until the error
+ * reaches 4mS, at which point it steps at second = 01.
+ * It appears that sometimes it steps 4mS (say at 7 min interval),
+ * then the next minute it decides that it was an error, so steps back.
+ * On the next minute it steps forward again :-(
+ * This is typically 16.5uS/S then 3975uS at the 4min re-sync,
+ * or 9.5uS/S then 3990.5uS at a 7min re-sync,
+ * at which point it may loose the "00" second time stamp.
+ * I assume that the most accurate time is just AFTER the re-sync.
+ * Hence remember the last cycle interval,
+ *
+ * Can run in any one of:
+ *
+ * PPSCD PPS signal sets CD which interupts, and grabs the current TOD
+ * (sun) *in the interupt code*, so as to avoid problems with
+ * the STREAMS scheduling.
+ *
+ * It appears that it goes 16.5 uS slow each second, then every 4 mins it
+ * generates no "00" second tick, and gains 3975 uS. Ho Hum ! (93/2/7)
+ */
+
+/* Definitions */
+#ifndef MAXUNITS
+#define MAXUNITS 4 /* maximum number of EES units permitted */
+#endif
+
+#ifndef EES232
+#define EES232 "/dev/ees%d" /* Device to open to read the data */
+#endif
+
+/* Other constant stuff */
+#ifndef EESPRECISION
+#define EESPRECISION (-10) /* what the heck - 2**-10 = 1ms */
+#endif
+#ifndef EESREFID
+#define EESREFID "MSF\0" /* String to identify the clock */
+#endif
+#ifndef EESHSREFID
+#define EESHSREFID (0x7f7f0000 | ((REFCLK_MSF_EES) << 8)) /* Numeric refid */
+#endif
+
+/* Description of clock */
+#define EESDESCRIPTION "EES M201 MSF Receiver"
+
+/* Speed we run the clock port at. If this is changed the UARTDELAY
+ * value should be recomputed to suit.
+ */
+#ifndef SPEED232
+#define SPEED232 B9600 /* 9600 baud */
+#endif
+
+/* What is the inherent delay for this mode of working, i.e. when is the
+ * data time stamped.
+ */
+#define SAFETY_SHIFT 10 /* Split the shift to avoid overflow */
+#define BITS_TO_L_FP(bits, baud) \
+ (((((bits)*2 +1) << (FRACTION_PREC-SAFETY_SHIFT)) / (2*baud)) << SAFETY_SHIFT)
+#define INH_DELAY_CBREAK BITS_TO_L_FP(119, 9600)
+#define INH_DELAY_PPS BITS_TO_L_FP( 0, 9600)
+
+#ifndef STREAM_PP1
+#define STREAM_PP1 "ppsclocd\0<-- patch space for module name1 -->"
+#endif
+#ifndef STREAM_PP2
+#define STREAM_PP2 "ppsclock\0<-- patch space for module name2 -->"
+#endif
+
+/* Offsets of the bytes of the serial line code. The clock gives
+ * local time with a GMT/BST indication. The EESM_ definitions
+ * give offsets into ees->lastcode.
+ */
+#define EESM_CSEC 0 /* centiseconds - always zero in our clock */
+#define EESM_SEC 1 /* seconds in BCD */
+#define EESM_MIN 2 /* minutes in BCD */
+#define EESM_HOUR 3 /* hours in BCD */
+#define EESM_DAYWK 4 /* day of week (Sun = 0 etc) */
+#define EESM_DAY 5 /* day of month in BCD */
+#define EESM_MON 6 /* month in BCD */
+#define EESM_YEAR 7 /* year MOD 100 in BCD */
+#define EESM_LEAP 8 /* 0x0f if leap year, otherwise zero */
+#define EESM_BST 9 /* 0x03 if BST, 0x00 if GMT */
+#define EESM_MSFOK 10 /* 0x3f if radio good, otherwise zero */
+ /* followed by a frame alignment byte (0xff) /
+ / which is not put into the lastcode buffer*/
+
+/* Length of the serial time code, in characters. The first length
+ * is less the frame alignment byte.
+ */
+#define LENEESPRT (EESM_MSFOK+1)
+#define LENEESCODE (LENEESPRT+1)
+
+/* Code state. */
+#define EESCS_WAIT 0 /* waiting for start of timecode */
+#define EESCS_GOTSOME 1 /* have an incomplete time code buffered */
+
+/* Default fudge factor and character to receive */
+#define DEFFUDGETIME 0 /* Default user supplied fudge factor */
+#ifndef DEFOSTIME
+#define DEFOSTIME 0 /* Default OS delay -- passed by Make ? */
+#endif
+#define DEFINHTIME INH_DELAY_PPS /* inherent delay due to sample point*/
+
+/* Limits on things. Reduce the number of samples to SAMPLEREDUCE by median
+ * elimination. If we're running with an accurate clock, chose the BESTSAMPLE
+ * as the estimated offset, otherwise average the remainder.
+ */
+#define FULLSHIFT 6 /* NCODES root 2 */
+#define NCODES (1<< FULLSHIFT) /* 64 */
+#define REDUCESHIFT (FULLSHIFT -1) /* SAMPLEREDUCE root 2 */
+
+/* Towards the high ( Why ?) end of half */
+#define BESTSAMPLE ((samplereduce * 3) /4) /* 24 */
+
+/* Leap hold time. After a leap second the clock will no longer be
+ * reliable until it resynchronizes. Hope 40 minutes is enough. */
+#define EESLEAPHOLD (40 * 60)
+
+#define EES_STEP_F (1 << 24) /* the receiver steps in units of about 4ms */
+#define EES_STEP_F_GRACE (EES_STEP_F/8) /*Allow for slop of 1/8 which is .5ms*/
+#define EES_STEP_NOTE (1 << 21)/* Log any unexpected jumps, say .5 ms .... */
+#define EES_STEP_NOTES 50 /* Only do a limited number */
+#define MAX_STEP 16 /* Max number of steps to remember */
+
+/* debug is a bit mask of debugging that is wanted */
+#define DB_SYSLOG_SMPLI 0x0001
+#define DB_SYSLOG_SMPLE 0x0002
+#define DB_SYSLOG_SMTHI 0x0004
+#define DB_SYSLOG_NSMTHE 0x0008
+#define DB_SYSLOG_NSMTHI 0x0010
+#define DB_SYSLOG_SMTHE 0x0020
+#define DB_PRINT_EV 0x0040
+#define DB_PRINT_CDT 0x0080
+#define DB_PRINT_CDTC 0x0100
+#define DB_SYSLOG_KEEPD 0x0800
+#define DB_SYSLOG_KEEPE 0x1000
+#define DB_LOG_DELTAS 0x2000
+#define DB_PRINT_DELTAS 0x4000
+#define DB_LOG_AWAITMORE 0x8000
+#define DB_LOG_SAMPLES 0x10000
+#define DB_NO_PPS 0x20000
+#define DB_INC_PPS 0x40000
+#define DB_DUMP_DELTAS 0x80000
+
+struct eesunit { /* EES unit control structure. */
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ l_fp reftime; /* reference time */
+ l_fp lastsampletime; /* time as in txt from last EES msg */
+ l_fp arrvtime; /* Time at which pkt arrived */
+ l_fp codeoffsets[NCODES]; /* the time of arrival of 232 codes */
+ l_fp offset; /* chosen offset (for clkbug) */
+ l_fp lowoffset; /* lowest sample offset (for clkbug) */
+ l_fp highoffset; /* highest " " (for clkbug) */
+ char lastcode[LENEESCODE+6]; /* last time code we received */
+ u_long lasttime; /* last time clock heard from */
+ u_long clocklastgood; /* last time good radio seen */
+ u_char lencode; /* length of code in buffer */
+ u_char nsamples; /* number of samples we've collected */
+ u_char codestate; /* state of 232 code reception */
+ 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 hour; /* hour of day */
+ u_char minute; /* minute of hour */
+ u_char second; /* seconds of minute */
+ char tz; /* timezone from clock */
+ u_char ttytype; /* method used */
+ u_char dump_vals; /* Should clock values be dumped */
+ u_char usealldata; /* Use ALL samples */
+ u_short day; /* day of year from last code */
+ u_long yearstart; /* start of current year */
+ u_long leaphold; /* time of leap hold expiry */
+ u_long badformat; /* number of bad format codes */
+ u_long baddata; /* number of invalid time codes */
+ u_long timestarted; /* time we started this */
+ long last_pps_no; /* The serial # of the last PPS */
+ char fix_pending; /* Is a "sync to time" pending ? */
+ /* Fine tuning - compensate for 4 mS ramping .... */
+ l_fp last_l; /* last time stamp */
+ u_char last_steps[MAX_STEP]; /* Most recent n steps */
+ int best_av_step; /* Best guess at average step */
+ char best_av_step_count; /* # of steps over used above */
+ char this_step; /* Current pos in buffer */
+ int last_step_late; /* How late the last step was (0-59) */
+ long jump_fsecs; /* # of fractions of a sec last jump */
+ u_long last_step; /* time of last step */
+ int last_step_secs; /* Number of seconds in last step */
+ int using_ramp; /* 1 -> noemal, -1 -> over stepped */
+};
+#define last_sec last_l.l_ui
+#define last_sfsec last_l.l_f
+#define this_uisec ((ees->arrvtime).l_ui)
+#define this_sfsec ((ees->arrvtime).l_f)
+#define msec(x) ((x) / (1<<22))
+#define LAST_STEPS (sizeof ees->last_steps / sizeof ees->last_steps[0])
+#define subms(x) ((((((x < 0) ? (-(x)) : (x)) % (1<<22))/2) * 625) / (1<<(22 -5)))
+
+/* Bitmask for what methods to try to use -- currently only PPS enabled */
+#define T_CBREAK 1
+#define T_PPS 8
+/* macros to test above */
+#define is_cbreak(x) ((x)->ttytype & T_CBREAK)
+#define is_pps(x) ((x)->ttytype & T_PPS)
+#define is_any(x) ((x)->ttytype)
+
+#define CODEREASON 20 /* reason codes */
+
+/* Data space for the unit structures. Note that we allocate these on
+ * the fly, but never give them back. */
+static struct eesunit *eesunits[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 inherent_delay[MAXUNITS]; /* when time stamp is taken */
+static l_fp fudgefactor[MAXUNITS]; /* fudgetime1 */
+static l_fp os_delay[MAXUNITS]; /* fudgetime2 */
+static l_fp offset_fudge[MAXUNITS]; /* Sum of above */
+static u_char stratumtouse[MAXUNITS];
+static u_char sloppyclockflag[MAXUNITS];
+
+static int deltas[60];
+
+static l_fp acceptable_slop; /* = { 0, 1 << (FRACTION_PREC -2) }; */
+static l_fp onesec; /* = { 1, 0 }; */
+
+/* Imported from the timer module */
+extern u_long current_time;
+
+#ifdef DEBUG
+static int debug;
+#endif
+
+#ifndef DUMP_BUF_SIZE /* Size of buffer to be used by dump_buf */
+#define DUMP_BUF_SIZE 10112
+#endif
+
+/* ees_reset - reset the count back to zero */
+#define ees_reset(ees) (ees)->nsamples = 0; \
+ (ees)->codestate = EESCS_WAIT
+
+/* ees_event - record and report an event */
+#define ees_event(ees, evcode) if ((ees)->status != (u_char)(evcode)) \
+ ees_report_event((ees), (evcode))
+
+/* Find the precision of the system clock by reading it */
+#define USECS 1000000
+#define MINSTEP 5 /* some systems increment uS on each call */
+#define MAXLOOPS (USECS/9)
+static int ees_get_precision()
+{
+ struct timeval tp;
+ struct timezone tzp;
+ long last;
+ int i;
+ long diff;
+ long val;
+ gettimeofday(&tp, &tzp);
+
+ last = tp.tv_usec;
+ for (i=0; i< 100000; i++) {
+ gettimeofday(&tp, &tzp);
+ diff = tp.tv_usec - last;
+ if (diff < 0) diff += USECS;
+ if (diff > MINSTEP) break;
+ last = tp.tv_usec;
+ }
+ syslog(LOG_INFO,
+ "I: ees: precision calculation given %duS after %d loop%s",
+ diff, i, (i==1) ? "" : "s");
+
+ if (i == 0) return -20 /* assume 1uS */;
+ if (i >= MAXLOOPS) return EESPRECISION /* Lies ! */;
+ for (i=0, val=USECS; val > 0; i--, val /= 2) if (diff > val) return i;
+ return EESPRECISION /* Lies ! */;
+}
+
+static void dump_buf(coffs, from, to, text)
+l_fp *coffs;
+int from;
+int to;
+char *text;
+{
+ char buff[DUMP_BUF_SIZE + 80];
+ int i;
+ register char *ptr = buff;
+ sprintf(ptr, text);
+ for (i=from; i<to; i++)
+ { while (*ptr) ptr++;
+ if ((ptr-buff) > DUMP_BUF_SIZE) syslog(LOG_DEBUG, "D: %s", ptr=buff);
+ sprintf(ptr, " %06d", ((int)coffs[i].l_f) / 4295);
+ }
+ syslog(LOG_DEBUG, "D: %s", buff);
+}
+
+/* msfees_init - initialize internal ees driver data */
+static void msfees_init()
+{
+ register int i;
+ /* Just zero the data arrays */
+ memset((char *)eesunits, 0, sizeof eesunits);
+ memset((char *)unitinuse, 0, sizeof unitinuse);
+
+ acceptable_slop.l_ui = 0;
+ acceptable_slop.l_uf = 1 << (FRACTION_PREC -2);
+
+ onesec.l_ui = 1;
+ onesec.l_uf = 0;
+
+ /* Initialize fudge factors to default. */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor[i].l_ui = 0;
+ fudgefactor[i].l_uf = DEFFUDGETIME;
+ os_delay[i].l_ui = 0;
+ os_delay[i].l_uf = DEFOSTIME;
+ inherent_delay[i].l_ui = 0;
+ inherent_delay[i].l_uf = DEFINHTIME;
+ offset_fudge[i] = os_delay[i];
+ L_ADD(&offset_fudge[i], &fudgefactor[i]);
+ L_ADD(&offset_fudge[i], &inherent_delay[i]);
+ stratumtouse[i] = 0;
+ sloppyclockflag[i] = 0;
+ }
+}
+
+
+/* msfees_start - open the EES devices and initialize data for processing */
+static int msfees_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct eesunit *ees;
+ register int i;
+ int fd232 = -1;
+ char eesdev[20];
+ struct termios ttyb, *ttyp;
+ static void ees_receive();
+ extern int io_addclock();
+ extern void io_closeclock();
+ extern char *emalloc();
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock: unit number %d invalid (max %d)",
+ unit, MAXUNITS-1);
+ return 0;
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "ees clock: unit number %d in use", unit);
+ return 0;
+ }
+
+ /* Unit okay, attempt to open the devices. We do them both at
+ * once to make sure we can */
+ (void) sprintf(eesdev, EES232, unit);
+
+ fd232 = open(eesdev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR, "ees clock: open of %s failed: %m", eesdev);
+ return 0;
+ }
+
+#ifdef TIOCEXCL
+ /* Set for exclusive use */
+ if (ioctl(fd232, TIOCEXCL, (char *)0) < 0) {
+ syslog(LOG_ERR, "ees clock: ioctl(%s, TIOCEXCL): %m", eesdev);
+ goto screwed;
+ }
+#endif
+
+ /* STRIPPED DOWN VERSION: Only PPS CD is supported at the moment */
+
+ /* Set port characteristics. If we don't have a STREAMS module or
+ * a clock line discipline, cooked mode is just usable, even though it
+ * strips the top bit. The only EES byte which uses the top
+ * bit is the year, and we don't use that anyway. If we do
+ * have the line discipline, we choose raw mode, and the
+ * line discipline code will block up the messages.
+ */
+
+ /* STIPPED DOWN VERSION: Only PPS CD is supported at the moment */
+
+ ttyp = &ttyb;
+ if (tcgetattr(fd232, ttyp) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcgetattr(%s): %m", eesdev);
+ goto screwed;
+ }
+
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
+ ttyp->c_oflag = 0;
+ ttyp->c_lflag = ICANON;
+ ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+ if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcsetattr(%s): %m", eesdev);
+ goto screwed;
+ }
+
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR, "msfees_start: tcflush(%s): %m", eesdev);
+ goto screwed;
+ }
+
+ inherent_delay[unit].l_uf = INH_DELAY_PPS;
+
+ /* offset fudge (how *late* the timestamp is) = fudge + os delays */
+ offset_fudge[unit] = os_delay[unit];
+ L_ADD(&offset_fudge[unit], &fudgefactor[unit]);
+ L_ADD(&offset_fudge[unit], &inherent_delay[unit]);
+
+ /* Looks like this might succeed. Find memory for the structure.
+ * Look to see if there are any unused ones, if not we malloc() one.
+ */
+ if (eesunits[unit] != 0) /* The one we want is okay */
+ ees = eesunits[unit];
+ else {
+ /* Look for an unused, but allocated struct */
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && eesunits[i] != 0)
+ break;
+ }
+
+ if (i < MAXUNITS) { /* Reclaim this one */
+ ees = eesunits[i];
+ eesunits[i] = 0;
+ } /* no spare -- make a new one */
+ else ees = (struct eesunit *) emalloc(sizeof(struct eesunit));
+ }
+ memset((char *)ees, 0, sizeof(struct eesunit));
+ eesunits[unit] = ees;
+
+ /* Set up the structures */
+ ees->peer = peer;
+ ees->unit = (u_char)unit;
+ ees->timestarted= current_time;
+ ees->ttytype = 0;
+ ees->io.clock_recv= ees_receive;
+ ees->io.srcclock= (caddr_t)ees;
+ ees->io.datalen = 0;
+ ees->io.fd = fd232;
+
+ /* Okay. Push one of the two (linked into the kernel, or dynamically
+ * loaded) STREAMS module, and give it to the I/O code to start
+ * receiving stuff.
+ */
+
+ {
+ int rc1;
+ /* Pop any existing onews first ... */
+ while (ioctl(fd232, I_POP, 0 ) >= 0) ;
+
+ /* Now try pushing either of the possible modules */
+ if ((rc1=ioctl(fd232, I_PUSH, STREAM_PP1)) < 0 &&
+ ioctl(fd232, I_PUSH, STREAM_PP2) < 0) {
+ syslog(LOG_ERR,
+ "ees clock: Push of `%s' and `%s' to %s failed %m",
+ STREAM_PP1, STREAM_PP2, eesdev);
+ goto screwed;
+ }
+ else {
+ syslog(LOG_INFO, "I: ees clock: PUSHed %s on %s",
+ (rc1 >= 0) ? STREAM_PP1 : STREAM_PP2, eesdev);
+ ees->ttytype |= T_PPS;
+ }
+ }
+
+ /* Add the clock */
+ if (!io_addclock(&ees->io)) {
+ /* Oh shit. Just close and return. */
+ syslog(LOG_ERR, "ees clock: io_addclock(%s): %m", eesdev);
+ goto screwed;
+ }
+
+
+ /* All done. Initialize a few random peer variables, then
+ * return success. */
+ peer->precision = ees_get_precision();
+ peer->stratum = stratumtouse[unit];
+ peer->rootdelay = 0; /* ++++ */
+ peer->rootdispersion = 0; /* ++++ */
+ if (stratumtouse[unit] <= 1) {
+ memmove((char *)&peer->refid, EESREFID, 4);
+ if (unit > 0 && unit < 10)
+ ((char *)&peer->refid)[3] = '0' + unit;
+ } else {
+ peer->refid = htonl(EESHSREFID);
+ }
+ unitinuse[unit] = 1;
+ syslog(LOG_ERR, "ees clock: %s OK on %d", eesdev, unit);
+ return (1);
+
+screwed:
+ if (fd232 != -1)
+ (void) close(fd232);
+ return (0);
+}
+
+
+/* msfees_shutdown - shut down a EES clock */
+static void msfees_shutdown(unit)
+ int unit;
+{
+ register struct eesunit *ees;
+ extern void io_closeclock();
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,
+ "ees clock: INTERNAL ERROR, unit number %d invalid (max %d)",
+ unit, MAXUNITS);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR,
+ "ees clock: INTERNAL ERROR, unit number %d not in use", unit);
+ return;
+ }
+
+ /* Tell the I/O module to turn us off. We're history. */
+ ees = eesunits[unit];
+ io_closeclock(&ees->io);
+ unitinuse[unit] = 0;
+}
+
+
+/* ees_report_event - note the occurance of an event */
+static void ees_report_event(ees, code)
+ struct eesunit *ees;
+ int code;
+{
+ if (ees->status != (u_char)code) {
+ ees->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ ees->lastevent = (u_char)code;
+ /* Should report event to trap handler in here.
+ * Soon...
+ */
+ }
+}
+
+
+/* ees_receive - receive data from the serial interface on an EES clock */
+static void ees_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register int n_sample;
+ register int day;
+ register struct eesunit *ees;
+ register u_char *dpt; /* Data PoinTeR: move along ... */
+ register u_char *dpend; /* Points just *after* last data char */
+ register char *cp;
+ l_fp tmp;
+ static void ees_process();
+ int call_pps_sample = 0;
+ l_fp pps_arrvstamp;
+ int sincelast;
+ int pps_step = 0;
+ int suspect_4ms_step = 0;
+ struct ppsclockev ppsclockev;
+ long *ptr = (long *) &ppsclockev;
+ extern errno;
+ int rc;
+
+ /* Get the clock this applies to and a pointer to the data */
+ ees = (struct eesunit *)rbufp->recv_srcclock;
+ dpt = (u_char *)&rbufp->recv_space;
+ dpend = dpt + rbufp->recv_length;
+ if ((debug & DB_LOG_AWAITMORE) && (rbufp->recv_length != LENEESCODE))
+ printf("[%d] ", rbufp->recv_length);
+
+ /* Check out our state and process appropriately */
+ switch (ees->codestate) {
+ case EESCS_WAIT:
+ /* Set an initial guess at the timestamp as the recv time.
+ * If just running in CBREAK mode, we can't improve this.
+ * If we have the CLOCK Line Discipline, PPSCD, or sime such,
+ * then we will do better later ....
+ */
+ ees->arrvtime = rbufp->recv_time;
+ ees->codestate = EESCS_GOTSOME;
+ ees->lencode = 0;
+ /*FALLSTHROUGH*/
+
+ case EESCS_GOTSOME:
+ cp = &(ees->lastcode[ees->lencode]);
+
+ /* Gobble the bytes until the final (possibly stripped) 0xff */
+ while (dpt < dpend && (*dpt & 0x7f) != 0x7f) {
+ *cp++ = (char)*dpt++;
+ ees->lencode++;
+ /* Oh dear -- too many bytes .. */
+ if (ees->lencode > LENEESPRT) {
+ syslog(LOG_INFO,
+"I: ees clock: %d + %d > %d [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
+ ees->lencode, dpend - dpt, LENEESPRT,
+#define D(x) (ees->lastcode[x])
+ D(0), D(1), D(2), D(3), D(4), D(5), D(6),
+ D(7), D(8), D(9), D(10), D(11), D(12));
+#undef D
+ ees->badformat++;
+ ees->reason = CODEREASON + 1;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+ }
+ /* Gave up because it was end of the buffer, rather than ff */
+ if (dpt == dpend) {
+ /* Incomplete. Wait for more. */
+ if (debug & DB_LOG_AWAITMORE) syslog(LOG_INFO,
+ "I: ees clock %d: %d == %d: await more",
+ ees->unit, dpt, dpend);
+ return;
+ }
+
+ /* This shouldn't happen ... ! */
+ if ((*dpt & 0x7f) != 0x7f) {
+ syslog(LOG_INFO, "I: ees clock: %0x & 0x7f != 0x7f", *dpt);
+ ees->badformat++;
+ ees->reason = CODEREASON + 2;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ /* Skip the 0xff */
+ dpt++;
+
+ /* Finally, got a complete buffer. Mainline code will
+ * continue on. */
+ cp = ees->lastcode;
+ break;
+
+ default:
+ syslog(LOG_ERR, "ees clock: INTERNAL ERROR: %d state %d",
+ ees->unit, ees->codestate);
+ ees->reason = CODEREASON + 5;
+ ees_event(ees, CEVNT_FAULT);
+ ees_reset(ees);
+ return;
+ }
+
+ /* Boy! After all that crap, the lastcode buffer now contains
+ * something we hope will be a valid time code. Do length
+ * checks and sanity checks on constant data.
+ */
+ ees->codestate = EESCS_WAIT;
+ ees->lasttime = current_time;
+ if (ees->lencode != LENEESPRT) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 6;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ cp = ees->lastcode;
+
+ /* Check that centisecond is zero */
+ if (cp[EESM_CSEC] != 0) {
+ ees->baddata++;
+ ees->reason = CODEREASON + 7;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ /* Check flag formats */
+ if (cp[EESM_LEAP] != 0 && cp[EESM_LEAP] != 0x0f) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 8;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ if (cp[EESM_BST] != 0 && cp[EESM_BST] != 0x03) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 9;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ if (cp[EESM_MSFOK] != 0 && cp[EESM_MSFOK] != 0x3f) {
+ ees->badformat++;
+ ees->reason = CODEREASON + 10;
+ ees_event(ees, CEVNT_BADREPLY);
+ ees_reset(ees);
+ return;
+ }
+
+ /* So far, so good. Compute day, hours, minutes, seconds,
+ * time zone. Do range checks on these.
+ */
+
+#define bcdunpack(val) ( (((val)>>4) & 0x0f) * 10 + ((val) & 0x0f) )
+#define istrue(x) ((x)?1:0)
+
+ ees->second = bcdunpack(cp[EESM_SEC]); /* second */
+ ees->minute = bcdunpack(cp[EESM_MIN]); /* minute */
+ ees->hour = bcdunpack(cp[EESM_HOUR]); /* hour */
+
+ day = bcdunpack(cp[EESM_DAY]); /* day of month */
+
+ switch (bcdunpack(cp[EESM_MON])) { /* month */
+
+ /* Add in lengths of all previous months. Add one more
+ if it is a leap year and after February.
+ */
+ case 12: day += NOV; /*FALLSTHROUGH*/
+ case 11: day += OCT; /*FALLSTHROUGH*/
+ case 10: day += SEP; /*FALLSTHROUGH*/
+ case 9: day += AUG; /*FALLSTHROUGH*/
+ case 8: day += JUL; /*FALLSTHROUGH*/
+ case 7: day += JUN; /*FALLSTHROUGH*/
+ case 6: day += MAY; /*FALLSTHROUGH*/
+ case 5: day += APR; /*FALLSTHROUGH*/
+ case 4: day += MAR; /*FALLSTHROUGH*/
+ case 3: day += FEB;
+ if (istrue(cp[EESM_LEAP])) day++; /*FALLSTHROUGH*/
+ case 2: day += JAN; /*FALLSTHROUGH*/
+ case 1: break;
+ default: ees->baddata++;
+ ees->reason = CODEREASON + 11;
+ ees_event(ees, CEVNT_BADDATE);
+ ees_reset(ees);
+ return;
+ }
+
+ ees->day = day;
+
+ /* Get timezone. The clocktime routine wants the number
+ * of hours to add to the delivered time to get UT.
+ * Currently -1 if BST flag set, 0 otherwise. This
+ * is the place to tweak things if double summer time
+ * ever happens.
+ */
+ ees->tz = istrue(cp[EESM_BST]) ? -1 : 0;
+
+ if (ees->day > 366 || ees->day < 1 ||
+ ees->hour > 23 || ees->minute > 59 || ees->second > 59) {
+ ees->baddata++;
+ ees->reason = CODEREASON + 12;
+ ees_event(ees, CEVNT_BADDATE);
+ ees_reset(ees);
+ return;
+ }
+
+ n_sample = ees->nsamples;
+
+ /* Now, compute the reference time value: text -> tmp.l_ui */
+ if (!clocktime(ees->day, ees->hour, ees->minute, ees->second,
+ ees->tz, rbufp->recv_time.l_ui, &ees->yearstart,
+ &tmp.l_ui)) {
+ ees->baddata++;
+ ees->reason = CODEREASON + 13;
+ ees_event(ees, CEVNT_BADDATE);
+ ees_reset(ees);
+ return;
+ }
+ tmp.l_uf = 0;
+
+ /* DON'T use ees->arrvtime -- it may be < reftime */
+ ees->lastsampletime = tmp;
+
+ /* If we are synchronised to the radio, update the reference time.
+ * Also keep a note of when clock was last good.
+ */
+ if (istrue(cp[EESM_MSFOK])) {
+ ees->reftime = tmp;
+ ees->clocklastgood = current_time;
+ }
+
+
+ /* Compute the offset. For the fractional part of the
+ * offset we use the expected delay for the message.
+ */
+ ees->codeoffsets[n_sample].l_ui = tmp.l_ui;
+ ees->codeoffsets[n_sample].l_uf = 0;
+
+ /* Number of seconds since the last step */
+ sincelast = this_uisec - ees->last_step;
+
+ memset(&ppsclockev, 0, sizeof ppsclockev);
+
+ rc = ioctl(ees->io.fd, CIOGETEV, (char *) &ppsclockev);
+ if (debug & DB_PRINT_EV) fprintf(stderr,
+ "[%x] CIOGETEV u%d %d (%x %d) gave %d (%d): %08x %08x %d\n",
+ DB_PRINT_EV, ees->unit, ees->io.fd, CIOGETEV, is_pps(ees),
+ rc, errno, ptr[0], ptr[1], ptr[2]);
+
+ /* If we managed to get the time of arrival, process the info */
+ if (rc >= 0) {
+ int conv = -1;
+ pps_step = ppsclockev.serial - ees->last_pps_no;
+
+ /* Possible that PPS triggered, but text message didn't */
+ if (pps_step == 2) syslog(LOG_ERR, "pps step = 2 @ %02d", ees->second);
+ if (pps_step == 2 && ees->second == 1) suspect_4ms_step |= 1;
+ if (pps_step == 2 && ees->second == 2) suspect_4ms_step |= 4;
+
+ /* allow for single loss of PPS only */
+ if (pps_step != 1 && pps_step != 2)
+ fprintf(stderr, "PPS step: %d too far off %d (%d)\n",
+ ppsclockev.serial, ees->last_pps_no, pps_step);
+ else if (!buftvtots((char *) &(ppsclockev.tv), &pps_arrvstamp))
+ fprintf(stderr, "buftvtots failed\n");
+ else { /* if ((ABS(time difference) - 0.25) < 0)
+ * then believe it ...
+ */
+ l_fp diff;
+ diff = pps_arrvstamp;
+ conv = 0;
+ L_SUB(&diff, &ees->arrvtime);
+if (debug & DB_PRINT_CDT) printf("[%x] Have %x.%08x and %x.%08x -> %x.%08x @ %s",
+ DB_PRINT_CDT, ees->arrvtime.l_ui, ees->arrvtime.l_uf,
+ pps_arrvstamp.l_ui, pps_arrvstamp.l_uf,
+ diff.l_ui, diff.l_uf,
+ ctime(&(ppsclockev.tv.tv_sec)));
+ if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf);
+ L_SUB(&diff, &acceptable_slop);
+ if (L_ISNEG(&diff)) { /* AOK -- pps_sample */
+ ees->arrvtime = pps_arrvstamp;
+ conv++;
+ call_pps_sample++;
+ }
+ /* Some loss of some signals around sec = 1 */
+ else if (ees->second == 1) {
+ diff = pps_arrvstamp;
+ L_ADD(&diff, &onesec);
+ L_SUB(&diff, &ees->arrvtime);
+ if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf);
+ L_SUB(&diff, &acceptable_slop);
+syslog(LOG_ERR, "Have sec==1 slip %ds a=%08x-p=%08x -> %x.%08x (u=%d) %s",
+ pps_arrvstamp.l_ui - ees->arrvtime.l_ui,
+ pps_arrvstamp.l_uf,
+ ees->arrvtime.l_uf,
+ diff.l_ui, diff.l_uf,
+ ppsclockev.tv.tv_usec,
+ ctime(&(ppsclockev.tv.tv_sec)));
+ if (L_ISNEG(&diff)) { /* AOK -- pps_sample */
+ suspect_4ms_step |= 2;
+ ees->arrvtime = pps_arrvstamp;
+ L_ADD(&ees->arrvtime, &onesec);
+ conv++;
+ call_pps_sample++;
+ }
+ }
+ }
+ ees->last_pps_no = ppsclockev.serial;
+ if (debug & DB_PRINT_CDTC) printf(
+ "[%x] %08x %08x %d u%d (%d %d)\n",
+ DB_PRINT_CDTC, pps_arrvstamp.l_ui,
+ pps_arrvstamp.l_uf, conv, ees->unit,
+ call_pps_sample, pps_step);
+ }
+
+ /* See if there has been a 4ms jump at a minute boundry */
+ { l_fp delta;
+#define delta_isec delta.l_ui
+#define delta_ssec delta.l_i
+#define delta_sfsec delta.l_f
+ long delta_f_abs;
+
+ delta.l_i = ees->arrvtime.l_i;
+ delta.l_f = ees->arrvtime.l_f;
+
+ L_SUB(&delta, &ees->last_l);
+ delta_f_abs = delta_sfsec;
+ if (delta_f_abs < 0) delta_f_abs = -delta_f_abs;
+
+ /* Dump the deltas each minute */
+ if (debug & DB_DUMP_DELTAS)
+ { if (0 <= ees->second &&
+ ees->second < ((sizeof deltas) / (sizeof deltas[0]))) deltas[ees->second] = delta_sfsec;
+ /* Dump on second 1, as second 0 sometimes missed */
+ if (ees->second == 1) {
+ char text[16 * ((sizeof deltas) / (sizeof deltas[0]))];
+ char *ptr=text;
+ int i;
+ for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) {
+ sprintf(ptr, " %d.%04d",
+ msec(deltas[i]), subms(deltas[i]));
+ while (*ptr) ptr++;
+ }
+ syslog(LOG_ERR, "Deltas: %d.%04d<->%d.%04d: %s",
+ msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE),
+ msec(EES_STEP_F + EES_STEP_F_GRACE), subms(EES_STEP_F + EES_STEP_F_GRACE),
+ text+1);
+ for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) deltas[i] = 0;
+ }
+ }
+
+ /* Lets see if we have a 4 mS step at a minute boundaary */
+ if ( ((EES_STEP_F - EES_STEP_F_GRACE) < delta_f_abs) &&
+ (delta_f_abs < (EES_STEP_F + EES_STEP_F_GRACE)) &&
+ (ees->second == 0 || ees->second == 1 || ees->second == 2) &&
+ (sincelast < 0 || sincelast > 122)
+ ) { /* 4ms jump at min boundry */
+ int old_sincelast;
+ int count=0;
+ int sum = 0;
+ /* Yes -- so compute the ramp time */
+ if (ees->last_step == 0) sincelast = 0;
+ old_sincelast = sincelast;
+
+ /* First time in, just set "ees->last_step" */
+ if(ees->last_step) {
+ int other_step = 0;
+ int third_step = 0;
+ int this_step = (sincelast + (60 /2)) / 60;
+ int p_step = ees->this_step;
+ int p;
+ ees->last_steps[p_step] = this_step;
+ p= p_step;
+ p_step++;
+ if (p_step >= LAST_STEPS) p_step = 0;
+ ees->this_step = p_step;
+ /* Find the "average" interval */
+ while (p != p_step) {
+ int this = ees->last_steps[p];
+ if (this == 0) break;
+ if (this != this_step) {
+ if (other_step == 0 && (
+ this== (this_step +2) ||
+ this== (this_step -2) ||
+ this== (this_step +1) ||
+ this== (this_step -1)))
+ other_step = this;
+ if (other_step != this) {
+ int delta = (this_step - other_step);
+ if (delta < 0) delta = - delta;
+ if (third_step == 0 && (
+ (delta == 1) ? (
+ this == (other_step +1) ||
+ this == (other_step -1) ||
+ this == (this_step +1) ||
+ this == (this_step -1))
+ :
+ (
+ this == (this_step + other_step)/2
+ )
+ )) third_step = this;
+ if (third_step != this) break;
+ }
+ }
+ sum += this;
+ p--;
+ if (p < 0) p += LAST_STEPS;
+ count++;
+ }
+syslog(LOG_ERR, "MSF%d: %d: This=%d (%d), other=%d/%d, sum=%d, count=%d, pps_step=%d, suspect=%x", ees->unit, p, ees->last_steps[p], this_step, other_step, third_step, sum, count, pps_step, suspect_4ms_step);
+ if (count != 0) sum = ((sum * 60) + (count /2)) / count;
+#define SV(x) (ees->last_steps[(x + p_step) % LAST_STEPS])
+syslog(LOG_ERR, "MSF%d: %x steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ ees->unit, suspect_4ms_step, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6),
+ SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15));
+printf("MSF%d: steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ ees->unit, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6),
+ SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15));
+#undef SV
+ ees->jump_fsecs = delta_sfsec;
+ ees->using_ramp = 1;
+ if (sincelast > 170)
+ ees->last_step_late += sincelast - ((sum) ? sum : ees->last_step_secs);
+ else ees->last_step_late = 30;
+ if (ees->last_step_late < -60 || ees->last_step_late > 120) ees->last_step_late = 30;
+ if (ees->last_step_late < 0) ees->last_step_late = 0;
+ if (ees->last_step_late >= 60) ees->last_step_late = 59;
+ sincelast = 0;
+ }
+ else { /* First time in -- just save info */
+ ees->last_step_late = 30;
+ ees->jump_fsecs = delta_sfsec;
+ ees->using_ramp = 1;
+ sum = 4 * 60;
+ }
+ ees->last_step = this_uisec;
+printf("MSF%d: d=%3d.%04d@%d :%d:%d:$%d:%d:%d\n",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs);
+syslog(LOG_ERR, "MSF%d: d=%3d.%04d@%d :%d:%d:%d:%d:%d",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs);
+ if (sum) ees->last_step_secs = sum;
+ }
+ /* OK, so not a 4ms step at a minute boundry */
+ else {
+ if (suspect_4ms_step) syslog(LOG_ERR,
+ "MSF%d: suspect = %x, but delta of %d.%04d [%d.%04d<%d.%04d<%d.%04d: %d %d]",
+ ees->unit, suspect_4ms_step, msec(delta_sfsec), subms(delta_sfsec),
+ msec(EES_STEP_F - EES_STEP_F_GRACE),
+ subms(EES_STEP_F - EES_STEP_F_GRACE),
+ msec(delta_f_abs),
+ subms(delta_f_abs),
+ msec(EES_STEP_F + EES_STEP_F_GRACE),
+ subms(EES_STEP_F + EES_STEP_F_GRACE),
+ ees->second,
+ sincelast);
+ if ((delta_f_abs > EES_STEP_NOTE) && ees->last_l.l_i) {
+ static ees_step_notes = EES_STEP_NOTES;
+ if (ees_step_notes > 0) {
+ ees_step_notes--;
+printf("MSF%d: D=%3d.%04d@%02d :%d%s\n",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, sincelast, ees_step_notes ? "" : " -- NO MORE !");
+syslog(LOG_ERR, "MSF%d: D=%3d.%04d@%02d :%d%s",
+ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, (ees->last_step) ? sincelast : -1, ees_step_notes ? "" : " -- NO MORE !");
+ }
+ }
+ }
+ }
+ ees->last_l = ees->arrvtime;
+
+ /* IF we have found that it's ramping
+ * && it's within twice the expected ramp period
+ * && there is a non zero step size (avoid /0 !)
+ * THEN we twiddle things
+ */
+ if (ees->using_ramp &&
+ sincelast < (ees->last_step_secs)*2 &&
+ ees->last_step_secs)
+ { long sec_of_ramp = sincelast + ees->last_step_late;
+ long fsecs;
+ l_fp inc;
+
+ /* Ramp time may vary, so may ramp for longer than last time */
+ if (sec_of_ramp > (ees->last_step_secs + 120))
+ sec_of_ramp = ees->last_step_secs;
+
+ /* sec_of_ramp * ees->jump_fsecs may overflow 2**32 */
+ fsecs = sec_of_ramp * (ees->jump_fsecs / ees->last_step_secs);
+
+ if (debug & DB_LOG_DELTAS) syslog(LOG_ERR,
+ "[%x] MSF%d: %3d/%03d -> d=%11d (%d|%d)",
+ DB_LOG_DELTAS,
+ ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
+ pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
+ if (debug & DB_PRINT_DELTAS) printf(
+ "MSF%d: %3d/%03d -> d=%11d (%d|%d)\n",
+ ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
+ pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
+
+ /* Must sign extend the result */
+ inc.l_i = (fsecs < 0) ? -1 : 0;
+ inc.l_f = fsecs;
+ if (debug & DB_INC_PPS)
+ { L_SUB(&pps_arrvstamp, &inc);
+ L_SUB(&ees->arrvtime, &inc);
+ }
+ else
+ { L_ADD(&pps_arrvstamp, &inc);
+ L_ADD(&ees->arrvtime, &inc);
+ }
+ }
+ else {
+ if (debug & DB_LOG_DELTAS) syslog(LOG_ERR,
+ "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x",
+ DB_LOG_DELTAS,
+ ees->unit, ees->using_ramp,
+ sincelast,
+ (ees->last_step_secs)*2,
+ ees->last_step_secs);
+ if (debug & DB_PRINT_DELTAS) printf(
+ "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x\n",
+ DB_LOG_DELTAS,
+ ees->unit, ees->using_ramp,
+ sincelast,
+ (ees->last_step_secs)*2,
+ ees->last_step_secs);
+ }
+
+ L_SUB(&ees->arrvtime, &offset_fudge[ees->unit]);
+ L_SUB(&pps_arrvstamp, &offset_fudge[ees->unit]);
+
+ if (call_pps_sample && !(debug & DB_NO_PPS)) {
+ /* Sigh -- it expects its args negated */
+ L_NEG(&pps_arrvstamp);
+ (void) pps_sample(&pps_arrvstamp);
+ }
+
+ /* Subtract off the local clock time stamp */
+ L_SUB(&ees->codeoffsets[n_sample], &ees->arrvtime);
+ if (debug & DB_LOG_SAMPLES) syslog(LOG_ERR,
+ "MSF%d: [%x] %d (ees: %d %d) (pps: %d %d)%s",
+ ees->unit, DB_LOG_DELTAS, n_sample,
+ ees->codeoffsets[n_sample].l_f,
+ ees->codeoffsets[n_sample].l_f / 4295,
+ pps_arrvstamp.l_f,
+ pps_arrvstamp.l_f /4295,
+ (debug & DB_NO_PPS) ? " [no PPS]" : "");
+
+ if (ees->nsamples++ == NCODES-1) ees_process(ees);
+
+ /* Done! */
+}
+
+
+static void set_x(fp_offset)
+l_fp *fp_offset;
+{
+ step_systime_real(fp_offset);
+}
+
+
+/* offcompare - auxiliary comparison routine for offset sort */
+
+static int
+offcompare(a, b)
+l_fp *a, *b;
+{
+ return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);
+}
+
+
+/* ees_process - process a pile of samples from the clock */
+static void ees_process(ees)
+ struct eesunit *ees;
+{
+ static last_samples = -1;
+ register int i, j;
+ register int noff;
+ register l_fp *coffs = ees->codeoffsets;
+ l_fp offset, tmp;
+ u_fp dispersion; /* ++++ */
+ int lostsync, isinsync;
+ int samples = ees->nsamples;
+ int samplelog;
+ int samplereduce = (samples + 1) / 2;
+
+ /* Reset things to zero so we don't have to worry later */
+ ees_reset(ees);
+
+ if (sloppyclockflag[ees->unit]) {
+ samplelog = (samples < 2) ? 0 :
+ (samples < 5) ? 1 :
+ (samples < 9) ? 2 :
+ (samples < 17) ? 3 :
+ (samples < 33) ? 4 : 5;
+ samplereduce = (1 << samplelog);
+ }
+
+ if (samples != last_samples &&
+ ((samples != (last_samples-1)) || samples < 3)) {
+ syslog(LOG_ERR, "Samples=%d (%d), samplereduce=%d ....",
+ samples, last_samples, samplereduce);
+ last_samples = samples;
+ }
+ if (samples < 1) return;
+
+ /* If requested, dump the raw data we have in the buffer */
+ if (ees->dump_vals) dump_buf(coffs, 0, samples, "Raw data is:");
+
+ /* Sort the offsets, trim off the extremes, then choose one. */
+ qsort((char *) coffs, samples, sizeof(l_fp), offcompare);
+
+ noff = samples;
+ i = 0;
+ while ((noff - i) > samplereduce) {
+ /* Trim off the sample which is further away
+ * from the median. We work this out by doubling
+ * the median, subtracting off the end samples, and
+ * looking at the sign of the answer, using the
+ * identity (c-b)-(b-a) == 2*b-a-c
+ */
+ tmp = coffs[(noff + i)/2];
+ L_ADD(&tmp, &tmp);
+ L_SUB(&tmp, &coffs[i]);
+ L_SUB(&tmp, &coffs[noff-1]);
+ if (L_ISNEG(&tmp)) noff--; else i++;
+ }
+
+ /* If requested, dump the reduce data we have in the buffer */
+ if (ees->dump_vals) dump_buf(coffs, i, noff, "Reduced to:");
+
+ /* What we do next depends on the setting of the sloppy clock flag.
+ * If it is on, average the remainder to derive our estimate.
+ * Otherwise, just pick a representative value from the remaining stuff
+ */
+ if (sloppyclockflag[ees->unit]) {
+ offset.l_ui = offset.l_uf = 0;
+ for (j = i; j < noff; j++)
+ L_ADD(&offset, &coffs[j]);
+ for (j = samplelog; j > 0; j--)
+ L_RSHIFTU(&offset);
+ }
+ else offset = coffs[i+BESTSAMPLE];
+
+ /* Compute the dispersion as the difference between the
+ * lowest and highest offsets that remain in the
+ * consideration list.
+ *
+ * It looks like MOST clocks have MOD (max error), so halve it !
+ */
+ tmp = coffs[noff-1];
+ L_SUB(&tmp, &coffs[i]);
+#define FRACT_SEC(n) ((1 << 30) / (n/2))
+ dispersion = LFPTOFP(&tmp) / 2; /* ++++ */
+ if (debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE)) syslog(
+ (debug & DB_SYSLOG_SMPLE) ? LOG_ERR : LOG_INFO,
+ "I: [%x] Offset=%06d (%d), disp=%06d%s [%d], %d %d=%d %d:%d %d=%d %d",
+ debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE),
+ offset.l_f / 4295, offset.l_f,
+ (dispersion * 1526) / 100,
+ (sloppyclockflag[ees->unit]) ? " by averaging" : "",
+ FRACT_SEC(10) / 4295,
+ (coffs[0].l_f) / 4295,
+ i,
+ (coffs[i].l_f) / 4295,
+ (coffs[samples/2].l_f) / 4295,
+ (coffs[i+BESTSAMPLE].l_f) / 4295,
+ noff-1,
+ (coffs[noff-1].l_f) / 4295,
+ (coffs[samples-1].l_f) / 4295);
+
+ /* Are we playing silly wotsits ?
+ * If we are using all data, see if there is a "small" delta,
+ * and if so, blurr this with 3/4 of the delta from the last value
+ */
+ if (ees->usealldata && ees->offset.l_uf) {
+ long diff = (long) (ees->offset.l_uf - offset.l_uf);
+
+ /* is the delta small enough ? */
+ if ((- FRACT_SEC(100)) < diff && diff < FRACT_SEC(100)) {
+ int samd = (64 * 4) / samples;
+ long new;
+ if (samd < 2) samd = 2;
+ new = offset.l_uf + ((diff * (samd -1)) / samd);
+
+ /* Sign change -> need to fix up int part */
+ if ((new & (1 << 31)) !=
+ (((long) offset.l_uf) & ( 1 << 31)))
+ { syslog(LOG_INFO, "I: %x != %x (%x %x), so add %d",
+ new & (1 << 31),
+ ((long) offset.l_uf) & ( 1 << 31),
+ new, (long) offset.l_uf,
+ (new < 0) ? -1 : 1);
+ offset.l_ui += (new < 0) ? -1 : 1;
+ }
+ dispersion /= 4;
+ if (debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE)) syslog(
+ (debug & DB_SYSLOG_SMTHE) ? LOG_ERR : LOG_INFO,
+ "I: [%x] Smooth data: %d -> %d, dispersion now %d",
+ debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE),
+ ((long) offset.l_uf) / 4295, new / 4295,
+ (dispersion * 1526) / 100);
+ offset.l_uf = (unsigned long) new;
+ }
+ else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) syslog(
+ (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
+ "[%x] No smooth as delta not %d < %d < %d",
+ debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
+ - FRACT_SEC(100), diff, FRACT_SEC(100));
+ }
+ else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) syslog(
+ (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
+ "I: [%x] No smooth as flag=%x and old=%x=%d (%d:%d)",
+ debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
+ ees->usealldata, ees->offset.l_f, ees->offset.l_uf,
+ offset.l_f, ees->offset.l_f - offset.l_f);
+
+ /* Collect offset info for debugging info */
+ ees->offset = offset;
+ ees->lowoffset = coffs[i];
+ ees->highoffset = coffs[noff-1];
+
+ /* Determine synchronization status. Can be unsync'd either
+ * by a report from the clock or by a leap hold.
+ *
+ * Loss of the radio signal for a short time does not cause
+ * us to go unsynchronised, since the receiver keeps quite
+ * good time on its own. The spec says 20ms in 4 hours; the
+ * observed drift in our clock (Cambridge) is about a second
+ * a day, but even that keeps us within the inherent tolerance
+ * of the clock for about 15 minutes. Observation shows that
+ * the typical "short" outage is 3 minutes, so to allow us
+ * to ride out those, we will give it 5 minutes.
+ */
+ lostsync = current_time - ees->clocklastgood > 300 ? 1 : 0;
+ isinsync = (lostsync || ees->leaphold > current_time) ? 0 : 1;
+
+ /* Done. Use time of last good, synchronised code as the
+ * reference time, and lastsampletime as the receive time.
+ */
+ if (ees->fix_pending) {
+ syslog(LOG_ERR, "MSF%d: fix_pending=%d -> jump %x.%08x\n",
+ ees->fix_pending, ees->unit, offset.l_i, offset.l_f);
+ ees->fix_pending = 0;
+ set_x(&offset);
+ L_CLR(&offset);
+ }
+ refclock_receive(ees->peer,
+ &offset,
+ 0, /* delay */
+ dispersion,
+ &ees->reftime,
+ &ees->lastsampletime, /* receive time */
+ (isinsync) ? 0 : LEAP_NOTINSYNC);
+ ees_event(ees, lostsync ? CEVNT_PROP : CEVNT_NOMINAL);
+}
+
+/* msfees_poll - called by the transmit procedure */
+static void msfees_poll(unit, peer)
+ int unit;
+ char *peer;
+{
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d invalid",
+ unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d unused",
+ unit);
+ return;
+ }
+
+ ees_process(eesunits[unit]);
+
+ if ((current_time - eesunits[unit]->lasttime) > 150)
+ ees_event(eesunits[unit], CEVNT_FAULT);
+}
+
+/* msfees_leap - called when a leap second occurs */
+static void msfees_leap()
+{
+ register int i;
+
+ /* This routine should be entered a few seconds after
+ * midnight UTC when a leap second occurs. To ensure we
+ * don't believe foolish time from the clock(s) we set a
+ * 40 minute hold on them. It shouldn't take anywhere
+ * near this amount of time to adjust if the clock is getTING
+ * data, but doing anything else is complicated.
+ */
+ for (i = 0; i < MAXUNITS; i++) if (unitinuse[i])
+ eesunits[i]->leaphold = current_time + EESLEAPHOLD;
+}
+
+/* msfees_control - set fudge factors, return statistics */
+static void msfees_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct eesunit *ees = eesunits[unit];
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock: unit %d invalid (max %d)",
+ unit, MAXUNITS-1);
+ return;
+ }
+
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ fudgefactor[unit] = in->fudgetime1;
+ if (in->haveflags & CLK_HAVETIME2)
+ os_delay[unit] = in->fudgetime2;
+ offset_fudge[unit] = os_delay[unit];
+ L_ADD(&offset_fudge[unit], &fudgefactor[unit]);
+ L_ADD(&offset_fudge[unit], &inherent_delay[unit]);
+ if (in->haveflags & CLK_HAVEVAL1) {
+ stratumtouse[unit] = (u_char)(in->fudgeval1 & 0xf);
+ if (unitinuse[unit]) {
+ /* Should actually reselect clock, but
+ * will wait for the next timecode
+ */
+ struct peer *peer = ees->peer;
+ peer->stratum = stratumtouse[unit];
+ if (stratumtouse[unit] <= 1) {
+ memmove((char *)&peer->refid,
+ EESREFID, 4);
+ if (unit>0 && unit<10)
+ ((char *)&peer->refid)[3] =
+ '0' + unit;
+ }
+ else peer->refid = htonl(EESHSREFID);
+ }
+ }
+ if (in->haveflags & CLK_HAVEVAL2) {
+ printf("Debug: %x -> %x\n", debug, in->fudgeval2);
+ syslog(LOG_ERR, "MSF%d: debug %x -> %x",
+ unit, debug, in->fudgeval2);
+ debug = in->fudgeval2;
+ }
+ if (in->haveflags & CLK_HAVEFLAG1) {
+ sloppyclockflag[unit] = in->flags & CLK_FLAG1;
+ }
+ if (in->haveflags & CLK_HAVEFLAG2) {
+ ees->fix_pending++;
+ /* if (in->flags & CLK_FLAG2 && unitinuse[unit])
+ ees->leaphold = 0; */
+ }
+ if (in->haveflags & CLK_HAVEFLAG3 && unitinuse[unit]) {
+ printf("dump_vals: %x -> %x\n", ees->dump_vals, in->flags & CLK_FLAG3);
+ ees->dump_vals = in->flags & CLK_FLAG3;
+ }
+ if (in->haveflags & CLK_HAVEFLAG4 && unitinuse[unit]) {
+ ees->usealldata = in->flags & CLK_FLAG4;
+ }
+ }
+
+ if (out != 0) {
+ out->type = REFCLK_MSF_EES;
+ out->haveflags
+ = CLK_HAVETIME1|CLK_HAVETIME2|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1|CLK_HAVEFLAG3|CLK_HAVEFLAG4;
+ out->clockdesc = EESDESCRIPTION;
+ out->fudgetime1 = fudgefactor[unit];
+ out->fudgetime2 = os_delay[unit];
+ out->fudgeval1 = (long)stratumtouse[unit];
+ /*out->fudgeval2= debug*/;
+ memmove((char *)&out->fudgeval2, EESREFID, 4);
+ if (unit > 0 && unit < 10)
+ ((char *)&out->fudgeval2)[3] = '0' + unit;
+ out->flags = sloppyclockflag[unit];
+ if (unitinuse[unit]) {
+ out->flags |= ees->dump_vals | ees->usealldata;
+ out->lencode = ees->lencode;
+ out->lastcode = ees->lastcode;
+ out->timereset = current_time - ees->timestarted;
+ out->polls = 0; /* we don't poll */
+ out->noresponse = 0; /* ditto */
+ out->badformat = ees->badformat;
+ out->baddata = ees->baddata;
+ out->lastevent = ees->lastevent;
+ out->currentstatus = ees->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;
+ }
+ }
+}
+
+
+/* msfees_buginfo - return clock dependent debugging info */
+static void msfees_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct eesunit *ees;
+
+ bug->nvalues = bug->ntimes = 0;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "ees clock: unit %d invalid (max %d)",
+ unit, MAXUNITS-1);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ ees = eesunits[unit];
+
+ bug->nvalues = 16;
+ bug->svalues = 0x0800;
+ bug->values[0] = (ees->lasttime) ? current_time - ees->lasttime : 0;
+ bug->values[1] = (ees->clocklastgood)?current_time-ees->clocklastgood:0;
+ bug->values[2] = (u_long)ees->status;
+ bug->values[3] = (u_long)ees->lastevent;
+ bug->values[4] = (u_long)ees->reason;
+ bug->values[5] = (u_long)ees->nsamples;
+ bug->values[6] = (u_long)ees->codestate;
+ bug->values[7] = (u_long)ees->day;
+ bug->values[8] = (u_long)ees->hour;
+ bug->values[9] = (u_long)ees->minute;
+ bug->values[10] = (u_long)ees->second;
+ bug->values[11] = (u_long)ees->tz;
+ bug->values[12] = ees->yearstart;
+ bug->values[13] = (ees->leaphold > current_time) ?
+ ees->leaphold - current_time : 0;
+ bug->values[14] = inherent_delay[unit].l_uf;
+ bug->values[15] = offset_fudge[unit].l_uf;
+
+ bug->ntimes = 11;
+ bug->stimes = 0x3f8;
+ bug->times[0] = ees->reftime;
+ bug->times[1] = ees->arrvtime;
+ bug->times[2] = ees->lastsampletime;
+ bug->times[3] = ees->offset;
+ bug->times[4] = ees->lowoffset;
+ bug->times[5] = ees->highoffset;
+ bug->times[6] = inherent_delay[unit];
+ bug->times[8] = os_delay[unit];
+ bug->times[7] = fudgefactor[unit];
+ bug->times[9] = offset_fudge[unit];
+ bug->times[10].l_ui = ees->yearstart;
+ bug->times[10].l_uf = 0;
+}
+
+struct refclock refclock_msfees = {
+ msfees_start, msfees_shutdown, msfees_poll,
+ msfees_control, msfees_init, msfees_buginfo, NOFLAGS
+};
+#endif /* defined(REFCLOCK) && defined(MSFEESPPS) && defined(STREAM) */
diff --git a/usr.sbin/xntpd/xntpd/refclock_old/refclock_mx4200.c b/usr.sbin/xntpd/xntpd/refclock_old/refclock_mx4200.c
new file mode 100644
index 000000000000..7cfa3cf0326b
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_old/refclock_mx4200.c
@@ -0,0 +1,1342 @@
+/*
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66.
+ *
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(REFCLOCK) && (defined(MX4200) || defined(MX4200CLK) || defined(MX4200PPS))
+
+#if !defined(lint) && !defined(__GNUC__)
+static char rcsid[] =
+ "@(#) /src/master/xntp-930612/xntpd/refclock_mx4200.c,v 1.5 1993/06/18 21:19:54 jbj Exp (LBL) ";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_calendar.h"
+#include "ntp_unixtime.h"
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(MX4200CLK)
+#include <sys/clkdefs.h>
+#endif /* MX4200CLK */
+#endif /* STREAM */
+
+#include <sys/ppsclock.h>
+
+#include "mx4200.h"
+#include "ntp_stdlib.h"
+
+/*
+ * This driver supports the Magnavox Model MX4200 GPS Receiver.
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 2 /* max number of mx4200 units */
+#define MX4200232 "/dev/gps%d"
+#define SPEED232 B4800 /* baud */
+
+/*
+ * The number of raw samples which we acquire to derive a single estimate.
+ */
+#define NSTAMPS 64
+
+/*
+ * Radio interface parameters
+ */
+#define MX4200PRECISION (-18) /* precision assumed (about 4 us) */
+#define MX4200REFID "GPS" /* reference id */
+#define MX4200DESCRIPTION "Magnavox MX4200 GPS Receiver" /* who we are */
+#define DEFFUDGETIME 0 /* default fudge time (ms) */
+
+/* Leap stuff */
+extern U_LONG leap_hoursfromleap;
+extern U_LONG leap_happened;
+static int leap_debug;
+
+/*
+ * mx4200_reset - reset the count back to zero
+ */
+#define mx4200_reset(mx4200) \
+ do { \
+ (mx4200)->nsamples = 0; \
+ } while (0)
+
+/*
+ * mx4200_event - record and report an event
+ */
+#define mx4200_event(mx4200, evcode) \
+ do { \
+ if ((mx4200)->status != (u_char)(evcode)) \
+ mx4200_report_event((mx4200), (evcode)); \
+ } while (0)
+
+/*
+ * Imported from the timer module
+ */
+extern U_LONG current_time;
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * MX4200 unit control structure.
+ */
+struct mx4200unit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ U_LONG gpssamples[NSTAMPS]; /* the GPS time samples */
+ l_fp unixsamples[NSTAMPS]; /* the UNIX time samples */
+
+
+ l_fp lastsampletime; /* time of last estimate */
+ u_int lastserial; /* last pps serial number */
+#ifdef notdef
+ l_fp lastrec; /* last receive time */
+ l_fp lastref; /* last timecode time */
+#endif
+ char lastcode[RX_BUFF_SIZE]; /* last timecode received */
+ U_LONG lasttime; /* last time clock heard from */
+ u_char nsamples; /* number of samples we've collected */
+ 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 lencode; /* length of last timecode */
+ u_char year; /* year of eternity */
+ u_short monthday; /* day of month */
+ u_char hour; /* hour of day */
+ u_char minute; /* minute of hour */
+ u_char second; /* seconds of minute */
+ u_char leap; /* leap indicators */
+ /*
+ * Status tallies
+ */
+#ifdef notdef
+ U_LONG polls; /* polls sent */
+ U_LONG noresponse; /* number of nonresponses */
+#endif
+ U_LONG badformat; /* bad format */
+ U_LONG baddata; /* bad data */
+ U_LONG timestarted; /* time we started this */
+};
+
+/*
+ * We demand that consecutive PPS samples are more than 0.995 seconds
+ * and less than 1.005 seconds apart.
+ */
+#define PPSLODIFF_UI 0 /* 0.900 as an l_fp */
+#define PPSLODIFF_UF 0xe6666610
+
+#define PPSHIDIFF_UI 1 /* 1.100 as an l_fp */
+#define PPSHIDIFF_UF 0x19999990
+
+/*
+ * reason codes
+ */
+#define PPSREASON 20
+#define CODEREASON 40
+#define PROCREASON 60
+
+/*
+ * Data space for the unit structures. Note that we allocate these on
+ * the fly, but never give them back.
+ */
+static struct mx4200unit *mx4200units[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];
+static U_LONG refid[MAXUNITS];
+
+static const char pmvxg[] = "PMVXG";
+
+/*
+ * Function prototypes
+ */
+static void mx4200_init P((void));
+static int mx4200_start P((u_int, struct peer *));
+static void mx4200_shutdown P((int));
+static void mx4200_receive P((struct recvbuf *));
+static void mx4200_process P((struct mx4200unit *));
+static void mx4200_report_event P((struct mx4200unit *, int));
+static void mx4200_poll P((int, struct peer *));
+static void mx4200_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void mx4200_buginfo P((int, struct refclockbug *));
+
+static char * mx4200_parse P((char *, struct calendar *, int *, int *));
+static int mx4200_needconf P((char *));
+static void mx4200_config P((struct mx4200unit *));
+static void mx4200_send P((int, const char *, ...));
+static int mx4200_cmpl_fp P((void *, void *));
+static u_char cksum P((char *, u_int));
+
+#ifdef DEBUG
+static void opendfile P((int));
+static void checkdfile P((void));
+#endif /* DEBUG */
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_mx4200 = {
+ mx4200_start, mx4200_shutdown, mx4200_poll,
+ mx4200_control, mx4200_init, mx4200_buginfo, NOFLAGS
+};
+
+/*
+ * mx4200_init - initialize internal mx4200 driver data
+ */
+static void
+mx4200_init()
+{
+ register int i;
+ /*
+ * Just zero the data arrays
+ */
+ memset((char *)mx4200units, 0, sizeof mx4200units);
+ 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 = DEFFUDGETIME;
+ stratumtouse[i] = 0;
+ sloppyclockflag[i] = 0;
+ memcpy((char *)&refid[i], MX4200REFID, 4);
+ }
+}
+
+#ifdef DEBUG
+static char dfile[] = "/var/tmp/MX4200.debug";
+static FILE *df = NULL;
+
+static void
+opendfile(create)
+ int create;
+{
+ if (!create && access(dfile, F_OK) < 0) {
+ syslog(LOG_ERR, "mx4200: open %s: %m", dfile);
+ return;
+ }
+ df = fopen(dfile, "a");
+ if (df == NULL)
+ syslog(LOG_ERR, "mx4200: open %s: %m", dfile);
+ else if (setvbuf(df, NULL, _IOLBF, 0) < 0)
+ syslog(LOG_ERR, "mx4200: setvbuf %s: %m", dfile);
+}
+
+static void
+checkdfile()
+{
+
+ if (df == NULL)
+ return;
+
+ if (access(dfile, F_OK) < 0) {
+ fclose(df);
+ opendfile(1);
+ }
+}
+
+#endif
+
+
+/*
+ * mx4200_start - open the MX4200 devices and initialize data for processing
+ */
+static int
+mx4200_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct mx4200unit *mx4200;
+ register int i;
+ int fd232;
+ char mx4200dev[20];
+
+ /*
+ * Check configuration info
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "mx4200_start: unit %d invalid", unit);
+ return (0);
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "mx4200_start: unit %d in use", unit);
+ return (0);
+ }
+
+ /*
+ * Open serial port
+ */
+ (void) sprintf(mx4200dev, MX4200232, unit);
+ fd232 = open(mx4200dev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR,
+ "mx4200_start: open of %s: %m", mx4200dev);
+ 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,
+ "mx4200_start: ioctl(%s, TCGETA): %m", mx4200dev);
+ 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,
+ "mx4200_start: ioctl(%s, TCSETA): %m", mx4200dev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(HAVE_TERMIOS)
+ /*
+ * POSIX serial line parameters (termios interface)
+ *
+ * The MX4200CLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The MX4200PPS 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,
+ "mx4200_start: tcgetattr(%s): %m", mx4200dev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ 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,
+ "mx4200_start: tcsetattr(%s): %m", mx4200dev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "mx4200_start: tcflush(%s): %m", mx4200dev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_TERMIOS */
+#ifdef STREAM
+#if defined(MX4200CLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "mx4200_start: ioctl(%s, I_PUSH, clk): %m", mx4200dev);
+ if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
+ syslog(LOG_ERR,
+ "mx4200_start: ioctl(%s, CLK_SETSTR): %m", mx4200dev);
+#endif /* MX4200CLK */
+#if defined(MX4200PPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "mx4200_start: ioctl(%s, I_PUSH, ppsclock): %m", mx4200dev);
+ else
+ fdpps = fd232;
+#endif /* MX4200PPS */
+#endif /* STREAM */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The MX4200CLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(MX4200CLK)
+ int ldisc = CLKLDISC;
+#endif /* MX4200CLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "mx4200_start: ioctl(%s, TIOCGETP): %m", mx4200dev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(MX4200CLK)
+ 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 /* MX4200CLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "mx4200_start: ioctl(%s, TIOCSETP): %m", mx4200dev);
+ goto screwed;
+ }
+#if defined(MX4200CLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "mx4200_start: ioctl(%s, TIOCSETD): %m",mx4200dev);
+ goto screwed;
+ }
+#endif /* MX4200CLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Allocate unit structure
+ */
+ if (mx4200units[unit] != 0) {
+ mx4200 = mx4200units[unit]; /* The one we want is okay */
+ } else {
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && mx4200units[i] != 0)
+ break;
+ }
+ if (i < MAXUNITS) {
+ /*
+ * Reclaim this one
+ */
+ mx4200 = mx4200units[i];
+ mx4200units[i] = 0;
+ } else {
+ mx4200 = (struct mx4200unit *)
+ emalloc(sizeof(struct mx4200unit));
+ }
+ }
+
+ memset((char *)mx4200, 0, sizeof(struct mx4200unit));
+ mx4200units[unit] = mx4200;
+
+ /*
+ * Set up the structures
+ */
+ mx4200->peer = peer;
+ mx4200->unit = (u_char)unit;
+ mx4200->timestarted = current_time;
+
+ mx4200->io.clock_recv = mx4200_receive;
+ mx4200->io.srcclock = (caddr_t)mx4200;
+ mx4200->io.datalen = 0;
+ mx4200->io.fd = fd232;
+ if (!io_addclock(&mx4200->io))
+ goto screwed;
+
+ /*
+ * All done. Initialize a few random peer variables, then
+ * return success.
+ */
+ peer->precision = MX4200PRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ unitinuse[unit] = 1;
+
+ /* Insure the receiver is properly configured */
+ mx4200_config(mx4200);
+
+#ifdef DEBUG
+ opendfile(0);
+#endif
+ return (1);
+
+ /*
+ * Something broke; abandon ship
+ */
+screwed:
+ (void) close(fd232);
+ return (0);
+}
+
+/*
+ * mx4200_shutdown - shut down a MX4200 clock
+ */
+static void
+mx4200_shutdown(unit)
+ int unit;
+{
+ register struct mx4200unit *mx4200;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "mx4200_shutdown: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "mx4200_shutdown: unit %d not in use", unit);
+ return;
+ }
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ mx4200 = mx4200units[unit];
+ io_closeclock(&mx4200->io);
+ unitinuse[unit] = 0;
+}
+
+static void
+mx4200_config(mx4200)
+ register struct mx4200unit *mx4200;
+{
+ register int fd = mx4200->io.fd;
+
+syslog(LOG_DEBUG, "mx4200_config");
+
+ /* Zero the output list (do it twice to flush possible junk) */
+ mx4200_send(fd, "%s,%03d,,%d,,,,,,", pmvxg, PMVXG_S_PORTCONF, 1);
+ mx4200_send(fd, "%s,%03d,,%d,,,,,,", pmvxg, PMVXG_S_PORTCONF, 1);
+
+ /* Switch to 2d mode */
+ mx4200_send(fd, "%s,%03d,%d,,%.1f,%.1f,,%d,%d,%c,%d",
+ pmvxg, PMVXG_S_INITMODEB,
+ 2, /* 2d mode */
+ 0.1, /* hor accel fact as per Steve */
+ 0.1, /* ver accel fact as per Steve */
+ 10, /* hdop limit as per Steve */
+ 5, /* elevation limit as per Steve */
+ 'U', /* time output mode */
+ 0); /* local time offset from gmt */
+
+ /* Configure time recovery */
+ mx4200_send(fd, "%s,%03d,%c,%c,%c,%d,%d,%d,",
+ pmvxg, PMVXG_S_TRECOVCONF,
+#ifdef notdef
+ 'K', /* known position */
+ 'D', /* dynamic position */
+#else
+ 'S', /* static position */
+#endif
+ 'U', /* steer clock to gps time */
+ 'A', /* always output time pulse */
+ 500, /* max time error in ns */
+ 0, /* user bias in ns */
+ 1); /* output to control port */
+}
+
+/*
+ * mx4200_report_event - note the occurrence of an event
+ */
+static void
+mx4200_report_event(mx4200, code)
+ struct mx4200unit *mx4200;
+ int code;
+{
+ struct peer *peer;
+
+ peer = mx4200->peer;
+ if (mx4200->status != (u_char)code) {
+ mx4200->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ mx4200->lastevent = (u_char)code;
+ syslog(LOG_INFO,
+ "mx4200 clock %s event %x", ntoa(&peer->srcadr), code);
+ }
+}
+
+/*
+ * mx4200_poll - mx4200 watchdog routine
+ */
+static void
+mx4200_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct mx4200unit *mx4200;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "mx4200_poll: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "mx4200_poll: unit %d not used", unit);
+ return;
+ }
+
+ mx4200 = mx4200units[unit];
+ if ((current_time - mx4200->lasttime) > 150) {
+ mx4200_event(mx4200, CEVNT_FAULT);
+
+ /* Request a status message which should trigger a reconfig */
+ mx4200_send(mx4200->io.fd, "%s,%03d", "CDGPQ", PMVXG_D_STATUS);
+ syslog(LOG_DEBUG, "mx4200_poll: request status");
+ }
+}
+
+static const char char2hex[] = "0123456789ABCDEF";
+
+/*
+ * mx4200_receive - receive gps data
+ */
+static void
+mx4200_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register struct mx4200unit *mx4200;
+ register char *dpt, *cp;
+ register U_LONG tmp_ui;
+ register U_LONG tmp_uf;
+ register U_LONG gpstime;
+ struct ppsclockev ev;
+ register struct calendar *jt;
+ struct calendar sjt;
+ register int n;
+ int valid, leapsec;
+ register u_char ck;
+
+ mx4200 = (struct mx4200unit *)rbufp->recv_srcclock;
+
+#ifdef DEBUG
+ if (debug > 3)
+ printf("mx4200_receive: nsamples = %d\n", mx4200->nsamples);
+#endif
+
+ /* Record the time of this event */
+ mx4200->lasttime = current_time;
+
+ /* Get the pps value */
+ if (ioctl(mx4200->io.fd, CIOGETEV, (char *)&ev) < 0) {
+ /* XXX Actually, if this fails, we're pretty much screwed */
+#ifdef DEBUG
+ if (debug) {
+ fprintf(stderr, "mx4200_receive: ");
+ perror("CIOGETEV");
+ }
+#endif
+ mx4200->reason = PPSREASON + 1;
+ mx4200_event(mx4200, CEVNT_FAULT);
+ mx4200_reset(mx4200);
+ return;
+ }
+ tmp_ui = ev.tv.tv_sec + (U_LONG)JAN_1970;
+ TVUTOTSF(ev.tv.tv_usec, tmp_uf);
+
+ /* Get buffer and length; sock away last timecode */
+ n = rbufp->recv_length;
+ dpt = rbufp->recv_buffer;
+ if (n <= 1)
+ return;
+ mx4200->lencode = n;
+ memmove(mx4200->lastcode, dpt, n);
+
+ /*
+ * We expect to see something like:
+ *
+ * $PMVXG,830,T,1992,07,09,04:18:34,U,S,-02154,00019,000000,00*1D\n
+ *
+ * Reject if any important landmarks are missing.
+ */
+ cp = dpt + n - 4;
+ if (cp < dpt || *dpt != '$' || cp[0] != '*' || cp[3] != '\n') {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: bad format\n");
+#endif
+ mx4200->badformat++;
+ mx4200->reason = PPSREASON + 2;
+ mx4200_event(mx4200, CEVNT_BADREPLY);
+ mx4200_reset(mx4200);
+ return;
+ }
+
+ /* Check checksum */
+ ck = cksum(&dpt[1], n - 5);
+ if (char2hex[ck >> 4] != cp[1] || char2hex[ck & 0xf] != cp[2]) {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: bad checksum\n");
+#endif
+ mx4200->badformat++;
+ mx4200->reason = PPSREASON + 3;
+ mx4200_event(mx4200, CEVNT_BADREPLY);
+ mx4200_reset(mx4200);
+ return;
+ }
+
+ /* Truncate checksum (and the buffer for that matter) */
+ *cp = '\0';
+
+ /* Leap second debugging stuff */
+ if ((leap_hoursfromleap && !leap_happened) || leap_debug > 0) {
+ /* generate reports for awhile after leap */
+ if (leap_hoursfromleap && !leap_happened)
+ leap_debug = 3600;
+ else
+ --leap_debug;
+ syslog(LOG_INFO, "mx4200 leap: %s \"%s\"",
+ umfptoa(tmp_ui, tmp_uf, 6), dpt);
+ }
+
+ /* Parse time recovery message */
+ jt = &sjt;
+ if ((cp = mx4200_parse(dpt, jt, &valid, &leapsec)) != NULL) {
+ /* Configure the receiver if necessary */
+ if (mx4200_needconf(dpt))
+ mx4200_config(mx4200);
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: mx4200_parse: %s\n", cp);
+#endif
+ mx4200->badformat++;
+ mx4200->reason = PPSREASON + 5;
+ mx4200_event(mx4200, CEVNT_BADREPLY);
+ mx4200_reset(mx4200);
+ return;
+ }
+
+ /* Setup leap second indicator */
+ if (leapsec == 0)
+ mx4200->leap = LEAP_NOWARNING;
+ else if (leapsec == 1)
+ mx4200->leap = LEAP_ADDSECOND;
+ else if (leapsec == -1)
+ mx4200->leap = LEAP_DELSECOND;
+ else
+ mx4200->leap = LEAP_NOTINSYNC; /* shouldn't happen */
+
+ /* Check parsed time (allow for possible leap seconds) */
+ if (jt->second >= 61 || jt->minute >= 60 || jt->hour >= 24) {
+#ifdef DEBUG
+ if (debug) {
+ printf("mx4200_receive: bad time %d:%02d:%02d",
+ jt->hour, jt->minute, jt->second);
+ if (leapsec != 0)
+ printf(" (leap %+d)", leapsec);
+ putchar('\n');
+ }
+#endif
+ mx4200->baddata++;
+ mx4200->reason = PPSREASON + 6;
+ mx4200_event(mx4200, CEVNT_BADTIME);
+ mx4200_reset(mx4200);
+ /* Eat the next pulse which the clock claims will be bad */
+ mx4200->nsamples = -1;
+ return;
+ }
+
+ /* Check parsed date */
+ if (jt->monthday > 31 || jt->month > 12 || jt->year < 1900) {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: bad date (%d/%d/%d)\n",
+ jt->monthday, jt->month, jt->year);
+#endif
+ mx4200->baddata++;
+ mx4200->reason = PPSREASON + 7;
+ mx4200_event(mx4200, CEVNT_BADDATE);
+ mx4200_reset(mx4200);
+ return;
+ }
+
+ /* Convert to ntp time */
+ gpstime = caltontp(jt);
+
+ /* The gps message describes the *next* pulse; pretend it's this one */
+ --gpstime;
+
+ /* Debugging */
+#ifdef DEBUG
+ checkdfile();
+ if (df != NULL) {
+ l_fp t;
+
+ t.l_ui = gpstime;
+ t.l_uf = 0;
+ M_SUB(t.l_ui, t.l_uf, tmp_ui, tmp_uf);
+ fprintf(df, "%s\t%s",
+ umfptoa(tmp_ui, tmp_uf, 6), mfptoa(t.l_ui, t.l_uf, 6));
+ if (debug > 3)
+ fprintf(df, "\t(gps: %lu)", gpstime);
+ if (leapsec != 0)
+ fprintf(df, "\t(leap sec %+d)", leapsec);
+ if (!valid)
+ fprintf(df, "\t(pulse not valid)");
+ fputc('\n', df);
+ }
+#endif
+
+ /* Check pps serial number against last one */
+ if (mx4200->lastserial + 1 != ev.serial && mx4200->lastserial != 0) {
+#ifdef DEBUG
+ if (debug) {
+ if (ev.serial == mx4200->lastserial)
+ printf("mx4200_receive: no new pps event\n");
+ else
+ printf("mx4200_receive: missed %d pps events\n",
+ ev.serial - mx4200->lastserial - 1);
+ }
+#endif
+ mx4200->reason = PPSREASON + 8;
+ mx4200_event(mx4200, CEVNT_FAULT);
+ mx4200_reset(mx4200);
+ /* fall through and this one collect as first sample */
+ }
+ mx4200->lastserial = ev.serial;
+
+/*
+ * XXX
+ * Since this message is for the next pulse, it's really the next pulse
+ * that the clock might be telling us will be invalid.
+ */
+ /* Toss if not designated "valid" by the gps */
+ if (!valid) {
+#ifdef DEBUG
+ if (debug)
+ printf("mx4200_receive: pps not valid\n");
+#endif
+ mx4200->reason = PPSREASON + 9;
+ mx4200_event(mx4200, CEVNT_BADTIME);
+ mx4200_reset(mx4200);
+ return;
+ }
+
+ /* Copy time into mx4200unit struct */
+ /* XXX (why?) */
+ mx4200->year = jt->year;
+ mx4200->monthday = jt->monthday;
+ mx4200->hour = jt->hour;
+ mx4200->minute = jt->minute;
+ mx4200->second = jt->second;
+
+ /* Sock away the GPS and UNIX timesamples */
+ n = mx4200->nsamples++;
+ if (n < 0)
+ return; /* oops, this pulse is bad */
+ mx4200->gpssamples[n] = gpstime;
+ mx4200->unixsamples[n].l_ui = mx4200->lastsampletime.l_ui = tmp_ui;
+ mx4200->unixsamples[n].l_uf = mx4200->lastsampletime.l_uf = tmp_uf;
+ if (mx4200->nsamples >= NSTAMPS) {
+ /*
+ * Here we've managed to complete an entire NSTAMPS
+ * second cycle without major mishap. Process what has
+ * been received.
+ */
+ mx4200_process(mx4200);
+ mx4200_reset(mx4200);
+ }
+}
+
+/* Compare two l_fp's, used with qsort() */
+static int
+mx4200_cmpl_fp(p1, p2)
+ register void *p1, *p2;
+{
+
+ if (!L_ISGEQ((l_fp *)p1, (l_fp *)p2))
+ return (-1);
+ if (L_ISEQU((l_fp *)p1, (l_fp *)p2))
+ return (0);
+ return (1);
+}
+
+/*
+ * mx4200_process - process a pile of samples from the clock
+ */
+static void
+mx4200_process(mx4200)
+ struct mx4200unit *mx4200;
+{
+ register int i, n;
+ register l_fp *fp, *op;
+ register U_LONG *lp;
+ l_fp off[NSTAMPS];
+ register U_LONG tmp_ui, tmp_uf;
+ register U_LONG date_ui, date_uf;
+ u_fp dispersion;
+
+ /* Compute offsets from the raw data. */
+ fp = mx4200->unixsamples;
+ op = off;
+ lp = mx4200->gpssamples;
+ for (i = 0; i < NSTAMPS; ++i, ++lp, ++op, ++fp) {
+ op->l_ui = *lp;
+ op->l_uf = 0;
+ L_SUB(op, fp);
+ }
+
+ /* Sort offsets into ascending order. */
+ qsort((char *)off, NSTAMPS, sizeof(l_fp), mx4200_cmpl_fp);
+
+ /*
+ * Reject the furthest from the median until 8 samples left
+ */
+ i = 0;
+ n = NSTAMPS;
+ while ((n - i) > 8) {
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ date_ui = off[(n+i)/2].l_ui;
+ date_uf = off[(n+i)/2].l_uf;
+ M_SUB(tmp_ui, tmp_uf, date_ui, date_uf);
+ M_SUB(date_ui, date_uf, off[i].l_ui, off[i].l_uf);
+ if (M_ISHIS(date_ui, date_uf, tmp_ui, tmp_uf)) {
+ /*
+ * reject low end
+ */
+ i++;
+ } else {
+ /*
+ * reject high end
+ */
+ n--;
+ }
+ }
+
+ /*
+ * Compute the dispersion based on the difference between the
+ * extremes of the remaining offsets.
+ */
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ M_SUB(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
+ dispersion = MFPTOFP(tmp_ui, tmp_uf);
+
+ /*
+ * Now compute the offset estimate. If the sloppy clock
+ * flag is set, average the remainder, otherwise pick the
+ * median.
+ */
+ if (sloppyclockflag[mx4200->unit]) {
+ tmp_ui = tmp_uf = 0;
+ while (i < n) {
+ M_ADD(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
+ i++;
+ }
+ M_RSHIFT(tmp_ui, tmp_uf);
+ M_RSHIFT(tmp_ui, tmp_uf);
+ M_RSHIFT(tmp_ui, tmp_uf);
+ i = 0;
+ off[0].l_ui = tmp_ui;
+ off[0].l_uf = tmp_uf;
+ } else {
+ i = (n + i) / 2;
+ }
+
+ /*
+ * Add the default MX4200 QT delay into this.
+ */
+#ifdef notdef
+ L_ADDUF(&off[i], MX4200QTFUDGE);
+#endif
+
+ /*
+ * Done. Use lastref as the reference time and lastrec
+ * as the receive time. ** note this can result in tossing
+ * out the peer in the protocol module if lastref > lastrec,
+ * so last rec is used for both values - dlm ***
+ */
+ refclock_receive(mx4200->peer, &off[i],
+ (s_fp)0, /* delay */
+ dispersion,
+ &mx4200->unixsamples[NSTAMPS-1], /* reftime */
+ &mx4200->unixsamples[NSTAMPS-1], /* rectime */
+ mx4200->leap);
+
+ mx4200_event(mx4200, CEVNT_NOMINAL);
+}
+
+/*
+ * mx4200_control - set fudge factors, return statistics
+ */
+static void
+mx4200_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct mx4200unit *mx4200;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "mx4200_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);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
+ sloppyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = mx4200units[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
+ }
+
+ if (out != 0) {
+ memset((char *)out, 0, sizeof (struct refclockstat));
+ out->type = REFCLK_GPS_MX4200;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 | CLK_HAVEVAL2 |
+ CLK_HAVEFLAG1;
+ out->clockdesc = MX4200DESCRIPTION;
+ out->fudgetime1 = fudgefactor[unit];
+ out->fudgeval1 = (LONG)stratumtouse[unit];
+ out->fudgeval2 = refid[unit];;
+ out->flags = sloppyclockflag[unit];
+ if (unitinuse[unit]) {
+ mx4200 = mx4200units[unit];
+ out->lencode = mx4200->lencode;
+ out->lastcode = mx4200->lastcode;
+ out->lastevent = mx4200->lastevent;
+ out->currentstatus = mx4200->status;
+
+ out->polls = 0; /* mx4200->polls; */
+ out->noresponse = 0; /* mx4200->noresponse; */
+ out->badformat = mx4200->badformat;
+ out->baddata = mx4200->baddata;
+ out->timereset = current_time - mx4200->timestarted;
+ }
+ }
+}
+
+/*
+ * mx4200_buginfo - return clock dependent debugging info
+ */
+static void
+mx4200_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct mx4200unit *mx4200;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "mx4200_buginfo: unit %d invalid", unit);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ mx4200 = mx4200units[unit];
+
+ memset((char *)bug, 0, sizeof(*bug));
+ bug->nvalues = 10;
+ bug->ntimes = 2;
+ if (mx4200->lasttime != 0)
+ bug->values[0] = current_time - mx4200->lasttime;
+ else
+ bug->values[0] = 0;
+ bug->values[1] = (U_LONG)mx4200->reason;
+ bug->values[2] = (U_LONG)mx4200->year;
+ bug->values[3] = (U_LONG)mx4200->monthday;
+ bug->values[4] = (U_LONG)mx4200->hour;
+ bug->values[5] = (U_LONG)mx4200->minute;
+ bug->values[6] = (U_LONG)mx4200->second;
+#ifdef notdef
+ bug->values[7] = mx4200->msec;
+ bug->values[8] = mx4200->noreply;
+ bug->values[9] = mx4200->yearstart;
+#endif
+ bug->stimes = 0x1c;
+#ifdef notdef
+ bug->times[0] = mx4200->lastref;
+ bug->times[1] = mx4200->lastrec;
+#endif
+}
+
+/*
+ * Returns true if the this is a status message. We use this as
+ * an indication that the receiver needs to be initialized.
+ */
+static int
+mx4200_needconf(buf)
+ char *buf;
+{
+ register LONG v;
+ char *cp;
+
+ cp = buf;
+
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Record type */
+ v = strtol(cp, &cp, 10);
+ if (v != PMVXG_D_STATUS)
+ return (0);
+ /*
+ * XXX
+ * Since we configure the receiver to not give us status
+ * messages and since the receiver outputs status messages by
+ * default after being reset to factory defaults when sent the
+ * "$PMVXG,018,C\r\n" message, any status message we get
+ * indicates the reciever needs to be initialized; thus, it is
+ * not necessary to decode the status message.
+ */
+#ifdef notdef
+ ++cp;
+
+ /* Receiver status */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Number of satellites which should be visible */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Number of satellites being tracked */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Time since last NAV */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return (0);
+ ++cp;
+
+ /* Initialization status */
+ v = strtol(cp, &cp, 10);
+ if (v == 0)
+#endif
+ return (1);
+}
+
+/* Parse a mx4200 time recovery message. Returns a string if error */
+static char *
+mx4200_parse(buf, jt, validp, leapsecp)
+ register char *buf;
+ register struct calendar *jt;
+ register int *validp, *leapsecp;
+{
+ register LONG v;
+ char *cp;
+
+ cp = buf;
+ memset((char *)jt, 0, sizeof(*jt));
+
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no rec-type");
+ ++cp;
+
+ /* Record type */
+ v = strtol(cp, &cp, 10);
+ if (v != PMVXG_D_TRECOVOUT)
+ return ("wrong rec-type");
+
+ /* Pulse valid indicator */
+ if (*cp++ != ',')
+ return ("no pulse-valid");
+ if (*cp == 'T')
+ *validp = 1;
+ else if (*cp == 'F')
+ *validp = 0;
+ else
+ return ("bad pulse-valid");
+ ++cp;
+
+ /* Year */
+ if (*cp++ != ',')
+ return ("no year");
+ jt->year = strtol(cp, &cp, 10);
+
+ /* Month of year */
+ if (*cp++ != ',')
+ return ("no month");
+ jt->month = strtol(cp, &cp, 10);
+
+ /* Day of month */
+ if (*cp++ != ',')
+ return ("no month day");
+ jt->monthday = strtol(cp, &cp, 10);
+
+ /* Hour */
+ if (*cp++ != ',')
+ return ("no hour");
+ jt->hour = strtol(cp, &cp, 10);
+
+ /* Minute */
+ if (*cp++ != ':')
+ return ("no minute");
+ jt->minute = strtol(cp, &cp, 10);
+
+ /* Second */
+ if (*cp++ != ':')
+ return ("no second");
+ jt->second = strtol(cp, &cp, 10);
+
+ /* Time indicator */
+ if (*cp++ != ',' || *cp++ == '\0')
+ return ("no time indicator");
+
+ /* Time recovery mode */
+ if (*cp++ != ',' || *cp++ == '\0')
+ return ("no time mode");
+
+ /* Oscillator offset */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no osc off");
+ ++cp;
+
+ /* Time mark error */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no time mark err");
+ ++cp;
+
+ /* User time bias */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no user bias");
+ ++cp;
+
+ /* Leap second flag */
+ if ((cp = strchr(cp, ',')) == NULL)
+ return ("no leap");
+ ++cp;
+ *leapsecp = strtol(cp, &cp, 10);
+
+ return (NULL);
+}
+
+/* Calculate the checksum */
+static u_char
+cksum(cp, n)
+ register char *cp;
+ register u_int n;
+{
+ register u_char ck;
+
+ for (ck = 0; n-- > 0; ++cp)
+ ck ^= *cp;
+ return (ck);
+}
+
+static void
+#if __STDC__
+mx4200_send(register int fd, const char *fmt, ...)
+#else
+mx4200_send(fd, fmt, va_alist)
+ register int fd;
+ const char *fmt;
+ va_dcl
+#endif
+{
+ register char *cp;
+ register int n, m;
+ va_list ap;
+ char buf[1024];
+ u_char ck;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ cp = buf;
+ *cp++ = '$';
+#ifdef notdef
+ /* BSD is rational */
+ n = vsnprintf(cp, sizeof(buf) - 1, fmt, ap);
+#else
+ /* SunOS sucks */
+ (void)vsprintf(cp, fmt, ap);
+ n = strlen(cp);
+#endif
+ ck = cksum(cp, n);
+ cp += n;
+ ++n;
+#ifdef notdef
+ /* BSD is rational */
+ n += snprintf(cp, sizeof(buf) - n - 5, "*%02X\r\n", ck);
+#else
+ /* SunOS sucks */
+ sprintf(cp, "*%02X\r\n", ck);
+ n += strlen(cp);
+#endif
+
+ m = write(fd, buf, n);
+ if (m < 0)
+ syslog(LOG_ERR, "mx4200_send: write: %m (%s)", buf);
+ else if (m != n)
+ syslog(LOG_ERR, "mx4200_send: write: %d != %d (%s)", m, n, buf);
+ va_end(ap);
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_old/refclock_omega.c b/usr.sbin/xntpd/xntpd/refclock_old/refclock_omega.c
new file mode 100644
index 000000000000..95a20a0d2c44
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_old/refclock_omega.c
@@ -0,0 +1,999 @@
+/*
+ * refclock_omega - clock driver for the Kinemetrics Truetime OM-DC OMEGA
+ * receiver.
+ *
+ * Version 1.0 11-Dec-92 Steve Clift (clift@ml.csiro.au)
+ * Initial version, mostly lifted from refclock_goes.c.
+ *
+ * 1.1 03-May-93 Steve Clift
+ * Tarted up the sample filtering mechanism to give improved
+ * one-off measurements. Improved measurement dispersion code
+ * to account for accumulated drift when the clock loses lock.
+ *
+ */
+
+#if defined(REFCLOCK) && (defined(OMEGA) || defined(OMEGACLK) || defined(OMEGAPPS))
+
+#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"
+
+#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(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+#if defined(STREAM)
+#include <stropts.h>
+#if defined(OMEGACLK)
+#include <sys/clkdefs.h>
+#endif /* OMEGACLK */
+#endif /* STREAM */
+
+#if defined (OMEGAPPS)
+#include <sys/ppsclock.h>
+#endif /* OMEGAPPS */
+
+#include "ntp_stdlib.h"
+
+/*
+ * Support for Kinemetrics Truetime OM-DC OMEGA Receiver
+ *
+ * Most of this code is copied from refclock_goes.c with thanks.
+ *
+ * the time code looks like follows; Send the clock a R or C and once per
+ * second a timestamp will appear that looks like this:
+ * ADDD:HH:MM:SSQCL
+ * A - control A
+ * Q Quality indication: indicates possible error of
+ * > >+- 5 seconds
+ * ? >+/- 500 milliseconds # >+/- 50 milliseconds
+ * * >+/- 5 milliseconds . >+/- 1 millisecond
+ * A-H less than 1 millisecond. Character indicates which station
+ * is being received as follows:
+ * A = Norway, B = Liberia, C = Hawaii, D = North Dakota,
+ * E = La Reunion, F = Argentina, G = Australia, H = Japan.
+ * C - Carriage return
+ * L - Line feed
+ * The carriage return start bit begins on 0 seconds and extends to 1 bit time.
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 4 /* max number of OMEGA units */
+#define OMEGA232 "/dev/omega%d"
+#define SPEED232 B9600 /* 9600 baud */
+
+/*
+ * Radio interface parameters
+ */
+#define OMEGADESCRIPTION "Kinemetrics OM-DC OMEGA Receiver" /* who we are */
+#define OMEGAMAXDISPERSE (FP_SECOND/32) /* max allowed sample dispersion */
+#define OMEGAPRECISION (-10) /* precision assumed (about 1 ms) */
+#define OMEGAREFID "VLF\0" /* reference id */
+#define LENOMEGA 13 /* length of standard response */
+#define GMT 0 /* hour offset from Greenwich */
+#define NSTAMPS 9 /* samples collected when polled */
+#define NSKEEP 5 /* samples to keep after discards */
+#define BMAX 50 /* timecode buffer length */
+
+/*
+ * The OM-DC puts out the start bit of the <CR> on the second, but
+ * we see the result after the <LF> is received, about 2ms later at
+ * 9600 baud. Use this as the default fudge time, and let the user
+ * fiddle it to account for driver latency etc.
+ */
+#define DEFFUDGETIME 0x00830000 /* default fudge time (~2ms) */
+
+/*
+ * Clock drift errors as u_fp values.
+ */
+#define U_FP5000MS (5*FP_SECOND) /* 5 seconds */
+#define U_FP500MS (FP_SECOND/2) /* 500 msec */
+#define U_FP50MS (FP_SECOND/20) /* 50 msec */
+#define U_FP5MS (FP_SECOND/200) /* 5 msec */
+
+/*
+ * Station codes
+ */
+#define STATION_NONE 0
+#define STATION_NORWAY 1
+#define STATION_LIBERIA 2
+#define STATION_HAWAII 3
+#define STATION_N_DAKOTA 4
+#define STATION_LA_REUNION 5
+#define STATION_ARGENTINA 6
+#define STATION_AUSTRALIA 7
+#define STATION_JAPAN 8
+
+/*
+ * Hack to avoid excercising the multiplier. I have no pride.
+ */
+#define MULBY10(x) (((x)<<3) + ((x)<<1))
+
+/*
+ * Imported from the timer module
+ */
+extern U_LONG current_time;
+extern struct event timerqueue[];
+
+/*
+ * Imported from ntp_loopfilter module
+ */
+extern int fdpps; /* pps file descriptor */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * OMEGA unit control structure
+ */
+struct omegaunit {
+ struct peer *peer; /* associated peer structure */
+ struct refclockio io; /* given to the I/O handler */
+ l_fp lastrec; /* last receive time */
+ l_fp lastref; /* last timecode time */
+ l_fp offset[NSTAMPS]; /* recent sample offsets */
+ char lastcode[BMAX]; /* last timecode received */
+ u_short station; /* which station we're locked to */
+ u_short polled; /* Hand in a time sample? */
+ U_LONG coderecv; /* timecodes received */
+ u_char lencode; /* length of last timecode */
+ U_LONG lasttime; /* last time clock heard from */
+ 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 failure */
+ 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_char leap; /* leap indicators */
+ u_short msec; /* millisecond of second */
+ u_char quality; /* quality char from last timecode */
+ U_LONG yearstart; /* start of current year */
+ /*
+ * Status tallies
+ */
+ U_LONG polls; /* polls sent */
+ U_LONG noreply; /* no replies to polls */
+ 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 omegaunit *omegaunits[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 fudgefactor1[MAXUNITS];
+static l_fp fudgefactor2[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static u_char readonlyclockflag[MAXUNITS];
+static U_LONG refid[MAXUNITS];
+
+/*
+ * Function prototypes
+ */
+static void omega_init P((void));
+static int omega_start P((u_int, struct peer *));
+static void omega_shutdown P((int));
+static void omega_report_event P((struct omegaunit *, int));
+static void omega_receive P((struct recvbuf *));
+static char omega_process P((struct omegaunit *, l_fp *, u_fp *));
+static void omega_poll P((int, struct peer *));
+static void omega_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void omega_buginfo P((int, struct refclockbug *));
+static void omega_send P((struct omegaunit *, char *));
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_omega = {
+ omega_start, omega_shutdown, omega_poll,
+ omega_control, omega_init, omega_buginfo, NOFLAGS
+};
+
+/*
+ * omega_init - initialize internal omega driver data
+ */
+static void
+omega_init()
+{
+ register int i;
+ /*
+ * Just zero the data arrays
+ */
+ memset((char *)omegaunits, 0, sizeof omegaunits);
+ memset((char *)unitinuse, 0, sizeof unitinuse);
+
+ /*
+ * Initialize fudge factors to default.
+ */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor1[i].l_ui = 0;
+ fudgefactor1[i].l_uf = DEFFUDGETIME;
+ fudgefactor2[i].l_ui = 0;
+ fudgefactor2[i].l_uf = 0;
+ stratumtouse[i] = 0;
+ readonlyclockflag[i] = 0;
+ memcpy((char *)&refid[i], OMEGAREFID, 4);
+ }
+}
+
+
+/*
+ * omega_start - open the OMEGA devices and initialize data for processing
+ */
+static int
+omega_start(unit, peer)
+ u_int unit;
+ struct peer *peer;
+{
+ register struct omegaunit *omega;
+ register int i;
+ int fd232;
+ char omegadev[20];
+
+ /*
+ * Check configuration info
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,"omega_start: unit %d invalid", unit);
+ return 0;
+ }
+ if (unitinuse[unit]) {
+ syslog(LOG_ERR, "omega_start: unit %d in use", unit);
+ return 0;
+ }
+
+ /*
+ * Open serial port
+ */
+ (void) sprintf(omegadev, OMEGA232, unit);
+ fd232 = open(omegadev, O_RDWR, 0777);
+ if (fd232 == -1) {
+ syslog(LOG_ERR, "omega_start: open of %s: %m", omegadev);
+ 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,
+ "omega_start: ioctl(%s, TCGETA): %m", omegadev);
+ 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,
+ "omega_start: ioctl(%s, TCSETA): %m", omegadev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_SYSV_TTYS */
+#if defined(HAVE_TERMIOS)
+ /*
+ * POSIX serial line parameters (termios interface)
+ *
+ * The OMEGACLK option provides timestamping at the driver level.
+ * It requires the tty_clk streams module.
+ *
+ * The OMEGAPPS 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,
+ "omega_start: tcgetattr(%s): %m", omegadev);
+ goto screwed;
+ }
+ ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
+ 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,
+ "omega_start: tcsetattr(%s): %m", omegadev);
+ goto screwed;
+ }
+ if (tcflush(fd232, TCIOFLUSH) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: tcflush(%s): %m", omegadev);
+ goto screwed;
+ }
+ }
+#endif /* HAVE_TERMIOS */
+#ifdef STREAM
+#if defined(OMEGACLK)
+ if (ioctl(fd232, I_PUSH, "clk") < 0)
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, I_PUSH, clk): %m", omegadev);
+ if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, CLK_SETSTR): %m", omegadev);
+#endif /* OMEGACLK */
+#if defined(OMEGAPPS)
+ if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, I_PUSH, ppsclock): %m", omegadev);
+ else
+ fdpps = fd232;
+#endif /* OMEGAPPS */
+#endif /* STREAM */
+#if defined(HAVE_BSD_TTYS)
+ /*
+ * 4.3bsd serial line parameters (sgttyb interface)
+ *
+ * The OMEGACLK option provides timestamping at the driver level.
+ * It requires the tty_clk line discipline and 4.3bsd or later.
+ */
+ { struct sgttyb ttyb;
+#if defined(OMEGACLK)
+ int ldisc = CLKLDISC;
+#endif /* OMEGACLK */
+
+ if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, TIOCGETP): %m", omegadev);
+ goto screwed;
+ }
+ ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
+#if defined(OMEGACLK)
+ 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 /* OMEGACLK */
+ if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, TIOCSETP): %m", omegadev);
+ goto screwed;
+ }
+#if defined(OMEGACLK)
+ if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
+ syslog(LOG_ERR,
+ "omega_start: ioctl(%s, TIOCSETD): %m",omegadev);
+ goto screwed;
+ }
+#endif /* OMEGACLK */
+ }
+#endif /* HAVE_BSD_TTYS */
+
+ /*
+ * Allocate unit structure
+ */
+ if (omegaunits[unit] != 0) {
+ omega = omegaunits[unit]; /* The one we want is okay */
+ } else {
+ for (i = 0; i < MAXUNITS; i++) {
+ if (!unitinuse[i] && omegaunits[i] != 0)
+ break;
+ }
+ if (i < MAXUNITS) {
+ /*
+ * Reclaim this one
+ */
+ omega = omegaunits[i];
+ omegaunits[i] = 0;
+ } else {
+ omega = (struct omegaunit *)
+ emalloc(sizeof(struct omegaunit));
+ }
+ }
+ memset((char *)omega, 0, sizeof(struct omegaunit));
+ omegaunits[unit] = omega;
+
+ /*
+ * Set up the structures
+ */
+ omega->peer = peer;
+ omega->unit = (u_char)unit;
+ omega->timestarted = current_time;
+ omega->station = STATION_NONE;
+
+ omega->io.clock_recv = omega_receive;
+ omega->io.srcclock = (caddr_t)omega;
+ omega->io.datalen = 0;
+ omega->io.fd = fd232;
+ if (!io_addclock(&omega->io)) {
+ goto screwed;
+ }
+
+ /*
+ * All done. Initialize a few random peer variables, then
+ * return success.
+ */
+ peer->precision = OMEGAPRECISION;
+ peer->rootdelay = 0;
+ peer->rootdispersion = 0;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ unitinuse[unit] = 1;
+ return 1;
+
+ /*
+ * Something broke; abandon ship
+ */
+screwed:
+ (void) close(fd232);
+ return 0;
+}
+
+
+/*
+ * omega_shutdown - shut down a OMEGA clock
+ */
+static void
+omega_shutdown(unit)
+ int unit;
+{
+ register struct omegaunit *omega;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_shutdown: unit %d invalid",
+ unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "omega_shutdown: unit %d not in use", unit);
+ return;
+ }
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ omega = omegaunits[unit];
+ io_closeclock(&omega->io);
+ unitinuse[unit] = 0;
+}
+
+
+/*
+ * omega_report_event - note the occurance of an event
+ */
+static void
+omega_report_event(omega, code)
+ struct omegaunit *omega;
+ int code;
+{
+ struct peer *peer;
+
+ peer = omega->peer;
+ if (omega->status != (u_char)code) {
+ omega->status = (u_char)code;
+ if (code != CEVNT_NOMINAL)
+ omega->lastevent = (u_char)code;
+ syslog(LOG_INFO,
+ "omega clock %s event %x\n", ntoa(&peer->srcadr), code);
+ }
+}
+
+
+/*
+ * omega_receive - receive data from the serial interface on a
+ * Kinemetrics OM-DC OMEGA clock.
+ */
+static void
+omega_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ register int i;
+ register struct omegaunit *omega;
+ register u_char *dpt;
+ register char *cp, *cpend;
+ register u_char *dpend;
+ l_fp tstmp;
+ u_fp dispersion, drift;
+
+ /*
+ * Get the clock this applies to and a pointers to the data
+ */
+ omega = (struct omegaunit *)rbufp->recv_srcclock;
+ dpt = (u_char *)&rbufp->recv_space;
+
+#ifndef PEDANTIC
+ /*
+ * The OM-DC outputs a timecode every second, but we only want
+ * a set of NSTAMPS timecodes when polled (every 64 seconds).
+ * Setting PEDANTIC causes a sanity check on every timecode.
+ */
+ if (!omega->polled)
+ return;
+#endif
+
+ /*
+ * Edit timecode to remove control chars
+ */
+ dpend = dpt + rbufp->recv_length;
+ cp = omega->lastcode;
+ cpend = omega->lastcode + BMAX - 1;
+ while (dpt < dpend && cp < cpend) {
+ if ((*cp = 0x7f & *dpt++) >= ' ') cp++;
+#ifdef OMEGACLK
+ else if (*cp == '\r') {
+ if (dpend - dpt < 8) {
+ /* short timestamp */
+ return;
+ }
+ if (!buftvtots(dpt,&omega->lastrec)) {
+ /* screwy timestamp */
+ return;
+ }
+ dpt += 8;
+ }
+#endif
+ }
+ *cp = '\0';
+ omega->lencode = cp - omega->lastcode;
+
+ if (omega->lencode == 0)
+ return;
+ else if (omega->lencode != LENOMEGA) {
+ omega->badformat++;
+ /* Sometimes get a lot of these, filling the log with noise */
+ /* omega_report_event(omega, CEVNT_BADREPLY); */
+ return;
+ }
+
+#ifndef OMEGACLK
+ omega->lastrec = rbufp->recv_time;
+#endif
+
+#ifdef DEBUG
+ if (debug)
+ printf("omega: timecode %d %s\n",
+ omega->lencode, omega->lastcode);
+#endif
+
+ /*
+ * We get down to business, check the timecode format
+ * and decode its contents.
+ */
+ cp = omega->lastcode;
+ omega->leap = 0;
+ /*
+ * Check timecode format.
+ */
+ if (!isdigit(cp[0]) || /* day of year */
+ !isdigit(cp[1]) ||
+ !isdigit(cp[2]) ||
+ cp[3] != ':' || /* <sp> */
+ !isdigit(cp[4]) || /* hours */
+ !isdigit(cp[5]) ||
+ cp[6] != ':' || /* : separator */
+ !isdigit(cp[7]) || /* minutes */
+ !isdigit(cp[8]) ||
+ cp[9] != ':' || /* : separator */
+ !isdigit(cp[10]) || /* seconds */
+ !isdigit(cp[11])) {
+ omega->badformat++;
+ omega_report_event(omega, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Convert and check values.
+ */
+ omega->year = 0; /* fake */
+ omega->day = cp[0] - '0';
+ omega->day = MULBY10(omega->day) + cp[1] - '0';
+ omega->day = MULBY10(omega->day) + cp[2] - '0';
+ omega->hour = MULBY10(cp[4] - '0') + cp[5] - '0';
+ omega->minute = MULBY10(cp[7] - '0') + cp[8] - '0';
+ omega->second = MULBY10(cp[10] - '0') + cp[11] - '0';
+ omega->msec = 0;
+
+ if (omega->day < 1 || omega->day > 366) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADDATE);
+ return;
+ }
+ if (omega->hour > 23 || omega->minute > 59 || omega->second > 59) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADTIME);
+ return;
+ }
+
+ /*
+ * Check quality/station-id flag. The OM-DC should normally stay
+ * permanently locked to a station, and its time error should be less
+ * than 1 msec. If it loses lock for any reason, it makes a worst
+ * case drift estimate based on the internally stored stability figure
+ * for its reference oscillator. The stability figure can be adjusted
+ * by the user based on experience. The default value is 1E05, which
+ * is pretty bad - 2E07 is about right for the unit I have.
+ *
+ * The following is arbitrary, change it if you're offended:
+ * For errors less than 50 msec, just clear the station indicator.
+ * For errors greater than 50 msec, flag loss of sync and report a
+ * propagation problem. If the error is greater than 500 msec,
+ * something is dreadfully wrong - report a clock fault.
+ *
+ * In each case, we set a drift estimate which is used below as an
+ * estimate of measurement accuracy.
+ */
+ omega->quality = cp[12];
+ if (cp[12] == '>' || cp[12] == '?') {
+ /* Error 500 to 5000 msec */
+ omega_report_event(omega, CEVNT_FAULT);
+ omega->leap = LEAP_NOTINSYNC;
+ omega->station = STATION_NONE;
+ drift = U_FP5000MS;
+ } else if (cp[12] == '#') {
+ /* Error 50 to 500 msec */
+ omega_report_event(omega, CEVNT_PROP);
+ omega->leap = LEAP_NOTINSYNC;
+ omega->station = STATION_NONE;
+ drift = U_FP500MS;
+ } else if (cp[12] == '*') {
+ /* Error 5 to 50 msec */
+ omega->lasttime = current_time;
+ omega->station = STATION_NONE;
+ drift = U_FP50MS;
+ } else if (cp[12] == '.') {
+ /* Error 1 to 5 msec */
+ omega->lasttime = current_time;
+ omega->station = STATION_NONE;
+ drift = U_FP5MS;
+ } else if ('A' <= cp[12] && cp[12] <= 'H') {
+ /* Error less than 1 msec */
+ omega->lasttime = current_time;
+ omega->station = cp[12] - 'A' + 1;
+ drift = 0;
+ } else {
+ omega->badformat++;
+ omega_report_event(omega, CEVNT_BADREPLY);
+ return;
+ }
+
+#ifdef PEDANTIC
+ /* If we haven't been polled, bail out. */
+ if (!omega->polled)
+ return;
+#endif
+
+ /*
+ * Now, compute the reference time value. Use the heavy
+ * machinery for the seconds and the millisecond field for the
+ * fraction when present.
+ *
+ * this code does not yet know how to do the years
+ */
+ tstmp = omega->lastrec;
+ if (!clocktime(omega->day, omega->hour, omega->minute,
+ omega->second, GMT, tstmp.l_ui,
+ &omega->yearstart, &omega->lastref.l_ui)) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADTIME);
+ return;
+ }
+ MSUTOTSF(omega->msec, omega->lastref.l_uf);
+
+ /*
+ * Adjust the read value by fudgefactor1 to correct RS232 delays.
+ */
+ L_ADD(&omega->lastref, &fudgefactor1[omega->unit]);
+
+ /* Carousel of NSTAMPS offsets. */
+ i = omega->coderecv % NSTAMPS;
+ omega->offset[i] = omega->lastref;
+ L_SUB(&omega->offset[i], &tstmp);
+ omega->coderecv++;
+
+ /* If we don't yet have a full set, return. */
+ if (omega->coderecv < NSTAMPS)
+ return;
+
+ /*
+ * Filter the samples, add the fudge factor and pass the
+ * offset and dispersion along. We use lastrec 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 the sample filter chokes because of excessive
+ * dispersion or whatever, get a new sample (omega->coderecv
+ * is still >= NSTAMPS) and try again.
+ */
+ if (!omega_process(omega, &tstmp, &dispersion)) {
+ omega->baddata++;
+ omega_report_event(omega, CEVNT_BADTIME);
+ return;
+ }
+
+ /*
+ * Add accumulated clock drift to the dispersion to get
+ * a (hopefully) meaningful measurement accuracy estimate.
+ */
+ dispersion += drift;
+ refclock_receive(omega->peer, &tstmp, GMT, dispersion,
+ &omega->lastrec, &omega->lastrec, omega->leap);
+
+ /*
+ * We have succeeded in answering the poll. If the clock
+ * is locked, we're nominal.
+ */
+ omega->polled = 0;
+ omega->coderecv = 0;
+ if (omega->leap != LEAP_NOTINSYNC)
+ omega_report_event(omega, CEVNT_NOMINAL);
+}
+
+
+/*
+ * omega_send - time to send the clock a signal to cough up a time sample
+ */
+static void
+omega_send(omega,cmd)
+ struct omegaunit *omega;
+ char *cmd;
+{
+ if (!readonlyclockflag[omega->unit]) {
+ /*
+ * Send a command to the clock.
+ */
+ if (write(omega->io.fd, cmd, 1) != 1) {
+ syslog(LOG_ERR, "omega_send: unit %d: %m", omega->unit);
+ omega_report_event(omega, CEVNT_FAULT);
+ }
+ }
+}
+
+
+/*
+ * Compare two l_fp's, used with qsort()
+ */
+static int
+omega_cmpl_fp(p1, p2)
+ register void *p1, *p2;
+{
+
+ if (!L_ISGEQ((l_fp *)p1, (l_fp *)p2))
+ return (-1);
+ if (L_ISEQU((l_fp *)p1, (l_fp *)p2))
+ return (0);
+ return (1);
+}
+
+
+/*
+ * omega_process - process a pile of samples from the clock
+ */
+static char
+omega_process(omega, offset, dispersion)
+ struct omegaunit *omega;
+ l_fp *offset;
+ u_fp *dispersion;
+{
+ register int i, n;
+ register U_LONG med_ui, med_uf, tmp_ui, tmp_uf;
+ l_fp off[NSTAMPS];
+ u_fp disp;
+
+ /* Copy in offsets and sort into ascending order */
+ for (i = 0; i < NSTAMPS; i++)
+ off[i] = omega->offset[i];
+ qsort((char *)off, NSTAMPS, sizeof(l_fp), omega_cmpl_fp);
+ /*
+ * Reject the furthest from the median until NSKEEP samples remain
+ */
+ i = 0;
+ n = NSTAMPS;
+ while ((n - i) > NSKEEP) {
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ med_ui = off[(n+i)/2].l_ui;
+ med_uf = off[(n+i)/2].l_uf;
+ M_SUB(tmp_ui, tmp_uf, med_ui, med_uf);
+ M_SUB(med_ui, med_uf, off[i].l_ui, off[i].l_uf);
+ if (M_ISHIS(med_ui, med_uf, tmp_ui, tmp_uf)) {
+ /* reject low end */
+ i++;
+ } else {
+ /* reject high end */
+ n--;
+ }
+ }
+
+ /*
+ * Compute the dispersion based on the difference between the
+ * extremes of the remaining offsets. If this is greater than
+ * the allowed sample set dispersion, bail out. Otherwise,
+ * return the median offset and the dispersion.
+ */
+ tmp_ui = off[n-1].l_ui;
+ tmp_uf = off[n-1].l_uf;
+ M_SUB(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
+ disp = MFPTOFP(tmp_ui, tmp_uf);
+ if (disp > OMEGAMAXDISPERSE)
+ return 0;
+ *offset = off[(n+1)/2];
+ *dispersion = disp;
+ return 1;
+}
+
+
+/*
+ * omega_poll - called by the transmit procedure
+ */
+static void
+omega_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ struct omegaunit *omega;
+
+ /*
+ * You don't need to poll this clock. It puts out timecodes
+ * once per second. If asked for a timestamp, take note.
+ * The next time a timecode comes in, it will be fed back.
+ */
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_poll: unit %d invalid", unit);
+ return;
+ }
+ if (!unitinuse[unit]) {
+ syslog(LOG_ERR, "omega_poll: unit %d not in use", unit);
+ return;
+ }
+ omega = omegaunits[unit];
+ if ((current_time - omega->lasttime) > 150) {
+ omega->noreply++;
+ omega_report_event(omegaunits[unit], CEVNT_TIMEOUT);
+ }
+
+ /*
+ * polled every 64 seconds. Ask OMEGA_RECEIVE to hand in a timestamp.
+ */
+ omega->polled = 1;
+ omega->polls++;
+ /*
+ * Ensure the clock is running in the correct mode - on-second
+ * timestamps.
+ */
+ omega_send(omega,"C");
+}
+
+
+/*
+ * omega_control - set fudge factors, return statistics
+ */
+static void
+omega_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct omegaunit *omega;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_control: unit %d invalid", unit);
+ return;
+ }
+
+ if (in != 0) {
+ if (in->haveflags & CLK_HAVETIME1)
+ fudgefactor1[unit] = in->fudgetime1;
+ if (in->haveflags & CLK_HAVETIME2)
+ fudgefactor2[unit] = in->fudgetime2;
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
+ readonlyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = omegaunits[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
+ }
+ }
+
+ if (out != 0) {
+ out->type = REFCLK_OMEGA_TRUETIME;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVETIME2 | CLK_HAVEVAL1 |
+ CLK_HAVEVAL2| CLK_HAVEFLAG1;
+ out->clockdesc = OMEGADESCRIPTION;
+ out->fudgetime1 = fudgefactor1[unit];
+ out->fudgetime2 = fudgefactor2[unit];
+ out->fudgeval1 = (LONG)stratumtouse[unit];
+ out->fudgeval2 = refid[unit];
+ out->flags = readonlyclockflag[unit];
+ if (unitinuse[unit]) {
+ omega = omegaunits[unit];
+ out->flags |= omega->station << 1;
+ out->lencode = omega->lencode;
+ out->lastcode = omega->lastcode;
+ out->timereset = current_time - omega->timestarted;
+ out->polls = omega->polls;
+ out->noresponse = omega->noreply;
+ out->badformat = omega->badformat;
+ out->baddata = omega->baddata;
+ out->lastevent = omega->lastevent;
+ out->currentstatus = omega->status;
+ }
+ }
+}
+
+
+/*
+ * omega_buginfo - return clock dependent debugging info
+ */
+static void
+omega_buginfo(unit, bug)
+ int unit;
+ register struct refclockbug *bug;
+{
+ register struct omegaunit *omega;
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR, "omega_buginfo: unit %d invalid", unit);
+ return;
+ }
+
+ if (!unitinuse[unit])
+ return;
+ omega = omegaunits[unit];
+
+ bug->nvalues = 11;
+ bug->ntimes = 5;
+ if (omega->lasttime != 0)
+ bug->values[0] = current_time - omega->lasttime;
+ else
+ bug->values[0] = 0;
+ bug->values[1] = (U_LONG)omega->reason;
+ bug->values[2] = (U_LONG)omega->year;
+ bug->values[3] = (U_LONG)omega->day;
+ bug->values[4] = (U_LONG)omega->hour;
+ bug->values[5] = (U_LONG)omega->minute;
+ bug->values[6] = (U_LONG)omega->second;
+ bug->values[7] = (U_LONG)omega->msec;
+ bug->values[8] = omega->noreply;
+ bug->values[9] = omega->yearstart;
+ bug->values[10] = omega->quality;
+ bug->stimes = 0x1c;
+ bug->times[0] = omega->lastref;
+ bug->times[1] = omega->lastrec;
+ bug->times[2] = omega->offset[0];
+ bug->times[3] = omega->offset[1];
+ bug->times[4] = omega->offset[2];
+}
+#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_old/refclock_parse.c b/usr.sbin/xntpd/xntpd/refclock_old/refclock_parse.c
new file mode 100644
index 000000000000..0d95d18908a5
--- /dev/null
+++ b/usr.sbin/xntpd/xntpd/refclock_old/refclock_parse.c
@@ -0,0 +1,3605 @@
+#if defined(REFCLOCK) && (defined(PARSE) || defined(PARSEPPS))
+/*
+ * /src/NTP/REPOSITORY/v3/xntpd/refclock_parse.c,v 3.53 1994/03/25 13:07:39 kardel Exp
+ *
+ * refclock_parse.c,v 3.53 1994/03/25 13:07:39 kardel Exp
+ *
+ * generic reference clock driver for receivers
+ *
+ * make use of a STREAMS module for input processing where
+ * available and configured. Currently the STREAMS module
+ * is only available for Suns running SunOS 4.x and SunOS5.x (new - careful!)
+ *
+ * Copyright (c) 1989,1990,1991,1992,1993,1994
+ * Frank Kardel Friedrich-Alexander Universitaet Erlangen-Nuernberg
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/*
+ * Defines:
+ * REFCLOCK && (PARSE||PARSEPPS)
+ * - enable this mess
+ * STREAM - allow for STREAMS modules
+ * ("parse", "ppsclocd", "ppsclock")
+ * PARSEPPS - provide PPS information to loopfilter (for
+ * backward compatibilty only)
+ * 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
+ * HAVE_TERMIOS - will use termios.h
+ * STREAM - will use streams and implies HAVE_TERMIOS
+ */
+
+/*
+ * This driver currently provides the support for
+ * - Meinberg DCF77 receiver DCF77 PZF 535 (TCXO version) (DCF)
+ * - Meinberg DCF77 receiver DCF77 PZF 535 (OCXO version) (DCF)
+ * - Meinberg DCF77 receiver U/A 31 (DCF)
+ * - ELV DCF7000 (DCF)
+ * - Schmid clock (DCF)
+ * - Conrad DCF77 receiver module (DCF)
+ * - FAU DCF77 NTP receiver (TimeBrick) (DCF)
+ * - Meinberg GPS166 (GPS)
+ * - Trimble SV6 (GPS)
+ *
+ */
+
+/*
+ * Meinberg receivers are connected via a 9600 baud serial line
+ *
+ * Receivers that do NOT support:
+ * - leap second indication
+ * DCF U/A 31
+ * DCF PZF535 (stock version)
+ *
+ * so...
+ * - for PZF535 please ask for revision PZFUERL4.6 or higher
+ * (support for leap second and alternate antenna)
+ *
+ * The Meinberg GPS receiver also has a special NTP time stamp
+ * format. The firmware release is Uni-Erlangen. Only this
+ * firmware release is supported by xntp3.
+ *
+ * Meinberg generic receiver setup:
+ * output time code every second
+ * Baud rate 9600 7E2S
+ */
+
+#include "ntpd.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_control.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#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)
+/* #error NEED TO DEFINE ONE OF "STREAM" or "HAVE_SYSV_TTYS" */
+NEED TO DEFINE ONE OF "STREAM", "HAVE_SYSV_TTYS" or "HAVE_TERMIOS"
+#endif
+
+#ifdef STREAM
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#ifndef HAVE_TERMIOS
+#define HAVE_TERMIOS
+#endif
+#endif
+
+#ifdef HAVE_TERMIOS
+#include <termios.h>
+#define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
+#define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
+#undef HAVE_SYSV_TTYS
+#endif
+
+#ifdef HAVE_SYSV_TTYS
+#include <termio.h>
+#define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
+#define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
+#endif
+
+#ifdef HAVE_BSD_TTYS
+/* #error CURRENTLY NO BSD TTY SUPPORT */
+CURRENTLY NO BSD TTY SUPPORT
+#endif
+
+#if !defined(O_RDWR) /* XXX SOLARIS */
+#include <fcntl.h>
+#endif /* !def(O_RDWR) */
+
+#ifdef PPSPPS
+#include <sys/ppsclock.h>
+#endif
+
+#include "ntp_select.h"
+#include "ntp_stdlib.h"
+
+#include "parse.h"
+
+#if !defined(NO_SCCSID) && !defined(lint) && !defined(__GNUC__)
+static char rcsid[]="refclock_parse.c,v 3.53 1994/03/25 13:07:39 kardel Exp";
+#endif
+
+/**===========================================================================
+ ** external interface to xntp mechanism
+ **/
+
+static void parse_init P((void));
+static int parse_start P((u_int, struct peer *));
+static void parse_shutdown P((int));
+static void parse_poll P((int, struct peer *));
+static void parse_control P((u_int, struct refclockstat *, struct refclockstat *));
+
+#define parse_buginfo noentry
+
+struct refclock refclock_parse = {
+ parse_start,
+ parse_shutdown,
+ parse_poll,
+ parse_control,
+ parse_init,
+ parse_buginfo,
+ NOFLAGS
+};
+
+/*
+ * the unit field selects for one the prototype to be used (lower 4 bits)
+ * and for the other the clock type in case of different but similar
+ * receivers (bits 4-6)
+ * the most significant bit encodes PPS support
+ * when the most significant bit is set the pps telegrams will be used
+ * for controlling the local clock (ntp_loopfilter.c)
+ * receiver specific configration data is kept in the clockinfo field.
+ */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 4 /* maximum number of "PARSE" units permitted */
+#define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */
+
+/**===========================================================================
+ ** function vector for dynamically binding io handling mechanism
+ **/
+
+typedef struct bind
+{
+ char *bd_description; /* name of type of binding */
+ int (*bd_init)(); /* initialize */
+ void (*bd_end)(); /* end */
+ int (*bd_setcs)(); /* set character size */
+ int (*bd_disable)(); /* disable */
+ int (*bd_enable)(); /* enable */
+ int (*bd_getfmt)(); /* get format */
+ int (*bd_setfmt)(); /* setfmt */
+ int (*bd_getstat)(); /* getstat */
+ int (*bd_setstat)(); /* setstat */
+ int (*bd_timecode)(); /* get time code */
+ void (*bd_receive)(); /* receive operation */
+ void (*bd_poll)(); /* poll operation */
+} bind_t;
+
+#define PARSE_END(_X_) (*(_X_)->binding->bd_end)(_X_)
+#define PARSE_SETCS(_X_, _CS_) (*(_X_)->binding->bd_setcs)(_X_, _CS_)
+#define PARSE_ENABLE(_X_) (*(_X_)->binding->bd_enable)(_X_)
+#define PARSE_DISABLE(_X_) (*(_X_)->binding->bd_disable)(_X_)
+#define PARSE_GETFMT(_X_, _DCT_) (*(_X_)->binding->bd_getfmt)(_X_, _DCT_)
+#define PARSE_SETFMT(_X_, _DCT_) (*(_X_)->binding->bd_setfmt)(_X_, _DCT_)
+#define PARSE_GETSTAT(_X_, _DCT_) (*(_X_)->binding->bd_getstat)(_X_, _DCT_)
+#define PARSE_SETSTAT(_X_, _DCT_) (*(_X_)->binding->bd_setstat)(_X_, _DCT_)
+#define PARSE_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)
+#define PARSE_POLL(_X_) (*(_X_)->binding->bd_poll)(_X_)
+
+/*
+ * io modes
+ */
+#define PARSE_F_NOPOLLONLY 0x0001 /* always do async io (possible PPS support via PARSE) */
+#define PARSE_F_POLLONLY 0x0002 /* never do async io (no PPS support via PARSE) */
+#define PARSE_F_PPSPPS 0x0004 /* use loopfilter PPS code (CIOGETEV) */
+#define PARSE_F_PPSONSECOND 0x0008 /* PPS pulses are on second */
+
+/**===========================================================================
+ ** refclock instance data
+ **/
+
+struct parseunit
+{
+ /*
+ * XNTP management
+ */
+ struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */
+ int fd; /* device file descriptor */
+ u_char unit; /* encoded unit/type/PPS */
+
+ /*
+ * XNTP io
+ */
+ struct refclockio io; /* io system structure (used in PPS mode) */
+ bind_t *binding; /* io handling binding */
+
+ /*
+ * parse state
+ */
+ parse_t parseio; /* io handling structure (user level parsing) */
+
+ /*
+ * type specific parameters
+ */
+ struct clockinfo *parse_type; /* link to clock description */
+
+ /*
+ * clock specific configuration
+ */
+ l_fp basedelay; /* clock local phase offset */
+ l_fp ppsdelay; /* clock local pps phase offset */
+
+ /*
+ * clock state handling/reporting
+ */
+ u_char flags; /* flags (leap_control) */
+ u_char status; /* current status */
+ u_char lastevent; /* last not NORMAL status */
+ U_LONG lastchange; /* time (xntp) when last state change accured */
+ U_LONG statetime[CEVNT_MAX+1]; /* accumulated time of clock states */
+ struct event stattimer; /* statistics timer */
+ U_LONG polls; /* polls from NTP protocol machine */
+ U_LONG noresponse; /* number of expected but not seen datagrams */
+ U_LONG badformat; /* bad format (failed format conversions) */
+ U_LONG baddata; /* usually bad receive length, bad format */
+
+ u_char pollonly; /* 1 for polling only (no PPS mode) */
+ u_char pollneeddata; /* 1 for receive sample expected in PPS mode */
+ U_LONG laststatus; /* last packet status (error indication) */
+ u_short lastformat; /* last format used */
+ U_LONG lastsync; /* time (xntp) when clock was last seen fully synchronized */
+ U_LONG timestarted; /* time (xntp) when peer clock was instantiated */
+ U_LONG nosynctime; /* time (xntp) when last nosync message was posted */
+ U_LONG lastmissed; /* time (xntp) when poll didn't get data (powerup heuristic) */
+ U_LONG ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
+ parsetime_t time; /* last (parse module) data */
+ void *localdata; /* optional local data */
+};
+
+
+/**===========================================================================
+ ** Clockinfo section all parameter for specific clock types
+ ** includes NTP paramaters, TTY parameters and IO handling parameters
+ **/
+
+static void poll_dpoll P((struct parseunit *));
+static void poll_poll P((struct parseunit *));
+static int poll_init P((struct parseunit *));
+static void poll_end P((struct parseunit *));
+
+typedef struct poll_info
+{
+ U_LONG rate; /* poll rate - once every "rate" seconds - 0 off */
+ char * string; /* string to send for polling */
+ U_LONG count; /* number of charcters in string */
+} poll_info_t;
+
+#define NO_FLAGS 0
+#define NO_POLL (void (*)())0
+#define NO_INIT (int (*)())0
+#define NO_END (void (*)())0
+#define NO_DATA (void *)0
+#define NO_FORMAT ""
+#define NO_PPSDELAY 0
+
+#define DCF_ID "DCF" /* generic DCF */
+#define DCF_A_ID "DCFa" /* AM demodulation */
+#define DCF_P_ID "DCFp" /* psuedo random phase shift */
+#define GPS_ID "GPS" /* GPS receiver */
+
+#define NOCLOCK_ROOTDELAY 0x00000000
+#define NOCLOCK_BASEDELAY 0x00000000
+#define NOCLOCK_DESCRIPTION ((char *)0)
+#define NOCLOCK_MAXUNSYNC 0
+#define NOCLOCK_CFLAG 0
+#define NOCLOCK_IFLAG 0
+#define NOCLOCK_OFLAG 0
+#define NOCLOCK_LFLAG 0
+#define NOCLOCK_ID "TILT"
+#define NOCLOCK_POLL NO_POLL
+#define NOCLOCK_INIT NO_INIT
+#define NOCLOCK_END NO_END
+#define NOCLOCK_DATA NO_DATA
+#define NOCLOCK_FORMAT NO_FORMAT
+#define NOCLOCK_TYPE CTL_SST_TS_UNSPEC
+
+#define DCF_TYPE CTL_SST_TS_LF
+#define GPS_TYPE CTL_SST_TS_UHF
+
+/*
+ * receiver specific constants
+ */
+#define MBG_CFLAG19200 (B19200|CS7|PARENB|CREAD|HUPCL)
+#define MBG_CFLAG (B9600|CS7|PARENB|CREAD|HUPCL)
+#define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)
+#define MBG_OFLAG 0
+#define MBG_LFLAG 0
+/*
+ * Meinberg DCF U/A 31 (AM) receiver
+ */
+#define DCFUA31_ROOTDELAY 0x00000D00 /* 50.78125ms */
+#define DCFUA31_BASEDELAY 0x02C00000 /* 10.7421875ms: 10 ms (+/- 3 ms) */
+#define DCFUA31_DESCRIPTION "Meinberg DCF U/A 31"
+#define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */
+#define DCFUA31_CFLAG MBG_CFLAG
+#define DCFUA31_IFLAG MBG_IFLAG
+#define DCFUA31_OFLAG MBG_OFLAG
+#define DCFUA31_LFLAG MBG_LFLAG
+
+/*
+ * Meinberg DCF PZF535/TCXO (FM/PZF) receiver
+ */
+#define DCFPZF535_ROOTDELAY 0x00000034 /* 800us */
+#define DCFPZF535_BASEDELAY 0x00800000 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
+#define DCFPZF535_DESCRIPTION "Meinberg DCF PZF 535/TCXO"
+#define DCFPZF535_MAXUNSYNC 60*60*12 /* only trust clock for 12 hours
+ * @ 5e-8df/f we have accumulated
+ * at most 2.16 ms (thus we move to
+ * NTP synchronisation */
+#define DCFPZF535_CFLAG MBG_CFLAG
+#define DCFPZF535_IFLAG MBG_IFLAG
+#define DCFPZF535_OFLAG MBG_OFLAG
+#define DCFPZF535_LFLAG MBG_LFLAG
+
+
+/*
+ * Meinberg DCF PZF535/OCXO receiver
+ */
+#define DCFPZF535OCXO_ROOTDELAY 0x00000034 /* 800us (max error * 10) */
+#define DCFPZF535OCXO_BASEDELAY 0x00800000 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
+#define DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/OCXO"
+#define DCFPZF535OCXO_MAXUNSYNC 60*60*96 /* only trust clock for 4 days
+ * @ 5e-9df/f we have accumulated
+ * at most an error of 1.73 ms
+ * (thus we move to NTP synchronisation) */
+#define DCFPZF535OCXO_CFLAG MBG_CFLAG
+#define DCFPZF535OCXO_IFLAG MBG_IFLAG
+#define DCFPZF535OCXO_OFLAG MBG_OFLAG
+#define DCFPZF535OCXO_LFLAG MBG_LFLAG
+
+/*
+ * Meinberg GPS166 receiver
+ */
+#define GPS166_ROOTDELAY 0x00000000 /* nothing here */
+#define GPS166_BASEDELAY 0x00800000 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
+#define GPS166_DESCRIPTION "Meinberg GPS166 receiver"
+#define GPS166_MAXUNSYNC 0 /* this clock is immediately lost */
+#define GPS166_CFLAG MBG_CFLAG
+#define GPS166_IFLAG MBG_IFLAG
+#define GPS166_OFLAG MBG_OFLAG
+#define GPS166_LFLAG MBG_LFLAG
+#define GPS166_POLL NO_POLL
+#define GPS166_INIT NO_INIT
+#define GPS166_END NO_END
+#define GPS166_DATA NO_DATA
+#define GPS166_ID GPS_ID
+#define GPS166_FORMAT NO_FORMAT
+
+/*
+ * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit)
+ *
+ * This is really not the hottest clock - but before you have nothing ...
+ */
+#define DCF7000_ROOTDELAY 0x00000364 /* 13 ms */
+#define DCF7000_BASEDELAY 0x67AE0000 /* 405 ms - slow blow */
+#define DCF7000_DESCRIPTION "ELV DCF7000"
+#define DCF7000_MAXUNSYNC (60*5) /* sorry - but it just was not build as a clock */
+#define DCF7000_CFLAG (B9600|CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL)
+#define DCF7000_IFLAG (IGNBRK)
+#define DCF7000_OFLAG 0
+#define DCF7000_LFLAG 0
+
+/*
+ * Schmid DCF Receiver Kit
+ *
+ * When the WSDCF clock is operating optimally we want the primary clock
+ * distance to come out at 300 ms. Thus, peer.distance in the WSDCF peer
+ * structure is set to 290 ms and we compute delays which are at least
+ * 10 ms long. The following are 290 ms and 10 ms expressed in u_fp format
+ */
+#define WS_POLLRATE 1 /* every second - watch interdependency with poll routine */
+#define WS_POLLCMD "\163"
+#define WS_CMDSIZE 1
+
+static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
+
+#define WSDCF_INIT poll_init
+#define WSDCF_POLL poll_dpoll
+#define WSDCF_END poll_end
+#define WSDCF_DATA ((void *)(&wsdcf_pollinfo))
+#define WSDCF_ROOTDELAY 0X00004A3D /* ~ 290ms */
+#define WSDCF_BASEDELAY 0x028F5C29 /* ~ 10ms */
+#define WSDCF_DESCRIPTION "WS/DCF Receiver"
+#define WSDCF_FORMAT "Schmid"
+#define WSDCF_MAXUNSYNC (60*60) /* assume this beast hold at 1 h better than 2 ms XXX-must verify */
+#define WSDCF_CFLAG (B1200|CS8|CREAD|CLOCAL)
+#define WSDCF_IFLAG 0
+#define WSDCF_OFLAG 0
+#define WSDCF_LFLAG 0
+
+/*
+ * RAW DCF77 - input of DCF marks via RS232 - many variants
+ */
+#define RAWDCF_FLAGS PARSE_F_NOPOLLONLY
+#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
+
+/*
+ * RAW DCF variants
+ */
+/*
+ * Conrad receiver
+ *
+ * simplest (cheapest) DCF clock - e. g. DCF77 receiver by Conrad
+ * (~40DM - roughly $30 ) followed by a level converter for RS232
+ */
+#define CONRAD_BASEDELAY 0x420C49B0 /* ~258 ms - Conrad receiver @ 50 Baud on a Sun */
+#define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)"
+
+/*
+ * TimeBrick receiver
+ */
+#define TIMEBRICK_BASEDELAY 0x35C29000 /* ~210 ms - TimeBrick @ 50 Baud on a Sun */
+#define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)"
+
+/*
+ * Trimble SV6 GPS receiver
+ */
+#define TRIM_POLLRATE 0 /* only true direct polling */
+#define TRIM_POLLCMD ">QTM<"
+#define TRIM_CMDSIZE 5
+
+static poll_info_t trimble_pollinfo = { TRIM_POLLRATE, TRIM_POLLCMD, TRIM_CMDSIZE };
+static int trimble_init P((struct parseunit *));
+
+#define TRIMBLESV6_CFLAG (B4800|CS8|CREAD)
+#define TRIMBLESV6_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
+#define TRIMBLESV6_OFLAG (OPOST|ONLCR)
+#define TRIMBLESV6_LFLAG (ICANON|ECHOK)
+#define TRIMBLESV6_FLAGS (PARSE_F_PPSPPS|PARSE_F_PPSONSECOND)
+#define TRIMBLESV6_POLL poll_dpoll
+#define TRIMBLESV6_INIT trimble_init
+#define TRIMBLESV6_END poll_end
+#define TRIMBLESV6_DATA ((void *)(&trimble_pollinfo))
+#define TRIMBLESV6_ID GPS_ID
+#define TRIMBLESV6_FORMAT NO_FORMAT
+#define TRIMBLESV6_ROOTDELAY 0x0
+#define TRIMBLESV6_BASEDELAY 0x0
+#define TRIMBLESV6_DESCRIPTION "Trimble SV6 GPS receiver"
+#define TRIMBLESV6_MAXUNSYNC 0
+#define TRIMBLESV6_EOL '<'
+
+static struct clockinfo
+{
+ U_LONG cl_flags; /* operation flags (io modes) */
+ void (*cl_poll)(); /* active poll routine */
+ int (*cl_init)(); /* active poll init routine */
+ void (*cl_end)(); /* active poll end routine */
+ void *cl_data; /* local data area for "poll" mechanism */
+ u_fp cl_rootdelay; /* rootdelay */
+ U_LONG cl_basedelay; /* current offset - unsigned l_fp fractional part */
+ U_LONG cl_ppsdelay; /* current PPS offset - unsigned l_fp fractional part */
+ char *cl_id; /* ID code (usually "DCF") */
+ char *cl_description; /* device name */
+ char *cl_format; /* fixed format */
+ u_char cl_type; /* clock type (ntp control) */
+ U_LONG cl_maxunsync; /* time to trust oscillator after loosing synch */
+ 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 */
+} clockinfo[] =
+{ /* 0. 0.0.128 - base offset for PPS support */
+ { /* 127.127.8.<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCFPZF535_ROOTDELAY,
+ DCFPZF535_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_P_ID,
+ DCFPZF535_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCFPZF535_MAXUNSYNC,
+ DCFPZF535_CFLAG,
+ DCFPZF535_IFLAG,
+ DCFPZF535_OFLAG,
+ DCFPZF535_LFLAG
+ },
+ { /* 127.127.8.4+<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCFPZF535OCXO_ROOTDELAY,
+ DCFPZF535OCXO_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_P_ID,
+ DCFPZF535OCXO_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCFPZF535OCXO_MAXUNSYNC,
+ DCFPZF535OCXO_CFLAG,
+ DCFPZF535OCXO_IFLAG,
+ DCFPZF535OCXO_OFLAG,
+ DCFPZF535OCXO_LFLAG
+ },
+ { /* 127.127.8.8+<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCFUA31_ROOTDELAY,
+ DCFUA31_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ DCFUA31_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCFUA31_MAXUNSYNC,
+ DCFUA31_CFLAG,
+ DCFUA31_IFLAG,
+ DCFUA31_OFLAG,
+ DCFUA31_LFLAG
+ },
+ { /* 127.127.8.12+<device> */
+ NO_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ DCF7000_ROOTDELAY,
+ DCF7000_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ DCF7000_DESCRIPTION,
+ NO_FORMAT,
+ DCF_TYPE,
+ DCF7000_MAXUNSYNC,
+ DCF7000_CFLAG,
+ DCF7000_IFLAG,
+ DCF7000_OFLAG,
+ DCF7000_LFLAG
+ },
+ { /* 127.127.8.16+<device> */
+ NO_FLAGS,
+ WSDCF_POLL,
+ WSDCF_INIT,
+ WSDCF_END,
+ WSDCF_DATA,
+ WSDCF_ROOTDELAY,
+ WSDCF_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ WSDCF_DESCRIPTION,
+ WSDCF_FORMAT,
+ DCF_TYPE,
+ WSDCF_MAXUNSYNC,
+ WSDCF_CFLAG,
+ WSDCF_IFLAG,
+ WSDCF_OFLAG,
+ WSDCF_LFLAG
+ },
+ { /* 127.127.8.20+<device> */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ RAWDCF_ROOTDELAY,
+ CONRAD_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ CONRAD_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ RAWDCF_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG
+ },
+ { /* 127.127.8.24+<device> */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_END,
+ NO_DATA,
+ RAWDCF_ROOTDELAY,
+ TIMEBRICK_BASEDELAY,
+ NO_PPSDELAY,
+ DCF_A_ID,
+ TIMEBRICK_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ RAWDCF_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG
+ },
+ { /* 127.127.8.28+<device> */
+ NO_FLAGS,
+ GPS166_POLL,
+ GPS166_INIT,
+ GPS166_END,
+ GPS166_DATA,
+ GPS166_ROOTDELAY,
+ GPS166_BASEDELAY,
+ NO_PPSDELAY,
+ GPS166_ID,
+ GPS166_DESCRIPTION,
+ GPS166_FORMAT,
+ GPS_TYPE,
+ GPS166_MAXUNSYNC,
+ GPS166_CFLAG,
+ GPS166_IFLAG,
+ GPS166_OFLAG,
+ GPS166_LFLAG
+ },
+ { /* 127.127.8.32+<device> */
+ TRIMBLESV6_FLAGS,
+ TRIMBLESV6_POLL,
+ TRIMBLESV6_INIT,
+ TRIMBLESV6_END,
+ TRIMBLESV6_DATA,
+ TRIMBLESV6_ROOTDELAY,
+ TRIMBLESV6_BASEDELAY,
+ NO_PPSDELAY,
+ TRIMBLESV6_ID,
+ TRIMBLESV6_DESCRIPTION,
+ TRIMBLESV6_FORMAT,
+ GPS_TYPE,
+ TRIMBLESV6_MAXUNSYNC,
+ TRIMBLESV6_CFLAG,
+ TRIMBLESV6_IFLAG,
+ TRIMBLESV6_OFLAG,
+ TRIMBLESV6_LFLAG
+ }
+};
+
+static int ncltypes = sizeof(clockinfo) / sizeof(struct clockinfo);
+
+#define CL_REALTYPE(x) (((x) >> 2) & 0x1F)
+#define CL_TYPE(x) ((CL_REALTYPE(x) >= ncltypes) ? ~0 : CL_REALTYPE(x))
+#define CL_PPS(x) ((x) & 0x80)
+#define CL_UNIT(x) ((x) & 0x3)
+
+/*
+ * Other constant stuff
+ */
+#define PARSEHSREFID 0x7f7f08ff /* 127.127.8.255 refid for hi strata */
+
+#define PARSENOSYNCREPEAT (10*60) /* mention uninitialized clocks all 10 minutes */
+#define PARSESTATISTICS (60*60) /* output state statistics every hour */
+
+static struct parseunit *parseunits[MAXUNITS];
+
+extern U_LONG current_time;
+extern s_char sys_precision;
+extern struct event timerqueue[];
+#ifdef PPSPPS
+extern int fdpps;
+#endif
+
+static int notice = 0;
+
+#define PARSE_STATETIME(parse, i) ((parse->status == i) ? parse->statetime[i] + current_time - parse->lastchange : parse->statetime[i])
+
+static void parse_event P((struct parseunit *, int));
+static void parse_process P((struct parseunit *, parsetime_t *));
+
+/**===========================================================================
+ ** implementation of i/o handling methods
+ ** (all STREAM, partial STREAM, user level)
+ **/
+
+/*
+ * define possible io handling methods
+ */
+#ifdef STREAM
+static int ppsclock_init P((struct parseunit *));
+static int stream_init P((struct parseunit *));
+static void stream_nop P((struct parseunit *));
+static int stream_enable P((struct parseunit *));
+static int stream_disable P((struct parseunit *));
+static int stream_setcs P((struct parseunit *, parsectl_t *));
+static int stream_getfmt P((struct parseunit *, parsectl_t *));
+static int stream_setfmt P((struct parseunit *, parsectl_t *));
+static int stream_getstat P((struct parseunit *, parsectl_t *));
+static int stream_setstat P((struct parseunit *, parsectl_t *));
+static int stream_timecode P((struct parseunit *, parsectl_t *));
+static void stream_receive P((struct recvbuf *));
+static void stream_poll P((struct parseunit *));
+#endif
+
+static int local_init P((struct parseunit *));
+static void local_end P((struct parseunit *));
+static int local_nop P((struct parseunit *));
+static int local_setcs P((struct parseunit *, parsectl_t *));
+static int local_getfmt P((struct parseunit *, parsectl_t *));
+static int local_setfmt P((struct parseunit *, parsectl_t *));
+static int local_getstat P((struct parseunit *, parsectl_t *));
+static int local_setstat P((struct parseunit *, parsectl_t *));
+static int local_timecode P((struct parseunit *, parsectl_t *));
+static void local_receive P((struct recvbuf *));
+static void local_poll P((struct parseunit *));
+
+static bind_t io_bindings[] =
+{
+#ifdef STREAM
+ {
+ "parse STREAM",
+ stream_init,
+ stream_nop,
+ stream_setcs,
+ stream_disable,
+ stream_enable,
+ stream_getfmt,
+ stream_setfmt,
+ stream_getstat,
+ stream_setstat,
+ stream_timecode,
+ stream_receive,
+ stream_poll
+ },
+ {
+ "ppsclock STREAM",
+ ppsclock_init,
+ local_end,
+ local_setcs,
+ local_nop,
+ local_nop,
+ local_getfmt,
+ local_setfmt,
+ local_getstat,
+ local_setstat,
+ local_timecode,
+ local_receive,
+ local_poll
+ },
+#endif
+ {
+ "normal",
+ local_init,
+ local_end,
+ local_setcs,
+ local_nop,
+ local_nop,
+ local_getfmt,
+ local_setfmt,
+ local_getstat,
+ local_setstat,
+ local_timecode,
+ local_receive,
+ local_poll
+ },
+ {
+ (char *)0,
+ }
+};
+
+#ifdef STREAM
+/*--------------------------------------------------
+ * ppsclock STREAM init
+ */
+static int
+ppsclock_init(parse)
+ struct parseunit *parse;
+{
+ /*
+ * now push the parse streams module
+ * it will ensure exclusive access to the device
+ */
+ if (ioctl(parse->fd, I_PUSH, (caddr_t)"ppsclocd") == -1 &&
+ ioctl(parse->fd, I_PUSH, (caddr_t)"ppsclock") == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m",
+ CL_UNIT(parse->unit));
+ return 0;
+ }
+ if (!local_init(parse))
+ {
+ (void)ioctl(parse->fd, I_POP, (caddr_t)0);
+ return 0;
+ }
+
+ parse->flags |= PARSE_PPSCLOCK;
+ return 1;
+}
+
+/*--------------------------------------------------
+ * parse STREAM init
+ */
+static int
+stream_init(parse)
+ struct parseunit *parse;
+{
+ /*
+ * now push the parse streams module
+ * to test whether it is there (Oh boy - neat kernel interface)
+ */
+ if (ioctl(parse->fd, I_PUSH, (caddr_t)"parse") == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ else
+ {
+ while(ioctl(parse->fd, I_POP, (caddr_t)0) == 0)
+ /* empty loop */;
+
+ /*
+ * now push it a second time after we have removed all
+ * module garbage
+ */
+ if (ioctl(parse->fd, I_PUSH, (caddr_t)"parse") == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+}
+
+ /*--------------------------------------------------
+ * STREAM setcs
+ */
+static int
+stream_setcs(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_SETCS;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_setcs: ioctl(fd, I_STR, PARSEIOC_SETCS): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM nop
+ */
+static void
+stream_nop(parse)
+ struct parseunit *parse;
+{
+}
+
+/*--------------------------------------------------
+ * STREAM enable
+ */
+static int
+stream_enable(parse)
+ struct parseunit *parse;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_ENABLE;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)0;
+ strioc.ic_len = 0;
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_enable: ioctl(fd, I_STR, PARSEIOC_ENABLE): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM disable
+ */
+static int
+stream_disable(parse)
+ struct parseunit *parse;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_DISABLE;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)0;
+ strioc.ic_len = 0;
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_disable: ioctl(fd, I_STR, PARSEIOC_DISABLE): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM getfmt
+ */
+static int
+stream_getfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_GETFMT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: ioctl(fd, I_STR, PARSEIOC_GETFMT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM setfmt
+ */
+static int
+stream_setfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_SETFMT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_setfmt: ioctl(fd, I_STR, PARSEIOC_SETFMT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM getstat
+ */
+static int
+stream_getstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_GETSTAT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_getstat: ioctl(fd, I_STR, PARSEIOC_GETSTAT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM setstat
+ */
+static int
+stream_setstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_SETSTAT;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: stream_setstat: ioctl(fd, I_STR, PARSEIOC_SETSTAT): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM timecode
+ */
+static int
+stream_timecode(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ struct strioctl strioc;
+
+ strioc.ic_cmd = PARSEIOC_TIMECODE;
+ strioc.ic_timout = 0;
+ strioc.ic_dp = (char *)tcl;
+ strioc.ic_len = sizeof (*tcl);
+
+ if (ioctl(parse->fd, I_STR, (caddr_t)&strioc) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_process: ioctl(fd, I_STR, PARSEIOC_TIMECODE): %m", CL_UNIT(parse->unit), parse->fd);
+ return 0;
+ }
+ return 1;
+}
+
+/*--------------------------------------------------
+ * STREAM receive
+ */
+static void
+stream_receive(rbufp)
+ struct recvbuf *rbufp;
+{
+ struct parseunit *parse = (struct parseunit *)rbufp->recv_srcclock;
+ parsetime_t parsetime;
+
+ if (rbufp->recv_length != sizeof(parsetime_t))
+ {
+ syslog(LOG_ERR,"PARSE receiver #%d: parse_receive: bad size (got %d expected %d)",
+ CL_UNIT(parse->unit), rbufp->recv_length, sizeof(parsetime_t));
+ parse->baddata++;
+ parse_event(parse, CEVNT_BADREPLY);
+ return;
+ }
+ memmove((caddr_t)&parsetime,
+ (caddr_t)&rbufp->recv_space,
+ sizeof(parsetime_t));
+
+ /*
+ * switch time stamp world - be sure to normalize small usec field
+ * errors.
+ */
+
+#define fix_ts(_X_) \
+ if ((&(_X_))->tv.tv_usec >= 1000000) \
+ { \
+ (&(_X_))->tv.tv_usec -= 1000000; \
+ (&(_X_))->tv.tv_sec += 1; \
+ }
+
+#define cvt_ts(_X_, _Y_) \
+ { \
+ l_fp ts; \
+ \
+ fix_ts((_X_)); \
+ if (!buftvtots((const char *)&(&(_X_))->tv, &ts)) \
+ { \
+ syslog(LOG_ERR,"parse: stream_receive: timestamp conversion error (buftvtots) (%s) (%d.%06d) ", (_Y_), (&(_X_))->tv.tv_sec, (&(_X_))->tv.tv_usec);\
+ return; \
+ } \
+ else \
+ { \
+ (&(_X_))->fp = ts; \
+ } \
+ }
+
+ if (PARSE_TIMECODE(parsetime.parse_state))
+ {
+ cvt_ts(parsetime.parse_time, "parse_time");
+ cvt_ts(parsetime.parse_stime, "parse_stime");
+ }
+
+ if (PARSE_PPS(parsetime.parse_state))
+ cvt_ts(parsetime.parse_ptime, "parse_ptime");
+
+ parse_process(parse, &parsetime);
+}
+
+/*--------------------------------------------------
+ * STREAM poll
+ */
+static void
+stream_poll(parse)
+ struct parseunit *parse;
+{
+ register int fd, i, rtc;
+ fd_set fdmask;
+ struct timeval timeout, starttime, curtime, selecttime;
+ parsetime_t parsetime;
+
+ /*
+ * now we do the following:
+ * - read the first packet from the parse module (OLD !!!)
+ * - read the second packet from the parse module (fresh)
+ * - compute values for xntp
+ */
+
+ FD_ZERO(&fdmask);
+ fd = parse->fd;
+ FD_SET(fd, &fdmask);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500000; /* 0.5 sec */
+
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+
+ if (GETTIMEOFDAY(&starttime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+
+ selecttime = timeout;
+
+ while ((rtc = select(fd + 1, &fdmask, 0, 0, &selecttime)) != 1)
+ {
+ /* no data from the radio clock */
+
+ if (rtc == -1)
+ {
+ if (errno == EINTR)
+ {
+ if (GETTIMEOFDAY(&curtime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+ selecttime.tv_sec = curtime.tv_sec - starttime.tv_sec;
+ if (curtime.tv_usec < starttime.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + curtime.tv_usec - starttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = curtime.tv_usec - starttime.tv_usec;
+ }
+
+
+ if (timercmp(&selecttime, &timeout, >))
+ {
+ /*
+ * elapsed real time passed timeout value - consider it timed out
+ */
+ break;
+ }
+
+ /*
+ * calculate residual timeout value
+ */
+ selecttime.tv_sec = timeout.tv_sec - selecttime.tv_sec;
+
+ if (selecttime.tv_usec > timeout.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + timeout.tv_usec - selecttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = timeout.tv_usec - selecttime.tv_usec;
+ }
+
+ FD_SET(fd, &fdmask);
+ continue;
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[old] from device (select() error: %m)", CL_UNIT(parse->unit));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[old] from device", CL_UNIT(parse->unit));
+ }
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+
+ return;
+ }
+
+ while (((i = read(fd, (char *)&parsetime, sizeof(parsetime))) < sizeof(parsetime)))
+ {
+ /* bad packet */
+ if ( i == -1)
+ {
+ if (errno == EINTR)
+ {
+ continue;
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[old] from streams module (read() error: %m)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[old] from streams module (got %d bytes - expected %d bytes)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ parse->baddata++;
+ parse_event(parse, CEVNT_BADREPLY);
+
+ return;
+ }
+
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 500000; /* 1.500 sec */
+ FD_ZERO(&fdmask);
+ FD_SET(fd, &fdmask);
+
+ if (GETTIMEOFDAY(&starttime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+
+ selecttime = timeout;
+
+ while ((rtc = select(fd + 1, &fdmask, 0, 0, &selecttime)) != 1)
+ {
+ /* no data from the radio clock */
+
+ if (rtc == -1)
+ {
+ if (errno == EINTR)
+ {
+ if (GETTIMEOFDAY(&curtime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+ selecttime.tv_sec = curtime.tv_sec - starttime.tv_sec;
+ if (curtime.tv_usec < starttime.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + curtime.tv_usec - starttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = curtime.tv_usec - starttime.tv_usec;
+ }
+
+
+ if (timercmp(&selecttime, &timeout, >))
+ {
+ /*
+ * elapsed real time passed timeout value - consider it timed out
+ */
+ break;
+ }
+
+ /*
+ * calculate residual timeout value
+ */
+ selecttime.tv_sec = timeout.tv_sec - selecttime.tv_sec;
+
+ if (selecttime.tv_usec > timeout.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + timeout.tv_usec - selecttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = timeout.tv_usec - selecttime.tv_usec;
+ }
+
+ FD_SET(fd, &fdmask);
+ continue;
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[new] from device (select() error: %m)", CL_UNIT(parse->unit));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data[new] from device", CL_UNIT(parse->unit));
+ }
+
+ /*
+ * we will return here iff we got a good old sample as this would
+ * be misinterpreted. bad samples are passed on to be logged into the
+ * state statistics
+ */
+ if ((parsetime.parse_status & CVT_MASK) == CVT_OK)
+ {
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+ return;
+ }
+ }
+
+ /*
+ * we get here either by a possible read() (rtc == 1 - while assertion)
+ * or by a timeout or a system call error. when a read() is possible we
+ * get the new data, otherwise we stick with the old
+ */
+ if ((rtc == 1) && ((i = read(fd, (char *)&parsetime, sizeof(parsetime))) < sizeof(parsetime)))
+ {
+ /* bad packet */
+ if ( i== -1)
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[new] from streams module (read() error: %m)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: bad read[new] from streams module (got %d bytes - expected %d bytes)", CL_UNIT(parse->unit), i, sizeof(parsetime));
+ }
+ parse->baddata++;
+ parse_event(parse, CEVNT_BADREPLY);
+
+ return;
+ }
+
+ /*
+ * process what we got
+ */
+ parse_process(parse, &parsetime);
+}
+#endif
+
+/*--------------------------------------------------
+ * local init
+ */
+static int
+local_init(parse)
+ struct parseunit *parse;
+{
+ return parse_ioinit(&parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local end
+ */
+static void
+local_end(parse)
+ struct parseunit *parse;
+{
+ parse_ioend(&parse->parseio);
+}
+
+
+/*--------------------------------------------------
+ * local nop
+ */
+static int
+local_nop(parse)
+ struct parseunit *parse;
+{
+ return 1;
+}
+
+/*--------------------------------------------------
+ * local setcs
+ */
+static int
+local_setcs(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_setcs(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local getfmt
+ */
+static int
+local_getfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_getfmt(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local setfmt
+ */
+static int
+local_setfmt(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_setfmt(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local getstat
+ */
+static int
+local_getstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_getstat(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local setstat
+ */
+static int
+local_setstat(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_setstat(tcl, &parse->parseio);
+}
+
+/*--------------------------------------------------
+ * local timecode
+ */
+static int
+local_timecode(parse, tcl)
+ struct parseunit *parse;
+ parsectl_t *tcl;
+{
+ return parse_timecode(tcl, &parse->parseio);
+}
+
+
+/*--------------------------------------------------
+ * local receive
+ */
+static void
+local_receive(rbufp)
+ struct recvbuf *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--)
+ {
+ if (parse_ioread(&parse->parseio, *s++, &rbufp->recv_time))
+ {
+ /*
+ * got something good to eat
+ */
+#ifdef PPSPPS
+ if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state) &&
+ (parse->flags & PARSE_PPSCLOCK))
+ {
+ l_fp ts;
+ struct ppsclockev ev;
+
+ if (ioctl(parse->fd, CIOGETEV, (caddr_t)&ev) == 0)
+ {
+ if (ev.serial != parse->ppsserial)
+ {
+ /*
+ * add PPS time stamp if available via ppsclock module
+ * and not supplied already.
+ */
+ if (!buftvtots((const char *)&ev.tv, &ts))
+ {
+ syslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
+ }
+ else
+ {
+ parse->parseio.parse_dtime.parse_ptime.fp = ts;
+ parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
+ }
+ }
+ parse->ppsserial = ev.serial;
+ }
+ }
+#endif
+ parse_process(parse, &parse->parseio.parse_dtime);
+ parse_iodone(&parse->parseio);
+ }
+ }
+}
+
+/*--------------------------------------------------
+ * local poll
+ */
+static void
+local_poll(parse)
+ struct parseunit *parse;
+{
+ register int fd, i, rtc;
+ fd_set fdmask;
+ struct timeval timeout, starttime, curtime, selecttime;
+ static struct timeval null_time = { 0, 0};
+ timestamp_t ts;
+
+ FD_ZERO(&fdmask);
+ fd = parse->fd;
+ FD_SET(fd, &fdmask);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 500000; /* 1.5 sec */
+
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+
+ if (GETTIMEOFDAY(&starttime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+
+ selecttime = timeout;
+
+ do
+ {
+ while ((rtc = select(fd + 1, &fdmask, 0, 0, &selecttime)) != 1)
+ {
+ /* no data from the radio clock */
+
+ if (rtc == -1)
+ {
+ if (errno == EINTR)
+ {
+ if (GETTIMEOFDAY(&curtime, 0L) == -1)
+ {
+ syslog(LOG_ERR,"gettimeofday failed: %m");
+ exit(1);
+ }
+ selecttime.tv_sec = curtime.tv_sec - starttime.tv_sec;
+ if (curtime.tv_usec < starttime.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + curtime.tv_usec - starttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = curtime.tv_usec - starttime.tv_usec;
+ }
+
+
+ if (!timercmp(&selecttime, &timeout, >))
+ {
+ /*
+ * calculate residual timeout value
+ */
+ selecttime.tv_sec = timeout.tv_sec - selecttime.tv_sec;
+
+ if (selecttime.tv_usec > timeout.tv_usec)
+ {
+ selecttime.tv_sec -= 1;
+ selecttime.tv_usec = 1000000 + timeout.tv_usec - selecttime.tv_usec;
+ }
+ else
+ {
+ selecttime.tv_usec = timeout.tv_usec - selecttime.tv_usec;
+ }
+
+ FD_SET(fd, &fdmask);
+ continue;
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data from device (select() error: %m)", CL_UNIT(parse->unit));
+ }
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data from device", CL_UNIT(parse->unit));
+ }
+
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+
+ return;
+ }
+
+ /*
+ * at least 1 character is available - gobble everthing up that is available
+ */
+ do
+ {
+ char inbuf[256];
+
+ register char *s = inbuf;
+
+ rtc = i = read(fd, inbuf, sizeof(inbuf));
+
+ get_systime(&ts.fp);
+
+ while (i-- > 0)
+ {
+ if (parse_ioread(&parse->parseio, *s++, ts))
+ {
+ /*
+ * got something good to eat
+ */
+ parse_process(parse, &parse->parseio.parse_dtime);
+ parse_iodone(&parse->parseio);
+ /*
+ * done if no more characters are available
+ */
+ FD_SET(fd, &fdmask);
+ if ((i == 0) &&
+ (select(fd + 1, &fdmask, 0, 0, &null_time) == 0))
+ return;
+ }
+ }
+ FD_SET(fd, &fdmask);
+ } while ((rtc = select(fd + 1, &fdmask, 0, 0, &null_time)) == 1);
+ FD_SET(fd, &fdmask);
+ } while (1);
+}
+
+/*--------------------------------------------------
+ * init_iobinding - find and initialize lower layers
+ */
+static bind_t *
+init_iobinding(parse)
+ struct parseunit *parse;
+{
+ register bind_t *b = io_bindings;
+
+ while (b->bd_description != (char *)0)
+ {
+ if ((*b->bd_init)(parse))
+ {
+ return b;
+ }
+ b++;
+ }
+ return (bind_t *)0;
+}
+
+/**===========================================================================
+ ** support routines
+ **/
+
+/*--------------------------------------------------
+ * convert a flag field to a string
+ */
+static char *
+parsestate(state, buffer)
+ unsigned LONG state;
+ char *buffer;
+{
+ static struct bits
+ {
+ unsigned LONG bit;
+ char *name;
+ } flagstrings[] =
+ {
+ { PARSEB_ANNOUNCE, "DST SWITCH WARNING" },
+ { PARSEB_POWERUP, "NOT SYNCHRONIZED" },
+ { PARSEB_NOSYNC, "TIME CODE NOT CONFIRMED" },
+ { PARSEB_DST, "DST" },
+ { PARSEB_UTC, "UTC DISPLAY" },
+ { PARSEB_LEAPADD, "LEAP ADD WARNING" },
+ { PARSEB_LEAPDEL, "LEAP DELETE WARNING" },
+ { PARSEB_LEAPSECOND, "LEAP SECOND" },
+ { PARSEB_ALTERNATE,"ALTERNATE ANTENNA" },
+ { PARSEB_TIMECODE, "TIME CODE" },
+ { PARSEB_PPS, "PPS" },
+ { PARSEB_POSITION, "POSITION" },
+ { 0 }
+ };
+
+ static struct sbits
+ {
+ unsigned LONG bit;
+ char *name;
+ } sflagstrings[] =
+ {
+ { PARSEB_S_LEAP, "LEAP INDICATION" },
+ { PARSEB_S_PPS, "PPS SIGNAL" },
+ { PARSEB_S_ANTENNA, "ANTENNA" },
+ { PARSEB_S_POSITION, "POSITION" },
+ { 0 }
+ };
+ int i;
+
+ *buffer = '\0';
+
+ i = 0;
+ while (flagstrings[i].bit)
+ {
+ if (flagstrings[i].bit & state)
+ {
+ if (buffer[0])
+ strcat(buffer, "; ");
+ strcat(buffer, flagstrings[i].name);
+ }
+ i++;
+ }
+
+ if (state & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
+ {
+ register char *s, *t;
+
+ if (buffer[0])
+ strcat(buffer, "; ");
+
+ strcat(buffer, "(");
+
+ t = s = buffer + strlen(buffer);
+
+ i = 0;
+ while (sflagstrings[i].bit)
+ {
+ if (sflagstrings[i].bit & state)
+ {
+ if (t != s)
+ {
+ strcpy(t, "; ");
+ t += 2;
+ }
+
+ strcpy(t, sflagstrings[i].name);
+ t += strlen(t);
+ }
+ i++;
+ }
+ strcpy(t, ")");
+ }
+ return buffer;
+}
+
+/*--------------------------------------------------
+ * convert a status flag field to a string
+ */
+static char *
+parsestatus(state, buffer)
+ unsigned LONG state;
+ char *buffer;
+{
+ static struct bits
+ {
+ unsigned LONG bit;
+ char *name;
+ } flagstrings[] =
+ {
+ { CVT_OK, "CONVERSION SUCCESSFUL" },
+ { CVT_NONE, "NO CONVERSION" },
+ { CVT_FAIL, "CONVERSION FAILED" },
+ { CVT_BADFMT, "ILLEGAL FORMAT" },
+ { CVT_BADDATE, "DATE ILLEGAL" },
+ { CVT_BADTIME, "TIME ILLEGAL" },
+ { 0 }
+ };
+ int i;
+
+ *buffer = '\0';
+
+ i = 0;
+ while (flagstrings[i].bit)
+ {
+ if (flagstrings[i].bit & state)
+ {
+ if (buffer[0])
+ strcat(buffer, "; ");
+ strcat(buffer, flagstrings[i].name);
+ }
+ i++;
+ }
+
+ return buffer;
+}
+
+/*--------------------------------------------------
+ * convert a clock status flag field to a string
+ */
+static char *
+clockstatus(state)
+ unsigned LONG state;
+{
+ static char buffer[20];
+ static struct status
+ {
+ unsigned LONG value;
+ char *name;
+ } flagstrings[] =
+ {
+ { CEVNT_NOMINAL, "NOMINAL" },
+ { CEVNT_TIMEOUT, "NO RESPONSE" },
+ { CEVNT_BADREPLY,"BAD FORMAT" },
+ { CEVNT_FAULT, "FAULT" },
+ { CEVNT_PROP, "PROPAGATION DELAY" },
+ { CEVNT_BADDATE, "ILLEGAL DATE" },
+ { CEVNT_BADTIME, "ILLEGAL TIME" },
+ { ~0 }
+ };
+ int i;
+
+ i = 0;
+ while (flagstrings[i].value != ~0)
+ {
+ if (flagstrings[i].value == state)
+ {
+ return flagstrings[i].name;
+ }
+ i++;
+ }
+
+ sprintf(buffer, "unknown #%d", state);
+
+ return buffer;
+}
+
+/*--------------------------------------------------
+ * mkascii - make a printable ascii string
+ * assumes (unless defined better) 7-bit ASCII
+ */
+#ifndef isprint
+#define isprint(_X_) (((_X_) > 0x1F) && ((_X_) < 0x7F))
+#endif
+
+static char *
+mkascii(buffer, blen, src, srclen)
+ register char *buffer;
+ register LONG blen;
+ register char *src;
+ register LONG srclen;
+{
+ register char *b = buffer;
+ register char *endb = (char *)0;
+
+ if (blen < 4)
+ return (char *)0; /* don't bother with mini buffers */
+
+ endb = buffer + blen - 4;
+
+ blen--; /* account for '\0' */
+
+ while (blen && srclen--)
+ {
+ if ((*src != '\\') && isprint(*src))
+ { /* printables are easy... */
+ *buffer++ = *src++;
+ blen--;
+ }
+ else
+ {
+ if (blen < 4)
+ {
+ while (blen--)
+ {
+ *buffer++ = '.';
+ }
+ *buffer = '\0';
+ return b;
+ }
+ else
+ {
+ if (*src == '\\')
+ {
+ strcpy(buffer,"\\\\");
+ buffer += 2;
+ blen -= 2;
+ }
+ else
+ {
+ sprintf(buffer, "\\x%02x", *src++);
+ blen -= 4;
+ buffer += 4;
+ }
+ }
+ }
+ if (srclen && !blen && endb) /* overflow - set last chars to ... */
+ strcpy(endb, "...");
+ }
+
+ *buffer = '\0';
+ return b;
+}
+
+
+/*--------------------------------------------------
+ * l_mktime - make representation of a relative time
+ */
+static char *
+l_mktime(delta)
+ unsigned LONG delta;
+{
+ unsigned LONG tmp, m, s;
+ static char buffer[40];
+
+ buffer[0] = '\0';
+
+ if ((tmp = delta / (60*60*24)) != 0)
+ {
+ sprintf(buffer, "%dd+", tmp);
+ delta -= tmp * 60*60*24;
+ }
+
+ s = delta % 60;
+ delta /= 60;
+ m = delta % 60;
+ delta /= 60;
+
+ sprintf(buffer+strlen(buffer), "%02d:%02d:%02d",
+ delta, m, s);
+
+ return buffer;
+}
+
+
+/*--------------------------------------------------
+ * parse_statistics - list summary of clock states
+ */
+static void
+parse_statistics(parse)
+ register struct parseunit *parse;
+{
+ register int i;
+
+ syslog(LOG_INFO, "PARSE receiver #%d: running time: %s",
+ CL_UNIT(parse->unit),
+ l_mktime(current_time - parse->timestarted));
+
+ syslog(LOG_INFO, "PARSE receiver #%d: current status: %s",
+ CL_UNIT(parse->unit),
+ clockstatus(parse->status));
+
+ for (i = 0; i <= CEVNT_MAX; i++)
+ {
+ register unsigned LONG stime;
+ register unsigned LONG percent, div = current_time - parse->timestarted;
+
+ percent = stime = PARSE_STATETIME(parse, i);
+
+ while (((unsigned LONG)(~0) / 10000) < percent)
+ {
+ percent /= 10;
+ div /= 10;
+ }
+
+ if (div)
+ percent = (percent * 10000) / div;
+ else
+ percent = 10000;
+
+ if (stime)
+ syslog(LOG_INFO, "PARSE receiver #%d: state %18s: %13s (%3d.%02d%%)",
+ CL_UNIT(parse->unit),
+ clockstatus(i),
+ l_mktime(stime),
+ percent / 100, percent % 100);
+ }
+}
+
+/*--------------------------------------------------
+ * cparse_statistics - wrapper for statistics call
+ */
+static void
+cparse_statistics(peer)
+ register struct peer *peer;
+{
+ register struct parseunit *parse = (struct parseunit *)peer;
+
+ parse_statistics(parse);
+ parse->stattimer.event_time = current_time + PARSESTATISTICS;
+ TIMER_ENQUEUE(timerqueue, &parse->stattimer);
+}
+
+/**===========================================================================
+ ** xntp interface routines
+ **/
+
+/*--------------------------------------------------
+ * parse_init - initialize internal parse driver data
+ */
+static void
+parse_init()
+{
+ memset((caddr_t)parseunits, 0, sizeof parseunits);
+}
+
+
+/*--------------------------------------------------
+ * parse_shutdown - shut down a PARSE clock
+ */
+static void
+parse_shutdown(unit)
+ int unit;
+{
+ register struct parseunit *parse;
+
+ unit = CL_UNIT(unit);
+
+ if (unit >= MAXUNITS) {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_shutdown: INTERNAL ERROR, unit invalid (max %d)",
+ unit,MAXUNITS);
+ return;
+ }
+
+ parse = parseunits[unit];
+
+ if (parse && !parse->peer) {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_shutdown: INTERNAL ERROR, unit not in use", unit);
+ return;
+ }
+
+ /*
+ * print statistics a last time and
+ * stop statistics machine
+ */
+ parse_statistics(parse);
+ TIMER_DEQUEUE(&parse->stattimer);
+
+#if PPSPPS
+ {
+ /*
+ * kill possible PPS association
+ */
+ if (fdpps == parse->fd)
+ fdpps = -1;
+ }
+#endif
+
+ if (parse->parse_type->cl_end)
+ {
+ parse->parse_type->cl_end(parse);
+ }
+
+ if (parse->binding)
+ PARSE_END(parse);
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ if (!parse->pollonly)
+ io_closeclock(&parse->io);
+ else
+ (void) close(parse->fd);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" removed",
+ CL_UNIT(parse->unit), parse->parse_type->cl_description);
+
+ parse->peer = (struct peer *)0; /* unused now */
+}
+
+/*--------------------------------------------------
+ * parse_start - open the PARSE devices and initialize data for processing
+ */
+static int
+parse_start(sysunit, peer)
+ u_int sysunit;
+ struct peer *peer;
+{
+ u_int unit;
+ int fd232, i;
+#ifdef HAVE_TERMIOS
+ struct termios tm; /* NEEDED FOR A LONG TIME ! */
+#endif
+#ifdef HAVE_SYSV_TTYS
+ struct termio tm; /* NEEDED FOR A LONG TIME ! */
+#endif
+ struct parseunit * parse;
+ char parsedev[sizeof(PARSEDEVICE)+20];
+ parsectl_t tmp_ctl;
+ u_int type;
+
+ type = CL_TYPE(sysunit);
+ unit = CL_UNIT(sysunit);
+
+ if (unit >= MAXUNITS)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: unit number invalid (max %d)",
+ unit, MAXUNITS-1);
+ return 0;
+ }
+
+ if ((type == ~0) || (clockinfo[type].cl_description == (char *)0))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: unsupported clock type %d (max %d)",
+ unit, CL_REALTYPE(sysunit), ncltypes-1);
+ return 0;
+ }
+
+ if (parseunits[unit] && parseunits[unit]->peer)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: unit in use", unit);
+ return 0;
+ }
+
+ /*
+ * Unit okay, attempt to open the device.
+ */
+ (void) sprintf(parsedev, PARSEDEVICE, unit);
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
+ fd232 = open(parsedev, O_RDWR|O_NOCTTY, 0777);
+ if (fd232 == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: open of %s failed: %m", unit, parsedev);
+ return 0;
+ }
+
+ /*
+ * Looks like this might succeed. Find memory for the structure.
+ * Look to see if there are any unused ones, if not we malloc()
+ * one.
+ */
+ if (parseunits[unit])
+ {
+ parse = parseunits[unit]; /* The one we want is okay - and free */
+ }
+ else
+ {
+ for (i = 0; i < MAXUNITS; i++)
+ {
+ if (parseunits[i] && !parseunits[i]->peer)
+ break;
+ }
+ if (i < MAXUNITS)
+ {
+ /*
+ * Reclaim this one
+ */
+ parse = parseunits[i];
+ parseunits[i] = (struct parseunit *)0;
+ }
+ else
+ {
+ parse = (struct parseunit *)
+ emalloc(sizeof(struct parseunit));
+ }
+ }
+
+ memset((char *)parse, 0, sizeof(struct parseunit));
+ parseunits[unit] = parse;
+
+ /*
+ * Set up the structures
+ */
+ parse->unit = (u_char)sysunit;
+ parse->timestarted = current_time;
+ parse->lastchange = current_time;
+ /*
+ * we want to filter input for the sake of
+ * getting an impression on dispersion
+ * also we like to average the median range
+ */
+ parse->flags = PARSE_STAT_FILTER|PARSE_STAT_AVG;
+ parse->pollneeddata = 0;
+ parse->pollonly = 1; /* go for default polling mode */
+ parse->lastformat = ~0; /* assume no format known */
+ parse->status = CEVNT_TIMEOUT; /* expect the worst */
+ parse->laststatus = ~0; /* be sure to mark initial status change */
+ parse->nosynctime = 0; /* assume clock reasonable */
+ parse->lastmissed = 0; /* assume got everything */
+ parse->ppsserial = 0;
+ parse->localdata = (void *)0;
+
+ parse->parse_type = &clockinfo[type];
+
+ parse->basedelay.l_ui = 0; /* we can only pre-configure delays less than 1 second */
+ parse->basedelay.l_uf = parse->parse_type->cl_basedelay;
+
+ parse->ppsdelay.l_ui = 0; /* we can only pre-configure delays less than 1 second */
+ parse->ppsdelay.l_uf = parse->parse_type->cl_ppsdelay;
+
+ peer->rootdelay = parse->parse_type->cl_rootdelay;
+ peer->sstclktype = parse->parse_type->cl_type;
+ peer->precision = sys_precision;
+ peer->stratum = STRATUM_REFCLOCK;
+ if (peer->stratum <= 1)
+ memmove((char *)&peer->refid, parse->parse_type->cl_id, 4);
+ else
+ peer->refid = htonl(PARSEHSREFID);
+
+ parse->fd = fd232;
+
+ parse->peer = peer; /* marks it also as busy */
+
+ parse->binding = init_iobinding(parse);
+
+ if (parse->binding == (bind_t *)0)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: io sub system initialisation failed.");
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+
+ /*
+ * configure terminal line
+ */
+ if (TTY_GETATTR(fd232, &tm) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcgetattr(%d, &tm): %m", unit, fd232);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ else
+ {
+#ifndef _PC_VDISABLE
+ memset((char *)tm.c_cc, 0, sizeof(tm.c_cc));
+#else
+ int disablec;
+ errno = 0; /* pathconf can deliver -1 without changing errno ! */
+
+ disablec = fpathconf(parse->fd, _PC_VDISABLE);
+ if (disablec == -1 && errno)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: fpathconf(fd, _PC_VDISABLE): %m", CL_UNIT(parse->unit));
+ memset((char *)tm.c_cc, 0, sizeof(tm.c_cc)); /* best guess */
+ }
+ else
+ if (disablec != -1)
+ memset((char *)tm.c_cc, disablec, sizeof(tm.c_cc));
+#endif
+
+ tm.c_cflag = clockinfo[type].cl_cflag;
+ 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);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ }
+
+ /*
+ * as we always(?) get 8 bit chars we want to be
+ * sure, that the upper bits are zero for less
+ * than 8 bit I/O - so we pass that information on.
+ * note that there can be only one bit count format
+ * per file descriptor
+ */
+
+ switch (tm.c_cflag & CSIZE)
+ {
+ case CS5:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS5;
+ break;
+
+ case CS6:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS6;
+ break;
+
+ case CS7:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS7;
+ break;
+
+ case CS8:
+ tmp_ctl.parsesetcs.parse_cs = PARSE_IO_CS8;
+ break;
+ }
+
+ if (!PARSE_SETCS(parse, &tmp_ctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setcs() FAILED.", unit);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ 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);
+
+ if (!PARSE_SETFMT(parse, &tmp_ctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+
+#ifdef TCFLSH
+ /*
+ * get rid of all IO accumulated so far
+ */
+ {
+#ifndef TCIOFLUSH
+#define TCIOFLUSH 2
+#endif
+ int flshcmd = TCIOFLUSH;
+
+ (void) ioctl(parse->fd, TCFLSH, (caddr_t)&flshcmd);
+ }
+#endif
+
+ tmp_ctl.parsestatus.flags = parse->flags & PARSE_STAT_FLAGS;
+
+ if (!PARSE_SETSTAT(parse, &tmp_ctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setstat() FAILED.", unit);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+
+ /*
+ * try to do any special initializations
+ */
+ if (parse->parse_type->cl_init)
+ {
+ if (parse->parse_type->cl_init(parse))
+ {
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0; /* well, ok - special initialisation broke */
+ }
+ }
+
+ if (!(parse->parse_type->cl_flags & PARSE_F_POLLONLY) &&
+ (CL_PPS(parse->unit) || (parse->parse_type->cl_flags & PARSE_F_NOPOLLONLY)))
+ {
+ /*
+ * Insert in async io device list.
+ */
+ parse->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
+ parse->io.srcclock = (caddr_t)parse;
+ parse->io.datalen = 0;
+ parse->io.fd = parse->fd; /* replicated, but what the heck */
+ if (!io_addclock(&parse->io))
+ {
+ if (parse->parse_type->cl_flags & PARSE_F_NOPOLLONLY)
+ {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CL_UNIT(parse->unit), parsedev);
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ else
+ {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: parse_start: addclock %s fails (switching to polling mode)", CL_UNIT(parse->unit), parsedev);
+ }
+ }
+ else
+ {
+ parse->pollonly = 0; /*
+ * update at receipt of time_stamp - also
+ * supports PPS processing
+ */
+ }
+ }
+
+#ifdef PPSPPS
+ if (parse->pollonly || (parse->parse_type->cl_flags & PARSE_F_PPSPPS))
+ {
+ if (fdpps == -1)
+ {
+ fdpps = parse->fd;
+ if (!PARSE_DISABLE(parse))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_disable() FAILED", CL_UNIT(parse->unit));
+ parse_shutdown(parse->unit); /* let our cleaning staff do the work */
+ return 0;
+ }
+ }
+ else
+ {
+ syslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: loopfilter PPS already active - no PPS via CIOGETEV", CL_UNIT(parse->unit));
+ }
+ }
+#endif
+
+ /*
+ * wind up statistics timer
+ */
+ parse->stattimer.peer = (struct peer *)parse; /* we know better, but what the heck */
+ parse->stattimer.event_handler = cparse_statistics;
+ parse->stattimer.event_time = current_time + PARSESTATISTICS;
+ TIMER_ENQUEUE(timerqueue, &parse->stattimer);
+
+ /*
+ * get out Copyright information once
+ */
+ if (!notice)
+ {
+ syslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-1993, Frank Kardel");
+ notice = 1;
+ }
+
+ /*
+ * print out configuration
+ */
+ syslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (device %s) added",
+ CL_UNIT(parse->unit),
+ parse->parse_type->cl_description, parsedev);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, %sPPS support, trust time %s, precision %d",
+ CL_UNIT(parse->unit),
+ parse->peer->stratum, (parse->pollonly || !CL_PPS(parse->unit)) ? "no " : "",
+ l_mktime(parse->parse_type->cl_maxunsync), parse->peer->precision);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: rootdelay %s s, phaseadjust %s s, %s IO handling",
+ CL_UNIT(parse->unit),
+ ufptoa(parse->parse_type->cl_rootdelay, 6),
+ lfptoa(&parse->basedelay, 8),
+ parse->binding->bd_description);
+
+ syslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CL_UNIT(parse->unit),
+ !(*parse->parse_type->cl_format) ? "<AUTOMATIC>" : parse->parse_type->cl_format);
+
+#ifdef PPSPPS
+ syslog(LOG_INFO, "PARSE receiver #%d: %sCD PPS support",
+ CL_UNIT(parse->unit),
+ (fdpps == parse->fd) ? "" : "NO ");
+#endif
+
+ return 1;
+}
+
+/*--------------------------------------------------
+ * parse_poll - called by the transmit procedure
+ */
+static void
+parse_poll(unit, peer)
+ int unit;
+ struct peer *peer;
+{
+ register struct parseunit *parse;
+
+ unit = CL_UNIT(unit);
+
+ if (unit >= MAXUNITS)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll: INTERNAL: unit invalid",
+ unit);
+ return;
+ }
+
+ parse = parseunits[unit];
+
+ if (!parse->peer)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll: INTERNAL: unit unused",
+ unit);
+ return;
+ }
+
+ if (peer != parse->peer)
+ {
+ syslog(LOG_ERR,
+ "PARSE receiver #%d: poll: INTERNAL: peer incorrect",
+ unit);
+ return;
+ }
+
+ /*
+ * Update clock stat counters
+ */
+ parse->polls++;
+
+ /*
+ * in PPS mode we just mark that we want the next sample
+ * for the clock filter
+ */
+ if (!parse->pollonly)
+ {
+ if (parse->pollneeddata)
+ {
+ /*
+ * bad news - didn't get a response last time
+ */
+ parse->noresponse++;
+ parse->lastmissed = current_time;
+ parse_event(parse, CEVNT_TIMEOUT);
+
+ syslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval", CL_UNIT(parse->unit));
+ }
+ parse->pollneeddata = 1;
+ if (parse->parse_type->cl_poll)
+ {
+ parse->parse_type->cl_poll(parse);
+ }
+ return;
+ }
+
+ /*
+ * the following code is only executed only when polling is used
+ */
+
+ PARSE_POLL(parse);
+}
+
+/*--------------------------------------------------
+ * parse_leap - called when a leap second occurs
+ */
+
+static void
+parse_leap()
+{
+ /*
+ * 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).
+ */
+}
+
+
+/*--------------------------------------------------
+ * parse_control - set fudge factors, return statistics
+ */
+static void
+parse_control(unit, in, out)
+ u_int unit;
+ struct refclockstat *in;
+ struct refclockstat *out;
+{
+ register struct parseunit *parse;
+ parsectl_t tmpctl;
+ unsigned LONG type;
+ static char outstatus[400]; /* status output buffer */
+
+ type = CL_TYPE(unit);
+ unit = CL_UNIT(unit);
+
+ if (out)
+ {
+ out->lencode = 0;
+ out->lastcode = 0;
+ out->polls = out->noresponse = 0;
+ out->badformat = out->baddata = 0;
+ out->timereset = 0;
+ out->currentstatus = out->lastevent = CEVNT_NOMINAL;
+ out->kv_list = (struct ctl_var *)0;
+ }
+
+ if (unit >= MAXUNITS)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (max %d)",
+ unit, MAXUNITS-1);
+ return;
+ }
+
+ parse = parseunits[unit];
+
+ if (!parse || !parse->peer)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
+ unit);
+ return;
+ }
+
+ if (in)
+ {
+ if (in->haveflags & CLK_HAVETIME1)
+ parse->basedelay = in->fudgetime1;
+
+ if (in->haveflags & CLK_HAVETIME2)
+ {
+ parse->ppsdelay = in->fudgetime2;
+ }
+
+ if (in->haveflags & CLK_HAVEVAL1)
+ {
+ parse->peer->stratum = (u_char)(in->fudgeval1 & 0xf);
+ if (parse->peer->stratum <= 1)
+ memmove((char *)&parse->peer->refid,
+ parse->parse_type->cl_id,
+ 4);
+ else
+ parse->peer->refid = htonl(PARSEHSREFID);
+ }
+
+ /*
+ * NOT USED - yet
+ *
+ if (in->haveflags & CLK_HAVEVAL2)
+ {
+ }
+ */
+ if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
+ {
+ parse->flags = (in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4)) |
+ (parse->flags & ~PARSE_STAT_FLAGS);
+ }
+
+ if (in->haveflags & (CLK_HAVEVAL2|CLK_HAVETIME2|CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
+ {
+ parsectl_t tmpctl;
+ tmpctl.parsestatus.flags = parse->flags & PARSE_STAT_FLAGS;
+
+ if (!PARSE_SETSTAT(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_setstat() FAILED", unit);
+ }
+ }
+ }
+
+ if (out)
+ {
+ register unsigned LONG sum = 0;
+ register char *t, *tt;
+ register struct tm *tm;
+ register short utcoff;
+ register char sign;
+ register int i;
+ time_t tim;
+
+ outstatus[0] = '\0';
+
+ out->haveflags = CLK_HAVETIME1|CLK_HAVETIME2|CLK_HAVEVAL1|CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3;
+ out->clockdesc = parse->parse_type->cl_description;
+
+ out->fudgetime1 = parse->basedelay;
+
+ out->fudgetime2 = parse->ppsdelay;
+
+ out->fudgeval1 = (LONG)parse->peer->stratum;
+
+ out->fudgeval2 = 0;
+
+ out->flags = parse->flags & PARSE_STAT_FLAGS;
+
+ out->type = REFCLK_PARSE;
+
+ /*
+ * figure out skew between PPS and RS232 - just for informational
+ * purposes - returned in time2 value
+ */
+ if (PARSE_SYNC(parse->time.parse_state))
+ {
+ if (PARSE_PPS(parse->time.parse_state) && PARSE_TIMECODE(parse->time.parse_state))
+ {
+ l_fp off;
+
+ /*
+ * we have a PPS and RS232 signal - calculate the skew
+ * WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
+ */
+ off = parse->time.parse_stime.fp;
+ L_SUB(&off, &parse->time.parse_ptime.fp); /* true offset */
+ tt = add_var(&out->kv_list, 40, RO);
+ sprintf(tt, "refclock_ppsskew=%s", lfptoms(&off, 6));
+ }
+ }
+
+ if (PARSE_PPS(parse->time.parse_state))
+ {
+ tt = add_var(&out->kv_list, 80, RO|DEF);
+ sprintf(tt, "refclock_ppstime=\"%s\"", prettydate(&parse->time.parse_ptime.fp));
+ }
+
+ /*
+ * all this for just finding out the +-xxxx part (there are always
+ * new and changing fields in the standards 8-().
+ *
+ * but we do it for the human user...
+ */
+ tim = parse->time.parse_time.fp.l_ui - JAN_1970;
+ tm = gmtime(&tim);
+ utcoff = tm->tm_hour * 60 + tm->tm_min;
+ tm = localtime(&tim);
+ utcoff = tm->tm_hour * 60 + tm->tm_min - utcoff + 12 * 60;
+ utcoff += 24 * 60;
+ utcoff %= 24 * 60;
+ utcoff -= 12 * 60;
+ if (utcoff < 0)
+ {
+ utcoff = -utcoff;
+ sign = '-';
+ }
+ else
+ {
+ sign = '+';
+ }
+
+ tt = add_var(&out->kv_list, 128, RO|DEF);
+ sprintf(tt, "refclock_time=\"");
+ tt += strlen(tt);
+
+ if (parse->time.parse_time.fp.l_ui == 0)
+ {
+ strcpy(tt, "<UNDEFINED>\"");
+ }
+ else
+ {
+ strcpy(tt, prettydate(&parse->time.parse_time.fp));
+ t = tt + strlen(tt);
+
+ sprintf(t, " (%c%02d%02d)\"", sign, utcoff / 60, utcoff % 60);
+ }
+
+ if (!PARSE_GETTIMECODE(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
+ }
+ else
+ {
+ tt = add_var(&out->kv_list, 128, RO|DEF);
+ sprintf(tt, "refclock_status=\"");
+ tt += strlen(tt);
+
+ /*
+ * copy PPS flags from last read transaction (informational only)
+ */
+ tmpctl.parsegettc.parse_state |= parse->time.parse_state &
+ (PARSEB_PPS|PARSEB_S_PPS);
+
+ (void) parsestate(tmpctl.parsegettc.parse_state, tt);
+
+ strcat(tt, "\"");
+
+ if (tmpctl.parsegettc.parse_count)
+ mkascii(outstatus+strlen(outstatus), sizeof(outstatus)- strlen(outstatus) - 1,
+ tmpctl.parsegettc.parse_buffer, tmpctl.parsegettc.parse_count - 1);
+
+ parse->badformat += tmpctl.parsegettc.parse_badformat;
+ }
+
+ tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
+
+ if (!PARSE_GETFMT(parse, &tmpctl))
+ {
+ syslog (LOG_ERR, "PARSE receiver #%d: parse_control: parse_getfmt() FAILED", unit);
+ }
+ else
+ {
+ tt = add_var(&out->kv_list, 80, RO|DEF);
+ sprintf(tt, "refclock_format=\"");
+
+ strncat(tt, tmpctl.parseformat.parse_buffer, tmpctl.parseformat.parse_count);
+ strcat(tt,"\"");
+ }
+
+ /*
+ * gather state statistics
+ */
+
+ tt = add_var(&out->kv_list, 200, RO|DEF);
+ strcpy(tt, "refclock_states=\"");
+ tt += strlen(tt);
+
+ for (i = 0; i <= CEVNT_MAX; i++)
+ {
+ register unsigned LONG stime;
+ register unsigned LONG div = current_time - parse->timestarted;
+ register unsigned LONG percent;
+
+ percent = stime = PARSE_STATETIME(parse, i);
+
+ while (((unsigned LONG)(~0) / 10000) < percent)
+ {
+ percent /= 10;
+ div /= 10;
+ }
+
+ if (div)
+ percent = (percent * 10000) / div;
+ else
+ percent = 10000;
+
+ if (stime)
+ {
+ sprintf(tt, "%s%s%s: %s (%d.%02d%%)",
+ sum ? "; " : "",
+ (parse->status == i) ? "*" : "",
+ clockstatus(i),
+ l_mktime(stime),
+ percent / 100, percent % 100);
+ sum += stime;
+ tt += strlen(tt);
+ }
+ }
+
+ sprintf(tt, "; running time: %s\"", l_mktime(sum));
+
+ tt = add_var(&out->kv_list, 32, RO);
+ sprintf(tt, "refclock_id=\"%s\"", parse->parse_type->cl_id);
+
+ tt = add_var(&out->kv_list, 80, RO);
+ 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.53 1994/03/25 13:07:39 kardel Exp\"");
+
+ out->lencode = strlen(outstatus);
+ out->lastcode = outstatus;
+ out->timereset = parse->timestarted;
+ out->polls = parse->polls;
+ out->noresponse = parse->noresponse;
+ out->badformat = parse->badformat;
+ out->baddata = parse->baddata;
+ out->lastevent = parse->lastevent;
+ out->currentstatus = parse->status;
+ }
+}
+
+/**===========================================================================
+ ** processing routines
+ **/
+
+/*--------------------------------------------------
+ * event handling - note that nominal events will also be posted
+ */
+static void
+parse_event(parse, event)
+ struct parseunit *parse;
+ int event;
+{
+ if (parse->status != (u_char) event)
+ {
+ parse->statetime[parse->status] += current_time - parse->lastchange;
+ parse->lastchange = current_time;
+
+ parse->status = (u_char)event;
+ if (event != CEVNT_NOMINAL)
+ parse->lastevent = parse->status;
+
+ report_event(EVNT_PEERCLOCK, parse->peer);
+ }
+}
+
+/*--------------------------------------------------
+ * process a PARSE time sample
+ */
+static void
+parse_process(parse, parsetime)
+ struct parseunit *parse;
+ parsetime_t *parsetime;
+{
+ unsigned char leap;
+ struct timeval usecdisp;
+ l_fp off, rectime, reftime, dispersion;
+
+ /*
+ * check for changes in conversion status
+ * (only one for each new status !)
+ */
+ if (parse->laststatus != parsetime->parse_status)
+ {
+ char buffer[200];
+
+ syslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
+ CL_UNIT(parse->unit), parsestatus(parsetime->parse_status, buffer));
+
+ if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
+ {
+ /*
+ * tell more about the story - list time code
+ * there is a slight change for a race condition and
+ * the time code might be overwritten by the next packet
+ */
+ parsectl_t tmpctl;
+
+ if (!PARSE_GETTIMECODE(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CL_UNIT(parse->unit));
+ }
+ else
+ {
+ syslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\"",
+ CL_UNIT(parse->unit), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, tmpctl.parsegettc.parse_count - 1));
+ parse->badformat += tmpctl.parsegettc.parse_badformat;
+ }
+ }
+
+ parse->laststatus = parsetime->parse_status;
+ }
+
+ /*
+ * examine status and post appropriate events
+ */
+ if ((parsetime->parse_status & CVT_MASK) != CVT_OK)
+ {
+ /*
+ * got bad data - tell the rest of the system
+ */
+ switch (parsetime->parse_status & CVT_MASK)
+ {
+ case CVT_NONE:
+ break; /* well, still waiting - timeout is handled at higher levels */
+
+ case CVT_FAIL:
+ parse->badformat++;
+ if (parsetime->parse_status & CVT_BADFMT)
+ {
+ parse_event(parse, CEVNT_BADREPLY);
+ }
+ else
+ if (parsetime->parse_status & CVT_BADDATE)
+ {
+ parse_event(parse, CEVNT_BADDATE);
+ }
+ else
+ if (parsetime->parse_status & CVT_BADTIME)
+ {
+ parse_event(parse, CEVNT_BADTIME);
+ }
+ else
+ {
+ parse_event(parse, CEVNT_BADREPLY); /* for the lack of something better */
+ }
+ }
+ return; /* skip the rest - useless */
+ }
+
+ /*
+ * check for format changes
+ * (in case somebody has swapped clocks 8-)
+ */
+ if (parse->lastformat != parsetime->parse_format)
+ {
+ parsectl_t tmpctl;
+
+ tmpctl.parseformat.parse_format = parsetime->parse_format;
+
+ if (!PARSE_GETFMT(parse, &tmpctl))
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CL_UNIT(parse->unit));
+ }
+ else
+ {
+ syslog(LOG_INFO, "PARSE receiver #%d: new packet format \"%s\"",
+ CL_UNIT(parse->unit), tmpctl.parseformat.parse_buffer);
+ }
+ parse->lastformat = parsetime->parse_format;
+ }
+
+ /*
+ * now, any changes ?
+ */
+ if (parse->time.parse_state != parsetime->parse_state)
+ {
+ char tmp1[200];
+ char tmp2[200];
+ /*
+ * something happend
+ */
+
+ (void) parsestate(parsetime->parse_state, tmp1);
+ (void) parsestate(parse->time.parse_state, tmp2);
+
+ syslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
+ CL_UNIT(parse->unit), tmp2, tmp1);
+ }
+
+ /*
+ * remember for future
+ */
+ parse->time = *parsetime;
+
+ /*
+ * check to see, whether the clock did a complete powerup or lost PZF signal
+ * and post correct events for current condition
+ */
+ if (PARSE_POWERUP(parsetime->parse_state))
+ {
+ /*
+ * this is bad, as we have completely lost synchronisation
+ * well this is a problem with the receiver here
+ * for PARSE U/A 31 the lost synchronisation ist true
+ * as it is the powerup state and the time is taken
+ * from a crude real time clock chip
+ * for the PZF series this is only partly true, as
+ * PARSE_POWERUP only means that the pseudo random
+ * phase shift sequence cannot be found. this is only
+ * bad, if we have never seen the clock in the SYNC
+ * state, where the PHASE and EPOCH are correct.
+ * for reporting events the above business does not
+ * really matter, but we can use the time code
+ * even in the POWERUP state after having seen
+ * the clock in the synchronized state (PZF class
+ * receivers) unless we have had a telegram disruption
+ * after having seen the clock in the SYNC state. we
+ * thus require having seen the clock in SYNC state
+ * *after* having missed telegrams (noresponse) from
+ * the clock. one problem remains: we might use erroneously
+ * POWERUP data if the disruption is shorter than 1 polling
+ * interval. fortunately powerdowns last usually longer than 64
+ * seconds and the receiver is at least 2 minutes in the
+ * POWERUP or NOSYNC state before switching to SYNC
+ */
+ parse_event(parse, CEVNT_FAULT);
+ if (parse->nosynctime)
+ {
+ /*
+ * repeated POWERUP/NOSYNC state - look whether
+ * the message should be repeated
+ */
+ if (current_time - parse->nosynctime > PARSENOSYNCREPEAT)
+ {
+ syslog(LOG_ERR,"PARSE receiver #%d: *STILL* NOT SYNCHRONIZED (POWERUP or no PZF signal)",
+ CL_UNIT(parse->unit));
+ parse->nosynctime = current_time;
+ }
+ }
+ else
+ {
+ syslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED",
+ CL_UNIT(parse->unit));
+ parse->nosynctime = current_time;
+ }
+ }
+ else
+ {
+ /*
+ * we have two states left
+ *
+ * SYNC:
+ * this state means that the EPOCH (timecode) and PHASE
+ * information has be read correctly (at least two
+ * successive PARSE timecodes were received correctly)
+ * this is the best possible state - full trust
+ *
+ * NOSYNC:
+ * The clock should be on phase with respect to the second
+ * signal, but the timecode has not been received correctly within
+ * at least the last two minutes. this is a sort of half baked state
+ * for PARSE U/A 31 this is bad news (clock running without timecode
+ * confirmation)
+ * PZF 535 has also no time confirmation, but the phase should be
+ * very precise as the PZF signal can be decoded
+ */
+ parse->nosynctime = 0; /* current state is better than worst state */
+
+ if (PARSE_SYNC(parsetime->parse_state))
+ {
+ /*
+ * currently completely synchronized - best possible state
+ */
+ parse->lastsync = current_time;
+ /*
+ * log OK status
+ */
+ parse_event(parse, CEVNT_NOMINAL);
+ }
+ else
+ {
+ /*
+ * we have had some problems receiving the time code
+ */
+ parse_event(parse, CEVNT_PROP);
+ }
+ }
+
+ if (PARSE_TIMECODE(parsetime->parse_state))
+ {
+ l_fp offset;
+
+ /*
+ * calculate time offset including systematic delays
+ * off = PARSE-timestamp + propagation delay - kernel time stamp
+ */
+ offset = parse->basedelay;
+
+ off = parsetime->parse_time.fp;
+
+ reftime = off;
+
+ L_ADD(&off, &offset);
+ rectime = off; /* this makes org time and xmt time somewhat artificial */
+
+ 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;
+ /*
+ * offset is already calculated
+ */
+ usecerror.tv_sec = parsetime->parse_usecerror / 1000000;
+ usecerror.tv_usec = parsetime->parse_usecerror % 1000000;
+
+ sTVTOTS(&usecerror, &off);
+ L_ADD(&off, &offset);
+ }
+ }
+
+ if (PARSE_PPS(parsetime->parse_state) && CL_PPS(parse->unit))
+ {
+ l_fp offset;
+
+ /*
+ * we have a PPS signal - much better than the RS232 stuff (we hope)
+ */
+ offset = parsetime->parse_ptime.fp;
+
+ L_ADD(&offset, &parse->ppsdelay);
+
+ if (PARSE_TIMECODE(parsetime->parse_state))
+ {
+ if (M_ISGEQ(off.l_i, off.l_f, -1, 0x80000000) &&
+ M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_f))
+ {
+ /*
+ * RS232 offsets within [-0.5..0.5[ - take PPS offsets
+ */
+
+ if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
+ {
+ reftime = off = offset;
+ rectime = offset;
+ /*
+ * implied on second offset
+ */
+ off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
+ off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
+ }
+ else
+ {
+ /*
+ * time code describes pulse
+ */
+ off = parsetime->parse_time.fp;
+
+ rectime = reftime = off; /* take reference time - fake rectime */
+
+ L_SUB(&off, &offset); /* true offset */
+ }
+ }
+ /*
+ * take RS232 offset when PPS when out of bounds
+ */
+ }
+ else
+ {
+ /*
+ * Well, no time code to guide us - assume on second pulse
+ * and pray, that we are within [-0.5..0.5[
+ */
+ reftime = off = offset;
+ rectime = offset;
+ /*
+ * implied on second offset
+ */
+ off.l_uf = ~off.l_uf; /* map [0.5..1[ -> [-0.5..0[ */
+ off.l_ui = (off.l_f < 0) ? ~0 : 0; /* sign extend */
+ }
+ }
+ else
+ {
+ if (!PARSE_TIMECODE(parsetime->parse_state))
+ {
+ /*
+ * Well, no PPS, no TIMECODE, no more work ...
+ */
+ return;
+ }
+ }
+
+
+#if defined(PPS) || defined(PPSCLK) || defined(PPSPPS) || defined(PARSEPPS)
+ if (CL_PPS(parse->unit) && !parse->pollonly && PARSE_SYNC(parsetime->parse_state))
+ {
+ /*
+ * only provide PPS information when clock
+ * is in sync
+ * thus PHASE and EPOCH are correct and PPS is not
+ * done via the CIOGETEV loopfilter mechanism
+ */
+#ifdef PPSPPS
+ if (fdpps != parse->fd)
+#endif
+ (void) pps_sample(&off);
+ }
+#endif /* PPS || PPSCLK || PPSPPS || PARSEPPS */
+
+ /*
+ * ready, unless the machine wants a sample
+ */
+ if (!parse->pollonly && !parse->pollneeddata)
+ return;
+
+ parse->pollneeddata = 0;
+
+ if (PARSE_PPS(parsetime->parse_state))
+ {
+ L_CLR(&dispersion);
+ }
+ else
+ {
+ /*
+ * convert usec dispersion into NTP TS world
+ */
+
+ usecdisp.tv_sec = parsetime->parse_usecdisp / 1000000;
+ usecdisp.tv_usec = parsetime->parse_usecdisp % 1000000;
+
+ TVTOTS(&usecdisp, &dispersion);
+ }
+
+ /*
+ * and now stick it into the clock machine
+ * samples are only valid iff lastsync is not too old and
+ * we have seen the clock in sync at least once
+ * after the last time we didn't see an expected data telegram
+ * see the clock states section above for more reasoning
+ */
+ if (((current_time - parse->lastsync) > parse->parse_type->cl_maxunsync) ||
+ (parse->lastsync <= parse->lastmissed))
+ {
+ leap = LEAP_NOTINSYNC;
+ }
+ else
+ {
+ 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
+ if (PARSE_LEAPDEL(parsetime->parse_state))
+ {
+ leap = LEAP_DELSECOND;
+ }
+ else
+ {
+ leap = LEAP_NOWARNING;
+ }
+ }
+
+ refclock_receive(parse->peer, &off, 0, LFPTOFP(&dispersion), &reftime, &rectime, leap);
+}
+
+/**===========================================================================
+ ** clock polling support
+ **/
+
+struct poll_timer
+{
+ struct event timer; /* we'd like to poll a a higher rate than 1/64s */
+};
+
+typedef struct poll_timer poll_timer_t;
+
+/*--------------------------------------------------
+ * direct poll routine
+ */
+static void
+poll_dpoll(parse)
+ struct parseunit *parse;
+{
+ register int rtc;
+ register char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
+ register int ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
+
+ rtc = write(parse->fd, ps, ct);
+ if (rtc < 0)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CL_UNIT(parse->unit));
+ }
+ else
+ if (rtc != ct)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%d of %d bytes sent)", CL_UNIT(parse->unit), rtc, ct);
+ }
+}
+
+/*--------------------------------------------------
+ * periodic poll routine
+ */
+static void
+poll_poll(parse)
+ struct parseunit *parse;
+{
+ register poll_timer_t *pt = (poll_timer_t *)parse->localdata;
+
+ poll_dpoll(parse);
+
+ if (pt != (poll_timer_t *)0)
+ {
+ pt->timer.event_time = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
+ TIMER_ENQUEUE(timerqueue, &pt->timer);
+ }
+}
+
+/*--------------------------------------------------
+ * init routine - setup timer
+ */
+static int
+poll_init(parse)
+ struct parseunit *parse;
+{
+ register poll_timer_t *pt;
+
+ if (((poll_info_t *)parse->parse_type->cl_data)->rate)
+ {
+ parse->localdata = (void *)malloc(sizeof(poll_timer_t));
+ memset((char *)parse->localdata, 0, sizeof(poll_timer_t));
+
+ pt = (poll_timer_t *)parse->localdata;
+
+ pt->timer.peer = (struct peer *)parse; /* well, only we know what it is */
+ pt->timer.event_handler = poll_poll;
+ poll_poll(parse);
+ }
+ else
+ {
+ parse->localdata = (void *)0;
+ }
+
+ return 0;
+}
+
+/*--------------------------------------------------
+ * end routine - clean up timer
+ */
+static void
+poll_end(parse)
+ struct parseunit *parse;
+{
+ if (parse->localdata != (void *)0)
+ {
+ TIMER_DEQUEUE(&((poll_timer_t *)parse->localdata)->timer);
+ free((char *)parse->localdata);
+ parse->localdata = (void *)0;
+ }
+}
+
+/**===========================================================================
+ ** special code for special clocks
+ **/
+
+/*--------------------------------------------------
+ * trimble init routine - setup EOL and then do poll_init.
+ */
+static int
+trimble_init(parse)
+ struct parseunit *parse;
+{
+#ifdef HAVE_TERMIOS
+ struct termios tm;
+#endif
+#ifdef HAVE_SYSV_TTYS
+ struct termio tm;
+#endif
+ /*
+ * configure terminal line for trimble receiver
+ */
+ if (TTY_GETATTR(parse->fd, &tm) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: trimble_init: tcgetattr(fd, &tm): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ else
+ {
+ tm.c_cc[VEOL] = TRIMBLESV6_EOL;
+
+ if (TTY_SETATTR(parse->fd, &tm) == -1)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: trimble_init: tcsetattr(fd, &tm): %m", CL_UNIT(parse->unit));
+ return 0;
+ }
+ }
+ return poll_init(parse);
+}
+#endif /* defined(REFCLOCK) && defined(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
+ *
+ * Revision 3.44 1994/01/25 17:32:23 kardel
+ * settable extended variables
+ *
+ * Revision 3.43 1994/01/23 16:28:39 kardel
+ * HAVE_TERMIOS introduced
+ *
+ * Revision 3.42 1994/01/22 11:35:04 kardel
+ * added HAVE_TERMIOS
+ *
+ * Revision 3.41 1993/11/27 18:44:37 kardel
+ * can't trust GPS166 on unsync
+ *
+ * Revision 3.40 1993/11/21 18:03:36 kardel
+ * useless declaration deleted
+ *
+ * Revision 3.39 1993/11/21 15:30:15 kardel
+ * static funcitions may be declared only at outer level
+ *
+ * Revision 3.38 1993/11/15 21:26:49 kardel
+ * conditional define comments fixed
+ *
+ * Revision 3.37 1993/11/11 11:20:49 kardel
+ * declaration fixes
+ *
+ * Revision 3.36 1993/11/10 12:17:14 kardel
+ * #ifdef glitch
+ *
+ * Revision 3.35 1993/11/01 21:15:06 kardel
+ * comments updated
+ *
+ * Revision 3.34 1993/11/01 20:01:08 kardel
+ * parse Solaris support (initial version)
+ *
+ * Revision 3.33 1993/10/30 09:44:58 kardel
+ * conditional compilation flag cleanup
+ *
+ * Revision 3.32 1993/10/22 14:28:43 kardel
+ * Oct. 22nd 1993 reconcilation
+ *
+ * Revision 3.31 1993/10/10 21:19:10 kardel
+ * compilation cleanup - (minimal porting tests)
+ *
+ * Revision 3.30 1993/10/09 21:44:35 kardel
+ * syslog strings fixed
+ *
+ * Revision 3.29 1993/10/09 14:40:15 kardel
+ * default precision setting fixed
+ *
+ * Revision 3.28 1993/10/08 14:48:22 kardel
+ * Changed offset determination logic:
+ * Take the PPS offset if it is available and the time
+ * code offset is within [-0.5..0.5[, otherwise stick
+ * to the time code offset
+ *
+ * Revision 3.27 1993/10/08 00:53:17 kardel
+ * announce also simulated PPS via CIOGETEV in ntpq cl
+ *
+ * Revision 3.26 1993/10/07 23:29:35 kardel
+ * trimble fixes
+ *
+ * Revision 3.25 1993/10/06 21:13:35 kardel
+ * test reversed (CIOGETEV support)
+ *
+ * Revision 3.24 1993/10/03 20:18:26 kardel
+ * Well, values > 999999 in the usec field from uniqtime() timestamps
+ * can prove harmful.
+ *
+ * Revision 3.23 1993/10/03 19:49:54 kardel
+ * buftvtots where failing on uninitialized time stamps
+ *
+ * Revision 3.22 1993/10/03 19:11:09 kardel
+ * restructured I/O handling
+ *
+ * Revision 3.21 1993/09/29 11:30:18 kardel
+ * special init for trimble to set EOL
+ *
+ * Revision 3.20 1993/09/27 22:46:28 kardel
+ * preserve module stack if I_PUSH parse fails
+ *
+ * Revision 3.19 1993/09/27 21:10:11 kardel
+ * wrong structure member
+ *
+ * Revision 3.18 1993/09/27 13:05:06 kardel
+ * Trimble is true polling only
+ *
+ * Revision 3.17 1993/09/27 12:47:10 kardel
+ * poll string support generalized
+ *
+ * Revision 3.16 1993/09/26 23:40:56 kardel
+ * new parse driver logic
+ *
+ * Revision 3.15 1993/09/24 15:00:51 kardel
+ * Sep 23rd distribution...
+ *
+ * Revision 3.14 1993/09/22 18:21:15 kardel
+ * support ppsclock streams module (-DSTREAM -DPPSPPS -DPARSEPPS -UPARSESTREAM)
+ *
+ * Revision 3.13 1993/09/05 15:38:33 kardel
+ * not every cpp understands #error...
+ *
+ * Revision 3.12 1993/09/02 20:04:19 kardel
+ * TTY cleanup
+ *
+ * Revision 3.11 1993/09/01 21:48:47 kardel
+ * conditional cleanup
+ *
+ * Revision 3.10 1993/09/01 11:32:45 kardel
+ * assuming HAVE_POSIX_TTYS when STREAM defined
+ *
+ * Revision 3.9 1993/08/31 22:31:46 kardel
+ * SINIX-M SysVR4 integration
+ *
+ * Revision 3.8 1993/08/27 00:29:50 kardel
+ * compilation cleanup
+ *
+ * Revision 3.7 1993/08/24 22:27:30 kardel
+ * cleaned up AUTOCONF DCF77 mess 8-) - wasn't too bad
+ *
+ * Revision 3.6 1993/08/24 21:36:23 kardel
+ * casting and ifdefs
+ *
+ * Revision 3.5 1993/07/09 23:36:59 kardel
+ * HAVE_POSIX_TTYS used to produce errors 8-( - BSD driver support still lacking
+ *
+ * Revision 3.4 1993/07/09 12:42:29 kardel
+ * RAW DCF now officially released
+ *
+ * Revision 3.3 1993/07/09 11:50:37 kardel
+ * running GPS also on 960 to be able to switch GPS/DCF77
+ *
+ * Revision 3.2 1993/07/09 11:37:34 kardel
+ * Initial restructured version + GPS support
+ *
+ * Revision 3.1 1993/07/06 10:01:07 kardel
+ * DCF77 driver goes generic...
+ *
+ */
diff --git a/usr.sbin/xntpd/xntpd/refclock_omega.c b/usr.sbin/xntpd/xntpd/refclock_omega.c
index 73be84d3859b..3d4e4b91d920 100644
--- a/usr.sbin/xntpd/xntpd/refclock_omega.c
+++ b/usr.sbin/xntpd/xntpd/refclock_omega.c
@@ -83,12 +83,10 @@
#define OMEGAMAXDISPERSE (FP_SECOND/32) /* max allowed sample dispersion */
#define OMEGAPRECISION (-10) /* precision assumed (about 1 ms) */
#define OMEGAREFID "VLF\0" /* reference id */
-#define OMEGAHSREFID 0x7f7f0b0a /* 127.127.11.10 refid hi strata */
#define LENOMEGA 13 /* length of standard response */
#define GMT 0 /* hour offset from Greenwich */
#define NSTAMPS 9 /* samples collected when polled */
#define NSKEEP 5 /* samples to keep after discards */
-#define BMAX 50 /* timecode buffer length */
/*
* The OM-DC puts out the start bit of the <CR> on the second, but
@@ -167,7 +165,7 @@ struct omegaunit {
u_char leap; /* leap indicators */
u_short msec; /* millisecond of second */
u_char quality; /* quality char from last timecode */
- U_LONG yearstart; /* start of current year */
+ u_long yearstart; /* start of current year */
/*
* Status tallies
*/
@@ -193,18 +191,19 @@ static l_fp fudgefactor1[MAXUNITS];
static l_fp fudgefactor2[MAXUNITS];
static u_char stratumtouse[MAXUNITS];
static u_char readonlyclockflag[MAXUNITS];
+static U_LONG refid[MAXUNITS];
/*
* Function prototypes
*/
static void omega_init P((void));
-static int omega_start P((u_int, struct peer *));
-static void omega_shutdown P((int));
+static int omega_start P((int, struct peer *));
+static void omega_shutdown P((int, struct peer *));
static void omega_report_event P((struct omegaunit *, int));
static void omega_receive P((struct recvbuf *));
static char omega_process P((struct omegaunit *, l_fp *, u_fp *));
static void omega_poll P((int, struct peer *));
-static void omega_control P((u_int, struct refclockstat *, struct refclockstat *));
+static void omega_control P((int, struct refclockstat *, struct refclockstat *));
static void omega_buginfo P((int, struct refclockbug *));
static void omega_send P((struct omegaunit *, char *));
@@ -239,6 +238,7 @@ omega_init()
fudgefactor2[i].l_uf = 0;
stratumtouse[i] = 0;
readonlyclockflag[i] = 0;
+ memcpy((char *)&refid[i], OMEGAREFID, 4);
}
}
@@ -248,7 +248,7 @@ omega_init()
*/
static int
omega_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
register struct omegaunit *omega;
@@ -443,10 +443,7 @@ omega_start(unit, peer)
peer->rootdelay = 0;
peer->rootdispersion = 0;
peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, OMEGAREFID, 4);
- else
- peer->refid = htonl(OMEGAHSREFID);
+ peer->refid = refid[unit];
unitinuse[unit] = 1;
return 1;
@@ -463,8 +460,9 @@ screwed:
* omega_shutdown - shut down a OMEGA clock
*/
static void
-omega_shutdown(unit)
+omega_shutdown(unit, peer)
int unit;
+ struct peer *peer;
{
register struct omegaunit *omega;
@@ -898,7 +896,7 @@ omega_poll(unit, peer)
*/
static void
omega_control(unit, in, out)
- u_int unit;
+ int unit;
struct refclockstat *in;
struct refclockstat *out;
{
@@ -914,41 +912,30 @@ omega_control(unit, in, out)
fudgefactor1[unit] = in->fudgetime1;
if (in->haveflags & CLK_HAVETIME2)
fudgefactor2[unit] = in->fudgetime2;
- 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
- */
- omega = omegaunits[unit];
- peer = omega->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid,
- OMEGAREFID, 4);
- else
- peer->refid = htonl(OMEGAHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
+ if (in->haveflags & CLK_HAVEVAL1)
+ stratumtouse[unit] = (u_char)(in->fudgeval1);
+ if (in->haveflags & CLK_HAVEVAL2)
+ refid[unit] = in->fudgeval2;
+ if (in->haveflags & CLK_HAVEFLAG1)
readonlyclockflag[unit] = in->flags & CLK_FLAG1;
+ if (unitinuse[unit]) {
+ struct peer *peer;
+
+ peer = omegaunits[unit]->peer;
+ peer->stratum = stratumtouse[unit];
+ peer->refid = refid[unit];
}
}
if (out != 0) {
out->type = REFCLK_OMEGA_TRUETIME;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVETIME2|
- CLK_HAVEVAL1|CLK_HAVEVAL2|
- CLK_HAVEFLAG1|CLK_HAVEFLAG2;
+ out->haveflags = CLK_HAVETIME1 | CLK_HAVETIME2 | CLK_HAVEVAL1 |
+ CLK_HAVEVAL2| CLK_HAVEFLAG1;
out->clockdesc = OMEGADESCRIPTION;
out->fudgetime1 = fudgefactor1[unit];
out->fudgetime2 = fudgefactor2[unit];
out->fudgeval1 = (LONG)stratumtouse[unit];
- out->fudgeval2 = 0;
+ out->fudgeval2 = refid[unit];
out->flags = readonlyclockflag[unit];
if (unitinuse[unit]) {
omega = omegaunits[unit];
@@ -962,13 +949,6 @@ omega_control(unit, in, out)
out->baddata = omega->baddata;
out->lastevent = omega->lastevent;
out->currentstatus = omega->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;
}
}
}
diff --git a/usr.sbin/xntpd/xntpd/refclock_parse.c b/usr.sbin/xntpd/xntpd/refclock_parse.c
index 0d95d18908a5..7ef54ab60ab9 100644
--- a/usr.sbin/xntpd/xntpd/refclock_parse.c
+++ b/usr.sbin/xntpd/xntpd/refclock_parse.c
@@ -49,7 +49,7 @@
* - Conrad DCF77 receiver module (DCF)
* - FAU DCF77 NTP receiver (TimeBrick) (DCF)
* - Meinberg GPS166 (GPS)
- * - Trimble SV6 (GPS)
+ * - Trimble SV6 (TSIP and TAIP protocol) (GPS)
*
*/
@@ -474,31 +474,67 @@ static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
#define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)"
/*
- * Trimble SV6 GPS receiver
+ * Trimble SV6 GPS receivers (TAIP and TSIP protocols)
*/
+#define ETX 0x03
+#define DLE 0x10
+
#define TRIM_POLLRATE 0 /* only true direct polling */
-#define TRIM_POLLCMD ">QTM<"
-#define TRIM_CMDSIZE 5
-
-static poll_info_t trimble_pollinfo = { TRIM_POLLRATE, TRIM_POLLCMD, TRIM_CMDSIZE };
-static int trimble_init P((struct parseunit *));
-
-#define TRIMBLESV6_CFLAG (B4800|CS8|CREAD)
-#define TRIMBLESV6_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
-#define TRIMBLESV6_OFLAG (OPOST|ONLCR)
-#define TRIMBLESV6_LFLAG (ICANON|ECHOK)
-#define TRIMBLESV6_FLAGS (PARSE_F_PPSPPS|PARSE_F_PPSONSECOND)
-#define TRIMBLESV6_POLL poll_dpoll
-#define TRIMBLESV6_INIT trimble_init
-#define TRIMBLESV6_END poll_end
-#define TRIMBLESV6_DATA ((void *)(&trimble_pollinfo))
-#define TRIMBLESV6_ID GPS_ID
-#define TRIMBLESV6_FORMAT NO_FORMAT
-#define TRIMBLESV6_ROOTDELAY 0x0
-#define TRIMBLESV6_BASEDELAY 0x0
-#define TRIMBLESV6_DESCRIPTION "Trimble SV6 GPS receiver"
-#define TRIMBLESV6_MAXUNSYNC 0
-#define TRIMBLESV6_EOL '<'
+
+#define TRIM_TAIPPOLLCMD ">QTM<"
+#define TRIM_TAIPCMDSIZE 5
+static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE };
+static int trimbletaip_init P((struct parseunit *));
+
+/* query time & UTC correction data */
+static char tsipquery[] = { DLE, 0x21, DLE, ETX, DLE, 0x2F, DLE, ETX };
+
+static poll_info_t trimbletsip_pollinfo = { TRIM_POLLRATE, tsipquery, sizeof(tsipquery) };
+static int trimbletsip_init P((struct parseunit *));
+
+#define TRIMBLETAIP_CFLAG (B4800|CS8|CREAD)
+#define TRIMBLETAIP_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
+#define TRIMBLETAIP_OFLAG (OPOST|ONLCR)
+#define TRIMBLETAIP_LFLAG (ICANON|ECHOK)
+#define TRIMBLETSIP_CFLAG (B9600|CS8|CLOCAL|CREAD|PARENB|PARODD)
+#define TRIMBLETSIP_IFLAG (IGNBRK)
+#define TRIMBLETSIP_OFLAG (0)
+#define TRIMBLETSIP_LFLAG (0)
+
+#define TRIMBLETAIP_FLAGS (PARSE_F_PPSPPS|PARSE_F_PPSONSECOND)
+#define TRIMBLETSIP_FLAGS (TRIMBLETAIP_FLAGS|PARSE_F_NOPOLLONLY)
+
+#define TRIMBLETAIP_POLL poll_dpoll
+#define TRIMBLETSIP_POLL poll_dpoll
+
+#define TRIMBLETAIP_INIT trimbletaip_init
+#define TRIMBLETSIP_INIT trimbletsip_init
+
+#define TRIMBLETAIP_END poll_end
+#define TRIMBLETSIP_END poll_end
+
+#define TRIMBLETAIP_DATA ((void *)(&trimbletaip_pollinfo))
+#define TRIMBLETSIP_DATA ((void *)(&trimbletsip_pollinfo))
+
+#define TRIMBLETAIP_ID GPS_ID
+#define TRIMBLETSIP_ID GPS_ID
+
+#define TRIMBLETAIP_FORMAT NO_FORMAT
+#define TRIMBLETSIP_FORMAT "Trimble SV6/TSIP"
+
+#define TRIMBLETAIP_ROOTDELAY 0x0
+#define TRIMBLETSIP_ROOTDELAY 0x0
+
+#define TRIMBLETAIP_BASEDELAY 0x0
+#define TRIMBLETSIP_BASEDELAY 0x51EB852 /* 20 ms as a l_uf - avg GPS time message latency */
+
+#define TRIMBLETAIP_DESCRIPTION "Trimble GPS (TAIP) receiver"
+#define TRIMBLETSIP_DESCRIPTION "Trimble GPS (TSIP) receiver"
+
+#define TRIMBLETAIP_MAXUNSYNC 0
+#define TRIMBLETSIP_MAXUNSYNC 0
+
+#define TRIMBLETAIP_EOL '<'
static struct clockinfo
{
@@ -674,23 +710,42 @@ static struct clockinfo
GPS166_LFLAG
},
{ /* 127.127.8.32+<device> */
- TRIMBLESV6_FLAGS,
- TRIMBLESV6_POLL,
- TRIMBLESV6_INIT,
- TRIMBLESV6_END,
- TRIMBLESV6_DATA,
- TRIMBLESV6_ROOTDELAY,
- TRIMBLESV6_BASEDELAY,
+ TRIMBLETAIP_FLAGS,
+ TRIMBLETAIP_POLL,
+ TRIMBLETAIP_INIT,
+ TRIMBLETAIP_END,
+ TRIMBLETAIP_DATA,
+ TRIMBLETAIP_ROOTDELAY,
+ TRIMBLETAIP_BASEDELAY,
+ NO_PPSDELAY,
+ TRIMBLETAIP_ID,
+ TRIMBLETAIP_DESCRIPTION,
+ TRIMBLETAIP_FORMAT,
+ GPS_TYPE,
+ TRIMBLETAIP_MAXUNSYNC,
+ TRIMBLETAIP_CFLAG,
+ TRIMBLETAIP_IFLAG,
+ TRIMBLETAIP_OFLAG,
+ TRIMBLETAIP_LFLAG
+ },
+ { /* 127.127.8.36+<device> */
+ TRIMBLETSIP_FLAGS,
+ TRIMBLETSIP_POLL,
+ TRIMBLETSIP_INIT,
+ TRIMBLETSIP_END,
+ TRIMBLETSIP_DATA,
+ TRIMBLETSIP_ROOTDELAY,
+ TRIMBLETSIP_BASEDELAY,
NO_PPSDELAY,
- TRIMBLESV6_ID,
- TRIMBLESV6_DESCRIPTION,
- TRIMBLESV6_FORMAT,
+ TRIMBLETSIP_ID,
+ TRIMBLETSIP_DESCRIPTION,
+ TRIMBLETSIP_FORMAT,
GPS_TYPE,
- TRIMBLESV6_MAXUNSYNC,
- TRIMBLESV6_CFLAG,
- TRIMBLESV6_IFLAG,
- TRIMBLESV6_OFLAG,
- TRIMBLESV6_LFLAG
+ TRIMBLETSIP_MAXUNSYNC,
+ TRIMBLETSIP_CFLAG,
+ TRIMBLETSIP_IFLAG,
+ TRIMBLETSIP_OFLAG,
+ TRIMBLETSIP_LFLAG
}
};
@@ -3409,11 +3464,12 @@ poll_end(parse)
** special code for special clocks
**/
+
/*--------------------------------------------------
- * trimble init routine - setup EOL and then do poll_init.
+ * trimble TAIP init routine - setup EOL and then do poll_init.
*/
static int
-trimble_init(parse)
+trimbletaip_init(parse)
struct parseunit *parse;
{
#ifdef HAVE_TERMIOS
@@ -3427,21 +3483,221 @@ trimble_init(parse)
*/
if (TTY_GETATTR(parse->fd, &tm) == -1)
{
- syslog(LOG_ERR, "PARSE receiver #%d: trimble_init: tcgetattr(fd, &tm): %m", CL_UNIT(parse->unit));
+ syslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tm): %m", CL_UNIT(parse->unit));
return 0;
}
else
{
- tm.c_cc[VEOL] = TRIMBLESV6_EOL;
+ tm.c_cc[VEOL] = TRIMBLETAIP_EOL;
if (TTY_SETATTR(parse->fd, &tm) == -1)
{
- syslog(LOG_ERR, "PARSE receiver #%d: trimble_init: tcsetattr(fd, &tm): %m", CL_UNIT(parse->unit));
+ syslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tm): %m", CL_UNIT(parse->unit));
return 0;
}
}
return poll_init(parse);
}
+
+/*
+ * This driver supports the Trimble SVee Six Plus GPS receiver module.
+ * It should support other Trimble receivers which use the Trimble Standard
+ * Interface Protocol (see below).
+ *
+ * The module has a serial I/O port for command/data and a 1 pulse-per-second
+ * output, about 1 microsecond wide. The leading edge of the pulse is
+ * coincident with the change of the GPS second. This is the same as
+ * the change of the UTC second +/- ~1 microsecond. Some other clocks
+ * specifically use a feature in the data message as a timing reference, but
+ * the SVee Six Plus does not do this. In fact there is considerable jitter
+ * on the timing of the messages, so this driver only supports the use
+ * of the PPS pulse for accurate timing. Where it is determined that
+ * the offset is way off, when first starting up xntpd for example,
+ * the timing of the data stream is used until the offset becomes low enough
+ * (|offset| < CLOCK_MAX), at which point the pps offset is used.
+ *
+ * It can use either option for receiving PPS information - the 'ppsclock'
+ * stream pushed onto the serial data interface to timestamp the Carrier
+ * Detect interrupts, where the 1PPS connects to the CD line. This only
+ * works on SunOS 4.1.x currently. To select this, define PPSPPS in
+ * Config.local. The other option is to use a pulse-stretcher/level-converter
+ * to convert the PPS pulse into a RS232 start pulse & feed this into another
+ * tty port. To use this option, define PPSCLK in Config.local. The pps input,
+ * by whichever method, is handled in ntp_loopfilter.c
+ *
+ * The receiver uses a serial message protocol called Trimble Standard
+ * Interface Protocol (it can support others but this driver only supports
+ * TSIP). Messages in this protocol have the following form:
+ *
+ * <DLE><id> ... <data> ... <DLE><ETX>
+ *
+ * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled
+ * on transmission and compressed back to one on reception. Otherwise
+ * the values of data bytes can be anything. The serial interface is RS-422
+ * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits
+ * in total!), and 1 stop bit. The protocol supports byte, integer, single,
+ * and double datatypes. Integers are two bytes, sent most significant first.
+ * Singles are IEEE754 single precision floating point numbers (4 byte) sent
+ * sign & exponent first. Doubles are IEEE754 double precision floating point
+ * numbers (8 byte) sent sign & exponent first.
+ * The receiver supports a large set of messages, only a small subset of
+ * which are used here. From driver to receiver the following are used:
+ *
+ * ID Description
+ *
+ * 21 Request current time
+ * 22 Mode Select
+ * 2C Set/Request operating parameters
+ * 2F Request UTC info
+ * 35 Set/Request I/O options
+
+ * From receiver to driver the following are recognised:
+ *
+ * ID Description
+ *
+ * 41 GPS Time
+ * 44 Satellite selection, PDOP, mode
+ * 46 Receiver health
+ * 4B Machine code/status
+ * 4C Report operating parameters (debug only)
+ * 4F UTC correction data (used to get leap second warnings)
+ * 55 I/O options (debug only)
+ *
+ * All others are accepted but ignored.
+ *
+ */
+
+#define PI 3.1415926535898 /* lots of sig figs */
+#define D2R PI/180.0
+
+/*-------------------------------------------------------------------
+ * sendcmd, sendbyte, sendetx, sendflt, sendint implement the command
+ * interface to the receiver.
+ *
+ * CAVEAT: the sendflt, sendint routines are byte order dependend and
+ * float implementation dependend - these must be converted to portable
+ * versions !
+ */
+
+union {
+ u_char bd[8];
+ int iv;
+ float fv;
+ double dv;
+} uval;
+
+struct txbuf
+{
+ short idx; /* index to first unused byte */
+ u_char *txt; /* pointer to actual data buffer */
+};
+
+void
+sendcmd(buf, c)
+ struct txbuf *buf;
+ u_char c;
+{
+ buf->txt[0] = DLE;
+ buf->txt[1] = c;
+ buf->idx = 2;
+}
+
+void sendbyte(buf, b)
+ struct txbuf *buf;
+ u_char b;
+{
+ if (b == DLE)
+ buf->txt[buf->idx++] = DLE;
+ buf->txt[buf->idx++] = b;
+}
+
+void
+sendetx(buf, parse)
+ struct txbuf *buf;
+ struct parseunit *parse;
+{
+ buf->txt[buf->idx++] = DLE;
+ buf->txt[buf->idx++] = ETX;
+
+ if (write(parse->fd, buf->txt, buf->idx) != buf->idx)
+ {
+ syslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CL_UNIT(parse->unit));
+ }
+}
+
+void
+sendint(buf, a)
+ struct txbuf *buf;
+ int a;
+{
+ uval.iv = a;
+ sendbyte(buf, uval.bd[2]);
+ sendbyte(buf, uval.bd[3]);
+}
+
+void
+sendflt(buf, a)
+ struct txbuf *buf;
+ float a;
+{
+ int i;
+
+ uval.fv = a;
+ for (i=0; i<=3; i++)
+ sendbyte(buf, uval.bd[i]);
+}
+
+/*--------------------------------------------------
+ * trimble TSIP init routine
+ */
+static int
+trimbletsip_init(parse)
+ struct parseunit *parse;
+{
+ u_char buffer[256];
+ struct txbuf buf;
+
+ buf.txt = buffer;
+
+ if (!poll_init(parse))
+ {
+ sendcmd(&buf, 0x1f); /* request software versions */
+ sendetx(&buf, parse);
+
+ sendcmd(&buf, 0x2c); /* set operating parameters */
+ sendbyte(&buf, 4); /* static */
+ sendflt(&buf, 5.0*D2R); /* elevation angle mask = 10 deg XXX */
+ sendflt(&buf, 4.0); /* s/n ratio mask = 6 XXX */
+ sendflt(&buf, 12.0); /* PDOP mask = 12 */
+ sendflt(&buf, 8.0); /* PDOP switch level = 8 */
+ sendetx(&buf, parse);
+
+ sendcmd(&buf, 0x22); /* fix mode select */
+ sendbyte(&buf, 0); /* automatic */
+ sendetx(&buf, parse);
+
+ sendcmd(&buf, 0x28); /* request system message */
+ sendetx(&buf, parse);
+
+ sendcmd(&buf, 0x8e); /* superpacket fix */
+ sendbyte(&buf, 0x2); /* binary mode */
+ sendetx(&buf, parse);
+
+ sendcmd(&buf, 0x35); /* set I/O options */
+ sendbyte(&buf, 0); /* no position output */
+ sendbyte(&buf, 0); /* no velocity output */
+ sendbyte(&buf, 7); /* UTC, compute on seconds, send only on request */
+ sendbyte(&buf, 0); /* no raw measurements */
+ sendetx(&buf, parse);
+
+ sendcmd(&buf, 0x2f); /* request UTC correction data */
+ sendetx(&buf, parse);
+ return 0;
+ }
+ else
+ return 1;
+}
+
#endif /* defined(REFCLOCK) && defined(PARSE) */
/*
diff --git a/usr.sbin/xntpd/xntpd/refclock_pst.c b/usr.sbin/xntpd/xntpd/refclock_pst.c
index 4b8909afb801..29cbfb1201ec 100644
--- a/usr.sbin/xntpd/xntpd/refclock_pst.c
+++ b/usr.sbin/xntpd/xntpd/refclock_pst.c
@@ -1,7 +1,7 @@
/*
- * refclock_pst - driver for the PSTI 1010/1020 WWV clock
+ * refclock_pst - clock driver for PSTI/Traconex WWV/WWVH receivers
*/
-#if defined(REFCLOCK) && (defined(PST) || defined(PSTCLK) || defined(PSTPPS))
+#if defined(REFCLOCK) && defined(PST)
#include <stdio.h>
#include <ctype.h>
@@ -10,1795 +10,320 @@
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-
-#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(HAVE_TERMIOS)
-#include <termios.h>
-#endif
-#if defined(STREAM)
-#include <stropts.h>
-#if defined(PSTCLK)
-#include <sys/clkdefs.h>
-#endif /* PSTCLK */
-#endif /* STREAM */
-
-#if defined (PSTPPS)
-#include <sys/ppsclock.h>
-#endif /* PSTPPS */
-
#include "ntp_stdlib.h"
/*
- * This driver is in good measure due to David Schachter, who wrote
- * the firmware for the PST clock. Not that he is to blame for
- * any of this, but he kindly loaned me a clock to allow me to
- * debug this.
- *
- * Postscript:
- *
- * The strategy in here is actually pretty good, especially if
- * you try to support the clock on something lacking low order
- * clock bits like a Sun, since all the business which is done
- * before taking a time stamp tends to randomize the taking of
- * the stamp with respect to the timer interrupt. It is, however,
- * a big cpu hog, and in some ways is a bit of a waste since, as
- * it turns out, the PST clock can give you no better than a
- * millisecond precision and it doesn't pay to try to push it
- * harder.
- *
- * In any event, like the first waffle off the iron, this one
- * should probably be tossed. My current preference would be
- * to retain the 12-a-minute schedule, but to use the QU command
- * instead of the QD and QT, and to only send a QM command with
- * the 12th poll of the minute to get the minutes-since-sync
- * and the station. Need to get a clock which supports QU,
- * however.
- *
- * End postscript
- *
- * This driver polls the clock using the QM, QT and QD commands.
- * Ntpd actually uses QU instead of the last two, something I would
- * like to have done as well since it gives you the day and time
- * atom, but the firmware in the clock I had (X04.01.999) didn't know
- * about this command.
- *
- * The QM command produces output like:
- *
- * O6B532352823C00270322
- * b c deeee
- *
- * We use (b) for the time zone, (c) to see whether time is available,
- * (d) to tell whether we are sync'd to WWV or WWVH, and (e) to determine
- * the number of minutes since the last signal was received. We
- * don't trust the clock for more than about 20 minutes on its own.
- * After this, we keep taking the time but mark the clock unsynchronized.
+ * This driver supports the PSTI 1010 and Traconex 1020 WWV/WWVH
+ * Receivers. No specific claim of accuracy is made for these receiver,
+ * but actual experience suggests that 10 ms would be a conservative
+ * assumption.
+ *
+ * The DIPswitches should be set for 9600 bps line speed, 24-hour day-
+ * of-year format and UTC time zone. Automatic correction for DST should
+ * be disabled. It is very important that the year be set correctly in
+ * the DIPswitches; otherwise, the day of year will be incorrect after
+ * 28 April of a normal or leap year. The propagation delay DIPswitches
+ * should be set according to the distance from the transmitter for both
+ * WWV and WWVH, as described in the instructions. While the delay can
+ * be set only to within 11 ms, the fudge time1 parameter can be used
+ * for vernier corrections.
*
- * The QT command returns something that looks like this:
+ * Using the poll sequence QTQDQM, the response timecode is in three
+ * sections totalling 50 ASCII printing characters, as concatenated by
+ * the driver, in the following format:
*
- * 18:57:50.263D
+ * ahh:mm:ss.fffs<cr> yy/dd/mm/ddd<cr> frdzycchhSSFTttttuuxx<cr>
*
- * Note that this particular sample is in 24 hour format, local time
- * (daylight savings time even). We allow just about anything for
- * this (sigh) since this leaves the clock owner free to set the
- * display mode in whatever way he finds convenient for setting
- * his watch.
+ * on-time = first <cr> * hh:mm:ss.fff = hours, minutes, seconds, milliseconds
+ * a = AM/PM indicator (' ' for 24-hour mode)
+ * yy = year (from internal switches)
+ * dd/mm/ddd = day of month, month, day of year
+ * s = daylight-saving indicator (' ' for 24-hour mode)
+ * f = frequency enable (O = all frequencies enabled)
+ * r = baud rate (3 = 1200, 6 = 9600)
+ * d = features indicator (@ = month/day display enabled)
+ * z = time zone (0 = UTC)
+ * y = year (5 = 91)
+ * cc = WWV propagation delay (52 = 22 ms)
+ * hh = WWVH propagation delay (81 = 33 ms)
+ * SS = status (80 or 82 = operating correctly)
+ * F = current receive frequency (4 = 15 MHz)
+ * T = transmitter (C = WWV, H = WWVH)
+ * tttt = time since last update (0000 = minutes)
+ * uu = flush character (03 = ^c)
+ * xx = 94 (unknown)
*
- * The QD command returns:
+ * The alarm condition is indicated by other than '8' at A, which occurs
+ * during initial synchronization and when received signal is lost for
+ * an extended period; unlock condition is indicated by other than
+ * "0000" in the tttt subfield at Q.
*
- * 89/10/19/292
+ * Fudge Factors
*
- * We actually only use the day-of-the-year here. We use the year
- * only to determine whether the PST clock thinks the current year
- * has 365 or 366 days in it.
- *
- * At the current writing, this code expects to be using a BSD-style
- * terminal driver. It will compile code which uses the CLKLDISC
- * line discipline if it thinks this is available, but use cooked
- * mode otherwise. The cooked mode stuff may not have been tested.
- */
-
-/*
- * Definitions
- */
-#define MAXUNITS 4 /* maximum number of PST units permitted */
-#define PSTDEV "/dev/pst%d" /* device we open. %d is unit number */
-#define NPSTSAMPS 12 /* take 12 PST samples per minute */
-
-/*
- * Other constant stuff
+ * There are no special fudge factors other than the generic.
*/
-#define PSTPRECISION (-9) /* what the heck */
-#define WWVREFID "WWV\0"
-#define WWVHREFID "WWVH"
-#define PSTHSREFID 0x7f7f030a /* 127.127.3.10 refid for hi strata */
/*
- * Parameters for the clock
+ * Interface definitions
*/
-#define SPEED232 B9600
-#define PSTMAGIC2 ('\r' | 0x80) /* HP-UX uses this also now */
-#ifdef CLKLDISC
-#define PSTMAGIC1 '\r'
-#define PSTEOL '\r'
-#else
-#define PSTEOL '\n'
-#endif
+#define DEVICE "/dev/pst%d" /* device name and unit */
+#define SPEED232 B9600 /* uart speed (9600 baud) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define WWVREFID "WWV\0" /* WWV reference ID */
+#define WWVHREFID "WWVH" /* WWVH reference ID */
+#define DESCRIPTION "PSTI/Traconex WWV/WWVH Receiver" /* WRU */
-/*
- * Description of clock. We fill in whether it is a 1010 or 1020,
- * and the firmware revision, using the QV command.
- */
-#define PSTDESCLEN 64
-#define PSTDESCRIPTION "%s %s (%s) WWV/H Receiver"
-#define PSTDEFDESC "PSTI/Traconex 10?0 (V??.??) WWV/H Receiver"
+#define NSAMPLES 3 /* stages of median filter */
+#define LENPST 46 /* min timecode length */
/*
- * Length of the PST time code. This must be the length of the output
- * of the QM command, plus QT, plus QD, plus two spaces. We make it
- * big just on principle.
+ * Imported from ntp_timer module
*/
-#define PSTCODELEN (128)
+extern u_long current_time; /* current time (s) */
/*
- * Minimum and maximum lengths
- */
-#define PSTMINQVLEN (16)
-#define PSTMAXQVLEN (24)
-
-#define PSTMINQMLEN (19)
-#define PSTMAXQMLEN (32)
-
-#define PSTMINQDLEN (12)
-#define PSTMAXQDLEN (12)
-
-#define PSTMINQTLEN (14)
-#define PSTMAXQTLEN (14)
-
-/*
- * It turns out that the QT command does *not* adjust for transmission
- * delays. Since the QT command returns 15 characters at 9600 baud,
- * the adjustment for this should be 15.6 ms. We'll default to this,
- * but don't let this stop you from fiddling with the fudge factors
- * to make things come out right
- */
-#define PSTQTFUDGE 0x04000000 /* about 15.6 ms */
-
-/*
- * Default propagation delays. About right for Toronto
- */
-#define DEFWWVPROP 0x01eb851f /* about 7.5 ms */
-#define DEFWWVHPROP 0x06c8b439 /* about 26.5 ms */
-
-/*
- * Maximum propagation delay we believe. 125 ms as an l_fp fraction
- */
-#define PSTMAXPROP 0x20000000
-
-/*
- * Default minutes since an update.
- */
-#define DEFMAXFREERUN (20)
-
-/*
- * Hack to avoid excercising the multiplier. I have no pride.
+ * Imported from ntpd module
*/
-#define MULBY10(x) (((x)<<3) + ((x)<<1))
+extern int debug; /* global debug flag */
/*
- * PST unit control structure.
+ * Unit control structure
*/
struct pstunit {
- struct peer *peer; /* associated peer structure */
- struct event psttimer; /* timeout timer structure */
- struct refclockio pstio; /* given to the I/O handler */
- l_fp rectimes[NPSTSAMPS]; /* times we received this stuff */
- l_fp reftimes[NPSTSAMPS]; /* times of codes received */
- l_fp lastrec; /* last receive time */
- l_fp lastref; /* last reference time */
- char description[PSTDESCLEN]; /* description of clock */
- char lastcode[PSTCODELEN]; /* last code we received */
- u_char lencode; /* length of the last code */
- u_char nextsample; /* the next offset expected */
- u_char unit; /* unit number for this guy */
- u_char state; /* what we're waiting for */
- s_char station; /* WWV or WWVH? */
- u_char flags; /* flag byte */
- u_char status; /* clock status */
- u_char lastevent; /* last clock event */
- u_char timezone; /* hour offset to time zone */
- u_char errors; /* number of errors detected */
- u_char year; /* year reported by clock */
- u_char month; /* month, from clock */
- u_char monthday; /* day, from clock */
- u_char hour; /* hour of day */
- u_char minute; /* minute of day */
- u_char second; /* second of day */
- u_char leap; /* leap indicators */
- s_char tzoffset; /* time zone offset */
- u_char reason; /* reason for failure */
- u_short millisecond; /* millisecond of day */
- u_short yearday; /* day of the year */
- u_short timesincesync; /* time since radio got sample */
- U_LONG yearstart; /* NTP time at year start */
- U_LONG lastupdate; /* last time data received */
- U_LONG polls; /* number of polls */
- U_LONG noreply; /* number of time outs */
- U_LONG badformat; /* number of bad format responses */
- U_LONG baddata; /* number of invalid time codes */
- U_LONG timestarted; /* time we started this */
-};
+ int pollcnt; /* poll message counter */
-/*
- * States we might be in
- */
-#define STATE_IDLE 0 /* not doing anything in particular */
-#define STATE_QV 1 /* trying to get version */
-#define STATE_QM 2 /* sent QM */
-#define STATE_QD 3 /* sent QD */
-#define STATE_QT 4 /* send QT */
-
-/*
- * Status flags
- */
-#define PST_LEAPYEAR 0x1 /* pst clock thinks it is a leap year */
-#define PST_SIGFAULT 0x2 /* signal fault */
-#define PST_HARDERR 0x4 /* hardware error */
-#define PST_NOTIME 0x8 /* no time available */
-#define PST_WWVH 0x10 /* synchronized to WWVH */
-#define PST_DOQV 0x20 /* get version, reinit delays */
-#define PST_DORESET 0x40 /* reset the clock */
-
-/*
- * The PST often encodes stuff by adding an ASCII '0' to it. The
- * largest range of values encoded this way is 0 through 31, or '0'
- * through 'O'. These macroes manipulate these values.
- */
-#define ISVALIDPST(c) ((c) >= '0' && (c) <= 'O')
-#define PSTTOBIN(c) ((int)(c) - '0')
-#define BINTOPST(c) ((char)((c) + '0'))
-
-/*
- * Status bits. Look at the QM command
- */
-#define SIGFAULT 0x1
-#define HARDFAULT 0x2
-#define OUTOFSPEC 0x4
-#define TIMEAVAILABLE 0x8
-
-/*
- * Module reason codes
- */
-#define QVREASON 20
-#define QMREASON 40
-#define QDREASON 60
-#define QTREASON 80
-
-/*
- * Station i.d. characters in QM output
- */
-#define WWV_CHAR 'C'
-#define WWVH_CHAR 'H'
-
-/*
- * We allow a few errors, but if we get more than 12 seconds behind
- * the schedule we start from sample 0 again. 4 seconds is the minimum
- * time between time out routine executions.
- */
-#define PSTMAXDELAY 12
-#define PSTMINTIMEOUT 4
-
-/*
- * The PST polling schedule. We poll 12 times per 64 seconds (far too
- * many, but what the heck). The polls are scheduled to finish in this
- * time with the assumption that the timer is good for no better than
- * 4 second resolution. If we get too far behind (due to bad samples
- * or no responses) we start over.
- */
-struct pstsched {
- u_short nextinterval;
- u_short tooold;
+ u_char tcswitch; /* timecode switch */
+ char *lastptr; /* pointer to timecode data */
};
-static struct pstsched psttab[NPSTSAMPS] = {
- { 4, PSTMAXDELAY+1 },
- { 4, PSTMAXDELAY+1+4 },
- { 8, PSTMAXDELAY+1+4+4 },
- { 4, PSTMAXDELAY+1+4+4+8 },
- { 8, PSTMAXDELAY+1+4+4+8+4 },
- { 4, PSTMAXDELAY+1+4+4+8+4+8 },
- { 4, PSTMAXDELAY+1+4+4+8+4+8+4 },
- { 8, PSTMAXDELAY+1+4+4+8+4+8+4+4 },
- { 4, PSTMAXDELAY+1+4+4+8+4+8+4+4+8 },
- { 8, PSTMAXDELAY+1+4+4+8+4+8+4+4+8+4 },
- { 4, PSTMAXDELAY+1+4+4+8+4+8+4+4+8+4+8 },
- { 4, PSTMAXDELAY+1+4+4+8+4+8+4+4+8+4+8+4 }
-};
-
-
-/*
- * Data space for the unit structures. Note that we allocate these on
- * the fly, but never give them back.
- */
-static struct pstunit *pstunits[MAXUNITS];
-static u_char unitinuse[MAXUNITS];
-
-/*
- * Structure to keep processed propagation data in.
- */
-struct pst_propagate {
- U_LONG remainder; /* left over submillisecond remainder */
- char msbchar; /* character for high order bits */
- char lsbchar; /* character for low order bits */
-};
-
-
-/*
- * Keep the fudge factors separately so they can be set even
- * when no clock is configured.
- */
-static l_fp wwv_prop_delay[MAXUNITS];
-static l_fp wwvh_prop_delay[MAXUNITS];
-static struct pst_propagate wwv_prop_data[MAXUNITS];
-static struct pst_propagate wwvh_prop_data[MAXUNITS];
-static u_char stratumtouse[MAXUNITS];
-static u_char sloppyclock[MAXUNITS];
-static u_short freerun[MAXUNITS];
-
-/*
- * Pointer to the default description
- */
-static char *pstdefdesc = PSTDEFDESC;
-
-/*
- * macro for writing to the clock, printing an error if we fail
- */
-#define pst_send(pst, str, len) \
- if (write((pst)->pstio.fd, (str), (len)) < 0) \
- pst_write_error((pst))
-
-/*
- * macro for resetting the clock structure to zero
- */
-#define pst_reset(pst) \
- do { \
- pst->nextsample = 0; \
- pst->station = 0; \
- pst->leap = 0; \
- } while (0)
-
-/*
- * macro for event reporting
- */
-#define pst_event(pst, evnt_code) \
- do { \
- if ((pst)->status != (u_char)(evnt_code)) \
- pst_do_event((pst), (evnt_code)); \
- } while (0)
-
-/*
- * Imported from the timer module
- */
-extern U_LONG current_time;
-extern struct event timerqueue[];
-
-/*
- * Imported from ntp_loopfilter module
- */
-extern int fdpps; /* pps file descriptor */
-
-/*
- * Imported from ntpd module
- */
-extern int debug; /* global debug flag */
-
/*
* Function prototypes
*/
-static void pst_init P((void));
-static int pst_start P((u_int, struct peer *));
-static void pst_shutdown P((int));
+static int pst_start P((int, struct peer *));
+static void pst_shutdown P((int, struct peer *));
static void pst_receive P((struct recvbuf *));
-static void pst_process P((struct pstunit *));
-static void pst_control P((u_int, struct refclockstat *, struct refclockstat *));
-static void pst_buginfo P((int, struct refclockbug *));
-static void pst_write_error P((struct pstunit *));
-static void pst_timeout P((struct peer *));
-static int pst_QV_process P((struct pstunit *, struct recvbuf *));
-static int pst_QM_process P((struct pstunit *, struct recvbuf *));
-static int pst_QD_process P((struct pstunit *, struct recvbuf *));
-static int pst_QT_process P((struct pstunit *, struct recvbuf *, l_fp *, l_fp *));
-static void pst_do_event P((struct pstunit *, int));
-static void pst_compute_delay P((U_LONG, struct pst_propagate *));
+static void pst_poll P((int, struct peer *));
/*
* Transfer vector
*/
struct refclock refclock_pst = {
- pst_start, pst_shutdown, noentry,
- pst_control, pst_init, pst_buginfo, NOFLAGS
+ pst_start, /* start up driver */
+ pst_shutdown, /* shut down driver */
+ pst_poll, /* transmit poll message */
+ noentry, /* not used (old pst_control) */
+ noentry, /* initialize driver */
+ noentry, /* not used (old pst_buginfo) */
+ NOFLAGS /* not used */
};
-/*
- * pst_init - initialize internal PST driver data
- */
-static void
-pst_init()
-{
- register int i;
-
- /*
- * Just zero the data arrays
- */
- memset((char *)pstunits, 0, sizeof pstunits);
- memset((char *)unitinuse, 0, sizeof unitinuse);
-
- /*
- * Initialize fudge factors to default.
- */
- for (i = 0; i < MAXUNITS; i++) {
- wwv_prop_delay[i].l_ui = 0;
- wwv_prop_delay[i].l_uf = DEFWWVPROP;
- pst_compute_delay(DEFWWVPROP, &wwv_prop_data[i]);
- wwvh_prop_delay[i].l_ui = 0;
- wwvh_prop_delay[i].l_uf = DEFWWVHPROP;
- pst_compute_delay(DEFWWVHPROP, &wwvh_prop_data[i]);
- stratumtouse[i] = 0;
- sloppyclock[i] = 0;
- freerun[i] = DEFMAXFREERUN;
- }
-}
-
/*
- * pst_start - open the PST device and initialize data for processing
+ * pst_start - open the devices and initialize data for processing
*/
static int
pst_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register struct pstunit *pst;
- register int i;
- int fd232;
- char pstdev[20];
-
- /*
- * Check configuration info
- */
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "pst_start: unit %d invalid", unit);
- return 0;
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "pst_start: unit %d in use", unit);
- return 0;
- }
+ register struct pstunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
/*
- * Open serial port
- */
- (void) sprintf(pstdev, PSTDEV, unit);
- fd232 = open(pstdev, O_RDWR, 0777);
- if (fd232 == -1) {
- syslog(LOG_ERR, "pst_start: open of %s: %m", pstdev);
- 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,
- "pst_start: ioctl(%s, TCGETA): %m", pstdev);
- 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,
- "pst_start: ioctl(%s, TCSETA): %m", pstdev);
- goto screwed;
- }
- }
-#endif /* HAVE_SYSV_TTYS */
-#if defined(HAVE_TERMIOS)
- /*
- * POSIX serial line parameters (termios interface)
- *
- * The PSTCLK option provides timestamping at the driver level.
- * It requires the tty_clk streams module.
- *
- * The PSTPPS 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.
+ * Open serial port. Use CLK line discipline, if available.
*/
- { struct termios ttyb, *ttyp;
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
+ return (0);
- ttyp = &ttyb;
- if (tcgetattr(fd232, ttyp) < 0) {
- syslog(LOG_ERR,
- "pst_start: tcgetattr(%s): %m", pstdev);
- goto screwed;
- }
- ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
- 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,
- "pst_start: tcsetattr(%s): %m", pstdev);
- goto screwed;
- }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- syslog(LOG_ERR,
- "pst_start: tcflush(%s): %m", pstdev);
- goto screwed;
- }
- }
-#endif /* HAVE_TERMIOS */
-#ifdef STREAM
-#if defined(PSTCLK)
- if (ioctl(fd232, I_PUSH, "clk") < 0)
- syslog(LOG_ERR,
- "pst_start: ioctl(%s, I_PUSH, clk): %m", pstdev);
- if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
- syslog(LOG_ERR,
- "pst_start: ioctl(%s, CLK_SETSTR): %m", pstdev);
-#endif /* PSTCLK */
-#if defined(PSTPPS)
- if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
- syslog(LOG_ERR,
- "pst_start: ioctl(%s, I_PUSH, ppsclock): %m", pstdev);
- else
- fdpps = fd232;
-#endif /* PSTPPS */
-#endif /* STREAM */
-#if defined(HAVE_BSD_TTYS)
/*
- * 4.3bsd serial line parameters (sgttyb interface)
- *
- * The PSTCLK option provides timestamping at the driver level.
- * It requires the tty_clk line discipline and 4.3bsd or later.
+ * Allocate and initialize unit structure
*/
- { struct sgttyb ttyb;
-#if defined(PSTCLK)
- int ldisc = CLKLDISC;
-#endif /* PSTCLK */
-
- if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "pst_start: ioctl(%s, TIOCGETP): %m", pstdev);
- goto screwed;
- }
- ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
-#if defined(PSTCLK)
- 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 /* PSTCLK */
- if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "pst_start: ioctl(%s, TIOCSETP): %m", pstdev);
- goto screwed;
+ if (!(up = (struct pstunit *)
+ emalloc(sizeof(struct pstunit)))) {
+ (void) close(fd);
+ return (0);
}
-#if defined(PSTCLK)
- if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR,
- "pst_start: ioctl(%s, TIOCSETD): %m",pstdev);
- goto screwed;
- }
-#endif /* PSTCLK */
- }
-#endif /* HAVE_BSD_TTYS */
-
- /*
- * Allocate unit structure
- */
- if (pstunits[unit] != 0) {
- pst = pstunits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < MAXUNITS; i++) {
- if (!unitinuse[i] && pstunits[i] != 0)
- break;
- }
- if (i < MAXUNITS) {
- /*
- * Reclaim this one
- */
- pst = pstunits[i];
- pstunits[i] = 0;
- } else {
- pst = (struct pstunit *)emalloc(sizeof(struct pstunit));
- }
+ memset((char *)up, 0, sizeof(struct pstunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = pst_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
}
- memset((char *)pst, 0, sizeof(struct pstunit));
- pstunits[unit] = pst;
+ pp->unitptr = (caddr_t)up;
/*
- * Set up the structure
+ * Initialize miscellaneous variables
*/
- pst->peer = peer;
- pst->unit = (u_char)unit;
- pst->state = STATE_IDLE;
- pst->flags |= PST_DOQV;
- pst->timestarted = current_time;
- (void) strcpy(pst->description, pstdefdesc);
-
- pst->psttimer.peer = (struct peer *)pst;
- pst->psttimer.event_handler = pst_timeout;
-
- pst->pstio.clock_recv = pst_receive;
- pst->pstio.srcclock = (caddr_t)pst;
- pst->pstio.datalen = 0;
- pst->pstio.fd = fd232;
- if (!io_addclock(&pst->pstio)) {
- goto screwed;
- }
-
- /*
- * All done. Initialize a few random peer variables, then
- * start the timer and return success.
- */
- peer->precision = PSTPRECISION;
- peer->rootdelay = 0;
- peer->rootdispersion = 0;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, WWVREFID, 4);
- else
- peer->refid = htonl(PSTHSREFID);
- pst->psttimer.event_time = current_time + PSTMINTIMEOUT;
- TIMER_ENQUEUE(timerqueue, &pst->psttimer);
- unitinuse[unit] = 1;
- return 1;
-
- /*
- * Something broke; abandon ship.
- */
-screwed:
- (void) close(fd232);
- return (0);
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, WWVREFID, 4);
+ up->pollcnt = 2;
+ return (1);
}
+
/*
- * pst_shutdown - shut down a PST clock
+ * pst_shutdown - shut down the clock
*/
static void
-pst_shutdown(unit)
+pst_shutdown(unit, peer)
int unit;
+ struct peer *peer;
{
- register struct pstunit *pst;
+ register struct pstunit *up;
+ struct refclockproc *pp;
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "pst_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "pst_shutdown: unit %d not in use", unit);
- return;
- }
-
- /*
- * Tell the I/O module to turn us off, and dequeue timer
- * if any. We're history.
- */
- pst = pstunits[unit];
- TIMER_DEQUEUE(&pst->psttimer);
- io_closeclock(&pst->pstio);
- unitinuse[unit] = 0;
+ pp = peer->procptr;
+ up = (struct pstunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
}
/*
- * pst_write_error - complain about writes to the clock
+ * pst_receive - receive data from the serial interface
*/
static void
-pst_write_error(pst)
- struct pstunit *pst;
-{
- /*
- * This will fill syslog is something is really wrong. Should
- * throttle it back.
- */
- syslog(LOG_ERR, "pst_write_error: unit %d: %m", pst->unit);
-}
-
-
-/*
- * pst_timeout - process a timeout event
- */
-static void
-pst_timeout(fakepeer)
- struct peer *fakepeer;
-{
- register struct pstunit *pst;
- U_LONG poll;
-
- /*
- * The timeout routine always initiates a chain of
- * query-responses from the clock, by sending either
- * a QV command (if we need to (re)set the propagation
- * delays into the clock), a QM command or an SRY
- * command (after a leap second). The pst_receive()
- * routine should complete the set of queries on its own
- * LONG before the next time out is due, so if we see any
- * state in here other than idle it means the clock hasn't
- * responded.
- */
- pst = (struct pstunit *)fakepeer;
- switch(pst->state) {
- case STATE_IDLE:
- poll = (U_LONG)psttab[pst->nextsample].nextinterval;
- break; /* all is well */
-
- case STATE_QV:
- pst->flags |= PST_DOQV; /* no response, do QV again */
- /*FALLSTHROUGH*/
-
- case STATE_QM:
- case STATE_QD:
- case STATE_QT:
- pst->noreply++; /* mark the lack of response */
- poll = PSTMINTIMEOUT; /* minimum time poll */
- break;
-
- default:
- syslog(LOG_ERR, "pst_timeout: unit %d invalid state %d",
- pst->unit, pst->state);
- poll = PSTMINTIMEOUT; /* minimum time poll */
- break;
- }
-
- if (pst->flags & PST_DORESET) {
- /*
- * Do a reset. At the next interrupt, start with
- * a QV command to set in the delays.
- */
- pst->flags &= ~PST_DORESET;
- pst->flags |= PST_DOQV;
- pst->state = STATE_IDLE;
- pst_send(pst, "\003SRY", 4);
- } else if (pst->flags & PST_DOQV) {
- pst->polls++;
- pst->flags &= ~PST_DOQV;
- pst->state = STATE_QV;
- pst_send(pst, "\003QV", 3);
- } else {
- pst->polls++;
- pst->state = STATE_QM;
- pst_send(pst, "\003QM", 3);
- }
-
- pst->psttimer.event_time += poll;
- TIMER_ENQUEUE(timerqueue, &pst->psttimer);
-}
-
-
-/*
- * pst_QV_process - decode the results of a QV poll and insert fudge
- * factors into the clock.
- */
-static int
-pst_QV_process(pst, rbufp)
- register struct pstunit *pst;
- struct recvbuf *rbufp;
-{
- register char *cp;
- register char *bp;
- register int len;
- char *model;
- char *company;
- char buf[20];
- static char wwvdelay[6] = { 'S', 'C', '\0', 'S', 'E', '\0' };
- static char wwvhdelay[6] = { 'S', 'H', '\0', 'S', 'G', '\0' };
-
- /*
- * The output of the QV command looks like:
- *
- * PSTI ITS V04.01.000\r
- *
- * or
- *
- * TRAC ITS V04.01.000\r
- *
- * or
- *
- * TRACONEX TS V05.02.001\r
- *
- * The minimum length of the string is about 16 characters.
- * The maximum length is sort of unbounded, but we get suspicious
- * if it is more than 34.
- */
- len = rbufp->recv_length;
- if (len > PSTMAXQVLEN + 10)
- len = PSTMAXQVLEN + 10;
-
- bp = rbufp->recv_buffer;
- cp = pst->lastcode;
- while (len-- > 0) {
- *cp = (*bp++) & 0x7f; /* strip parity */
- if (!isprint(*cp))
- break;
- cp++;
- }
- pst->lencode = (u_char)(cp - pst->lastcode);
-
- /*
- * Okay, got all printable characters from the string
- * copied. We expect to have been terminated by the
- * EOL character. If not, forget it. If the length
- * is insane, forget it.
- */
-
- if (*cp != PSTEOL
- || pst->lencode < PSTMINQVLEN || pst->lencode > PSTMAXQVLEN) {
- pst->reason = QVREASON + 1;
- return 0;
- }
-
- /*
- * Now, format check what we can. Dump it at the least
- * sign of trouble.
- */
- cp = pst->lastcode;
- model = NULL;
- if (*cp++ != 'P' || *cp++ != 'S' || *cp++ != 'T'
- || *cp++ != 'I' || *cp++ != ' ') {
- cp = pst->lastcode;
- if (*cp++ != 'T' || *cp++ != 'R' || *cp++ != 'A'
- || *cp++ != 'C' || *cp++ != ' ') {
- cp = pst->lastcode;
- if (*cp++ != 'T' || *cp++ != 'R' || *cp++ != 'A'
- || *cp++ != 'C' || *cp++ != 'O' || *cp++ != 'N'
- || *cp++ != 'E' || *cp++ != 'X' || *cp != ' ') {
- pst->reason = QVREASON + 2;
- return 0;
- }
- company = "Traconex";
- model = "1030";
- }
- company = "Traconex";
- } else {
- company = "Precision Standard Time";
- }
-
- if (*cp == 'M')
- model = "1010";
- else if (*cp == 'I')
- model = "1020";
- else if (model == NULL) {
- pst->reason = QVREASON + 3;
- return 0;
- }
- cp++;
-
- if (*cp++ != 'T' || *cp++ != 'S' || *cp++ != ' ') {
- pst->reason = QVREASON + 4;
- return 0;
- }
- if (*cp != 'X' && *cp != 'V') {
- pst->reason = QVREASON + 5;
- return 0;
- }
-
- /*
- * Next is the version. Copy it into the buffer.
- */
- bp = buf;
- *bp++ = *cp++;
- while (isdigit(*cp) || *cp == '.')
- *bp++ = *cp++;
- *bp++ = '\0';
-
- /*
- * Final bit of fluff is to set the description
- */
- (void) sprintf(pst->description, PSTDESCRIPTION, company, model, buf);
-
- /*
- * Now the serious stuff. Since we are now sure that the
- * clock is there, we can be fairly sure that the delay
- * setting commands will take. Send them.
- */
- wwvdelay[2] = wwv_prop_data[pst->unit].msbchar;
- wwvdelay[5] = wwv_prop_data[pst->unit].lsbchar;
- pst_send(pst, wwvdelay, 6);
-
- /*
- * Same thing for WWVH
- */
- wwvhdelay[2] = wwvh_prop_data[pst->unit].msbchar;
- wwvhdelay[5] = wwvh_prop_data[pst->unit].lsbchar;
- pst_send(pst, wwvhdelay, 6);
-
- /*
- * Should be okay. Return positive response.
- */
- return 1;
-}
-
-
-/*
- * pst_QM_process - process the output of a QM command
- */
-static int
-pst_QM_process(pst, rbufp)
- register struct pstunit *pst;
- struct recvbuf *rbufp;
-{
- register char *cp;
- register char *bp;
- register int n;
-
- /*
- * The output of the QM command looks like:
- *
- * O6B532352823C00270322
- *
- * The minimum length of the string is 19 characters.
- * The maximum length is sort of unbounded, but we get suspicious
- * if it is more than 42.
- */
- n = rbufp->recv_length;
- if (n > PSTMAXQMLEN + 10)
- n = PSTMAXQMLEN + 10;
-
- bp = rbufp->recv_buffer;
- cp = pst->lastcode;
- while (n-- > 0) {
- *cp = (*bp++) & 0x7f; /* strip parity */
- if (!isprint(*cp))
- break;
- cp++;
- }
- pst->lencode = (u_char)(cp - pst->lastcode);
-
- /*
- * Okay, got all printable characters from the string
- * copied. We expect to have been terminated by the
- * EOL character. If not, forget it. If the length
- * is insane, forget it.
- */
- if (*cp != PSTEOL
- || pst->lencode < PSTMINQMLEN || pst->lencode > PSTMAXQMLEN) {
- pst->reason = QMREASON + 1;
- return 0;
- }
-
- /*
- * Ensure that the first PSTMINQMLEN characters are valid with
- * respect to the way the clock encodes binary data.
- */
- cp = pst->lastcode;
- n = pst->lencode;
- while (n-- > 0) {
- if (!ISVALIDPST(*cp)) {
- pst->reason = QMREASON + 2;
- return 0;
- }
- cp++;
- }
-
- /*
- * Collect information we are interested in.
- */
- cp = pst->lastcode;
- pst->timezone = PSTTOBIN(cp[3]);
- if (pst->timezone > 23) {
- pst->reason = QMREASON + 3;
- return 0;
- }
-
- pst->flags &=
- ~(PST_LEAPYEAR|PST_SIGFAULT|PST_HARDERR|PST_NOTIME|PST_WWVH);
- n = PSTTOBIN(cp[4]);
- if (n > 15) {
- pst->reason = QMREASON + 4;
- return 0;
- }
- if (((n + 2) & 0x3) == 0)
- pst->flags |= PST_LEAPYEAR;
-
- n = PSTTOBIN(cp[9]);
- if (n > 15) {
- pst->reason = QMREASON + 5;
- return 0;
- }
- if (n & SIGFAULT)
- pst->flags |= PST_SIGFAULT;
- if (n & HARDFAULT)
- pst->flags |= PST_HARDERR;
- if (!(n & TIMEAVAILABLE))
- pst->flags |= PST_NOTIME;
-
- if (cp[12] == 'H') {
- pst->flags |= PST_WWVH;
- } else if (cp[12] == 'C') {
- pst->flags &= ~PST_WWVH;
- } else {
- pst->reason = QMREASON + 6;
- return 0;
- }
-
- if (wwv_prop_data[pst->unit].msbchar != cp[5] ||
- wwv_prop_data[pst->unit].lsbchar != cp[6] ||
- wwvh_prop_data[pst->unit].msbchar != cp[7] ||
- wwvh_prop_data[pst->unit].lsbchar != cp[8])
- pst->flags |= PST_DOQV;
-
- bp = cp + 13;
- pst->timesincesync = 0;
- while (bp < (cp + 17)) {
- if (!isdigit(*bp)) {
- pst->reason = QMREASON + 6;
- return 0;
- }
- pst->timesincesync = MULBY10(pst->timesincesync)
- + PSTTOBIN(*bp);
- bp++;
- }
-
- /*
- * That's about all we can do. Return success.
- */
- return 1;
-}
-
-
-/*
- * pst_QD_process - process the output of a QD command
- */
-static int
-pst_QD_process(pst, rbufp)
- register struct pstunit *pst;
- struct recvbuf *rbufp;
-{
- register char *cp;
- register char *bp;
- register int n;
- char *cpstart;
- int len;
-
- /*
- * The output of the QM command looks like:
- *
- * 88/05/17/138\r
- *
- * The minimum length of the string is 12 characters as is
- * the maximum length.
- */
- n = rbufp->recv_length;
- if (n > PSTMAXQDLEN + 10)
- n = PSTMAXQDLEN + 10;
-
- bp = rbufp->recv_buffer;
- cp = &pst->lastcode[pst->lencode];
- *cp++ = ' ';
- cpstart = cp;
- while (n-- > 0) {
- *cp = (*bp++) & 0x7f; /* strip parity */
- if (!isprint(*cp))
- break;
- cp++;
- }
- len = (cp - cpstart);
- pst->lencode = (u_char)(cp - pst->lastcode);
-
- /*
- * Okay, got all printable characters from the string
- * copied. We expect to have been terminated by the
- * EOL character. If not, forget it. If the length
- * is insane, forget it.
- */
- if (*cp != PSTEOL ||
- len < PSTMINQDLEN || len > PSTMAXQDLEN) {
- pst->reason = QDREASON + 1;
- return 0;
- }
-
- /*
- * Ensure that the characters are formatted validly. They
- * are either digits or '/'s.
- */
- cp = cpstart;
- if (!isdigit(cp[0]) || !isdigit(cp[1]) || cp[2] != '/' ||
- !isdigit(cp[3]) || !isdigit(cp[4]) || cp[5] != '/' ||
- !isdigit(cp[6]) || !isdigit(cp[7]) || cp[8] != '/' ||
- !isdigit(cp[9]) || !isdigit(cp[10]) || !isdigit(cp[11])) {
- pst->reason = QDREASON + 2;
- return 0;
- }
-
- /*
- * Decode into year, month, day and year day
- */
- pst->year = MULBY10(PSTTOBIN(cp[0])) + PSTTOBIN(cp[1]);
- pst->month = MULBY10(PSTTOBIN(cp[3])) + PSTTOBIN(cp[4]);
- pst->monthday = MULBY10(PSTTOBIN(cp[6])) + PSTTOBIN(cp[7]);
- pst->yearday = MULBY10(PSTTOBIN(cp[9])) + PSTTOBIN(cp[10]);
- pst->yearday = MULBY10(pst->yearday) + PSTTOBIN(cp[11]);
-
- /*
- * Format check these.
- */
- if (pst->month > 12 || pst->monthday > 31 || pst->yearday > 366) {
- pst->reason = QDREASON + 3;
- return 0;
- }
- if (!(pst->flags & PST_LEAPYEAR) && pst->yearday > 365) {
- pst->reason = QDREASON + 4;
- return 0;
- }
-
- /*
- * Done all we can.
- */
- return 1;
-}
-
-
-/*
- * pst_QT_process - process the output of a QT command, return the times
- */
-static int
-pst_QT_process(pst, rbufp, tsclk, tsrec)
- register struct pstunit *pst;
+pst_receive(rbufp)
struct recvbuf *rbufp;
- l_fp *tsclk;
- l_fp *tsrec;
{
- register char *cp;
- register char *bp;
- register int n;
- char *cpstart;
- int len;
- int hour;
- int minute;
- int second;
- int msec;
- int tzoff;
+ register struct pstunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ l_fp trtmp;
+ u_long ltemp;
+ char ampmchar; /* AM/PM indicator */
+ char daychar; /* standard/daylight indicator */
+ char junque[10]; /* "yy/dd/mm/" discard */
+ char info[14]; /* "frdzycchhSSFT" clock info */
/*
- * The output of the QT command looks like:
- *
- * A09:57:50.263D
- *
- * The minimum length of the string is 14 characters as is
- * the maximum length.
+ * Initialize pointers and read the timecode and timestamp
*/
- n = rbufp->recv_length;
- if (n > PSTMAXQTLEN + 10)
- n = PSTMAXQTLEN + 10;
-
- bp = rbufp->recv_buffer;
- cp = &pst->lastcode[pst->lencode];
- *cp++ = ' ';
- cpstart = cp;
- while (n-- > 0) {
- *cp = (*bp++) & 0x7f; /* strip parity */
- if (!isprint(*cp))
- break;
- cp++;
- }
- len = (cp - cpstart);
- pst->lencode = (u_char)(cp - pst->lastcode);
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct pstunit *)pp->unitptr;
+ up->lastptr += refclock_gtlin(rbufp, up->lastptr, pp->lastcode
+ + BMAX - 2 - up->lastptr, &trtmp);
+ *up->lastptr++ = ' ';
+ *up->lastptr = '\0';
/*
- * Okay, got all printable characters from the string
- * copied. We expect to have been terminated by the
- * EOL character. If not, forget it. If the length
- * is insane, forget it.
- */
- if (*cp != PSTEOL ||
- len < PSTMINQTLEN || len > PSTMAXQTLEN) {
- pst->reason = QTREASON + 1;
- return 0;
- }
- *cp = '\0';
-#ifdef PSTCLK
- /*
- * Receive time stamp should be in buffer after the code.
- * Make sure we have enough characters in there.
- */
- if (&rbufp->recv_buffer[rbufp->recv_length] - bp < 8) {
- pst->reason = QTREASON + 2;
- return 0;
- }
- if (!buftvtots(bp, tsrec)) {
- pst->reason = QTREASON + 3;
- return 0;
- }
-#else
- /*
- * Use the timestamp collected with the input.
+ * Note we get a buffer and timestamp for each <cr>, but only
+ * the first timestamp is retained.
*/
- *tsrec = rbufp->recv_time;
+ if (!up->tcswitch)
+ pp->lastrec = trtmp;
+ up->tcswitch++;
+ pp->lencode = up->lastptr - pp->lastcode;
+ if (up->tcswitch < 3)
+ return;
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
+#ifdef DEBUG
+ if (debug)
+ printf("pst: timecode %d %s\n", pp->lencode,
+ pp->lastcode);
#endif
/*
- * Ensure that the characters are formatted validly. Mostly
- * digits, but the occasional `:' and `.'.
- */
- cp = cpstart;
- if (!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]) || !isdigit(cp[12])) {
- pst->reason = QTREASON + 4;
- return 0;
- }
-
- /*
- * Extract the hour, minute, second and millisecond
- */
- hour = MULBY10(PSTTOBIN(cp[1])) + PSTTOBIN(cp[2]);
- minute = MULBY10(PSTTOBIN(cp[4])) + PSTTOBIN(cp[5]);
- second = MULBY10(PSTTOBIN(cp[7])) + PSTTOBIN(cp[8]);
- msec = MULBY10(PSTTOBIN(cp[10])) + PSTTOBIN(cp[11]);
- msec = MULBY10(msec) + PSTTOBIN(cp[12]);
-
- if (minute > 59 || second > 59) {
- pst->reason = QTREASON + 5;
- return 0;
- }
-
- /*
- * Trouble here. Adjust the hours for AM/PM, if this is
- * on, and for daylight saving time.
- */
- if (*cp == 'A') {
- if (hour > 12 || hour == 0) {
- pst->reason = QTREASON + 5;
- return 0;
- }
- if (hour == 12)
- hour = 0;
- } else if (*cp == 'P') {
- if (hour > 12 || hour == 0)
- return 0;
- if (hour < 12)
- hour += 12;
- } else if (*cp != ' ') {
- pst->reason = QTREASON + 6;
- return 0;
- }
-
- if (cp[13] == 'D')
- tzoff = -1;
- else if (cp[13] == ' ')
- tzoff = 0;
- else {
- pst->reason = QTREASON + 7;
- return 0;
- }
-
- /*
- * Adjust for the timezone. The PST manual is screwy here.
- * it says the timezone is an integer in the range 0 to 23,
- * but this doesn't allow us to tell the difference between
- * +12 and -12. Assume the 12 hour timezone is west of
- * GMT.
- */
- if (pst->timezone <= 12)
- tzoff += pst->timezone;
- else
- tzoff -= (24 - pst->timezone);
-
-
- /*
- * Record for posterity
- */
- pst->hour = (u_char)hour;
- pst->minute = (u_char)minute;
- pst->second = (u_char)second;
- pst->millisecond = (u_short)msec;
- pst->tzoffset = (s_char)tzoff;
-
- /*
- * All that to get the day-hour-minute-second. Turn this
- * into the seconds part of a time stamp. Also use the
- * milliseconds part directly as the fractional part.
- */
- MSUTOTSF(msec, tsclk->l_uf);
- if (!clocktime((int)pst->yearday, hour, minute, second, tzoff,
- tsrec->l_ui, &pst->yearstart, &tsclk->l_ui)) {
- pst->reason = QTREASON + 8;
- return 0;
- }
-
- /*
- * Add in the fudge
- */
- if (pst->flags & PST_WWVH)
- L_ADDUF(tsclk, wwvh_prop_data[pst->unit].remainder);
- else
- L_ADDUF(tsclk, wwv_prop_data[pst->unit].remainder);
-
- /*
- * Glad that's over with
- */
- return 1;
-}
-
-
-/*
- * pst_do_event - update our status and report any changes
- */
-static void
-pst_do_event(pst, evnt_code)
- register struct pstunit *pst;
- int evnt_code;
-{
- if (pst->status != (u_char)evnt_code) {
- pst->status = (u_char)evnt_code;
- if (evnt_code != CEVNT_NOMINAL)
- pst->lastevent = (u_char)evnt_code;
- /*
- * Should trap this, but the trap code isn't up to
- * it yet.
- */
- }
-}
-
-
-
-/*
- * pst_process - process the data collected to produce an offset estimate
- */
-static void
-pst_process(pst)
- register struct pstunit *pst;
-{
- register int i;
- register int n;
- register U_LONG tmp_ui;
- register U_LONG tmp_uf;
- register U_LONG date_ui;
- register U_LONG date_uf;
- u_fp dispersion;
- l_fp off[NPSTSAMPS];
-
- /*
- * Compute offsets from the raw data. Sort them into
- * ascending order.
+ * We get down to business, check the timecode format and decode
+ * its contents. If the timecode has invalid length or is not in
+ * proper format, we declare bad format and exit.
*/
- for (i = 0; i < NPSTSAMPS; i++) {
- tmp_ui = pst->reftimes[i].l_ui;
- tmp_uf = pst->reftimes[i].l_uf;
- M_SUB(tmp_ui, tmp_uf, pst->rectimes[i].l_ui,
- pst->rectimes[i].l_uf);
- for (n = i; n > 0; n--) {
- if (M_ISGEQ(tmp_ui, tmp_uf, off[n-1].l_ui,
- off[n-1].l_uf))
- break;
- off[n] = off[n-1];
- }
- off[n].l_ui = tmp_ui;
- off[n].l_uf = tmp_uf;
+ if (pp->lencode < LENPST) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
}
/*
- * Reject the furthest from the median until 8 samples left
+ * Timecode format:
+ * "ahh:mm:ss.fffs yy/dd/mm/ddd frdzycchhSSFTttttuuxx"
*/
- i = 0;
- n = NPSTSAMPS;
- while ((n - i) > 8) {
- tmp_ui = off[n-1].l_ui;
- tmp_uf = off[n-1].l_uf;
- date_ui = off[(n+i)/2].l_ui;
- date_uf = off[(n+i)/2].l_uf;
- M_SUB(tmp_ui, tmp_uf, date_ui, date_uf);
- M_SUB(date_ui, date_uf, off[i].l_ui, off[i].l_uf);
- if (M_ISHIS(date_ui, date_uf, tmp_ui, tmp_uf)) {
- /*
- * reject low end
- */
- i++;
- } else {
- /*
- * reject high end
- */
- n--;
- }
+ if (sscanf(pp->lastcode, "%c%2d:%2d:%2d.%3d%c %9s%3d%13s%4ld",
+ &ampmchar, &pp->hour, &pp->minute, &pp->second,
+ &pp->msec, &daychar, junque, &pp->day,
+ info, &ltemp) != 10) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
}
/*
- * Compute the dispersion based on the difference between the
- * extremes of the remaining offsets.
+ * Decode synchronization, quality and last update. If
+ * unsynchronized, set the leap bits accordingly and exit. Once
+ * synchronized, the dispersion depends only on when the clock
+ * was last heard, which depends on the time since last update,
+ * as reported by the clock.
*/
- tmp_ui = off[n-1].l_ui;
- tmp_uf = off[n-1].l_uf;
- M_SUB(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
- dispersion = MFPTOFP(tmp_ui, tmp_uf);
-
- /*
- * Now compute the offset estimate. If the sloppy clock
- * flag is set, average the remainder, otherwise pick the
- * median.
- */
- if (sloppyclock[pst->unit]) {
- tmp_ui = tmp_uf = 0;
- while (i < n) {
- M_ADD(tmp_ui, tmp_uf, off[i].l_ui, off[i].l_uf);
- i++;
- }
- M_RSHIFT(tmp_ui, tmp_uf);
- M_RSHIFT(tmp_ui, tmp_uf);
- M_RSHIFT(tmp_ui, tmp_uf);
- i = 0;
- off[0].l_ui = tmp_ui;
- off[0].l_uf = tmp_uf;
+ if (info[9] != '8') {
+ pp->leap = LEAP_NOTINSYNC;
} else {
- i = (n+i)/2;
- }
-
- /*
- * Add the default PST QT delay into this.
- */
- L_ADDUF(&off[i], PSTQTFUDGE);
-
- /*
- * Set the reference ID to the appropriate station
- */
- if (stratumtouse[pst->unit] <= 1) {
- if (pst->station >= 0)
- memmove((char *)&pst->peer->refid, WWVREFID, 4);
+ pp->leap = 0;
+ pp->lasttime = current_time - ltemp;
+ if (info[12] == 'H')
+ memcpy((char *)&pp->refid, WWVHREFID, 4);
else
- memmove((char *)&pst->peer->refid, WWVHREFID, 4);
+ memcpy((char *)&pp->refid, WWVREFID, 4);
+ if (peer->stratum <= 1)
+ peer->refid = pp->refid;
}
/*
- * Give the data to the reference clock support code
- */
- record_clock_stats(&(pst->peer->srcadr), pst->lastcode);
- refclock_receive(pst->peer, &off[i], 0, dispersion, &pst->reftimes[NPSTSAMPS-1],
- &pst->rectimes[NPSTSAMPS-1], pst->leap);
-
- /*
- * If the don't-sync flag isn't on, we're nominal.
- */
- if (pst->leap == 0)
- pst_event(pst, CEVNT_NOMINAL);
- pst_reset(pst);
-}
-
-
-
-/*
- * pst_receive - receive data from a PST clock, call the appropriate
- * routine to process it, and advance the state.
- */
-static void
-pst_receive(rbufp)
- struct recvbuf *rbufp;
-{
- register struct pstunit *pst;
- register U_LONG tmp;
-
- pst = (struct pstunit *)rbufp->recv_srcclock;
-
- /*
- * Process based on the current state.
- */
- switch(pst->state) {
- case STATE_IDLE:
- return; /* Ignore the input */
-
- case STATE_QV:
- if (!pst_QV_process(pst, rbufp)) {
- /*
- * Set the state to idle, but request another
- * QV poll.
- */
- pst->badformat++;
- pst_event(pst, CEVNT_BADREPLY);
- pst->state = STATE_IDLE;
- pst->flags |= PST_DOQV;
- } else {
- /*
- * This went okay. Advance the state to
- * QM and send the request.
- */
- pst->state = STATE_QM;
- pst_send(pst, "QM", 2);
- }
- return;
-
- case STATE_QM:
- if (!pst_QM_process(pst, rbufp)) {
- /*
- * Idle us and note the error
- */
- pst->badformat++;
- pst_event(pst, CEVNT_BADREPLY);
- pst->state = STATE_IDLE;
- return;
- }
- if (pst->flags & PST_NOTIME) {
- /*
- * Here we aren't getting any time because the
- * clock is still searching. Don't bother
- * looking for anything. Remove any leap
- * second hold, however, since this should
- * ensure the clock is sensible.
- */
- pst_event(pst, CEVNT_FAULT);
- pst->state = STATE_IDLE;
- if (pst->nextsample > 0)
- pst_reset(pst); /* Make sure rate low */
- return;
- }
-
- /*
- * Next is QD. Do it.
- */
- pst->state = STATE_QD;
- pst_send(pst, "QD", 2);
- return;
-
- case STATE_QD:
- if (!pst_QD_process(pst, rbufp)) {
- /*
- * Idle us and note the error
- */
- pst->badformat++;
- pst_event(pst, CEVNT_BADDATE);
- pst->state = STATE_IDLE;
- } else {
- /*
- * Last step is QT.
- */
- pst->state = STATE_QT;
- pst_send(pst, "QT", 2);
- }
- return;
-
- case STATE_QT:
- pst->state = STATE_IDLE;
- if (!pst_QT_process(pst, rbufp, &pst->lastref, &pst->lastrec)) {
- /*
- * Note the error
- */
- pst->baddata++;
- pst_event(pst, CEVNT_BADTIME);
- return;
- }
- break;
-
- default:
- syslog(LOG_ERR,
- "pst_receive: unit %d invalid state %d",
- pst->unit, pst->state);
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
return;
}
-
-
- /*
- * You may not have noticed this, but the only way we end up
- * out here is if we've completed polling and have a couple of
- * valid time stamps. First see if we should reset the
- * structure.
- */
- if (pst->nextsample > 0) {
- tmp = pst->lastrec.l_ui - pst->rectimes[0].l_ui;
- if (tmp > (U_LONG)psttab[pst->nextsample].tooold)
- pst_reset(pst);
- }
-
- pst->rectimes[pst->nextsample] = pst->lastrec;
- pst->reftimes[pst->nextsample] = pst->lastref;
- pst->nextsample++;
- if (pst->flags & PST_WWVH)
- pst->station--;
- else
- pst->station++;
-
- if (pst->flags & (PST_SIGFAULT|PST_HARDERR)) {
- pst_event(pst, CEVNT_FAULT);
- pst->leap = LEAP_NOTINSYNC;
- } else if (pst->timesincesync > freerun[pst->unit]) {
- pst_event(pst, CEVNT_PROP);
- pst->leap = LEAP_NOTINSYNC;
- }
-
- if (pst->nextsample >= NPSTSAMPS)
- pst_process(pst);
+ trtmp = pp->lastrec;
+ trtmp.l_ui -= ltemp;
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion, &trtmp,
+ &pp->lastrec, pp->leap);
}
/*
- * pst_compute_delay - compute appropriate things to tell clock about delays
+ * pst_poll - called by the transmit procedure
*/
static void
-pst_compute_delay(prop_delay, prop_data)
- U_LONG prop_delay;
- struct pst_propagate *prop_data;
+pst_poll(unit, peer)
+ int unit;
+ struct peer *peer;
{
- register int code;
- register U_LONG tsf;
+ register struct pstunit *up;
+ struct refclockproc *pp;
/*
- * Convert (truncate) the delay to milliseconds. Save the
- * characters needed to send this to the clock and compute
- * the remainder to be added in later.
+ * Time to poll the clock. The PSTI/Traconex clock responds to a
+ * "QTQDQMT" by returning a timecode in the format specified
+ * above. If nothing is heard from the clock for two polls,
+ * declare a timeout and keep going.
*/
- code = tsftomsu(prop_delay, 0);
- MSUTOTSF(code, tsf);
- prop_data->remainder = prop_delay - tsf;
- if (prop_data->remainder & 0x80000000)
- prop_data->remainder = 0;
- prop_data->msbchar = BINTOPST((code >> 2) & 0x1f);
- prop_data->lsbchar = BINTOPST(code & 0x3);
-}
-
-
-/*
- * pst_control - set fudge factors, return statistics
- */
-static void
-pst_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- register struct pstunit *pst;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "pst_control: unit %d invalid", unit);
- return;
- }
-
- if (in != 0) {
- int doqv = 0;
-
- if (in->haveflags & CLK_HAVETIME1)
- if (in->fudgetime1.l_ui == 0
- && in->fudgetime1.l_uf <= PSTMAXPROP) {
- wwv_prop_delay[unit] = in->fudgetime1;
- doqv = 1;
- pst_compute_delay(wwv_prop_delay[unit].l_uf,
- &wwv_prop_data[unit]);
- }
- if (in->haveflags & CLK_HAVETIME2)
- if (in->fudgetime2.l_ui == 0
- && in->fudgetime2.l_uf <= PSTMAXPROP) {
- wwvh_prop_delay[unit] = in->fudgetime2;
- doqv = 1;
- pst_compute_delay(wwvh_prop_delay[unit].l_uf,
- &wwvh_prop_data[unit]);
- }
- if (in->haveflags & CLK_HAVEVAL1) {
- stratumtouse[unit] = (u_char)(in->fudgeval1 & 0xf);
- }
- if (in->haveflags & CLK_HAVEVAL2) {
- if (in->fudgeval2 > 0 && in->fudgeval2 < 9990)
- freerun[unit] = (u_short)in->fudgeval2;
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
- sloppyclock[unit] = in->flags & CLK_FLAG1;
- }
- if (unitinuse[unit]) {
- /*
- * Should actually reselect clock, but
- * will wait for the next timecode
- */
- if (in->haveflags & CLK_HAVEVAL1) {
- pstunits[unit]->peer->stratum
- = stratumtouse[unit];
- if (stratumtouse[unit] > 1)
- pstunits[unit]->peer->refid
- = htonl(PSTHSREFID);
- }
-
- if ((in->haveflags & CLK_HAVEFLAG3) &&
- (in->flags & CLK_FLAG3)) {
- pstunits[unit]->flags |= PST_DORESET;
- } else if (doqv || ((in->haveflags & CLK_HAVEFLAG2) &&
- (in->flags & CLK_FLAG2))) {
- pstunits[unit]->flags |= PST_DOQV;
- }
- }
- }
-
- if (out != 0) {
- out->type = REFCLK_WWV_PST;
- out->flags = 0;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVETIME2|CLK_HAVEVAL1|
- CLK_HAVEVAL2|CLK_HAVEFLAG1;
- out->fudgetime1 = wwv_prop_delay[unit];
- out->fudgetime2 = wwvh_prop_delay[unit];
- out->fudgeval1 = (LONG)stratumtouse[unit];
- out->fudgeval2 = (LONG)freerun[unit];
- out->flags = sloppyclock[unit];
- if (unitinuse[unit]) {
- pst = pstunits[unit];
- out->clockdesc = pst->description;
- out->lencode = pst->lencode;
- out->lastcode = pst->lastcode;
- out->timereset = current_time - pst->timestarted;
- out->polls = pst->polls;
- out->noresponse = pst->noreply;
- out->badformat = pst->badformat;
- out->baddata = pst->baddata;
- out->lastevent = pst->lastevent;
- out->currentstatus = pst->status;
- } else {
- out->clockdesc = pstdefdesc;
- out->lencode = 0;
- out->lastcode = "";
- out->polls = out->noresponse = 0;
- out->badformat = out->baddata = 0;
- out->timereset = 0;
- out->currentstatus = out->lastevent = CEVNT_NOMINAL;
- }
- }
+ pp = peer->procptr;
+ up = (struct pstunit *)pp->unitptr;
+ if (up->pollcnt == 0)
+ refclock_report(peer, CEVNT_TIMEOUT);
+ else
+ up->pollcnt--;
+ up->tcswitch = 0;
+ up->lastptr = pp->lastcode;
+ if (write(pp->io.fd, "QTQDQMT", 6) != 6) {
+ refclock_report(peer, CEVNT_FAULT);
+ } else
+ pp->polls++;
}
-
-/*
- * pst_buginfo - return clock dependent debugging info
- */
-static void
-pst_buginfo(unit, bug)
- int unit;
- register struct refclockbug *bug;
-{
- register struct pstunit *pst;
- register int i;
-
- bug->nvalues = bug->ntimes = 0;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "pst_buginfo: unit %d invalid", unit);
- return;
- }
-
- if (!unitinuse[unit])
- return;
- pst = pstunits[unit];
-
- bug->nvalues = 14;
- bug->svalues = (1<<10);
- bug->values[0] = (U_LONG)pst->nextsample;
- bug->values[1] = (U_LONG)pst->state;
- bug->values[2] = (U_LONG)pst->reason;
- bug->values[3] = (U_LONG)pst->flags;
- bug->values[4] = (U_LONG)pst->yearday;
- bug->values[5] = (U_LONG)pst->hour;
- bug->values[6] = (U_LONG)pst->minute;
- bug->values[7] = (U_LONG)pst->second;
- bug->values[8] = (U_LONG)pst->millisecond;
- bug->values[9] = (U_LONG)pst->timezone;
- bug->values[10] = (U_LONG)((LONG)pst->tzoffset);
- bug->values[11] = (U_LONG)pst->timesincesync;
- bug->values[12] = pst->yearstart;
- bug->ntimes = ((NPSTSAMPS*2)+2) > NCLKBUGTIMES ? NCLKBUGTIMES :
- ((NPSTSAMPS*2)+2);
- bug->stimes = 0;
- for (i = 0; i < (bug->ntimes-2)/2; i++) {
- bug->times[2*i] = pst->rectimes[i];
- bug->times[(2*i) + 1] = pst->reftimes[i];
- }
- bug->times[bug->ntimes - 2] = pst->lastrec;
- bug->times[bug->ntimes - 1] = pst->lastref;
-}
#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_tpro.c b/usr.sbin/xntpd/xntpd/refclock_tpro.c
index 54d9f3cb5287..388103c7c1c6 100644
--- a/usr.sbin/xntpd/xntpd/refclock_tpro.c
+++ b/usr.sbin/xntpd/xntpd/refclock_tpro.c
@@ -1,7 +1,8 @@
/*
- * refclock_tpro - clock driver for the KSI/Odetics TPRO-S IRIG-B reader
+ * refclock_tpro - clock driver for the KSI/Odetics TPRO-S IRIG-B reader
*/
-#if defined(REFCLOCK) && defined(TPRO)
+#if defined(REFCLOCK) && defined(TPRO) && defined(sun)
+
#include <stdio.h>
#include <ctype.h>
#include <sys/time.h>
@@ -20,31 +21,19 @@
*/
/*
- * Definitions
+ * TPRO interface definitions
*/
-#define MAXUNITS 1 /* max number of TPRO units */
-#define TPROFD "/dev/tpro%d" /* name of driver device */
-#define BMAX 50 /* timecode buffer length */
+#define DEVICE "/dev/tpro%d" /* device name and unit */
+#define PRECISION (-20) /* precision assumed (1 us) */
+#define REFID "IRIG" /* reference ID */
+#define DESCRIPTION "KSI/Odetics TPRO/S IRIG Interface" /* WRU */
-/*
- * TPRO interface parameters. The "IRIG" can be changed to "GPS" for the
- * TPRO-GPS.
- */
-#define TPROPRECISION (-20) /* precision assumed (1 us) */
-#define TPROREFID "IRIG" /* reference id */
-#define TPRODESCRIPTION "KSI/Odetics TPRO-S IRIG-B Reader" /* who we are */
-#define TPROHSREFID 0x7f7f0c0a /* 127.127.12.10 refid hi strata */
-#define GMT 0 /* hour offset from Greenwich */
-
-/*
- * Hack to avoid excercising the multiplier. I have no pride.
- */
-#define MULBY10(x) (((x)<<3) + ((x)<<1))
+#define NSAMPLES 3 /* stages of median filter */
/*
* Imported from ntp_timer module
*/
-extern U_LONG current_time; /* current time (s) */
+extern u_long current_time; /* current time (s) */
/*
* Imported from ntpd module
@@ -52,250 +41,106 @@ extern U_LONG current_time; /* current time (s) */
extern int debug; /* global debug flag */
/*
- * TPRO unit control structure.
+ * Unit control structure
*/
struct tprounit {
- struct peer *peer; /* associated peer structure */
- struct refclockio io; /* given to the I/O handler */
- struct tproval tprodata; /* data returned from tpro read */
- l_fp lastrec; /* last local time */
- l_fp lastref; /* last timecode time */
- char lastcode[BMAX]; /* last timecode received */
- u_char lencode; /* length of last timecode */
- U_LONG lasttime; /* last time clock heard from */
- u_char unit; /* unit number for this guy */
- u_char status; /* clock status */
- u_char lastevent; /* last clock event */
- 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_LONG usec; /* microsecond of second */
- U_LONG yearstart; /* start of current year */
- u_char leap; /* leap indicators */
- /*
- * 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 */
+ struct tproval tprodata; /* data returned from tpro read */
};
/*
- * Data space for the unit structures. Note that we allocate these on
- * the fly, but never give them back.
- */
-static struct tprounit *tprounits[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 tpro_init P(());
-static int tpro_start P((u_int, struct peer *));
-static void tpro_shutdown P((int));
-static void tpro_report_event P((struct tprounit *, int));
-static void tpro_receive P((struct recvbuf *));
+static int tpro_start P((int, struct peer *));
+static void tpro_shutdown P((int, struct peer *));
static void tpro_poll P((int unit, struct peer *));
-static void tpro_control P((u_int, struct refclockstat *, struct refclockstat *));
-static void tpro_buginfo P((int, struct refclockbug *));
/*
* Transfer vector
*/
-struct refclock refclock_tpro = {
- tpro_start, tpro_shutdown, tpro_poll,
- tpro_control, tpro_init, tpro_buginfo, NOFLAGS
+struct refclock refclock_tpro = {
+ tpro_start, /* start up driver */
+ tpro_shutdown, /* shut down driver */
+ tpro_poll, /* transmit poll message */
+ noentry, /* not used (old tpro_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old tpro_buginfo) */
+ NOFLAGS /* not used */
};
-/*
- * tpro_init - initialize internal tpro driver data
- */
-static void
-tpro_init()
-{
- register int i;
- /*
- * Just zero the data arrays
- */
- memset((char *)tprounits, 0, sizeof tprounits);
- 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;
- }
-}
/*
* tpro_start - open the TPRO device and initialize data for processing
*/
static int
tpro_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register struct tprounit *tpro;
- register int i;
- char tprodev[20];
- int fd_tpro;
+ register struct tprounit *up;
+ struct refclockproc *pp;
+ char device[20];
+ int fd;
/*
- * Check configuration info.
+ * Open TPRO device
*/
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "tpro_start: unit %d invalid", unit);
- return (0);
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "tpro_start: unit %d in use", unit);
+ (void)sprintf(device, DEVICE, unit);
+ fd = open(device, O_RDONLY | O_NDELAY, 0777);
+ if (fd == -1) {
+ syslog(LOG_ERR, "tpro_start: open of %s: %m", device);
return (0);
}
/*
- * Open TPRO device
+ * Allocate and initialize unit structure
*/
- (void) sprintf(tprodev, TPROFD, unit);
- fd_tpro = open(tprodev, O_RDWR, 0777);
- if (fd_tpro == -1) {
- syslog(LOG_ERR, "tpro_start: open of %s: %m", tprodev);
+ if (!(up = (struct tprounit *)
+ emalloc(sizeof(struct tprounit)))) {
+ (void) close(fd);
return (0);
}
-
- /*
- * Allocate unit structure
- */
- if (tprounits[unit] != 0) {
- tpro = tprounits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < MAXUNITS; i++) {
- if (!unitinuse[i] && tprounits[i] != 0)
- break;
- }
- if (i < MAXUNITS) {
- /*
- * Reclaim this one
- */
- tpro = tprounits[i];
- tprounits[i] = 0;
- } else {
- tpro = (struct tprounit *)
- emalloc(sizeof(struct tprounit));
- }
+ memset((char *)up, 0, sizeof(struct tprounit));
+ pp = peer->procptr;
+ pp->io.clock_recv = noentry;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
}
- memset((char *)tpro, 0, sizeof(struct tprounit));
- tprounits[unit] = tpro;
-
- /*
- * Set up the structures
- */
- tpro->peer = peer;
- tpro->unit = (u_char)unit;
- tpro->timestarted = current_time;
-
- tpro->io.clock_recv = tpro_receive;
- tpro->io.srcclock = (caddr_t)tpro;
- tpro->io.datalen = 0;
- tpro->io.fd = fd_tpro;
+ pp->unitptr = (caddr_t)up;
/*
- * All done. Initialize a few random peer variables, then
- * return success. Note that root delay and root dispersion are
- * always zero for this clock.
+ * Initialize miscellaneous peer variables
*/
- peer->precision = TPROPRECISION;
- peer->rootdelay = 0;
- peer->rootdispersion = 0;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, TPROREFID, 4);
- else
- peer->refid = htonl(TPROHSREFID);
- unitinuse[unit] = 1;
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
return (1);
}
/*
- * tpro_shutdown - shut down a TPRO clock
+ * tpro_shutdown - shut down the clock
*/
static void
-tpro_shutdown(unit)
+tpro_shutdown(unit, peer)
int unit;
-{
- register struct tprounit *tpro;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "tpro_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "tpro_shutdown: unit %d not in use", unit);
- return;
- }
-
- /*
- * Tell the I/O module to turn us off. We're history.
- */
- tpro = tprounits[unit];
- io_closeclock(&tpro->io);
- unitinuse[unit] = 0;
-}
-
-/*
- * tpro_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
-tpro_report_event(tpro, code)
- struct tprounit *tpro;
- int code;
-{
struct peer *peer;
+{
+ register struct tprounit *up;
+ struct refclockproc *pp;
- peer = tpro->peer;
- if (tpro->status != (u_char)code) {
- tpro->status = (u_char)code;
- if (code != CEVNT_NOMINAL)
- tpro->lastevent = (u_char)code;
- syslog(LOG_INFO,
- "clock %s event %x", ntoa(&peer->srcadr), code);
- }
+ pp = peer->procptr;
+ up = (struct tprounit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
}
/*
- * tpro_receive - receive data from the TPRO device.
- *
- * Note: This interface would be interrupt-driven. We don't use that
- * now, but include a dummy routine for possible future adventures.
- */
-static void
-tpro_receive(rbufp)
- struct recvbuf *rbufp;
-{
-}
-
-/*
* tpro_poll - called by the transmit procedure
*/
static void
@@ -303,196 +148,80 @@ tpro_poll(unit, peer)
int unit;
struct peer *peer;
{
- struct tprounit *tpro;
- struct tproval *tptr;
- l_fp tstmp;
+ register struct tprounit *up;
+ struct refclockproc *pp;
+ struct tproval *tp;
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "tpro_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "tpro_poll: unit %d not in use", unit);
- return;
- }
- tpro = tprounits[unit];
- tpro->polls++;
+ /*
+ * This is the main routine. It snatches the time from the TPRO
+ * board and tacks on a local timestamp.
+ */
+ pp = peer->procptr;
+ up = (struct tprounit *)pp->unitptr;
- tptr = &tpro->tprodata;
- if (read(tpro->io.fd, (char *)tptr, sizeof(struct tproval)) < 0) {
- tpro_report_event(tpro, CEVNT_BADREPLY);
+ tp = &up->tprodata;
+ if (read(pp->io.fd, (char *)tp, sizeof(struct tproval)) < 0) {
+ refclock_report(peer, CEVNT_FAULT);
return;
}
- gettstamp(&tpro->lastrec);
- tpro->lasttime = current_time;
+ gettstamp(&pp->lastrec);
+ pp->lasttime = current_time;
+ pp->polls++;
/*
- * Get TPRO time and convert to timestamp format. Note: we
+ * We get down to business, check the timecode format and decode
+ * its contents. If the timecode has invalid length or is not in
+ * proper format, we declare bad format and exit. Note: we
* can't use the sec/usec conversion produced by the driver,
- * since the year may be suspect.
+ * since the year may be suspect. All format error checking is
+ * done by the sprintf() and sscanf() routines.
*/
- sprintf(tpro->lastcode,
+ if (sprintf(pp->lastcode,
"%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
- tptr->day100, tptr->day10, tptr->day1, tptr->hour10, tptr->hour1,
- tptr->min10, tptr->min1, tptr->sec10, tptr->sec1,
- tptr->ms100, tptr->ms10, tptr->ms1, tptr->usec100, tptr->usec10,
- tptr->usec1, tptr->status);
- record_clock_stats(&(tpro->peer->srcadr), tpro->lastcode);
- tpro->lencode = strlen(tpro->lastcode);
+ tp->day100, tp->day10, tp->day1, tp->hour10, tp->hour1,
+ tp->min10, tp->min1, tp->sec10, tp->sec1, tp->ms100,
+ tp->ms10, tp->ms1, tp->usec100, tp->usec10, tp->usec1,
+ tp->status)) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
- tpro->day = MULBY10(MULBY10(tptr->day100) + tptr->day10) + tptr->day1;
- tpro->hour = MULBY10(tptr->hour10) + tptr->hour1;
- tpro->minute = MULBY10(tptr->min10) + tptr->min1;
- tpro->second = MULBY10(tptr->sec10) + tptr->sec1;
- tpro->usec = MULBY10(MULBY10(tptr->ms100) + tptr->ms10) + tptr->ms1;
- tpro->usec = tpro->usec * 10 + tptr->usec100;
- tpro->usec = tpro->usec * 10 + tptr->usec10;
- tpro->usec = tpro->usec * 10 + tptr->usec1;
#ifdef DEBUG
if (debug)
- printf("tpro: %3d %02d:%02d:%02d.%06ld %1x\n",
- tpro->day, tpro->hour, tpro->minute, tpro->second,
- tpro->usec, tptr->status);
+ printf("tpro: time %s timecode %d %s\n",
+ ulfptoa(&pp->lastrec, 6), pp->lencode,
+ pp->lastcode);
#endif
- if (tptr->status != 0xff) {
- tpro_report_event(tpro, CEVNT_BADREPLY);
+ record_clock_stats(&peer->srcadr, pp->lastcode);
+ if (sscanf(pp->lastcode, "%3d %2d:%2d:%2d.%6ld", &pp->day,
+ &pp->hour, &pp->minute, &pp->second, &pp->usec)
+ != 5) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ if (tp->status != 0xff) {
+ pp->leap = LEAP_NOTINSYNC;
+ refclock_report(peer, CEVNT_FAULT);
return;
+ } else {
+ pp->leap = 0;
+ pp->lasttime = current_time;
}
/*
- * Now, compute the reference time value. Use the heavy
- * machinery for the seconds and the millisecond field for the
- * fraction when present. If an error in conversion to internal
- * format is found, the program declares bad data and exits.
- * Note that this code does not yet know how to do the years and
- * relies on the clock-calendar chip for sanity.
- */
- if (!clocktime(tpro->day, tpro->hour, tpro->minute,
- tpro->second, GMT, tpro->lastrec.l_ui,
- &tpro->yearstart, &tpro->lastref.l_ui)) {
- tpro->baddata++;
- tpro_report_event(tpro, CEVNT_BADTIME);
- return;
- }
- TVUTOTSF(tpro->usec, tpro->lastref.l_uf);
- tstmp = tpro->lastref;
- L_SUB(&tstmp, &tpro->lastrec);
- tpro->coderecv++;
- L_ADD(&tstmp, &(fudgefactor[tpro->unit]));
- refclock_receive(tpro->peer, &tstmp, GMT, 0,
- &tpro->lastrec, &tpro->lastrec, tpro->leap);
-}
-
-/*
- * tpro_control - set fudge factors, return statistics
- */
-static void
-tpro_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- register struct tprounit *tpro;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "tpro_control: unit %d invalid)", unit);
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
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
- */
- tpro = tprounits[unit];
- peer = tpro->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid,
- TPROREFID, 4);
- else
- peer->refid = htonl(TPROHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
- sloppyclockflag[unit] = in->flags & CLK_FLAG1;
- }
- }
-
- if (out != 0) {
- out->type = REFCLK_IRIG_TPRO;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1;
- out->clockdesc = TPRODESCRIPTION;
- 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]) {
- tpro = tprounits[unit];
- out->lencode = tpro->lencode;
- out->lastcode = tpro->lastcode;
- out->timereset = current_time - tpro->timestarted;
- out->polls = tpro->polls;
- out->noresponse = tpro->noreply;
- out->badformat = tpro->badformat;
- out->baddata = tpro->baddata;
- out->lastevent = tpro->lastevent;
- out->currentstatus = tpro->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;
- }
- }
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
}
-/*
- * tpro_buginfo - return clock dependent debugging info
- */
-static void
-tpro_buginfo(unit, bug)
- int unit;
- register struct refclockbug *bug;
-{
- register struct tprounit *tpro;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "tpro_buginfo: unit %d invalid)", unit);
- return;
- }
-
- if (!unitinuse[unit])
- return;
- tpro = tprounits[unit];
-
- bug->nvalues = 11;
- bug->ntimes = 5;
- if (tpro->lasttime != 0)
- bug->values[0] = current_time - tpro->lasttime;
- else
- bug->values[0] = 0;
- bug->values[2] = (U_LONG)tpro->year;
- bug->values[3] = (U_LONG)tpro->day;
- bug->values[4] = (U_LONG)tpro->hour;
- bug->values[5] = (U_LONG)tpro->minute;
- bug->values[6] = (U_LONG)tpro->second;
- bug->values[7] = (U_LONG)tpro->usec;
- bug->values[9] = tpro->yearstart;
- bug->stimes = 0x1c;
- bug->times[0] = tpro->lastref;
- bug->times[1] = tpro->lastrec;
-}
#endif
diff --git a/usr.sbin/xntpd/xntpd/refclock_trak.c b/usr.sbin/xntpd/xntpd/refclock_trak.c
index f2b3eb11fc9d..d10d75234fbd 100644
--- a/usr.sbin/xntpd/xntpd/refclock_trak.c
+++ b/usr.sbin/xntpd/xntpd/refclock_trak.c
@@ -1,11 +1,10 @@
/*
- * 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
+ * refclock_trak - clock driver for the TRAK 8820 GPS Station Clock
+ *
+ * Thanks to Tomoaki TSURUOKA <tsuruoka@nc.fukuoka-u.ac.jp> for the
+ * previous version from which this one was developed.
*/
-#if defined(REFCLOCK) && (defined(TRAK) || defined(TRAKCLK) || defined(TRAKPPS))
+#if defined(REFCLOCK) && defined(TRAK)
#include <stdio.h>
#include <ctype.h>
@@ -14,494 +13,201 @@
#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.
+ * This driver supports the TRAK 8820 GPS Station Clock. The claimed
+ * accuracy at the 1-pps output is 200-300 ns relative to the broadcast
+ * signal; however, in most cases the actual accuracy is limited by the
+ * precision of the timecode and the latencies of the serial interface
+ * and operating system.
*
- * Most of codes are copied from refclock_as2201.c, Thanks a lot.
+ * For best accuracy, this radio requires the LDISC_ACTS line
+ * discipline, which captures a timestamp at the '*' on-time character
+ * of the timecode. Using this discipline the jitter is in the order of
+ * 1 ms and systematic error about 0.5 ms. If unavailable, the buffer
+ * timestamp is used, which is captured at the \r ending the timecode
+ * message. This introduces a systematic error of 23 character times, or
+ * about 24 ms at 9600 bps, together with a jitter well over 8 ms on Sun
+ * IPC-class machines.
*
- * 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)
+ * Using the memus, the radio should be set for 9600 bps, one stop bit
+ * and no parity. It should be set to operate in computer (no echo)
+ * mode. The timecode format includes neither the year nor leap-second
+ * warning. No provisions are included in this preliminary version of
+ * the driver to read and record detailed internal radio status.
*
- * 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
+ * In operation, this driver sends a RQTS\r request to the radio at
+ * initialization in order to put it in continuous time output mode. The
+ * radio then sends the following message once each second:
+ *
+ * *RQTS U,ddd:hh:mm:ss.0,q<cr><lf>
+ *
+ * on-time = '*' * ddd = day of year
+ * hh:mm:ss = hours, minutes, seconds
+ * q = quality indicator (phase error), 0-6:
+ * 0 > 20 us
+ * 6 > 10 us
+ * 5 > 1 us
+ * 4 > 100 ns
+ * 3 > 10 ns
+ * 2 < 10 ns
+ *
+ * The alarm condition is indicated by '0' at Q, which means the radio
+ * has a phase error than 20 usec relative to the broadcast time. The
+ * absence of year, DST and leap-second warning in this format is also
+ * alarming.
+ *
+ * The continuous time mode is disabled using the RQTX<cr> request,
+ * following which the radio sends a RQTX DONE<cr><lf> response. In the
+ * normal mode, other control and status requests are effective,
+ * including the leap-second status request RQLS<cr>. The radio responds
+ * wtih RQLS yy,mm,dd<cr><lf>, where yy,mm,dd are the year, month and
+ * day. Presumably, this gives the epoch of the next leap second,
+ * RQLS 00,00,00 if none is specified in the GPS message. Specified in
+ * this form, the information is generally useless and is ignored by
+ * the driver.
+ *
+ * Fudge Factors
+ *
+ * There are no special fudge factors other than the generic.
*/
-#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
+ * Interface definitions
*/
-#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 */
+#define DEVICE "/dev/trak%d" /* device name and unit */
+#define SPEED232 B9600 /* uart speed (9600 baud) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define REFID "TRAK" /* reference ID */
+#define DESCRIPTION "TRACK 8810/8820 Station Clock" /* WRU */
-/*
- * Hack to avoid excercising the multiplier. I have no pride.
- */
-#define MULBY10(x) (((x)<<3) + ((x)<<1))
+#define NSAMPLES 3 /* stages of median filter */
+#define LENTRAK 24 /* timecode length */
+#define C_CTO "RQTS\r" /* start continuous time output */
/*
* Imported from ntp_timer module
*/
-extern U_LONG current_time; /* current time (s) */
-
-/*
- * Imported from ntp_loopfilter module
- */
-extern int fdpps; /* pps file descriptor */
+extern u_long current_time; /* current time (s) */
/*
* Imported from ntpd module
*/
-extern int debug; /* global debug flag */
+extern int debug; /* global debug flag */
/*
- * GPS unit control structure.
+ * 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 */
-};
-
+struct wwvbunit {
+ int pollcnt; /* poll message counter */
-/*
- * 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];
+ u_char tcswitch; /* timecode switch */
+ char qualchar; /* quality indicator */
+};
/*
* 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 int trak_start P((int, struct peer *));
+static void trak_shutdown P((int, struct peer *));
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 *));
+static void trak_poll P((int, struct peer *));
/*
* Transfer vector
*/
-struct refclock refclock_trak = {
- trak_start, trak_shutdown, trak_poll,
- trak_control, trak_init, trak_buginfo, NOFLAGS
+struct refclock refclock_trak = {
+ trak_start, /* start up driver */
+ trak_shutdown, /* shut down driver */
+ trak_poll, /* transmit poll message */
+ noentry, /* not used (old trak_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old trak_buginfo) */
+ NOFLAGS /* not used */
};
-/*
- * 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
+ * trak_start - open the devices and initialize data for processing
*/
static int
trak_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register struct gpsunit *gps;
- register int i;
- int fd232;
- char trakdev[20];
-#ifdef TRAKPPS
- struct ppsclockev ev;
-#endif /* TRAKPPS */
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
/*
- * Check configuration info
+ * Open serial port. The LDISC_ACTS line discipline inserts a
+ * timestamp following the "*" on-time character of the
+ * timecode.
*/
- 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);
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS)))
return (0);
- }
/*
- * Open serial port
+ * Allocate and initialize unit structure
*/
- (void) sprintf(trakdev, GPS232, unit);
- fd232 = open(trakdev, O_RDWR, 0777);
- if (fd232 == -1) {
- syslog(LOG_ERR, "trak_start: open of %s: %m", trakdev);
+ if (!(up = (struct wwvbunit *)
+ emalloc(sizeof(struct wwvbunit)))) {
+ (void) close(fd);
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));
- }
+ memset((char *)up, 0, sizeof(struct wwvbunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = trak_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
}
- bzero((char *)gps, sizeof(struct gpsunit));
- gpsunits[unit] = gps;
+ pp->unitptr = (caddr_t)up;
/*
- * Set up the structures
+ * Initialize miscellaneous variables
*/
- 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;
- }
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
/*
- * 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
+ * Start continuous time output. If something breaks, fold the
+ * tent and go home.
*/
- {
- void gps_send();
- gps_send(gps,"\rRQTS,U\r");
- gps_send(gps,"SEL 00\r");
+ if (write(pp->io.fd, C_CTO, sizeof(C_CTO)) != sizeof(C_CTO)) {
+ refclock_report(peer, CEVNT_FAULT);
+ (void) close(fd);
+ free(up);
+ return (0);
}
-
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.
+ * trak_shutdown - shut down the clock
*/
static void
-trak_report_event(gps, code)
- struct gpsunit *gps;
- int code;
-{
+trak_shutdown(unit, peer)
+ int unit;
struct peer *peer;
+{
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
- 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);
- }
+ pp = peer->procptr;
+ up = (struct wwvbunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
}
@@ -512,495 +218,122 @@ static void
trak_receive(rbufp)
struct recvbuf *rbufp;
{
- register int i,cmdtype;
- register struct gpsunit *gps;
-
-#if defined(TRAKPPS)
- struct ppsclockev ev;
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
l_fp trtmp;
-#endif /* TRAKPPS */
- register u_char *dpt;
- register u_char *cp;
- register u_char *dpend;
- l_fp tstmp;
- u_fp dispersion;
+ char *dpt, *dpend;
+ char qchar;
/*
- * Get the clock this applies to and pointers to the data.
- * Edit the timecode to remove control chars and trashbits.
+ * Initialize pointers and read the timecode and timestamp. We
+ * then chuck out everything, including runts, except one
+ * message each poll interval.
*/
- 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;
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct wwvbunit *)pp->unitptr;
+ pp->lencode = refclock_gtlin(rbufp, pp->lastcode, BMAX,
+ &pp->lastrec);
+ if (up->tcswitch || pp->lencode < 9)
+ return;
+ up->tcswitch = 1;
+
+ /*
+ * We get a buffer and timestamp following the '*' on-time
+ * character. If a valid timestamp, we use that in place of the
+ * buffer timestamp and edit out the timestamp for prettyprint
+ * billboards.
+ */
+ dpt = pp->lastcode;
+ dpend = dpt + pp->lencode;
+ if (*dpt == '*' && buftvtots(dpt + 1, &trtmp)) {
+ if (trtmp.l_i == pp->lastrec.l_i || trtmp.l_i ==
+ pp->lastrec.l_i + 1) {
+ pp->lastrec = trtmp;
+ dpt += 9;
+ while (dpt < dpend)
+ *(dpt - 8) = *dpt++;
}
-#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;
-
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
#ifdef DEBUG
if (debug)
- printf("gps: timecode %d %s\n",
- gps->lencode, gps->lastcode);
+ printf("trak: timecode %d %s\n", pp->lencode,
+ pp->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
+ * We get down to business, check the timecode format and decode
+ * its contents. If the timecode has invalid length or is not in
+ * proper format, we declare bad format and exit.
*/
-#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:
+ if (pp->lencode < LENTRAK) {
+ refclock_report(peer, CEVNT_BADREPLY);
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);
+ * Timecode format: "*RQTS U,ddd:hh:mm:ss.0,q"
+ */
+ if (sscanf(pp->lastcode, "*RQTS U,%3d:%2d:%2d:%2d.0,%c",
+ &pp->day, &pp->hour, &pp->minute, &pp->second, &qchar) != 5) {
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
- if (!gps->polled) return;
-
/*
- * Test for synchronization Check for quality byte.
+ * Decode quality and leap characters. If unsynchronized, set
+ * the leap bits accordingly and exit.
*/
-/*
- 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 (qchar == '0')
+ pp->leap = LEAP_NOTINSYNC;
+ else {
+ pp->leap = 0;
+ pp->lasttime = current_time;
}
-*/
- 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.
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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);
+ if (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
return;
}
- refclock_receive(gps->peer, &tstmp, GMT, dispersion,
- &gps->lastrec, &gps->lastrec, gps->leap);
- /*
- * after all, clear polled flag
- */
- gps->polled = 0;
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &pp->lastrec, &pp->lastrec, pp->leap);
}
-/*
- * ==================================================================
- * 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;
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
- 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
+ * We don't really do anything here, except arm the receiving
+ * side to capture a sample and check for timeouts.
*/
-#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;
- }
- }
+ pp = peer->procptr;
+ up = (struct wwvbunit *)pp->unitptr;
+ if (up->pollcnt == 0)
+ refclock_report(peer, CEVNT_TIMEOUT);
+ else
+ up->pollcnt--;
+ up->tcswitch = 0;
+ pp->polls++;
}
-/*
- * 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/usr.sbin/xntpd/xntpd/refclock_wwvb.c b/usr.sbin/xntpd/xntpd/refclock_wwvb.c
index 9b2563a797db..ea0c82e28ec1 100644
--- a/usr.sbin/xntpd/xntpd/refclock_wwvb.c
+++ b/usr.sbin/xntpd/xntpd/refclock_wwvb.c
@@ -1,7 +1,7 @@
/*
- * refclock_wwvb - clock driver for the Spectracom WWVB receivers
+ * refclock_wwvb - clock driver for Spectracom WWVB receivers
*/
-#if defined(REFCLOCK) && (defined(WWVB) || defined(WWVBCLK) || defined(WWVBPPS))
+#if defined(REFCLOCK) && defined(WWVB)
#include <stdio.h>
#include <ctype.h>
@@ -10,62 +10,63 @@
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-
-#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(HAVE_TERMIOS)
-#include <termios.h>
-#endif
-#if defined(STREAM)
-#include <stropts.h>
-#if defined(WWVBCLK)
-#include <sys/clkdefs.h>
-#endif /* WWVBCLK */
-#endif /* STREAM */
-
-#if defined (WWVBPPS)
-#include <sys/ppsclock.h>
-#endif /* WWVBPPS */
-
#include "ntp_stdlib.h"
/*
* This driver supports the Spectracom Model 8170 and Netclock/2 WWVB
- * Synchronized Clock under Unix and on a Gizmo board. There are two
- * formats used by these clocks. Format 0 (zero), which is available
- * with both the Netclock/2 and 8170, is in the following format:
+ * Synchronized Clock. This clock has proven a reliable source of time,
+ * except in some cases of high ambient conductive RF interference. The
+ * claimed accuracy of the clock is 100 usec relative to the broadcast
+ * signal; however, in most cases the actual accuracy is limited by the
+ * precision of the timecode and the latencies of the serial interface
+ * and operating system.
+ *
+ * The DIPswitches on this clock should be set to 24-hour display, AUTO
+ * DST off, time zone 0 (UTC), data format 0 or 2 (see below) and baud
+ * rate 9600. If this clock is to used as the source for the IRIG Audio
+ * Decoder (refclock_irig.c in this distribution), set the DIPswitches
+ * for AM IRIG output and IRIG format 1 (IRIG B with signature control).
+ *
+ * There are two timecode formats used by these clocks. Format 0, which
+ * is available with both the Netclock/2 and 8170, and format 2, which
+ * is available only with the Netclock/2 and specially modified 8170.
+ *
+ * Format 0 (22 ASCII printing characters):
+ *
+ * <cr><lf>i ddd hh:mm:ss TZ=zz<cr><lf>
+ *
+ * on-time = first <cr> * hh:mm:ss = hours, minutes, seconds
+ * i = synchronization flag (' ' = in synch, '?' = out of synch)
*
- * <cr><lf>I<sp><sp>ddd<sp>hh:mm:ss<sp><sp>TZ=nn<cr><lf>
+ * The alarm condition is indicated by other than ' ' at A, which occurs
+ * during initial synchronization and when received signal is lost for
+ * about ten hours.
*
- * The ddd, hh, mm and ss fields show the day of year, hours, minutes
- * and seconds, respectively. The nn field shows the local hour offset
- * relative to UTC and should always be set to 00. The I is normally
- * <sp> when the clock is synchronized and '?' when it isn't (it could
- * also be a '*' if we set the time manually, but this is forbidden.
+ * Format 2 (24 ASCII printing characters):
*
- * Format 2 (two), which is available only with the Netclock/2 and
- * specially modified 8170, is in the following format:
+ * <cr><lf>iqyy ddd hh:mm:ss.fff ld
*
- * <cr><lf>IQyy<sp>ddd<sp>hh:mm:ss.mmm<sp>LD
+ * on-time = <cr>
+ * i = synchronization flag (' ' = in synch, '?' = out of synch)
+ * q = quality indicator (' ' = locked, 'A'...'D' = unlocked)
+ * yy = year (as broadcast)
+ * ddd = day of year
+ * hh:mm:ss.fff = hours, minutes, seconds, milliseconds
*
- * The ddd, hh and ss fields and I are as in format 0. The yy field
- * shows the year and mmm the milliseconds, respectively. The Q is
- * normally <sp> when the time error is less than 1 ms and and a
+ * The alarm condition is indicated by other than ' ' at A, which occurs
+ * during initial synchronization and when received signal is lost for
+ * about ten hours. The unlock condition is indicated by other than ' '
+ * at Q.
+ *
+ * The Q is normally ' ' when the time error is less than 1 ms and a
* character in the set 'A'...'D' when the time error is less than 10,
- * 100, 500 and greater than 500 ms respectively. The L is normally
- * <sp>, but is set to 'L' early in the month of an upcoming UTC
- * leap second and reset to <sp> on the first day of the following
- * month. The D is set to 'S' for standard time 'I' on the day
- * preceding a switch to daylight time, 'D' for daylight time and 'O'
- * on the day preceding a switch to standard time. The start bit of the
- * first <cr> is supposed to be synchronized to the on-time second.
+ * 100, 500 and greater than 500 ms respectively. The L is normally ' ',
+ * but is set to 'L' early in the month of an upcoming UTC leap second
+ * and reset to ' ' on the first day of the following month. The D is
+ * set to 'S' for standard time 'I' on the day preceding a switch to
+ * daylight time, 'D' for daylight time and 'O' on the day preceding a
+ * switch to standard time. The start bit of the first <cr> is
+ * synchronized to the indicated time as returned.
*
* This driver does not need to be told which format is in use - it
* figures out which one from the length of the message. A three-stage
@@ -74,485 +75,168 @@
* jitter of the radio itself, which is a known problem with the older
* radios.
*
- * This driver supports the 1-pps signal provided by the radio and
- * connected via a level converted described in the gadget directory.
- * The signal is captured using a separate, dedicated, serial port and
- * the tty_clk line discipline/streams modules described in the kernel
- * directory. For the highest precision, the signal is captured using
- * the carrier-detect line of the same serial port using the ppsclock
- * streams module described in the ppsclock directory.
- *
- * Bugs:
+ * Fudge Factors
*
- * The year indication so carefully provided in format 2 is not used.
+ * This driver can retrieve a table of quality data maintained
+ * internally by the Netclock/2 receiver. If flag4 of the fudge
+ * configuration command is set to 1, the driver will retrieve this
+ * table and write it to the clockstats file on when the first timecode
+ * message of a new day is received.
*/
/*
- * Definitions
+ * Interface definitions
*/
-#define MAXUNITS 4 /* max number of WWVB units */
-#define WWVB232 "/dev/wwvb%d" /* name of radio device */
+#define DEVICE "/dev/wwvb%d" /* device name and unit */
#define SPEED232 B9600 /* uart speed (9600 baud) */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define REFID "WWVB" /* reference ID */
+#define DESCRIPTION "Spectracom WWVB Receiver" /* WRU */
-/*
- * Radio interface parameters
- */
-#define WWVBPRECISION (-13) /* precision assumed (about 100 us) */
-#define WWVBREFID "WWVB" /* reference id */
-#define WWVBDESCRIPTION "Spectracom WWVB Receiver" /* who we are */
-#define WWVBHSREFID 0x7f7f040a /* 127.127.4.10 refid hi strata */
-#define GMT 0 /* hour offset from Greenwich */
-#define NCODES 3 /* stages of median filter */
+#define NSAMPLES 3 /* stages of median filter */
#define LENWWVB0 22 /* format 0 timecode length */
#define LENWWVB2 24 /* format 2 timecode length */
-#define FMTWWVBU 0 /* unknown format timecode id */
-#define FMTWWVB0 1 /* format 0 timecode id */
-#define FMTWWVB2 2 /* format 2 timecode id */
-#define BMAX 80 /* timecode buffer length */
-#define CODEDIFF 0x20000000 /* 0.125 seconds as an l_fp fraction */
#define MONLIN 15 /* number of monitoring lines */
-/*
- * 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 */
+extern u_long current_time; /* current time (s) */
/*
* Imported from ntpd module
*/
-extern int debug; /* global debug flag */
+extern int debug; /* global debug flag */
/*
* WWVB unit control structure
*/
struct wwvbunit {
- struct peer *peer; /* associated peer structure */
- struct refclockio io; /* given to the I/O handler */
- l_fp lastrec; /* last receive time */
- l_fp lastref; /* last timecode time */
- l_fp offset[NCODES]; /* recent sample offsets */
- char lastcode[BMAX]; /* last timecode received */
- u_char format; /* timecode format */
- u_char tcswitch; /* timecode switch */
- u_char pollcnt; /* poll message counter */
- u_char lencode; /* length of last timecode */
- U_LONG lasttime; /* last time clock heard from */
- 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_char leap; /* leap indicators */
- u_short msec; /* millisecond of second */
- u_char quality; /* quality char from format 2 */
- U_LONG yearstart; /* start of current year */
- u_char lasthour; /* last hour (for monitor) */
- u_char linect; /* count of ignored lines (for monitor */
+ int pollcnt; /* poll message counter */
- /*
- * 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 */
+ u_char tcswitch; /* timecode switch */
+ l_fp laststamp; /* last receive timestamp */
+ u_char lasthour; /* last hour (for monitor) */
+ u_char linect; /* count ignored lines (for monitor */
};
/*
- * Data space for the unit structures. Note that we allocate these on
- * the fly, but never give them back.
- */
-static struct wwvbunit *wwvbunits[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 wwvb_init P((void));
-static int wwvb_start P((u_int, struct peer *));
-static void wwvb_shutdown P((int));
-static void wwvb_report_event P((struct wwvbunit *, int));
+static int wwvb_start P((int, struct peer *));
+static void wwvb_shutdown P((int, struct peer *));
static void wwvb_receive P((struct recvbuf *));
-static char wwvb_process P((struct wwvbunit *, l_fp *, u_fp *));
static void wwvb_poll P((int, struct peer *));
-static void wwvb_control P((u_int, struct refclockstat *, struct refclockstat *));
-static void wwvb_buginfo P((int, struct refclockbug *));
/*
* Transfer vector
*/
struct refclock refclock_wwvb = {
- wwvb_start, wwvb_shutdown, wwvb_poll,
- wwvb_control, wwvb_init, wwvb_buginfo, NOFLAGS
+ wwvb_start, /* start up driver */
+ wwvb_shutdown, /* shut down driver */
+ wwvb_poll, /* transmit poll message */
+ noentry, /* not used (old wwvb_control) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used (old wwvb_buginfo) */
+ NOFLAGS /* not used */
};
-/*
- * wwvb_init - initialize internal wwvb driver data
- */
-static void
-wwvb_init()
-{
- register int i;
- /*
- * Just zero the data arrays
- */
- memset((char *)wwvbunits, 0, sizeof wwvbunits);
- 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;
- }
-}
-
/*
- * wwvb_start - open the WWVB devices and initialize data for processing
+ * wwvb_start - open the devices and initialize data for processing
*/
static int
wwvb_start(unit, peer)
- u_int unit;
+ int unit;
struct peer *peer;
{
- register struct wwvbunit *wwvb;
- register int i;
- int fd232;
- char wwvbdev[20];
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
/*
- * Check configuration info
+ * Open serial port. Use CLK line discipline, if available.
*/
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "wwvb_start: unit %d invalid", unit);
+ (void)sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
return (0);
- }
- if (unitinuse[unit]) {
- syslog(LOG_ERR, "wwvb_start: unit %d in use", unit);
- return (0);
- }
/*
- * Open serial port
+ * Allocate and initialize unit structure
*/
- (void) sprintf(wwvbdev, WWVB232, unit);
- fd232 = open(wwvbdev, O_RDWR, 0777);
- if (fd232 == -1) {
- syslog(LOG_ERR, "wwvb_start: open of %s: %m", wwvbdev);
+ if (!(up = (struct wwvbunit *)
+ emalloc(sizeof(struct wwvbunit)))) {
+ (void) close(fd);
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,
- "wwvb_start: ioctl(%s, TCGETA): %m", wwvbdev);
- 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,
- "wwvb_start: ioctl(%s, TCSETA): %m", wwvbdev);
- goto screwed;
- }
- }
-#endif /* HAVE_SYSV_TTYS */
-#if defined(HAVE_TERMIOS)
- /*
- * POSIX serial line parameters (termios interface)
- *
- * The WWVBCLK option provides timestamping at the driver level.
- * It requires the tty_clk streams module.
- *
- * The WWVBPPS 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,
- "wwvb_start: tcgetattr(%s): %m", wwvbdev);
- goto screwed;
- }
- ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
- 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,
- "wwvb_start: tcsetattr(%s): %m", wwvbdev);
- goto screwed;
- }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- syslog(LOG_ERR,
- "wwvb_start: tcflush(%s): %m", wwvbdev);
- goto screwed;
- }
- }
-#endif /* HAVE_TERMIOS */
-#ifdef STREAM
-#if defined(WWVBCLK)
- if (ioctl(fd232, I_PUSH, "clk") < 0)
- syslog(LOG_ERR,
- "wwvb_start: ioctl(%s, I_PUSH, clk): %m", wwvbdev);
- if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
- syslog(LOG_ERR,
- "wwvb_start: ioctl(%s, CLK_SETSTR): %m", wwvbdev);
-#endif /* WWVBCLK */
-#if defined(WWVBPPS)
- if (ioctl(fd232, I_PUSH, "ppsclock") < 0)
- syslog(LOG_ERR,
- "wwvb_start: ioctl(%s, I_PUSH, ppsclock): %m", wwvbdev);
- else
- fdpps = fd232;
-#endif /* WWVBPPS */
-#endif /* STREAM */
-#if defined(HAVE_BSD_TTYS)
- /*
- * 4.3bsd serial line parameters (sgttyb interface)
- *
- * The WWVBCLK option provides timestamping at the driver level.
- * It requires the tty_clk line discipline and 4.3bsd or later.
- */
- { struct sgttyb ttyb;
-#if defined(WWVBCLK)
- int ldisc = CLKLDISC;
-#endif /* WWVBCLK */
-
- if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "wwvb_start: ioctl(%s, TIOCGETP): %m", wwvbdev);
- goto screwed;
- }
- ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
-#if defined(WWVBCLK)
- 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 /* WWVBCLK */
- if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
- syslog(LOG_ERR,
- "wwvb_start: ioctl(%s, TIOCSETP): %m", wwvbdev);
- goto screwed;
- }
-#if defined(WWVBCLK)
- if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR,
- "wwvb_start: ioctl(%s, TIOCSETD): %m",wwvbdev);
- goto screwed;
- }
-#endif /* WWVBCLK */
- }
-#endif /* HAVE_BSD_TTYS */
-
- /*
- * Allocate unit structure
- */
- if (wwvbunits[unit] != 0) {
- wwvb = wwvbunits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < MAXUNITS; i++) {
- if (!unitinuse[i] && wwvbunits[i] != 0)
- break;
- }
- if (i < MAXUNITS) {
- /*
- * Reclaim this one
- */
- wwvb = wwvbunits[i];
- wwvbunits[i] = 0;
- } else {
- wwvb = (struct wwvbunit *)
- emalloc(sizeof(struct wwvbunit));
- }
+ memset((char *)up, 0, sizeof(struct wwvbunit));
+ pp = peer->procptr;
+ pp->io.clock_recv = wwvb_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ (void) close(fd);
+ free(up);
+ return (0);
}
- memset((char *)wwvb, 0, sizeof(struct wwvbunit));
- wwvbunits[unit] = wwvb;
+ pp->unitptr = (caddr_t)up;
/*
- * Set up the structures
+ * Initialize miscellaneous variables
*/
- wwvb->peer = peer;
- wwvb->unit = (u_char)unit;
- wwvb->timestarted = current_time;
- wwvb->pollcnt = 2;
-
- wwvb->io.clock_recv = wwvb_receive;
- wwvb->io.srcclock = (caddr_t)wwvb;
- wwvb->io.datalen = 0;
- wwvb->io.fd = fd232;
- if (!io_addclock(&wwvb->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 = WWVBPRECISION;
- peer->rootdelay = 0;
- peer->rootdispersion = 0;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid, WWVBREFID, 4);
- else
- peer->refid = htonl(WWVBHSREFID);
- unitinuse[unit] = 1;
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ up->pollcnt = 2;
return (1);
-
- /*
- * Something broke; abandon ship.
- */
-screwed:
- (void) close(fd232);
- return (0);
-}
-
-/*
- * wwvb_shutdown - shut down a WWVB clock
- */
-static void
-wwvb_shutdown(unit)
- int unit;
-{
- register struct wwvbunit *wwvb;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "wwvb_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "wwvb_shutdown: unit %d not in use", unit);
- return;
- }
-
- /*
- * Tell the I/O module to turn us off. We're history.
- */
- wwvb = wwvbunits[unit];
- io_closeclock(&wwvb->io);
- unitinuse[unit] = 0;
}
/*
- * wwvb_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.
+ * wwvb_shutdown - shut down the clock
*/
static void
-wwvb_report_event(wwvb, code)
- struct wwvbunit *wwvb;
- int code;
-{
+wwvb_shutdown(unit, peer)
+ int unit;
struct peer *peer;
+{
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
- peer = wwvb->peer;
- if (wwvb->status != (u_char)code) {
- wwvb->status = (u_char)code;
- if (code != CEVNT_NOMINAL)
- wwvb->lastevent = (u_char)code;
- syslog(LOG_INFO,
- "clock %s event %x", ntoa(&peer->srcadr), code);
- }
+ pp = peer->procptr;
+ up = (struct wwvbunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
}
/*
- * wwvb_receive - receive data from the serial interface on a Spectracom
- * clock
+ * wwvb_receive - receive data from the serial interface
*/
static void
wwvb_receive(rbufp)
struct recvbuf *rbufp;
{
- register int i;
- register struct wwvbunit *wwvb;
- register char *dpt, *cp, *dp;
- int dpend;
- l_fp tstmp, trtmp;
- u_fp dispersion;
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+ l_fp trtmp;
+ u_long ltemp;
+ int temp;
+ char syncchar; /* synchronization indicator */
+ char qualchar; /* quality indicator */
+ char leapchar; /* leap indicator */
/*
- * Get the clock this applies to and a pointers to the data.
- * Check for the presence of a timestamp left by the tty_clock
- * line discipline/streams module and, if present, use that
- * instead of the timestamp captured by the i/o routines.
+ * Initialize pointers and read the timecode and timestamp
*/
- wwvb = (struct wwvbunit *)rbufp->recv_srcclock;
- dpt = (char *)&rbufp->recv_space;
- dpend = rbufp->recv_length;
- if (dpend > BMAX - 1)
- dpend = BMAX - 1;
- wwvb-> pollcnt = 2;
- trtmp = rbufp->recv_time;
- if (dpend >= 9) {
- dp = dpt + dpend - 9;
- if (*dp == '\n' || *dp == '\r') {
- dpend -= 8;
- if (!buftvtots(dp + 1, &tstmp)) {
-#ifdef DEBUG
- if (debug)
- printf("wwvb_receive: invalid timestamp");
-#endif
- } else {
-#ifdef DEBUG
- if (debug) {
- L_SUB(&trtmp, &tstmp);
- printf("wwvb: delta %s",
- lfptoa(&trtmp, 6));
- gettstamp(&trtmp);
- L_SUB(&trtmp, &tstmp);
- printf(" SIGIO %s\n",
- lfptoa(&trtmp, 6));
- }
-#endif
- trtmp = tstmp;
- }
- }
- }
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct wwvbunit *)pp->unitptr;
+ temp = refclock_gtlin(rbufp, pp->lastcode, BMAX, &trtmp);
+
/*
* Note we get a buffer and timestamp for both a <cr> and <lf>,
* but only the <cr> timestamp is retained. Note: in format 0 on
@@ -563,38 +247,24 @@ wwvb_receive(rbufp)
* you have a pps gadget and don't have to have the year, format
* 0 provides the lowest jitter.
*/
- if (dpend == 1) {
- if (wwvb->tcswitch == 0) {
- wwvb->tcswitch = 1;
- wwvb->lastrec = trtmp;
+ if (temp == 0) {
+ if (up->tcswitch == 0) {
+ up->tcswitch = 1;
+ up->laststamp = trtmp;
} else
- wwvb->tcswitch = 0;
+ up->tcswitch = 0;
return;
}
- tstmp = wwvb->lastrec;
- wwvb->lastrec = trtmp;
- wwvb->tcswitch = 1;
-
- /*
- * Edit timecode to remove control chars. Note the receive
- * timestamp is determined at the first <cr>; however, we don't
- * get the timecode for that timestamp until the next <cr>. We
- * assume that, if we happen to come up during a timestamp, or
- * other awkward time, the format and data checks will cause the
- * driver to resynchronize after maybe a few false starts.
- */
- if (dpend <= 0)
- return;
- cp = dp = wwvb->lastcode;
- for (i = 0; i < dpend; i++)
- if ((*dp = 0x7f & *dpt++) >= ' ') dp++;
- *dp = '\0';
- wwvb->lencode = dp - cp;
- record_clock_stats(&(wwvb->peer->srcadr), wwvb->lastcode);
+ pp->lencode = temp;
+ pp->lastrec = up->laststamp;
+ up->laststamp = trtmp;
+ up->tcswitch = 1;
+ up->pollcnt = 2;
+ record_clock_stats(&peer->srcadr, pp->lastcode);
#ifdef DEBUG
if (debug)
- printf("wwvb: timecode %d %d %s\n",
- wwvb->linect, wwvb->lencode, wwvb->lastcode);
+ printf("wwvb: timecode %d %s\n", pp->lencode,
+ pp->lastcode);
#endif
/*
@@ -602,279 +272,113 @@ wwvb_receive(rbufp)
* its contents. This code uses the timecode length to determine
* whether format 0 or format 2. If the timecode has invalid
* length or is not in proper format, we declare bad format and
- * exit; if the converted decimal values are out of range, we
- * declare bad data and exit.
+ * exit.
*/
- cp = wwvb->lastcode;
- wwvb->leap = 0;
- wwvb->format = FMTWWVBU;
- if ((cp[0] == ' ' || cp[0] == '?') && wwvb->lencode == LENWWVB0) {
+ switch (pp->lencode) {
+
+ case LENWWVB0:
/*
- * Check timecode format 0
+ * Timecode format 0: "I ddd hh:mm:ss TZ=nn"
*/
- if (cp[1] != ' ' || /* <sp> separator */
- cp[2] != ' ' || /* <sp> separator */
- !isdigit(cp[3]) || /* day of year */
- !isdigit(cp[4]) ||
- !isdigit(cp[5]) ||
- cp[6] != ' ' || /* <sp> separator */
- !isdigit(cp[7]) || /* hours */
- !isdigit(cp[8]) ||
- cp[9] != ':' || /* : separator */
- !isdigit(cp[10]) || /* minutes */
- !isdigit(cp[11]) ||
- cp[12] != ':' || /* : separator */
- !isdigit(cp[13]) || /* seconds */
- !isdigit(cp[14])) {
- wwvb->badformat++;
- wwvb_report_event(wwvb, CEVNT_BADREPLY);
- return;
- }
- else
- wwvb->format = FMTWWVB0;
+ qualchar = leapchar = ' ';
+ if (sscanf(pp->lastcode, "%c %3d %2d:%2d:%2d",
+ &syncchar, &pp->day, &pp->hour, &pp->minute,
+ &pp->second) == 5)
+ break;
- /*
- * Convert format 0 and check values
- */
- wwvb->year = 0; /* fake */
- wwvb->day = cp[3] - '0';
- wwvb->day = MULBY10(wwvb->day) + cp[4] - '0';
- wwvb->day = MULBY10(wwvb->day) + cp[5] - '0';
- wwvb->hour = MULBY10(cp[7] - '0') + cp[8] - '0';
- wwvb->minute = MULBY10(cp[10] - '0') + cp[11] - '0';
- wwvb->second = MULBY10(cp[13] - '0') + cp[14] - '0';
- wwvb->msec = 0;
- if (cp[0] != ' ')
- wwvb->leap = LEAP_NOTINSYNC;
- else
- wwvb->lasttime = current_time;
- if (wwvb->day < 1 || wwvb->day > 366) {
- wwvb->baddata++;
- wwvb_report_event(wwvb, CEVNT_BADDATE);
- return;
- }
- if (wwvb->hour > 23 || wwvb->minute > 59
- || wwvb->second > 59) {
- wwvb->baddata++;
- wwvb_report_event(wwvb, CEVNT_BADTIME);
- return;
- }
- } else if ((cp[0] == ' ' || cp[0] == '?') && wwvb->lencode == LENWWVB2) {
+ case LENWWVB2:
/*
- * Check timecode format 2
+ * Timecode format 2: "IQyy ddd hh:mm:ss.mmm LD"
*/
- if (!isdigit(cp[2]) || /* year of century */
- !isdigit(cp[3]) ||
- cp[4] != ' ' || /* <sp> separator */
- !isdigit(cp[5]) || /* day of year */
- !isdigit(cp[6]) ||
- !isdigit(cp[7]) ||
- cp[8] != ' ' || /* <sp> separator */
- !isdigit(cp[9]) || /* hour */
- !isdigit(cp[10]) ||
- cp[11] != ':' || /* : separator */
- !isdigit(cp[12]) || /* minute */
- !isdigit(cp[13]) ||
- cp[14] != ':' || /* : separator */
- !isdigit(cp[15]) || /* second */
- !isdigit(cp[16]) ||
- cp[17] != '.' || /* . separator */
- !isdigit(cp[18]) || /* millisecond */
- !isdigit(cp[19]) ||
- !isdigit(cp[20]) ||
- cp[21] != ' ') { /* <sp> separator */
- wwvb->badformat++;
- wwvb_report_event(wwvb, CEVNT_BADREPLY);
- return;
- }
- else
- wwvb->format = FMTWWVB2;
+ if (sscanf(pp->lastcode, "%c%c %2d %3d %2d:%2d:%2d.%3d %c",
+ &syncchar, &qualchar, &pp->year, &pp->day,
+ &pp->hour, &pp->minute, &pp->second, &pp->msec,
+ &leapchar) == 9)
+ break;
- /*
- * Convert format 2 and check values
- */
- wwvb->year = MULBY10(cp[2] - '0') + cp[3] - '0';
- wwvb->day = cp[5] - '0';
- wwvb->day = MULBY10(wwvb->day) + cp[6] - '0';
- wwvb->day = MULBY10(wwvb->day) + cp[7] - '0';
- wwvb->hour = MULBY10(cp[9] - '0') + cp[10] - '0';
- wwvb->minute = MULBY10(cp[12] - '0') + cp[13] - '0';
- wwvb->second = MULBY10(cp[15] - '0') + cp[16] - '0';
- wwvb->msec = cp[18] - '0';
- wwvb->msec = MULBY10(wwvb->msec) + cp[19] - '0';
- wwvb->msec = MULBY10(wwvb->msec) + cp[20] - '0';
- wwvb->quality = cp[1];
- if (cp[0] != ' ')
- wwvb->leap = LEAP_NOTINSYNC;
+ default:
- /*
- * This nonsense adjusts the last time the clock was
- * heard from depending on the quality indicator. Once
- * the clock has been heard, the dispersion depends only
- * on when the clock was last heard. The first time the
- * clock is heard, the time last heard is faked based on
- * the quality indicator. The magic numbers (in seconds)
- * are from the clock specifications.
- */
- if (wwvb->lasttime != 0) {
- if (cp[1] == ' ')
- wwvb->lasttime = current_time;
- } else {
- switch (cp[1]) {
- case ' ':
- wwvb->lasttime = current_time;
- break;
- case 'A':
- wwvb->lasttime = current_time - 800;
- break;
- case 'B':
- wwvb->lasttime = current_time - 5300;
- break;
- case 'C':
- wwvb->lasttime = current_time - 25300;
- break;
- /* Don't believe anything else */
- }
- }
- if (cp[22] == 'L')
- wwvb->leap = LEAP_ADDSECOND;
- if (wwvb->day < 1 || wwvb->day > 366) {
- wwvb->baddata++;
- wwvb_report_event(wwvb, CEVNT_BADDATE);
- return;
- }
- if (wwvb->hour > 23 || wwvb->minute > 59
- || wwvb->second > 59) {
- wwvb->baddata++;
- wwvb_report_event(wwvb, CEVNT_BADTIME);
- return;
- }
- } else {
- if (wwvb->linect > 0)
- wwvb->linect--;
- else {
- wwvb->badformat++;
- wwvb_report_event(wwvb, CEVNT_BADREPLY);
- }
+ if (up->linect > 0)
+ up->linect--;
+ else
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
- if (sloppyclockflag[wwvb->unit] & CLK_FLAG4 &&
- wwvb->hour < wwvb->lasthour)
- wwvb->linect = MONLIN;
- wwvb->lasthour = wwvb->hour;
/*
- * Now, compute the reference time value. Use the heavy
- * machinery for the seconds and the millisecond field for the
- * fraction when present. If an error in conversion to internal
- * format is found, the program declares bad data and exits.
- * Note that this code does not yet know how to do the years and
- * relies on the clock-calendar chip for sanity.
+ * Decode synchronization, quality and leap characters. If
+ * unsynchronized, set the leap bits accordingly and exit.
+ * Otherwise, set the leap bits according to the leap character.
+ * Once synchronized, the dispersion depends only on when the
+ * clock was last heard. The first time the clock is heard, the
+ * time last heard is faked based on the quality indicator. The
+ * magic numbers (in seconds) are from the clock specifications.
*/
- if (!clocktime(wwvb->day, wwvb->hour, wwvb->minute,
- wwvb->second, GMT, tstmp.l_ui,
- &wwvb->yearstart, &wwvb->lastref.l_ui)) {
- wwvb->baddata++;
- wwvb_report_event(wwvb, CEVNT_BADTIME);
+ switch (qualchar) {
+
+ case ' ':
+ ltemp = 0;
+ break;
+
+ case 'A':
+ ltemp = 800;
+ break;
+
+ case 'B':
+ ltemp = 5300;
+ break;
+
+ case 'C':
+ ltemp = 25300;
+ break;
+
+ case 'D':
+ ltemp = NTP_MAXAGE;
+ break;
+
+ default:
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
- MSUTOTSF(wwvb->msec, wwvb->lastref.l_uf);
- i = ((int)(wwvb->coderecv)) % NCODES;
- wwvb->offset[i] = wwvb->lastref;
- L_SUB(&wwvb->offset[i], &tstmp);
- if (wwvb->coderecv == 0)
- for (i = 1; i < NCODES; i++)
- wwvb->offset[i] = wwvb->offset[0];
- wwvb->coderecv++;
+ if (syncchar != ' ')
+ pp->leap = LEAP_NOTINSYNC;
+ else {
+ if (leapchar == 'L')
+ pp->leap = LEAP_ADDSECOND;
+ else
+ pp->leap = 0;
+ pp->lasttime = current_time - ltemp;
+ }
+
+ /*
+ * If the monitor flag is set (flag4), we dump the internal
+ * quality table at the first timecode beginning the day.
+ */
+ if (pp->sloppyclockflag & CLK_FLAG4 && pp->hour <
+ up->lasthour)
+ up->linect = MONLIN;
+ up->lasthour = pp->hour;
/*
- * Process the samples in the median filter, add the fudge
- * factor and pass the offset and dispersion along. We use
- * lastrec 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.
+ * Process the new sample in the median filter and determine the
+ * reference clock offset and dispersion. We use lastrec 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 (!wwvb_process(wwvb, &tstmp, &dispersion)) {
- wwvb->baddata++;
- wwvb_report_event(wwvb, CEVNT_BADTIME);
+ if (!refclock_process(pp, NSAMPLES, NSAMPLES)) {
+ refclock_report(peer, CEVNT_BADTIME);
return;
}
- L_ADD(&tstmp, &(fudgefactor[wwvb->unit]));
- refclock_receive(wwvb->peer, &tstmp, GMT, dispersion,
- &wwvb->lastrec, &wwvb->lastrec, wwvb->leap);
+ trtmp = pp->lastrec;
+ trtmp.l_ui -= ltemp;
+ refclock_receive(peer, &pp->offset, 0, pp->dispersion,
+ &trtmp, &pp->lastrec, pp->leap);
}
-/*
- * wwvb_process - process a pile of samples from the clock
- *
- * This routine uses a three-stage median filter to calculate offset and
- * dispersion. reduce jitter. The dispersion is calculated as the span
- * of the filter (max - min), unless the quality character (format 2) is
- * non-blank, in which case the dispersion is calculated on the basis of
- * the inherent tolerance of the internal radio oscillator, which is
- * +-2e-5 according to the radio specifications.
- */
-static char
-wwvb_process(wwvb, offset, dispersion)
- struct wwvbunit *wwvb;
- 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 = wwvb->offset[i].l_ui;
- tmp_uf = wwvb->offset[i].l_uf;
- M_SUB(tmp_ui, tmp_uf, wwvb->offset[j].l_ui,
- wwvb->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 (wwvb->lasttime == 0)
- disp_tmp2 = NTP_MAXDISPERSE;
- else if (wwvb->quality != ' ')
- disp_tmp2 = current_time - wwvb->lasttime;
- if (not_median1 == 0) {
- if (not_median2 == 1)
- median = 2;
- else
- median = 1;
- } else {
- median = 0;
- }
- *offset = wwvb->offset[median];
- *dispersion = disp_tmp2;
- return (1);
-}
/*
* wwvb_poll - called by the transmit procedure
@@ -884,162 +388,33 @@ wwvb_poll(unit, peer)
int unit;
struct peer *peer;
{
- struct wwvbunit *wwvb;
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
char poll;
/*
- * Time to request a time code. The Spectracom clock responds
- * to a "T" sent to it by returning a time code as stated in the
- * comments in the header. Note there is no checking on state,
- * since this may not be the only customer reading the clock.
- * Only one customer need poll the clock; all others just listen
- * in. If nothing is heard from the clock for two polls, declare
- * a timeout and keep going.
+ * Time to poll the clock. The Spectracom clock responds to a
+ * 'T' by returning a timecode in the format(s) specified above.
+ * Note there is no checking on state, since this may not be the
+ * only customer reading the clock. Only one customer need poll
+ * the clock; all others just listen in. If nothing is heard
+ * from the clock for two polls, declare a timeout and keep
+ * going.
*/
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "wwvb_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- syslog(LOG_ERR, "wwvb_poll: unit %d not in use", unit);
- return;
- }
- wwvb = wwvbunits[unit];
- if (wwvb->pollcnt > 0) {
- wwvb->pollcnt--;
- if (wwvb->pollcnt == 0)
- wwvb_report_event(wwvbunits[unit], CEVNT_TIMEOUT);
- }
- if (wwvb->pollcnt == 0)
- wwvb->noreply++;
- if (wwvb->linect > 0)
+ pp = peer->procptr;
+ up = (struct wwvbunit *)pp->unitptr;
+ if (up->pollcnt == 0)
+ refclock_report(peer, CEVNT_TIMEOUT);
+ else
+ up->pollcnt--;
+ if (up->linect > 0)
poll = 'R';
else
poll = 'T';
- if (write(wwvb->io.fd, &poll, 1) != 1) {
- syslog(LOG_ERR, "wwvb_poll: unit %d: %m", wwvb->unit);
- wwvb_report_event(wwvb, CEVNT_FAULT);
- } else {
- wwvb->polls++;
- }
-}
-
-/*
- * wwvb_control - set fudge factors, return statistics
- */
-static void
-wwvb_control(unit, in, out)
- u_int unit;
- struct refclockstat *in;
- struct refclockstat *out;
-{
- register struct wwvbunit *wwvb;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "wwvb_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
- */
- wwvb = wwvbunits[unit];
- peer = wwvb->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memmove((char *)&peer->refid,
- WWVBREFID, 4);
- else
- peer->refid = htonl(WWVBHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG4) {
- sloppyclockflag[unit] = in->flags & CLK_FLAG4;
- }
- }
-
- if (out != 0) {
- out->type = REFCLK_WWVB_SPECTRACOM;
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG4;
- out->clockdesc = WWVBDESCRIPTION;
- 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]) {
- wwvb = wwvbunits[unit];
- out->lencode = wwvb->lencode;
- out->lastcode = wwvb->lastcode;
- out->timereset = current_time - wwvb->timestarted;
- out->polls = wwvb->polls;
- out->noresponse = wwvb->noreply;
- out->badformat = wwvb->badformat;
- out->baddata = wwvb->baddata;
- out->lastevent = wwvb->lastevent;
- out->currentstatus = wwvb->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;
- }
- }
+ if (write(pp->io.fd, &poll, 1) != 1) {
+ refclock_report(peer, CEVNT_FAULT);
+ } else
+ pp->polls++;
}
-/*
- * wwvb_buginfo - return clock dependent debugging info
- */
-static void
-wwvb_buginfo(unit, bug)
- int unit;
- register struct refclockbug *bug;
-{
- register struct wwvbunit *wwvb;
-
- if (unit >= MAXUNITS) {
- syslog(LOG_ERR, "wwvb_buginfo: unit %d invalid", unit);
- return;
- }
-
- if (!unitinuse[unit])
- return;
- wwvb = wwvbunits[unit];
-
- bug->nvalues = 11;
- bug->ntimes = 5;
- if (wwvb->lasttime != 0)
- bug->values[0] = current_time - wwvb->lasttime;
- else
- bug->values[0] = 0;
- bug->values[1] = (U_LONG)wwvb->reason;
- bug->values[2] = (U_LONG)wwvb->year;
- bug->values[3] = (U_LONG)wwvb->day;
- bug->values[4] = (U_LONG)wwvb->hour;
- bug->values[5] = (U_LONG)wwvb->minute;
- bug->values[6] = (U_LONG)wwvb->second;
- bug->values[7] = (U_LONG)wwvb->msec;
- bug->values[8] = wwvb->noreply;
- bug->values[9] = wwvb->yearstart;
- bug->values[10] = wwvb->quality;
- bug->stimes = 0x1c;
- bug->times[0] = wwvb->lastref;
- bug->times[1] = wwvb->lastrec;
- bug->times[2] = wwvb->offset[0];
- bug->times[3] = wwvb->offset[1];
- bug->times[4] = wwvb->offset[2];
-}
#endif
diff --git a/usr.sbin/xntpd/xntpdc/Makefile.tmpl b/usr.sbin/xntpd/xntpdc/Makefile.tmpl
index 32ed02419146..80c8f93d406b 100644
--- a/usr.sbin/xntpd/xntpdc/Makefile.tmpl
+++ b/usr.sbin/xntpd/xntpdc/Makefile.tmpl
@@ -1,5 +1,5 @@
#
-# Makefile.tmpl,v 3.1 1993/07/06 01:11:58 jbj Exp
+# Makefile.tmpl
#
PROGRAM= xntpdc
#
diff --git a/usr.sbin/xntpd/xntpdc/ntpdc.c b/usr.sbin/xntpd/xntpdc/ntpdc.c
index 3113c9ff7817..387540bd365b 100644
--- a/usr.sbin/xntpd/xntpdc/ntpdc.c
+++ b/usr.sbin/xntpd/xntpdc/ntpdc.c
@@ -1,4 +1,4 @@
-/* ntpdc.c,v 3.1 1993/07/06 01:11:59 jbj Exp
+/*
* xntpdc - control and monitor your xntpd daemon
*/
#include <stdio.h>
@@ -26,7 +26,7 @@ static char * prompt = "xntpdc> "; /* prompt to ask him about */
/*
* Keyid used for authenticated requests. Obtained on the fly.
*/
-static U_LONG info_auth_keyid;
+static u_long info_auth_keyid;
/*
* Type of key md5 or des
@@ -51,7 +51,7 @@ static void docmd P((char *));
static void tokenize P((char *, char **, int *));
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 int getnetnum P((char *, u_long *, char *));
static void help P((struct parse *, FILE *));
#if defined(sgi) || defined(SYS_BSDI) || defined(__STDC__)
static int helpsort P((const void *, const void *));
@@ -62,7 +62,6 @@ static void printusage P((struct xcmd *, FILE *));
static void timeout P((struct parse *, FILE *));
static void delay P((struct parse *, FILE *));
static void host P((struct parse *, FILE *));
-static void ntp_poll P((struct parse *, FILE *));
static void keyid P((struct parse *, FILE *));
static void keytype P((struct parse *, FILE *));
static void passwd P((struct parse *, FILE *));
@@ -72,17 +71,17 @@ static void quit P((struct parse *, FILE *));
static void version P((struct parse *, FILE *));
static void warning P((char *, char *, char *));
static void error P((char *, char *, char *));
-static U_LONG getkeyid P((char *));
+static u_long getkeyid P((char *));
/*
* Built-in commands we understand
*/
static struct xcmd builtins[] = {
- { "?", help, { OPT|STR, NO, NO, NO },
+ { "?", help, { OPT|NTP_STR, NO, NO, NO },
{ "command", "", "", "" },
"tell the use and syntax of commands" },
- { "help", help, { OPT|STR, NO, NO, NO },
+ { "help", help, { OPT|NTP_STR, NO, NO, NO },
{ "command", "", "", "" },
"tell the use and syntax of commands" },
{ "timeout", timeout, { OPT|UINT, NO, NO, NO },
@@ -91,19 +90,16 @@ static struct xcmd builtins[] = {
{ "delay", delay, { OPT|INT, NO, NO, NO },
{ "msec", "", "", "" },
"set the delay added to encryption time stamps" },
- { "host", host, { OPT|STR, NO, NO, NO },
+ { "host", host, { OPT|NTP_STR, NO, NO, NO },
{ "hostname", "", "", "" },
"specify the host whose NTP server we talk to" },
- { "poll", ntp_poll, { OPT|UINT, OPT|STR, NO, NO },
- { "n", "verbose", "", "" },
- "poll an NTP server in client mode `n' times" },
- { "passwd", passwd, { NO, NO, NO, NO },
+ { "passwd", passwd, { OPT|NTP_STR, NO, NO, NO },
{ "", "", "", "" },
"specify a password to use for authenticated requests"},
- { "hostnames", hostnames, { OPT|STR, NO, NO, NO },
+ { "hostnames", hostnames, { OPT|NTP_STR, NO, NO, NO },
{ "yes|no", "", "", "" },
"specify whether hostnames or net numbers are printed"},
- { "debug", setdebug, { OPT|STR, NO, NO, NO },
+ { "debug", setdebug, { OPT|NTP_STR, NO, NO, NO },
{ "no|more|less", "", "", "" },
"set/change debugging level" },
{ "quit", quit, { NO, NO, NO, NO },
@@ -112,7 +108,7 @@ static struct xcmd builtins[] = {
{ "keyid", keyid, { OPT|UINT, NO, NO, NO },
{ "key#", "", "", "" },
"set keyid to use for authenticated requests" },
- { "keytype", keytype, { STR, NO, NO, NO },
+ { "keytype", keytype, { NTP_STR, NO, NO, NO },
{ "key type (md5|des)", "", "", "" },
"set key type to use for authenticated requests (des|md5)" },
{ "version", version, { NO, NO, NO, NO },
@@ -130,7 +126,7 @@ static struct xcmd builtins[] = {
#define DEFSTIMEOUT (2) /* 2 second time out after first */
#define DEFDELAY 0x51EB852 /* 20 milliseconds, l_fp fraction */
#define DEFHOST "localhost" /* default host name */
-#define LENHOSTNAME 256 /* host name is 256 characters LONG */
+#define LENHOSTNAME 256 /* host name is 256 characters long */
#define MAXCMDS 100 /* maximum commands on cmd line */
#define MAXHOSTS 100 /* maximum hosts on cmd line */
#define MAXLINE 512 /* maximum line length */
@@ -313,7 +309,7 @@ static int
openhost(hname)
char *hname;
{
- U_LONG netnum;
+ u_long netnum;
char temphost[LENHOSTNAME];
if (server_entry == NULL) {
@@ -429,9 +425,9 @@ getresponse(implcode, reqcode, ritems, rsize, rdata)
/*
* This is pretty tricky. We may get between 1 and many packets
* back in response to the request. We peel the data out of
- * each packet and collect it in one LONG block. When the last
+ * each packet and collect it in one long block. When the last
* packet in the sequence is received we'll know how many we
- * should have had. Note we use one LONG time out, should reconsider.
+ * should have had. Note we use one long time out, should reconsider.
*/
*ritems = 0;
*rsize = 0;
@@ -702,7 +698,8 @@ sendrequest(implcode, reqcode, auth, qitems, qsize, qdata)
* doquery - send a request and process the response
*/
int
-doquery(implcode, reqcode, auth, qitems, qsize, qdata, ritems, rsize, rdata)
+doquery(implcode, reqcode, auth, qitems, qsize, qdata, ritems, rsize, rdata,
+ quiet_mask)
int implcode;
int reqcode;
int auth;
@@ -712,6 +709,7 @@ doquery(implcode, reqcode, auth, qitems, qsize, qdata, ritems, rsize, rdata)
int *ritems;
int *rsize;
char **rdata;
+ int quiet_mask;
{
int res;
char junk[512];
@@ -755,7 +753,8 @@ doquery(implcode, reqcode, auth, qitems, qsize, qdata, ritems, rsize, rdata)
*/
res = getresponse(implcode, reqcode, ritems, rsize, rdata);
- if (res > 0) {
+ /* log error message if not told to be quiet */
+ if ((res > 0) && (((1 << res) & quiet_mask) == 0)) {
switch(res) {
case INFO_ERR_IMPL:
(void) fprintf(stderr,
@@ -764,6 +763,7 @@ doquery(implcode, reqcode, auth, qitems, qsize, qdata, ritems, rsize, rdata)
case INFO_ERR_REQ:
(void) fprintf(stderr,
"***Server doesn't implement this request\n");
+ break;
case INFO_ERR_FMT:
(void) fprintf(stderr,
"***Server reports a format error in the received packet (shouldn't happen)\n");
@@ -1030,7 +1030,7 @@ getarg(str, code, argp)
static char *digits = "0123456789";
switch (code & ~OPT) {
- case STR:
+ case NTP_STR:
argp->string = str;
break;
case ADD:
@@ -1081,7 +1081,7 @@ getarg(str, code, argp)
static int
getnetnum(host, num, fullhost)
char *host;
- U_LONG *num;
+ u_long *num;
char *fullhost;
{
struct hostent *hp;
@@ -1089,13 +1089,13 @@ getnetnum(host, num, fullhost)
if (decodenetnum(host, num)) {
if (fullhost != 0) {
(void) sprintf(fullhost,
- "%d.%d.%d.%d", ((htonl(*num)>>24)&0xff),
- ((htonl(*num)>>16)&0xff), ((htonl(*num)>>8)&0xff),
- (htonl(*num)&0xff));
+ "%u.%u.%u.%u", (u_int)((htonl(*num)>>24)&0xff),
+ (u_int)((htonl(*num)>>16)&0xff), (u_int)((htonl(*num)>>8)&0xff),
+ (u_int)(htonl(*num)&0xff));
}
return 1;
} else if ((hp = gethostbyname(host)) != 0) {
- memmove((char *)num, hp->h_addr, sizeof(U_LONG));
+ memmove((char *)num, hp->h_addr, sizeof(u_long));
if (fullhost != 0)
(void) strcpy(fullhost, hp->h_name);
return 1;
@@ -1112,7 +1112,7 @@ getnetnum(host, num, fullhost)
*/
char *
nntohost(netnum)
- U_LONG netnum;
+ u_long netnum;
{
if (!showhostnames)
return numtoa(netnum);
@@ -1267,18 +1267,18 @@ delay(pcmd, fp)
FILE *fp;
{
int isneg;
- U_LONG val;
+ u_long val;
if (pcmd->nargs == 0) {
val = delay_time.l_ui * 1000 + delay_time.l_uf / 4294967;
- (void) fprintf(fp, "delay %d ms\n", val);
+ (void) fprintf(fp, "delay %lu ms\n", val);
} else {
if (pcmd->argval[0].ival < 0) {
isneg = 1;
- val = (U_LONG)(-pcmd->argval[0].ival);
+ val = (u_long)(-pcmd->argval[0].ival);
} else {
isneg = 0;
- val = (U_LONG)pcmd->argval[0].ival;
+ val = (u_long)pcmd->argval[0].ival;
}
delay_time.l_ui = val / 1000;
@@ -1317,19 +1317,6 @@ host(pcmd, fp)
/*
- * poll - do one (or more) polls of the host via NTP
- */
-/*ARGSUSED*/
-static void
-ntp_poll(pcmd, fp)
- struct parse *pcmd;
- FILE *fp;
-{
- (void) fprintf(fp, "poll not implemented yet\n");
-}
-
-
-/*
* keyid - get a keyid to use for authenticating requests
*/
static void
@@ -1341,7 +1328,7 @@ keyid(pcmd, fp)
if (info_auth_keyid == 0)
(void) fprintf(fp, "no keyid defined\n");
else
- (void) fprintf(fp, "keyid is %u\n", info_auth_keyid);
+ (void) fprintf(fp, "keyid is %lu\n", info_auth_keyid);
} else {
info_auth_keyid = pcmd->argval[0].uval;
}
@@ -1396,11 +1383,16 @@ passwd(pcmd, fp)
return;
}
}
- pass = getpass("Password: ");
- if (*pass == '\0')
- (void) fprintf(fp, "Password unchanged\n");
- else
- authusekey(info_auth_keyid, info_auth_keytype, pass);
+ if (!interactive) {
+ authusekey(info_auth_keyid, info_auth_keytype,
+ pcmd->argval[0].string);
+ } else {
+ pass = getpass("Password: ");
+ if (*pass == '\0')
+ (void) fprintf(fp, "Password unchanged\n");
+ else
+ authusekey(info_auth_keyid, info_auth_keytype, pass);
+ }
}
@@ -1515,7 +1507,7 @@ error(fmt, st1, st2)
/*
* getkeyid - prompt the user for a keyid to use
*/
-static U_LONG
+static u_long
getkeyid(prompt)
char *prompt;
{
@@ -1536,5 +1528,5 @@ char *prompt;
*p = '\0';
if (fi != stdin)
fclose(fi);
- return (U_LONG)atoi(pbuf);
+ return (u_long)atoi(pbuf);
}
diff --git a/usr.sbin/xntpd/xntpdc/ntpdc.h b/usr.sbin/xntpd/xntpdc/ntpdc.h
index 7784ebc5a672..bb2302428216 100644
--- a/usr.sbin/xntpd/xntpdc/ntpdc.h
+++ b/usr.sbin/xntpd/xntpdc/ntpdc.h
@@ -1,4 +1,4 @@
-/* ntpdc.h,v 3.1 1993/07/06 01:12:01 jbj Exp
+/*
* ntpdc.h - definitions of interest to xntpdc
*/
#include "ntp_fp.h"
@@ -18,7 +18,7 @@
#define OPT 0x80 /* this argument is optional, or'd with type */
#define NO 0x0
-#define STR 0x1 /* string argument */
+#define NTP_STR 0x1 /* string argument */
#define UINT 0x2 /* unsigned integer */
#define INT 0x3 /* signed integer */
#define ADD 0x4 /* IP network address */
@@ -28,9 +28,9 @@
*/
typedef union {
char *string;
- LONG ival;
- U_LONG uval;
- U_LONG netnum;
+ long ival;
+ u_long uval;
+ u_long netnum;
} arg_v;
/*
@@ -55,5 +55,5 @@ struct xcmd {
char *comment;
};
-extern int doquery P((int, int, int, int, int, char *, int *, int *, char **));
-extern char * nntohost P((U_LONG));
+extern int doquery P((int, int, int, int, int, char *, int *, int *, char **, int));
+extern char * nntohost P((u_long));
diff --git a/usr.sbin/xntpd/xntpdc/ntpdc_ops.c b/usr.sbin/xntpd/xntpdc/ntpdc_ops.c
index 4fa9324784cc..4d50619a170e 100644
--- a/usr.sbin/xntpd/xntpdc/ntpdc_ops.c
+++ b/usr.sbin/xntpd/xntpdc/ntpdc_ops.c
@@ -1,4 +1,4 @@
-/* ntpdc_ops.c,v 3.1 1993/07/06 01:12:02 jbj Exp
+/*
* ntpdc_ops.c - subroutines which are called to perform operations by xntpdc
*/
#include <stdio.h>
@@ -6,6 +6,10 @@
#include <sys/types.h>
#include <sys/time.h>
#include <netdb.h>
+#ifndef __bsdi__
+#include <netinet/in.h>
+#endif
+#include <arpa/inet.h>
#include "ntpdc.h"
#include "ntp_control.h"
@@ -49,8 +53,6 @@ static void monitor P((struct parse *, FILE *));
static void reset P((struct parse *, FILE *));
static void preset P((struct parse *, FILE *));
static void readkeys P((struct parse *, FILE *));
-static void dodirty P((struct parse *, FILE *));
-static void dontdirty P((struct parse *, FILE *));
static void trustkey P((struct parse *, FILE *));
static void untrustkey P((struct parse *, FILE *));
static void do_trustkey P((struct parse *, FILE *, int));
@@ -89,7 +91,7 @@ struct xcmd opcmds[] = {
{ "pstats", peerstats, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
{ "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
"display statistical information for one or more peers" },
- { "loopinfo", loopinfo, { OPT|STR, NO, NO, NO },
+ { "loopinfo", loopinfo, { OPT|NTP_STR, NO, NO, NO },
{ "oneline|multiline", "", "", "" },
"display loop filter information" },
{ "sysinfo", sysinfo, { NO, NO, NO, NO },
@@ -107,47 +109,47 @@ struct xcmd opcmds[] = {
{ "timerstats", timerstats, { NO, NO, NO, NO },
{ "", "", "", "" },
"display event timer subsystem statistics" },
- { "addpeer", addpeer, { ADD, OPT|UINT, OPT|UINT, OPT|STR },
+ { "addpeer", addpeer, { ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR },
{ "addr", "keyid", "version", "minpoll|prefer" },
"configure a new peer association" },
- { "addserver", addserver, { ADD, OPT|UINT, OPT|UINT, OPT|STR },
+ { "addserver", addserver, { ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR },
{ "addr", "keyid", "version", "minpoll|prefer" },
"configure a new server" },
- { "broadcast", broadcast, { ADD, OPT|UINT, OPT|UINT, OPT|STR },
+ { "broadcast", broadcast, { ADD, OPT|UINT, OPT|UINT, OPT|NTP_STR },
{ "addr", "keyid", "version", "minpoll" },
"configure broadcasting time service" },
{ "unconfig", unconfig, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
{ "peer_address", "peer2_addr", "peer3_addr", "peer4_addr" },
"unconfigure existing peer assocations" },
- { "set", set, { STR, OPT|STR, OPT|STR, OPT|STR },
- { "bclient|mclient|auth", "...", "...", "..." },
- "set a system flag (bclient, mclient, auth)" },
- { "clear", sys_clear, { STR, OPT|STR, OPT|STR, OPT|STR },
- { "bclient|mclient|auth", "...", "...", "..." },
- "clear a system flag (bclient, mclient, auth)" },
+ { "enable", set, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
+ { "auth|bclient|pll|pps|monitor|stats", "...", "...", "..." },
+ "set a system flag (auth, bclient, pll, pps, monitor, stats)" },
+ { "disable", sys_clear, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
+ { "auth|bclient|pll|pps|monitor|stats", "...", "...", "..." },
+ "clear a system flag (auth, bclient, pll, pps, monitor, stats)" },
{ "reslist", reslist, { NO, NO, NO, NO },
{ "", "", "", "" },
"display the server's restrict list" },
- { "restrict", restrict, { ADD, ADD, STR, OPT|STR },
+ { "restrict", restrict, { ADD, ADD, NTP_STR, OPT|NTP_STR },
{ "address", "mask",
"ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer",
"..." },
"create restrict entry/add flags to entry" },
- { "unrestrict", unrestrict, { ADD, ADD, STR, OPT|STR },
+ { "unrestrict", unrestrict, { ADD, ADD, NTP_STR, OPT|NTP_STR },
{ "address", "mask",
"ntpport|ignore|noserve|notrust|noquery|nomodify|nopeer",
"..." },
"remove flags from a restrict entry" },
- { "delrestrict", delrestrict, { ADD, ADD, OPT|STR, NO },
+ { "delrestrict", delrestrict, { ADD, ADD, OPT|NTP_STR, NO },
{ "address", "mask", "ntpport", "" },
"delete a restrict entry" },
- { "monlist", monlist, { NO, NO, NO, NO },
- { "", "", "", "" },
+ { "monlist", monlist, { OPT|INT, NO, NO, NO },
+ { "version", "", "", "" },
"display data the server's monitor routines have collected" },
- { "monitor", monitor, { STR, NO, NO, NO },
+ { "monitor", monitor, { NTP_STR, NO, NO, NO },
{ "on|off", "", "", "" },
"turn the server's monitoring facility on or off" },
- { "reset", reset, { STR, OPT|STR, OPT|STR, OPT|STR },
+ { "reset", reset, { NTP_STR, OPT|NTP_STR, OPT|NTP_STR, OPT|NTP_STR },
{ "io|sys|mem|timer|auth|allpeers", "...", "...", "..." },
"reset various subsystem statistics counters" },
{ "preset", preset, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
@@ -155,13 +157,7 @@ struct xcmd opcmds[] = {
"reset stat counters associated with particular peer(s)" },
{ "readkeys", readkeys, { NO, NO, NO, NO },
{ "", "", "", "" },
- "request a reread of the `keys' file and re-init of system keys" },
- { "dodirty", dodirty, { NO, NO, NO, NO },
- { "", "", "", "" },
- "placeholder, historical interest only" },
- { "dontdirty", dontdirty, { NO, NO, NO, NO },
- { "", "", "", "" },
- "placeholder, historical interest only" },
+ "request a reread of the keys file and re-init of system keys" },
{ "trustkey", trustkey, { UINT, OPT|UINT, OPT|UINT, OPT|UINT },
{ "keyid", "keyid", "keyid", "keyid" },
"add one or more key ID's to the trusted list" },
@@ -195,7 +191,7 @@ struct xcmd opcmds[] = {
{ "clockstat", clockstat, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
{ "address", "address", "address", "address" },
"display clock status information" },
- { "fudge", fudge, { ADD, STR, STR, NO },
+ { "fudge", fudge, { ADD, NTP_STR, NTP_STR, NO },
{ "address", "time1|time2|val1|val2|flags", "value", "" },
"set/change one of a clock's fudge factors" },
{ "clkbug", clkbug, { ADD, OPT|ADD, OPT|ADD, OPT|ADD },
@@ -297,7 +293,7 @@ peerlist(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_PEER_LIST, 0, 0, 0, (char *)NULL, &items,
- &itemsize, (char **)&plist);
+ &itemsize, (char **)&plist, 0);
if (res != 0 && items == 0)
return;
@@ -359,7 +355,7 @@ dopeers(pcmd, fp, dmstyle)
l_fp tempts;
res = doquery(IMPL_XNTPD, REQ_PEER_LIST_SUM, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&plist);
+ &items, &itemsize, (char **)&plist, 0);
if (res != 0 && items == 0)
return;
@@ -417,6 +413,21 @@ dopeers(pcmd, fp, dmstyle)
}
}
+/* Convert a refid & stratum (in host order) to a string */
+static char*
+refid_string(refid, stratum)
+ u_long refid;
+ int stratum;
+{
+ if (stratum <= 1) {
+ static char junk[5];
+ junk[4] = 0;
+ memmove(junk, (char *)&refid, 4);
+ return junk;
+ }
+
+ return numtoa(refid);
+}
/*
* printpeer - print detail information for a peer
@@ -427,7 +438,6 @@ printpeer(pp, fp)
FILE *fp;
{
register int i;
- char junk[5];
char *str;
l_fp tempts;
@@ -438,32 +448,25 @@ printpeer(pp, fp)
modetoa(pp->hmode), modetoa(pp->pmode),
pp->stratum, pp->precision);
- if (pp->stratum <= 1) {
- junk[4] = 0;
- memmove(junk, (char *)&pp->refid, 4);
- str = junk;
- } else {
- str = numtoa(pp->refid);
- }
(void) fprintf(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), 5),
- ufptoa(HTONS_FP(pp->rootdispersion), 5));
+ refid_string(pp->refid, pp->stratum), fptoa(NTOHS_FP(pp->rootdelay), 5),
+ ufptoa(NTOHS_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));
+ "ppoll %d, hpoll %d, keyid %lu, version %d, association %u\n",
+ pp->ppoll, pp->hpoll, (u_long)pp->keyid, pp->version, ntohs(pp->associd));
(void) fprintf(fp,
"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, "boffset %s, ttl %d\n",
+ fptoa(NTOHS_FP(pp->estbdelay), 5), pp->ttl);
- (void) fprintf(fp, "timer %ds, flags", ntohl(pp->timer));
+ (void) fprintf(fp, "timer %lds, flags", (long)ntohl(pp->timer));
if (pp->flags == 0) {
(void) fprintf(fp, " none\n");
} else {
@@ -473,44 +476,44 @@ printpeer(pp, fp)
str = ",";
}
if (pp->flags & INFO_FLAG_CONFIG) {
- (void) fprintf(fp, "%s configured", str);
+ (void) fprintf(fp, "%s config", str);
str = ",";
}
- if (pp->flags & INFO_FLAG_MINPOLL) {
- (void) fprintf(fp, "%s minpoll", str);
+ if (pp->flags & INFO_FLAG_REFCLOCK) {
+ (void) fprintf(fp, "%s refclock", str);
str = ",";
}
if (pp->flags & INFO_FLAG_AUTHENABLE) {
- (void) fprintf(fp, "%s authenable", str);
+ (void) fprintf(fp, "%s auth", str);
str = ",";
}
- if (pp->flags & INFO_FLAG_REFCLOCK) {
- (void) fprintf(fp, "%s reference_clock", str);
+ if (pp->flags & INFO_FLAG_BCLIENT) {
+ (void) fprintf(fp, "%s bclient", str);
str = ",";
}
if (pp->flags & INFO_FLAG_PREFER) {
- (void) fprintf(fp, "%s preferred_peer", str);
+ (void) fprintf(fp, "%s prefer", str);
}
(void) fprintf(fp, "\n");
}
- HTONL_FP(&pp->reftime, &tempts);
+ NTOHL_FP(&pp->reftime, &tempts);
(void) fprintf(fp, "reference time: %s\n",
prettydate(&tempts));
- HTONL_FP(&pp->org, &tempts);
+ NTOHL_FP(&pp->org, &tempts);
(void) fprintf(fp, "originate timestamp: %s\n",
prettydate(&tempts));
- HTONL_FP(&pp->rec, &tempts);
+ NTOHL_FP(&pp->rec, &tempts);
(void) fprintf(fp, "receive timestamp: %s\n",
prettydate(&tempts));
- HTONL_FP(&pp->xmt, &tempts);
+ NTOHL_FP(&pp->xmt, &tempts);
(void) fprintf(fp, "transmit timestamp: %s\n",
prettydate(&tempts));
(void) fprintf(fp, "filter delay: ");
for (i = 0; i < NTP_SHIFT; i++) {
(void) fprintf(fp, " %-8.8s",
- fptoa(HTONS_FP(pp->filtdelay[i]), 5));
+ fptoa(NTOHS_FP(pp->filtdelay[i]), 5));
if (i == (NTP_SHIFT>>1)-1)
(void) fprintf(fp, "\n ");
}
@@ -518,7 +521,7 @@ printpeer(pp, fp)
(void) fprintf(fp, "filter offset:");
for (i = 0; i < NTP_SHIFT; i++) {
- HTONL_FP(&pp->filtoffset[i], &tempts);
+ NTOHL_FP(&pp->filtoffset[i], &tempts);
(void) fprintf(fp, " %-8.8s", lfptoa(&tempts, 6));
if (i == (NTP_SHIFT>>1)-1)
(void) fprintf(fp, "\n ");
@@ -534,12 +537,12 @@ printpeer(pp, fp)
(void) fprintf(fp, "\n");
- HTONL_FP(&pp->offset, &tempts);
+ NTOHL_FP(&pp->offset, &tempts);
(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));
+ lfptoa(&tempts, 6), fptoa(NTOHS_FP(pp->delay), 5),
+ ufptoa(NTOHS_FP(pp->dispersion), 5),
+ ufptoa(NTOHS_FP(pp->selectdisp), 5));
}
@@ -567,7 +570,7 @@ showpeer(pcmd, fp)
res = doquery(IMPL_XNTPD, REQ_PEER_INFO, 0, qitems,
sizeof(struct info_peer_list), (char *)plist, &items,
- &itemsize, (char **)&pp);
+ &itemsize, (char **)&pp, 0);
if (res != 0 && items == 0)
return;
@@ -611,7 +614,7 @@ peerstats(pcmd, fp)
res = doquery(IMPL_XNTPD, REQ_PEER_STATS, 0, qitems,
sizeof(struct info_peer_list), (char *)plist, &items,
- &itemsize, (char **)&pp);
+ &itemsize, (char **)&pp, 0);
if (res != 0 && items == 0)
return;
@@ -627,44 +630,28 @@ peerstats(pcmd, fp)
nntohost(pp->srcadr));
(void) fprintf(fp, "local interface: %s\n",
numtoa(pp->dstadr));
- (void) fprintf(fp, "time last received: %ds\n",
- ntohl(pp->timereceived));
- (void) fprintf(fp, "time until next send: %ds\n",
- ntohl(pp->timetosend));
- (void) fprintf(fp, "reachability change: %ds\n",
- ntohl(pp->timereachable));
- (void) fprintf(fp, "packets sent: %d\n",
- ntohl(pp->sent));
- (void) fprintf(fp, "packets received: %d\n",
- ntohl(pp->received));
- (void) fprintf(fp, "packets processed: %d\n",
- ntohl(pp->processed));
- (void) fprintf(fp, "bad length packets: %d\n",
- ntohl(pp->badlength));
- (void) fprintf(fp, "bad auth packets: %d\n",
- ntohl(pp->badauth));
- (void) fprintf(fp, "bogus origin packets: %d\n",
- ntohl(pp->bogusorg));
- (void) fprintf(fp, "duplicate packets: %d\n",
- ntohl(pp->oldpkt));
- (void) fprintf(fp, "bad delay rejections: %d\n",
- ntohl(pp->baddelay));
- (void) fprintf(fp, "select delay rejects: %d\n",
- ntohl(pp->seldelay));
- (void) fprintf(fp, "select disp rejects: %d\n",
- ntohl(pp->seldisp));
- (void) fprintf(fp, "select finds broken: %d\n",
- ntohl(pp->selbroken));
- (void) fprintf(fp, "too old for select: %d\n",
- ntohl(pp->selold));
- (void) fprintf(fp, "sel candidate order: %d\n",
+ (void) fprintf(fp, "time last received: %lds\n",
+ (long)ntohl(pp->timereceived));
+ (void) fprintf(fp, "time until next send: %lds\n",
+ (long)ntohl(pp->timetosend));
+ (void) fprintf(fp, "reachability change: %lds\n",
+ (long)ntohl(pp->timereachable));
+ (void) fprintf(fp, "packets sent: %ld\n",
+ (long)ntohl(pp->sent));
+ (void) fprintf(fp, "packets received: %ld\n",
+ (long)ntohl(pp->processed));
+ (void) fprintf(fp, "bad authentication: %ld\n",
+ (long)ntohl(pp->badauth));
+ (void) fprintf(fp, "bogus origin: %ld\n",
+ (long)ntohl(pp->bogusorg));
+ (void) fprintf(fp, "duplicate: %ld\n",
+ (long)ntohl(pp->oldpkt));
+ (void) fprintf(fp, "bad dispersion: %ld\n",
+ (long)ntohl(pp->seldisp));
+ (void) fprintf(fp, "bad reference time: %ld\n",
+ (long)ntohl(pp->selbroken));
+ (void) fprintf(fp, "candidate order: %d\n",
(int)pp->candidate);
- (void) fprintf(fp, "falseticker order: %d\n",
- (int)pp->falseticker);
- (void) fprintf(fp, "select order: %d\n",
- (int)pp->select);
- (void) fprintf(fp, "select total: %d\n",
- (int)pp->select_total);
if (items > 0)
(void) fprintf(fp, "\n");
pp++;
@@ -699,7 +686,7 @@ loopinfo(pcmd, fp)
}
res = doquery(IMPL_XNTPD, REQ_LOOP_INFO, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&il);
+ &items, &itemsize, (char **)&il, 0);
if (res != 0 && items == 0)
return;
@@ -713,26 +700,26 @@ loopinfo(pcmd, fp)
if (oneline) {
l_fp temp2ts;
- HTONL_FP(&il->last_offset, &tempts);
- HTONL_FP(&il->drift_comp, &temp2ts);
+ NTOHL_FP(&il->last_offset, &tempts);
+ NTOHL_FP(&il->drift_comp, &temp2ts);
(void) fprintf(fp,
- "offset %s, drift %s, compliance %d, timer %d seconds\n",
- lfptoa(&tempts, 7),
- lfptoa(&temp2ts, 7),
- ntohl(il->compliance),
- ntohl(il->watchdog_timer));
+ "offset %s, frequency %s, time_const %ld, watchdog %ld\n",
+ lfptoa(&tempts, 6),
+ lfptoa(&temp2ts, 3),
+ (u_long)ntohl(il->compliance),
+ (u_long)ntohl(il->watchdog_timer));
} else {
- HTONL_FP(&il->last_offset, &tempts);
- (void) fprintf(fp, "offset: %s seconds\n",
- lfptoa(&tempts, 7));
- HTONL_FP(&il->drift_comp, &tempts);
- (void) fprintf(fp, "frequency: %s seconds\n",
- lfptoa(&tempts, 7));
- (void) fprintf(fp, "compliance: %d seconds\n",
- ntohl(il->compliance));
- (void) fprintf(fp, "timer: %d seconds\n",
- ntohl(il->watchdog_timer));
+ NTOHL_FP(&il->last_offset, &tempts);
+ (void) fprintf(fp, "offset: %s s\n",
+ lfptoa(&tempts, 6));
+ NTOHL_FP(&il->drift_comp, &tempts);
+ (void) fprintf(fp, "frequency: %s ppm\n",
+ lfptoa(&tempts, 3));
+ (void) fprintf(fp, "poll adjust: %ld\n",
+ (u_long)ntohl(il->compliance));
+ (void) fprintf(fp, "watchdog timer: %ld s\n",
+ (u_long)ntohl(il->watchdog_timer));
}
}
@@ -750,12 +737,10 @@ sysinfo(pcmd, fp)
int items;
int itemsize;
int res;
- char junk[5];
- char *str;
l_fp tempts;
res = doquery(IMPL_XNTPD, REQ_SYS_INFO, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&is);
+ &items, &itemsize, (char **)&is, 0);
if (res != 0 && items == 0)
return;
@@ -766,54 +751,54 @@ sysinfo(pcmd, fp)
if (!checkitemsize(itemsize, sizeof(struct info_sys)))
return;
- (void) fprintf(fp, "system peer: %s\n", nntohost(is->peer));
- (void) fprintf(fp, "system peer mode: %s\n", modetoa(is->peer_mode));
- (void) fprintf(fp, "leap indicator: %c%c\n",
+ (void) fprintf(fp, "system peer: %s\n", nntohost(is->peer));
+ (void) fprintf(fp, "system peer mode: %s\n", modetoa(is->peer_mode));
+ (void) fprintf(fp, "leap indicator: %c%c\n",
is->leap & 0x2 ? '1' : '0',
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, "sync distance: %s\n",
+ (void) fprintf(fp, "stratum: %d\n", (int)is->stratum);
+ (void) fprintf(fp, "precision: %d\n", (int)is->precision);
+ (void) fprintf(fp, "root distance: %s s\n",
fptoa(NTOHS_FP(is->rootdelay), 5));
- (void) fprintf(fp, "sync dispersion: %s\n",
+ (void) fprintf(fp, "root dispersion: %s s\n",
ufptoa(NTOHS_FP(is->rootdispersion), 5));
- if (is->stratum <= 1) {
- junk[4] = 0;
- memmove(junk, (char *)&is->refid, 4);
- str = junk;
- } else {
- str = numtoa(is->refid);
- }
- (void) fprintf(fp, "reference ID: [%s]\n", str);
-
- HTONL_FP(&is->reftime, &tempts);
- (void) fprintf(fp, "reference time: %s\n", prettydate(&tempts));
-
- (void) fprintf(fp, "system flags: ");
- if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_MCLIENT |
- INFO_FLAG_AUTHENABLE)) == 0) {
+ (void) fprintf(fp, "reference ID: [%s]\n",
+ refid_string(is->refid, is->stratum));
+ NTOHL_FP(&is->reftime, &tempts);
+ (void) fprintf(fp, "reference time: %s\n", prettydate(&tempts));
+
+ (void) fprintf(fp, "system flags: ");
+ if ((is->flags & (INFO_FLAG_BCLIENT | INFO_FLAG_AUTHENABLE |
+ INFO_FLAG_PLL | INFO_FLAG_PPS | INFO_FLAG_PLL_SYNC |
+ INFO_FLAG_PPS_SYNC | INFO_FLAG_MONITOR | INFO_FLAG_FILEGEN)) == 0) {
(void) fprintf(fp, "none\n");
} else {
- res = 0;
- if (is->flags & INFO_FLAG_BCLIENT) {
- (void) fprintf(fp, "bclient");
- res = 1;
- }
- if (is->flags & INFO_FLAG_MCLIENT) {
- (void) fprintf(fp, "mclient");
- res = 1;
- }
+ if (is->flags & INFO_FLAG_BCLIENT)
+ (void) fprintf(fp, "bclient ");
if (is->flags & INFO_FLAG_AUTHENABLE)
- (void) fprintf(fp, "%sauthenticate",
- res ? ", " : "");
+ (void) fprintf(fp, "auth ");
+ if (is->flags & INFO_FLAG_PLL)
+ (void) fprintf(fp, "pll ");
+ if (is->flags & INFO_FLAG_PPS)
+ (void) fprintf(fp, "pps ");
+ if (is->flags & INFO_FLAG_PLL_SYNC)
+ (void) fprintf(fp, "kernel_sync ");
+ if (is->flags & INFO_FLAG_PPS_SYNC)
+ (void) fprintf(fp, "pps_sync ");
+ if (is->flags & INFO_FLAG_MONITOR)
+ (void) fprintf(fp, "monitor ");
+ if (is->flags & INFO_FLAG_FILEGEN)
+ (void) fprintf(fp, "stats ");
(void) fprintf(fp, "\n");
}
-
- HTONL_FP(&is->bdelay, &tempts);
- (void) fprintf(fp, "broadcast delay: %s\n", lfptoa(&tempts, 7));
-
- HTONL_FP(&is->authdelay, &tempts);
- (void) fprintf(fp, "encryption delay: %s\n", lfptoa(&tempts, 7));
+ (void) fprintf(fp, "frequency: %s ppm\n",
+ fptoa(ntohl(is->frequency), 3));
+ (void) fprintf(fp, "stability: %s ppm\n",
+ ufptoa(ntohl(is->stability), 3));
+ (void) fprintf(fp, "broadcastdelay: %s s\n",
+ fptoa(NTOHS_FP(is->bdelay), 6));
+ NTOHL_FP(&is->authdelay, &tempts);
+ (void) fprintf(fp, "authdelay: %s s\n", lfptoa(&tempts, 6));
}
@@ -832,7 +817,7 @@ sysstats(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_SYS_STATS, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&ss);
+ &items, &itemsize, (char **)&ss, 0);
if (res != 0 && items == 0)
return;
@@ -847,29 +832,29 @@ sysstats(pcmd, fp)
return;
}
- (void) fprintf(fp, "system uptime: %d\n",
- ntohl(ss->timeup));
- (void) fprintf(fp, "time since reset: %d\n",
- ntohl(ss->timereset));
- (void) fprintf(fp, "bad stratum in packet: %d\n",
- ntohl(ss->badstratum));
- (void) fprintf(fp, "old version packets: %d\n",
- ntohl(ss->oldversionpkt));
- (void) fprintf(fp, "new version packets: %d\n",
- ntohl(ss->newversionpkt));
- (void) fprintf(fp, "unknown version number: %d\n",
- ntohl(ss->unknownversion));
- (void) fprintf(fp, "bad packet length: %d\n",
- ntohl(ss->badlength));
- (void) fprintf(fp, "packets processed: %d\n",
- ntohl(ss->processed));
- (void) fprintf(fp, "bad authentication: %d\n",
- ntohl(ss->badauth));
+ (void) fprintf(fp, "system uptime: %ld\n",
+ (u_long)ntohl(ss->timeup));
+ (void) fprintf(fp, "time since reset: %ld\n",
+ (u_long)ntohl(ss->timereset));
+ (void) fprintf(fp, "bad stratum in packet: %ld\n",
+ (u_long)ntohl(ss->badstratum));
+ (void) fprintf(fp, "old version packets: %ld\n",
+ (u_long)ntohl(ss->oldversionpkt));
+ (void) fprintf(fp, "new version packets: %ld\n",
+ (u_long)ntohl(ss->newversionpkt));
+ (void) fprintf(fp, "unknown version number: %ld\n",
+ (u_long)ntohl(ss->unknownversion));
+ (void) fprintf(fp, "bad packet length: %ld\n",
+ (u_long)ntohl(ss->badlength));
+ (void) fprintf(fp, "packets processed: %ld\n",
+ (u_long)ntohl(ss->processed));
+ (void) fprintf(fp, "bad authentication: %ld\n",
+ (u_long)ntohl(ss->badauth));
if (itemsize != sizeof(struct info_sys_stats))
return;
- (void) fprintf(fp, "limitation rejects: %d\n",
- ntohl(ss->limitrejected));
+ (void) fprintf(fp, "limitation rejects: %ld\n",
+ (u_long)ntohl(ss->limitrejected));
}
@@ -889,7 +874,7 @@ iostats(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_IO_STATS, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&io);
+ &items, &itemsize, (char **)&io, 0);
if (res != 0 && items == 0)
return;
@@ -900,34 +885,33 @@ iostats(pcmd, fp)
if (!checkitemsize(itemsize, sizeof(struct info_io_stats)))
return;
- (void) fprintf(fp, "time since reset: %d\n",
- ntohl(io->timereset));
- (void) fprintf(fp, "total receive buffers: %d\n",
- (int)ntohs(io->totalrecvbufs));
- (void) fprintf(fp, "free receive buffers: %d\n",
- (int)ntohs(io->freerecvbufs));
- (void) fprintf(fp, "used receive buffers: %d\n",
- (int)ntohs(io->fullrecvbufs));
- (void) fprintf(fp, "low water refills: %d\n",
- (int)ntohs(io->lowwater));
- (void) fprintf(fp, "dropped packets: %d\n",
- ntohl(io->dropped));
- (void) fprintf(fp, "ignored packets: %d\n",
- ntohl(io->ignored));
- (void) fprintf(fp, "received packets: %d\n",
- ntohl(io->received));
- (void) fprintf(fp, "packets sent: %d\n",
- ntohl(io->sent));
- (void) fprintf(fp, "packets not sent: %d\n",
- ntohl(io->notsent));
- (void) fprintf(fp, "interrupts handled: %d\n",
- ntohl(io->interrupts));
- (void) fprintf(fp, "received by interrupt: %d\n",
- ntohl(io->int_received));
+ (void) fprintf(fp, "time since reset: %ld\n",
+ (u_long)ntohl(io->timereset));
+ (void) fprintf(fp, "receive buffers: %d\n",
+ ntohs(io->totalrecvbufs));
+ (void) fprintf(fp, "free receive buffers: %d\n",
+ ntohs(io->freerecvbufs));
+ (void) fprintf(fp, "used receive buffers: %d\n",
+ ntohs(io->fullrecvbufs));
+ (void) fprintf(fp, "low water refills: %d\n",
+ ntohs(io->lowwater));
+ (void) fprintf(fp, "dropped packets: %ld\n",
+ (u_long)ntohl(io->dropped));
+ (void) fprintf(fp, "ignored packets: %ld\n",
+ (u_long)ntohl(io->ignored));
+ (void) fprintf(fp, "received packets: %ld\n",
+ (u_long)ntohl(io->received));
+ (void) fprintf(fp, "packets sent: %ld\n",
+ (u_long)ntohl(io->sent));
+ (void) fprintf(fp, "packets not sent: %ld\n",
+ (u_long)ntohl(io->notsent));
+ (void) fprintf(fp, "interrupts handled: %ld\n",
+ (u_long)ntohl(io->interrupts));
+ (void) fprintf(fp, "received by int: %ld\n",
+ (u_long)ntohl(io->int_received));
}
-
/*
* memstats - print peer memory statistics
*/
@@ -944,7 +928,7 @@ memstats(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_MEM_STATS, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&mem);
+ &items, &itemsize, (char **)&mem, 0);
if (res != 0 && items == 0)
return;
@@ -955,18 +939,18 @@ memstats(pcmd, fp)
if (!checkitemsize(itemsize, sizeof(struct info_mem_stats)))
return;
- (void) fprintf(fp, "time since reset: %d\n",
- ntohl(mem->timereset));
+ (void) fprintf(fp, "time since reset: %ld\n",
+ (u_long)ntohl(mem->timereset));
(void) fprintf(fp, "total peer memory: %d\n",
- (int)ntohs(mem->totalpeermem));
+ ntohs(mem->totalpeermem));
(void) fprintf(fp, "free peer memory: %d\n",
- (int)ntohs(mem->freepeermem));
- (void) fprintf(fp, "calls to findpeer: %d\n",
- ntohl(mem->findpeer_calls));
- (void) fprintf(fp, "new peer allocations: %d\n",
- ntohl(mem->allocations));
- (void) fprintf(fp, "peer demobilizations: %d\n",
- ntohl(mem->demobilizations));
+ ntohs(mem->freepeermem));
+ (void) fprintf(fp, "calls to findpeer: %ld\n",
+ (u_long)ntohl(mem->findpeer_calls));
+ (void) fprintf(fp, "new peer allocations: %ld\n",
+ (u_long)ntohl(mem->allocations));
+ (void) fprintf(fp, "peer demobilizations: %ld\n",
+ (u_long)ntohl(mem->demobilizations));
(void) fprintf(fp, "hash table counts: ");
for (i = 0; i < HASH_SIZE; i++) {
@@ -995,7 +979,7 @@ timerstats(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_TIMER_STATS, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&tim);
+ &items, &itemsize, (char **)&tim, 0);
if (res != 0 && items == 0)
return;
@@ -1006,14 +990,14 @@ timerstats(pcmd, fp)
if (!checkitemsize(itemsize, sizeof(struct info_timer_stats)))
return;
- (void) fprintf(fp, "time since reset: %d\n",
- ntohl(tim->timereset));
- (void) fprintf(fp, "alarms handled: %d\n",
- ntohl(tim->alarms));
- (void) fprintf(fp, "alarm overruns: %d\n",
- ntohl(tim->overflows));
- (void) fprintf(fp, "calls to transmit: %d\n",
- ntohl(tim->xmtcalls));
+ (void) fprintf(fp, "time since reset: %ld\n",
+ (u_long)ntohl(tim->timereset));
+ (void) fprintf(fp, "alarms handled: %ld\n",
+ (u_long)ntohl(tim->alarms));
+ (void) fprintf(fp, "alarm overruns: %ld\n",
+ (u_long)ntohl(tim->overflows));
+ (void) fprintf(fp, "calls to transmit: %ld\n",
+ (u_long)ntohl(tim->xmtcalls));
}
@@ -1065,7 +1049,7 @@ doconfig(pcmd, fp, mode)
int items;
int itemsize;
char *dummy;
- U_LONG keyid;
+ u_long keyid;
u_int version;
u_int flags;
int res;
@@ -1092,19 +1076,14 @@ doconfig(pcmd, fp, mode)
items = 3;
while (pcmd->nargs > items) {
if (STREQ(pcmd->argval[items].string,
- "minpoll")) {
- flags |= CONF_FLAG_MINPOLL;
- } else {
- if (STREQ(pcmd->argval[items].string,
- "prefer")) {
- flags |= CONF_FLAG_PREFER;
- } else {
- (void) fprintf(fp,
- "`%s' not understood\n",
- pcmd->argval[3].string);
- res++;
+ "prefer"))
+ flags |= CONF_FLAG_PREFER;
+ else {
+ (void) fprintf(fp,
+ "%s not understood\n",
+ pcmd->argval[3].string);
+ res++;
break;
- }
}
items++;
}
@@ -1124,7 +1103,7 @@ doconfig(pcmd, fp, mode)
res = doquery(IMPL_XNTPD, REQ_CONFIG, 1, 1,
sizeof(struct conf_peer), (char *)&cpeer, &items,
- &itemsize, &dummy);
+ &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1154,7 +1133,7 @@ unconfig(pcmd, fp)
res = doquery(IMPL_XNTPD, REQ_UNCONFIG, 1, qitems,
sizeof(struct conf_unpeer), (char *)plist, &items,
- &itemsize, &dummy);
+ &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1206,12 +1185,18 @@ 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 if (STREQ(pcmd->argval[items].string, "pll"))
+ sys.flags |= SYS_FLAG_PLL;
+ else if (STREQ(pcmd->argval[items].string, "pps"))
+ sys.flags |= SYS_FLAG_PPS;
+ else if (STREQ(pcmd->argval[items].string, "monitor"))
+ sys.flags |= SYS_FLAG_MONITOR;
+ else if (STREQ(pcmd->argval[items].string, "stats"))
+ sys.flags |= SYS_FLAG_FILEGEN;
else {
- (void) fprintf(fp, "unknown flag %s\n",
+ (void) fprintf(fp, "Unknown flag %s\n",
pcmd->argval[items].string);
res = 1;
}
@@ -1222,7 +1207,7 @@ doset(pcmd, fp, req)
res = doquery(IMPL_XNTPD, req, 1, 1,
sizeof(struct conf_sys_flags), (char *)&sys, &items,
- &itemsize, &dummy);
+ &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1273,14 +1258,14 @@ reslist(pcmd, fp)
char *addr;
char *mask;
struct resflags *rf;
- U_LONG count;
+ u_long count;
u_short flags;
u_short mflags;
char flagstr[300];
static char *comma = ", ";
res = doquery(IMPL_XNTPD, REQ_GET_RESTRICT, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&rl);
+ &items, &itemsize, (char **)&rl, 0);
if (res != 0 && items == 0)
return;
@@ -1296,7 +1281,10 @@ reslist(pcmd, fp)
(void) fprintf(fp,
"=====================================================================\n");
while (items > 0) {
- addr = numtoa(rl->addr);
+ if ((rl->mask == (U_LONG)0xffffffff))
+ addr = numtohost(rl->addr);
+ else
+ addr = numtoa( rl->addr );
mask = numtoa(rl->mask);
count = ntohl(rl->count);
flags = ntohs(rl->flags);
@@ -1329,7 +1317,7 @@ reslist(pcmd, fp)
if (flagstr[0] == '\0')
(void) strcpy(flagstr, "none");
- (void) fprintf(fp, "%-15.15s %-15.15s %9d %s\n",
+ (void) fprintf(fp, "%-15.15s %-15.15s %9ld %s\n",
addr, mask, count, flagstr);
rl++;
items--;
@@ -1387,8 +1375,8 @@ do_restrict(pcmd, fp, req_code)
int items;
int itemsize;
char *dummy;
- U_LONG num;
- U_LONG bit;
+ u_long num;
+ u_long bit;
int i;
int res;
int err;
@@ -1411,7 +1399,7 @@ do_restrict(pcmd, fp, req_code)
cres.flags |= resflags[i].bit;
if (req_code == REQ_UNRESTRICT) {
(void) fprintf(fp,
- "Flag `%s' inappropriate\n",
+ "Flag %s inappropriate\n",
resflags[i].str);
err++;
}
@@ -1449,7 +1437,7 @@ do_restrict(pcmd, fp, req_code)
res = doquery(IMPL_XNTPD, req_code, 1, 1,
sizeof(struct conf_restrict), (char *)&cres, &items,
- &itemsize, &dummy);
+ &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1466,14 +1454,26 @@ monlist(pcmd, fp)
struct parse *pcmd;
FILE *fp;
{
- struct info_monitor *ml;
- struct old_info_monitor *oml;
+ char *struct_star;
+ struct in_addr addr;
int items;
int itemsize;
int res;
+ int version = -1;
- res = doquery(IMPL_XNTPD, REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&ml);
+ if (pcmd->nargs > 0) {
+ version = pcmd->argval[0].ival;
+ }
+
+ res = doquery(IMPL_XNTPD,
+ (version == 1 || version == -1) ? REQ_MON_GETLIST_1 :
+ REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
+ &items, &itemsize, &struct_star,
+ (version < 0) ? (1 << INFO_ERR_REQ) : 0);
+
+ if (res == INFO_ERR_REQ && version < 0)
+ res = doquery(IMPL_XNTPD, REQ_MON_GETLIST, 0, 0, 0, (char *)NULL,
+ &items, &itemsize, &struct_star, 0);
if (res != 0 && items == 0)
return;
@@ -1481,49 +1481,72 @@ monlist(pcmd, fp)
if (!checkitems(items, fp))
return;
- if (itemsize == sizeof(struct info_monitor)) {
+ if (itemsize == sizeof(struct info_monitor_1)) {
+ struct info_monitor_1 *ml = (struct info_monitor_1 *) struct_star;
(void) fprintf(fp,
- " address port count mode version lastdrop lasttime firsttime\n");
+ "remote address port local address count m ver drop last first\n");
(void) fprintf(fp,
"===============================================================================\n");
while (items > 0) {
- (void) fprintf(fp, "%-20.20s %5d %9d %4d %3d %9u %9u %9u\n",
+ addr.s_addr = ml->daddr;
+ (void) fprintf(fp,
+ "%-22.22s %5d %-15s %8ld %1d %1d %6lu %6lu %7lu\n",
nntohost(ml->addr),
ntohs(ml->port),
- ntohl(ml->count),
+ inet_ntoa(addr),
+ (u_long)ntohl(ml->count),
ml->mode,
ml->version,
- ntohl(ml->lastdrop),
- ntohl(ml->lasttime),
- ntohl(ml->firsttime));
+ (u_long)ntohl(ml->lastdrop),
+ (u_long)ntohl(ml->lasttime),
+ (u_long)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;
- }
+ } else if (itemsize == sizeof(struct info_monitor)) {
+ struct info_monitor *ml = (struct info_monitor *) struct_star;
- oml = (struct old_info_monitor *)ml;
+ (void) fprintf(fp,
+ " address port count mode ver lastdrop lasttime firsttime\n");
+ (void) fprintf(fp,
+ "===============================================================================\n");
+ while (items > 0) {
+ addr.s_addr = ml->lastdrop;
+ (void) fprintf(fp,
+ "%-25.25s %5d %9ld %4d %2d %9lu %9lu %9lu\n",
+ nntohost(ml->addr),
+ ntohs(ml->port),
+ (u_long)ntohl(ml->count),
+ ml->mode,
+ ml->version,
+ (u_long)ntohl(ml->lastdrop),
+ (u_long)ntohl(ml->lasttime),
+ (u_long)ntohl(ml->firsttime));
+ ml++;
+ items--;
+ }
+ } else if (itemsize == sizeof(struct old_info_monitor)) {
+ struct old_info_monitor *oml = (struct old_info_monitor *)struct_star;
(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",
+ (void) fprintf(fp, "%-20.20s %5d %9ld %4d %3d %9lu %9lu\n",
nntohost(oml->addr),
ntohs(oml->port),
- ntohl(oml->count),
+ (u_long)ntohl(oml->count),
oml->mode,
oml->version,
- ntohl(oml->lasttime),
- ntohl(oml->firsttime));
+ (u_long)ntohl(oml->lasttime),
+ (u_long)ntohl(oml->firsttime));
oml++;
items--;
}
+ } else {
+ /* issue warning according to new info_monitor size */
+ checkitemsize(itemsize, sizeof(struct info_monitor));
}
}
@@ -1552,7 +1575,7 @@ monitor(pcmd, fp)
}
res = doquery(IMPL_XNTPD, req_code, 1, 0, 0, (char *)0,
- &items, &itemsize, &dummy);
+ &items, &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1601,7 +1624,7 @@ reset(pcmd, fp)
break;
}
if (sreset[i].flag == 0) {
- (void) fprintf(fp, "Flag `%s' unknown\n",
+ (void) fprintf(fp, "Flag %s unknown\n",
pcmd->argval[res].string);
err++;
} else {
@@ -1616,7 +1639,7 @@ reset(pcmd, fp)
res = doquery(IMPL_XNTPD, REQ_RESET_STATS, 1, 1,
sizeof(struct reset_flags), (char *)&rflags, &items,
- &itemsize, &dummy);
+ &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1647,7 +1670,7 @@ preset(pcmd, fp)
res = doquery(IMPL_XNTPD, REQ_RESET_PEER, 1, qitems,
sizeof(struct conf_unpeer), (char *)plist, &items,
- &itemsize, &dummy);
+ &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1669,53 +1692,7 @@ readkeys(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_REREAD_KEYS, 1, 0, 0, (char *)0,
- &items, &itemsize, &dummy);
-
- if (res == 0)
- (void) fprintf(fp, "done!\n");
- return;
-}
-
-
-/*
- * dodirty - request the server to do something dirty
- */
-/*ARGSUSED*/
-static void
-dodirty(pcmd, fp)
- struct parse *pcmd;
- FILE *fp;
-{
- int items;
- int itemsize;
- char *dummy;
- int res;
-
- res = doquery(IMPL_XNTPD, REQ_DO_DIRTY_HACK, 1, 0, 0, (char *)0,
- &items, &itemsize, &dummy);
-
- if (res == 0)
- (void) fprintf(fp, "done!\n");
- return;
-}
-
-
-/*
- * dontdirty - request the server to not do something dirty
- */
-/*ARGSUSED*/
-static void
-dontdirty(pcmd, fp)
- struct parse *pcmd;
- FILE *fp;
-{
- int items;
- int itemsize;
- char *dummy;
- int res;
-
- res = doquery(IMPL_XNTPD, REQ_DONT_DIRTY_HACK, 1, 0, 0, (char *)0,
- &items, &itemsize, &dummy);
+ &items, &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1756,7 +1733,7 @@ do_trustkey(pcmd, fp, req)
FILE *fp;
int req;
{
- U_LONG keyids[MAXARGS];
+ u_long keyids[MAXARGS];
int i;
int items;
int itemsize;
@@ -1769,8 +1746,8 @@ do_trustkey(pcmd, fp, req)
keyids[ritems++] = pcmd->argval[i].uval;
}
- res = doquery(IMPL_XNTPD, req, 1, ritems, sizeof(U_LONG),
- (char *)keyids, &items, &itemsize, &dummy);
+ res = doquery(IMPL_XNTPD, req, 1, ritems, sizeof(u_long),
+ (char *)keyids, &items, &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1794,7 +1771,7 @@ authinfo(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_AUTHINFO, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&ia);
+ &items, &itemsize, (char **)&ia, 0);
if (res != 0 && items == 0)
return;
@@ -1805,20 +1782,18 @@ authinfo(pcmd, fp)
if (!checkitemsize(itemsize, sizeof(struct info_auth)))
return;
- (void) fprintf(fp, "time since reset: %d\n",
- ntohl(ia->timereset));
- (void) fprintf(fp, "key lookups: %d\n",
- ntohl(ia->keylookups));
- (void) fprintf(fp, "keys not found: %d\n",
- ntohl(ia->keynotfound));
- (void) fprintf(fp, "encryptions: %d\n",
- ntohl(ia->encryptions));
- (void) fprintf(fp, "decryptions: %d\n",
- ntohl(ia->decryptions));
- (void) fprintf(fp, "successful decryptions: %d\n",
- ntohl(ia->decryptions));
- (void) fprintf(fp, "uncached keys: %d\n",
- ntohl(ia->keyuncached));
+ (void) fprintf(fp, "time since reset: %ld\n",
+ (u_long)ntohl(ia->timereset));
+ (void) fprintf(fp, "key lookups: %ld\n",
+ (u_long)ntohl(ia->keylookups));
+ (void) fprintf(fp, "keys not found: %ld\n",
+ (u_long)ntohl(ia->keynotfound));
+ (void) fprintf(fp, "uncached keys: %ld\n",
+ (u_long)ntohl(ia->keyuncached));
+ (void) fprintf(fp, "encryptions: %ld\n",
+ (u_long)ntohl(ia->encryptions));
+ (void) fprintf(fp, "decryptions: %ld\n",
+ (u_long)ntohl(ia->decryptions));
}
@@ -1839,7 +1814,7 @@ traps(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_TRAPS, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&it);
+ &items, &itemsize, (char **)&it, 0);
if (res != 0 && items == 0)
return;
@@ -1865,10 +1840,10 @@ traps(pcmd, fp)
else
(void) fprintf(fp, "normal priority\n");
- (void) fprintf(fp, "set for %d secs, last set %d secs ago\n",
- it->origtime, it->settime);
- (void) fprintf(fp, "sequence %d, number of resets %d\n",
- it->sequence, it->resets);
+ (void) fprintf(fp, "set for %ld secs, last set %ld secs ago\n",
+ (long)it->origtime, (long)it->settime);
+ (void) fprintf(fp, "sequence %d, number of resets %ld\n",
+ it->sequence, (long)it->resets);
}
}
@@ -1925,7 +1900,7 @@ do_addclr_trap(pcmd, fp, req)
}
res = doquery(IMPL_XNTPD, req, 1, 1, sizeof(struct conf_trap),
- (char *)&ctrap, &items, &itemsize, &dummy);
+ (char *)&ctrap, &items, &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -1968,7 +1943,7 @@ do_changekey(pcmd, fp, req)
FILE *fp;
int req;
{
- U_LONG key;
+ u_long key;
int items;
int itemsize;
char *dummy;
@@ -1977,8 +1952,8 @@ do_changekey(pcmd, fp, req)
key = htonl(pcmd->argval[0].uval);
- res = doquery(IMPL_XNTPD, req, 1, 1, sizeof(U_LONG),
- (char *)&key, &items, &itemsize, &dummy);
+ res = doquery(IMPL_XNTPD, req, 1, 1, sizeof(u_long),
+ (char *)&key, &items, &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -2002,7 +1977,7 @@ ctlstats(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_GET_CTLSTATS, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&ic);
+ &items, &itemsize, (char **)&ic, 0);
if (res != 0 && items == 0)
return;
@@ -2013,36 +1988,36 @@ ctlstats(pcmd, fp)
if (!checkitemsize(itemsize, sizeof(struct info_control)))
return;
- (void) fprintf(fp, "time since reset: %d\n",
- ntohl(ic->ctltimereset));
- (void) fprintf(fp, "requests received: %d\n",
- ntohl(ic->numctlreq));
- (void) fprintf(fp, "responses sent: %d\n",
- ntohl(ic->numctlresponses));
- (void) fprintf(fp, "fragments sent: %d\n",
- ntohl(ic->numctlfrags));
- (void) fprintf(fp, "async messages sent: %d\n",
- ntohl(ic->numasyncmsgs));
- (void) fprintf(fp, "error msgs sent: %d\n",
- ntohl(ic->numctlerrors));
- (void) fprintf(fp, "total bad pkts: %d\n",
- ntohl(ic->numctlbadpkts));
- (void) fprintf(fp, "packet too short: %d\n",
- ntohl(ic->numctltooshort));
- (void) fprintf(fp, "response on input: %d\n",
- ntohl(ic->numctlinputresp));
- (void) fprintf(fp, "fragment on input: %d\n",
- ntohl(ic->numctlinputfrag));
- (void) fprintf(fp, "error set on input: %d\n",
- ntohl(ic->numctlinputerr));
- (void) fprintf(fp, "bad offset on input: %d\n",
- ntohl(ic->numctlbadoffset));
- (void) fprintf(fp, "bad version packets: %d\n",
- ntohl(ic->numctlbadversion));
- (void) fprintf(fp, "data in pkt too short: %d\n",
- ntohl(ic->numctldatatooshort));
- (void) fprintf(fp, "unknown op codes: %d\n",
- ntohl(ic->numctlbadop));
+ (void) fprintf(fp, "time since reset: %ld\n",
+ (u_long)ntohl(ic->ctltimereset));
+ (void) fprintf(fp, "requests received: %ld\n",
+ (u_long)ntohl(ic->numctlreq));
+ (void) fprintf(fp, "responses sent: %ld\n",
+ (u_long)ntohl(ic->numctlresponses));
+ (void) fprintf(fp, "fragments sent: %ld\n",
+ (u_long)ntohl(ic->numctlfrags));
+ (void) fprintf(fp, "async messages sent: %ld\n",
+ (u_long)ntohl(ic->numasyncmsgs));
+ (void) fprintf(fp, "error msgs sent: %ld\n",
+ (u_long)ntohl(ic->numctlerrors));
+ (void) fprintf(fp, "total bad pkts: %ld\n",
+ (u_long)ntohl(ic->numctlbadpkts));
+ (void) fprintf(fp, "packet too short: %ld\n",
+ (u_long)ntohl(ic->numctltooshort));
+ (void) fprintf(fp, "response on input: %ld\n",
+ (u_long)ntohl(ic->numctlinputresp));
+ (void) fprintf(fp, "fragment on input: %ld\n",
+ (u_long)ntohl(ic->numctlinputfrag));
+ (void) fprintf(fp, "error set on input: %ld\n",
+ (u_long)ntohl(ic->numctlinputerr));
+ (void) fprintf(fp, "bad offset on input: %ld\n",
+ (u_long)ntohl(ic->numctlbadoffset));
+ (void) fprintf(fp, "bad version packets: %ld\n",
+ (u_long)ntohl(ic->numctlbadversion));
+ (void) fprintf(fp, "data in pkt too short: %ld\n",
+ (u_long)ntohl(ic->numctldatatooshort));
+ (void) fprintf(fp, "unknown op codes: %ld\n",
+ (u_long)ntohl(ic->numctlbadop));
}
@@ -2080,7 +2055,7 @@ leapinfo(pcmd, fp)
l_fp ts;
res = doquery(IMPL_XNTPD, REQ_GET_LEAPINFO, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&il);
+ &items, &itemsize, (char **)&il, 0);
if (res != 0 && items == 0)
return;
@@ -2103,23 +2078,23 @@ leapinfo(pcmd, fp)
(void) fprintf(fp, "Leap overide option in effect\n");
if (il->leap_bits & INFO_LEAP_SEENSTRATUM1)
(void) fprintf(fp, "Stratum 1 restrictions in effect\n");
- (void) fprintf(fp, "time to next leap interrupt: %d seconds\n",
- ntohl(il->leap_timer));
+ (void) fprintf(fp, "time to next leap interrupt: %ld s\n",
+ (u_long)ntohl(il->leap_timer));
gettstamp(&ts);
(void) fprintf(fp, "date of next leap interrupt: %s\n",
humandate(ts.l_ui + ntohl(il->leap_timer)));
- (void) fprintf(fp, "calls to leap process: %u\n",
- ntohl(il->leap_processcalls));
- (void) fprintf(fp, "leap more than month away: %u\n",
- ntohl(il->leap_notclose));
- (void) fprintf(fp, "leap less than month away: %u\n",
- ntohl(il->leap_monthofleap));
- (void) fprintf(fp, "leap less than day away: %u\n",
- ntohl(il->leap_dayofleap));
- (void) fprintf(fp, "leap in less than 2 hours: %u\n",
- ntohl(il->leap_hoursfromleap));
- (void) fprintf(fp, "leap happened: %u\n",
- ntohl(il->leap_happened));
+ (void) fprintf(fp, "calls to leap process: %lu\n",
+ (u_long)ntohl(il->leap_processcalls));
+ (void) fprintf(fp, "leap more than month away: %lu\n",
+ (u_long)ntohl(il->leap_notclose));
+ (void) fprintf(fp, "leap less than month away: %lu\n",
+ (u_long)ntohl(il->leap_monthofleap));
+ (void) fprintf(fp, "leap less than day away: %lu\n",
+ (u_long)ntohl(il->leap_dayofleap));
+ (void) fprintf(fp, "leap in less than 2 hours: %lu\n",
+ (u_long)ntohl(il->leap_hoursfromleap));
+ (void) fprintf(fp, "leap happened: %lu\n",
+ (u_long)ntohl(il->leap_happened));
}
@@ -2134,20 +2109,21 @@ clockstat(pcmd, fp)
extern struct clktype clktypes[];
struct info_clock *cl;
/* 8 is the maximum number of clocks which will fit in a packet */
- U_LONG clist[min(MAXARGS, 8)];
+ u_long clist[min(MAXARGS, 8)];
int qitems;
int items;
int itemsize;
int res;
l_fp ts;
struct clktype *clk;
+ u_long ltemp;
for (qitems = 0; qitems < min(pcmd->nargs, 8); qitems++)
clist[qitems] = pcmd->argval[qitems].netnum;
res = doquery(IMPL_XNTPD, REQ_GET_CLOCKINFO, 0, qitems,
sizeof(U_LONG), (char *)clist, &items,
- &itemsize, (char **)&cl);
+ &itemsize, (char **)&cl, 0);
if (res != 0 && items == 0)
return;
@@ -2165,35 +2141,36 @@ clockstat(pcmd, fp)
if (clk->code == cl->type)
break;
if (clk->code >= 0)
- (void) fprintf(fp, "clock type: %s\n",
+ (void) fprintf(fp, "clock type: %s\n",
clk->clocktype);
else
- (void) fprintf(fp, "clock type: unknown type (%d)\n",
+ (void) fprintf(fp, "clock type: unknown type (%d)\n",
cl->type);
(void) fprintf(fp, "last event: %d\n",
cl->lastevent);
(void) fprintf(fp, "current status: %d\n",
cl->currentstatus);
- (void) fprintf(fp, "number of polls: %u\n",
- ntohl(cl->polls));
- (void) fprintf(fp, "no response to poll: %u\n",
- ntohl(cl->noresponse));
- (void) fprintf(fp, "bad format responses: %u\n",
- ntohl(cl->badformat));
- (void) fprintf(fp, "bad data responses: %u\n",
- ntohl(cl->baddata));
- (void) fprintf(fp, "running time: %u\n",
- ntohl(cl->timestarted));
+ (void) fprintf(fp, "number of polls: %lu\n",
+ (u_long)ntohl(cl->polls));
+ (void) fprintf(fp, "no response to poll: %lu\n",
+ (u_long)ntohl(cl->noresponse));
+ (void) fprintf(fp, "bad format responses: %lu\n",
+ (u_long)ntohl(cl->badformat));
+ (void) fprintf(fp, "bad data responses: %lu\n",
+ (u_long)ntohl(cl->baddata));
+ (void) fprintf(fp, "running time: %lu\n",
+ (u_long)ntohl(cl->timestarted));
NTOHL_FP(&cl->fudgetime1, &ts);
(void) fprintf(fp, "fudge time 1: %s\n",
- lfptoa(&ts, 7));
+ lfptoa(&ts, 6));
NTOHL_FP(&cl->fudgetime2, &ts);
(void) fprintf(fp, "fudge time 2: %s\n",
- lfptoa(&ts, 7));
- (void) fprintf(fp, "fudge value 1: %ld\n",
- ntohl(cl->fudgeval1));
- (void) fprintf(fp, "fudge value 2: %ld\n",
- ntohl(cl->fudgeval2));
+ lfptoa(&ts, 6));
+ (void) fprintf(fp, "stratum: %ld\n",
+ (u_long)ntohl(cl->fudgeval1));
+ ltemp = ntohl(cl->fudgeval2);
+ (void) fprintf(fp, "reference ID: %s\n",
+ (char *)&ltemp);
(void) fprintf(fp, "fudge flags: 0x%x\n",
cl->flags);
@@ -2218,7 +2195,7 @@ fudge(pcmd, fp)
char *dummy;
l_fp ts;
int res;
- LONG val;
+ long val;
int err;
@@ -2231,13 +2208,13 @@ fudge(pcmd, fp)
if (!atolfp(pcmd->argval[2].string, &ts))
err = 1;
else
- HTONL_FP(&ts, &fudgedata.fudgetime);
+ NTOHL_FP(&ts, &fudgedata.fudgetime);
} else if (STREQ(pcmd->argval[1].string, "time2")) {
fudgedata.which = htonl(FUDGE_TIME2);
if (!atolfp(pcmd->argval[2].string, &ts))
err = 1;
else
- HTONL_FP(&ts, &fudgedata.fudgetime);
+ NTOHL_FP(&ts, &fudgedata.fudgetime);
} else if (STREQ(pcmd->argval[1].string, "val1")) {
fudgedata.which = htonl(FUDGE_VAL1);
if (!atoint(pcmd->argval[2].string, &val))
@@ -2257,13 +2234,13 @@ fudge(pcmd, fp)
else
fudgedata.fudgeval_flags = htonl(val & 0xf);
} else {
- (void) fprintf(stderr, "What fudge is `%s'?\n",
+ (void) fprintf(stderr, "What fudge is %s?\n",
pcmd->argval[1].string);
return;
}
if (err) {
- (void) fprintf(stderr, "Can't decode the value `%s'\n",
+ (void) fprintf(stderr, "Unknown fudge parameter %s\n",
pcmd->argval[2].string);
return;
}
@@ -2271,7 +2248,7 @@ fudge(pcmd, fp)
res = doquery(IMPL_XNTPD, REQ_SET_CLKFUDGE, 1, 1,
sizeof(struct conf_fudge), (char *)&fudgedata, &items,
- &itemsize, &dummy);
+ &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -2288,10 +2265,11 @@ clkbug(pcmd, fp)
{
register int i;
register int n;
- register U_LONG s;
+ register u_long s;
struct info_clkbug *cl;
/* 8 is the maximum number of clocks which will fit in a packet */
- U_LONG clist[min(MAXARGS, 8)];
+ u_long clist[min(MAXARGS, 8)];
+ u_long ltemp;
int qitems;
int items;
int itemsize;
@@ -2303,7 +2281,7 @@ clkbug(pcmd, fp)
res = doquery(IMPL_XNTPD, REQ_GET_CLKBUGINFO, 0, qitems,
sizeof(U_LONG), (char *)clist, &items,
- &itemsize, (char **)&cl);
+ &itemsize, (char **)&cl, 0);
if (res != 0 && items == 0)
return;
@@ -2319,19 +2297,18 @@ clkbug(pcmd, fp)
numtoa(cl->clockadr));
n = (int)cl->nvalues;
(void) fprintf(fp, "values: %d", n);
- s = (U_LONG)ntohs(cl->svalues);
+ s = ntohs(cl->svalues);
if (n > NUMCBUGVALUES)
n = NUMCBUGVALUES;
for (i = 0; i < n; i++) {
+ ltemp = (u_long)ntohl(cl->values[i]);
+ ltemp &= 0xffffffff;
if ((i & 0x3) == 0)
(void) fprintf(fp, "\n");
- if (s & (1<<i)) {
- (void) fprintf(fp, "%12ld",
- (LONG)ntohl(cl->values[i]));
- } else {
- (void) fprintf(fp, "%12lu",
- ntohl(cl->values[i]));
- }
+ if (s & (1 << i))
+ (void) fprintf(fp, "%12ld", ltemp);
+ else
+ (void) fprintf(fp, "%12lu", ltemp);
}
(void) fprintf(fp, "\n");
@@ -2348,8 +2325,8 @@ clkbug(pcmd, fp)
for (;needsp > 0; needsp--)
putc(' ', fp);
}
- HTONL_FP(&cl->times[i], &ts);
- if (s & (1<<i)) {
+ NTOHL_FP(&cl->times[i], &ts);
+ if (s & (1 << i)) {
(void) fprintf(fp, "%17s",
lfptoa(&ts, 6));
needsp = 22;
@@ -2376,7 +2353,7 @@ setprecision(pcmd, fp)
struct parse *pcmd;
FILE *fp;
{
- LONG precision;
+ long precision;
int items;
int itemsize;
char *dummy;
@@ -2384,8 +2361,8 @@ setprecision(pcmd, fp)
precision = htonl(pcmd->argval[0].ival);
- res = doquery(IMPL_XNTPD, REQ_SET_PRECISION, 1, 1, sizeof(LONG),
- (char *)&precision, &items, &itemsize, &dummy);
+ res = doquery(IMPL_XNTPD, REQ_SET_PRECISION, 1, 1, sizeof(long),
+ (char *)&precision, &items, &itemsize, &dummy, 0);
if (res == 0)
(void) fprintf(fp, "done!\n");
@@ -2407,7 +2384,7 @@ kerninfo(pcmd, fp)
int res;
res = doquery(IMPL_XNTPD, REQ_GET_KERNEL, 0, 0, 0, (char *)NULL,
- &items, &itemsize, (char **)&ik);
+ &items, &itemsize, (char **)&ik, 0);
if (res != 0 && items == 0)
return;
if (!check1item(items, fp))
@@ -2418,20 +2395,20 @@ kerninfo(pcmd, fp)
/*
* pll variables
*/
- (void)fprintf(fp, "pll offset: %d us\n",
- ntohl(ik->offset));
+ (void)fprintf(fp, "pll offset: %ld us\n",
+ (u_long)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, "maximum error: %ld us\n",
+ (u_long)ntohl(ik->maxerror));
+ (void)fprintf(fp, "estimated error: %ld us\n",
+ (u_long)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, "pll time constant: %ld\n",
+ (u_long)ntohl(ik->constant));
+ (void)fprintf(fp, "precision: %ld us\n",
+ (u_long)ntohl(ik->precision));
(void)fprintf(fp, "frequency tolerance: %s ppm\n",
fptoa((s_fp)ntohl(ik->tolerance), 0));
@@ -2449,16 +2426,16 @@ kerninfo(pcmd, fp)
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, "pps jitter: %ld us\n",
+ (u_long)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));
+ (void)fprintf(fp, "calibration cycles: %ld\n",
+ (u_long)ntohl(ik->calcnt));
+ (void)fprintf(fp, "jitter exceeded: %ld\n",
+ (u_long)ntohl(ik->jitcnt));
+ (void)fprintf(fp, "stability exceeded: %ld\n",
+ (u_long)ntohl(ik->stbcnt));
+ (void)fprintf(fp, "calibration errors: %ld\n",
+ (u_long)ntohl(ik->errcnt));
}