summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd
diff options
context:
space:
mode:
authorroberto <roberto@FreeBSD.org>2008-08-17 17:37:33 +0000
committerroberto <roberto@FreeBSD.org>2008-08-17 17:37:33 +0000
commit4ded1c1fa0bc21c61f91a2dbe864835986745121 (patch)
tree16d100fbc9dae63888d48b464e471ba0e5065193 /contrib/ntp/ntpd
parent8b5a86d4fda08a9c68231415812edcb26be52f79 (diff)
downloadFreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.zip
FreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.tar.gz
Flatten the dist and various 4.n.n trees in preparation of future ntp imports.
Diffstat (limited to 'contrib/ntp/ntpd')
-rw-r--r--contrib/ntp/ntpd/Makefile.am60
-rw-r--r--contrib/ntp/ntpd/Makefile.in960
-rw-r--r--contrib/ntp/ntpd/check_y2k.c627
-rw-r--r--contrib/ntp/ntpd/cmd_args.c418
-rw-r--r--contrib/ntp/ntpd/jupiter.h255
-rw-r--r--contrib/ntp/ntpd/map_vme.c135
-rw-r--r--contrib/ntp/ntpd/ntp_config.c2371
-rw-r--r--contrib/ntp/ntpd/ntp_control.c2928
-rw-r--r--contrib/ntp/ntpd/ntp_crypto.c4031
-rw-r--r--contrib/ntp/ntpd/ntp_filegen.c547
-rw-r--r--contrib/ntp/ntpd/ntp_intres.c1065
-rw-r--r--contrib/ntp/ntpd/ntp_io.c2257
-rw-r--r--contrib/ntp/ntpd/ntp_loopfilter.c1000
-rw-r--r--contrib/ntp/ntpd/ntp_monitor.c335
-rw-r--r--contrib/ntp/ntpd/ntp_peer.c880
-rw-r--r--contrib/ntp/ntpd/ntp_proto.c3208
-rw-r--r--contrib/ntp/ntpd/ntp_refclock.c1129
-rw-r--r--contrib/ntp/ntpd/ntp_request.c2756
-rw-r--r--contrib/ntp/ntpd/ntp_restrict.c586
-rw-r--r--contrib/ntp/ntpd/ntp_timer.c377
-rw-r--r--contrib/ntp/ntpd/ntp_util.c797
-rw-r--r--contrib/ntp/ntpd/ntpd.c1274
-rw-r--r--contrib/ntp/ntpd/ntpsim.c368
-rw-r--r--contrib/ntp/ntpd/refclock_acts.c984
-rw-r--r--contrib/ntp/ntpd/refclock_arbiter.c429
-rw-r--r--contrib/ntp/ntpd/refclock_arc.c1529
-rw-r--r--contrib/ntp/ntpd/refclock_as2201.c388
-rw-r--r--contrib/ntp/ntpd/refclock_atom.c504
-rw-r--r--contrib/ntp/ntpd/refclock_bancomm.c433
-rw-r--r--contrib/ntp/ntpd/refclock_chronolog.c341
-rw-r--r--contrib/ntp/ntpd/refclock_chu.c1687
-rw-r--r--contrib/ntp/ntpd/refclock_conf.c331
-rw-r--r--contrib/ntp/ntpd/refclock_datum.c869
-rw-r--r--contrib/ntp/ntpd/refclock_dumbclock.c385
-rw-r--r--contrib/ntp/ntpd/refclock_fg.c348
-rw-r--r--contrib/ntp/ntpd/refclock_gpsvme.c622
-rw-r--r--contrib/ntp/ntpd/refclock_heath.c421
-rw-r--r--contrib/ntp/ntpd/refclock_hopfpci.c273
-rw-r--r--contrib/ntp/ntpd/refclock_hopfser.c378
-rw-r--r--contrib/ntp/ntpd/refclock_hpgps.c604
-rw-r--r--contrib/ntp/ntpd/refclock_irig.c1049
-rw-r--r--contrib/ntp/ntpd/refclock_jjy.c710
-rw-r--r--contrib/ntp/ntpd/refclock_jupiter.c1140
-rw-r--r--contrib/ntp/ntpd/refclock_leitch.c620
-rw-r--r--contrib/ntp/ntpd/refclock_local.c264
-rw-r--r--contrib/ntp/ntpd/refclock_msfees.c1455
-rw-r--r--contrib/ntp/ntpd/refclock_mx4200.c1654
-rw-r--r--contrib/ntp/ntpd/refclock_neoclock4x.c1068
-rw-r--r--contrib/ntp/ntpd/refclock_nmea.c723
-rw-r--r--contrib/ntp/ntpd/refclock_oncore.c3723
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.c954
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.h168
-rw-r--r--contrib/ntp/ntpd/refclock_parse.c5386
-rw-r--r--contrib/ntp/ntpd/refclock_pcf.c224
-rw-r--r--contrib/ntp/ntpd/refclock_pst.c321
-rw-r--r--contrib/ntp/ntpd/refclock_ptbacts.c16
-rw-r--r--contrib/ntp/ntpd/refclock_ripencc.c4870
-rw-r--r--contrib/ntp/ntpd/refclock_shm.c305
-rw-r--r--contrib/ntp/ntpd/refclock_tpro.c216
-rw-r--r--contrib/ntp/ntpd/refclock_trak.c359
-rw-r--r--contrib/ntp/ntpd/refclock_true.c873
-rw-r--r--contrib/ntp/ntpd/refclock_tt560.c274
-rw-r--r--contrib/ntp/ntpd/refclock_ulink.c497
-rw-r--r--contrib/ntp/ntpd/refclock_usno.c674
-rw-r--r--contrib/ntp/ntpd/refclock_wwv.c2859
-rw-r--r--contrib/ntp/ntpd/refclock_wwvb.c441
-rw-r--r--contrib/ntp/ntpd/refclock_zyfer.c346
67 files changed, 0 insertions, 70079 deletions
diff --git a/contrib/ntp/ntpd/Makefile.am b/contrib/ntp/ntpd/Makefile.am
deleted file mode 100644
index 0fa4e21..0000000
--- a/contrib/ntp/ntpd/Makefile.am
+++ /dev/null
@@ -1,60 +0,0 @@
-#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
-AUTOMAKE_OPTIONS = ../util/ansi2knr
-bin_PROGRAMS = ntpd @MAKE_NTPDSIM@
-noinst_LIBRARIES = libntpd.a
-INCLUDES = -I$(top_srcdir)/include -I../include
-# LDADD might need RESLIB and ADJLIB.
-# If LIBPARSE, we need libntpd.a 2wagain afterwards...
-LDADD = version.o libntpd.a @LIBPARSE@ libntpd.a
-# ntpd may need:
-# log10 refclock_wwv.o
-# sqrt ntp_control.o
-# floor refclock_wwv.o
-# which are (usually) provided by -lm.
-ntpd_LDADD = $(LDADD) ../libntp/libntp.a -lm @LCRYPTO@
-ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@
-ntpdsim_CFLAGS = $(CFLAGS) -DSIM
-check_y2k_LDADD = $(LDADD) ../libntp/libntp.a
-DISTCLEANFILES = .version version.c
-#EXTRA_DIST = ntpd.mak
-ETAGS_ARGS = Makefile.am
-### Y2Kfixes
-check_PROGRAMS = @MAKE_CHECK_Y2K@
-EXTRA_PROGRAMS = check_y2k ntpdsim
-
-check-local: @MAKE_CHECK_Y2K@
- test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
-
-# SIM: cmd_args.c ntp_config.c ntp_io.c ntpd.c + ntpsim.c (include/ntpsim.h)
-# ntp_resolver.c is presently unused...
-ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c
-ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c
-libntpd_a_SOURCES = jupiter.h map_vme.c ntp_control.c \
- ntp_crypto.c ntp_filegen.c \
- ntp_intres.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_util.c \
- refclock_acts.c refclock_arbiter.c refclock_arc.c refclock_as2201.c \
- refclock_atom.c refclock_bancomm.c refclock_chronolog.c \
- refclock_chu.c refclock_conf.c refclock_datum.c refclock_dumbclock.c \
- refclock_fg.c refclock_gpsvme.c refclock_heath.c refclock_hopfser.c \
- refclock_hopfpci.c refclock_hpgps.c refclock_irig.c refclock_jjy.c \
- refclock_jupiter.c refclock_leitch.c refclock_local.c \
- refclock_msfees.c refclock_mx4200.c refclock_nmea.c refclock_oncore.c \
- refclock_palisade.c refclock_palisade.h refclock_parse.c \
- refclock_pcf.c refclock_pst.c refclock_ptbacts.c refclock_shm.c \
- refclock_tpro.c refclock_trak.c refclock_true.c refclock_tt560.c \
- refclock_ulink.c refclock_usno.c refclock_wwv.c refclock_wwvb.c \
- refclock_zyfer.c refclock_ripencc.c refclock_neoclock4x.c
-
-$(PROGRAMS): $(LDADD)
-
-../libntp/libntp.a:
- cd ../libntp && $(MAKE)
-
-../libparse/libparse.a:
- cd ../libparse && $(MAKE)
-
-version.o: $(ntpd_OBJECTS) ../libntp/libntp.a @LIBPARSE@ Makefile $(top_srcdir)/version
- env CSET=`cat $(top_srcdir)/version` $(top_builddir)/scripts/mkver ntpd
- $(COMPILE) -c version.c
diff --git a/contrib/ntp/ntpd/Makefile.in b/contrib/ntp/ntpd/Makefile.in
deleted file mode 100644
index eef0774..0000000
--- a/contrib/ntp/ntpd/Makefile.in
+++ /dev/null
@@ -1,960 +0,0 @@
-# Makefile.in generated by automake 1.7.7 from Makefile.am.
-# @configure_input@
-
-# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-# Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-top_builddir = ..
-
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-INSTALL = @INSTALL@
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-target_triplet = @target@
-ACLOCAL = @ACLOCAL@
-AMDEP_FALSE = @AMDEP_FALSE@
-AMDEP_TRUE = @AMDEP_TRUE@
-AMTAR = @AMTAR@
-ARLIB_DIR = @ARLIB_DIR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CHUTEST = @CHUTEST@
-CLKTEST = @CLKTEST@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DCFD = @DCFD@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EF_LIBS = @EF_LIBS@
-EF_PROGS = @EF_PROGS@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LCRYPTO = @LCRYPTO@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBPARSE = @LIBPARSE@
-LIBS = @LIBS@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MAKE_ADJTIMED = @MAKE_ADJTIMED@
-MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@
-MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@
-MAKE_LIBPARSE = @MAKE_LIBPARSE@
-MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
-MAKE_NTPDSIM = @MAKE_NTPDSIM@
-MAKE_NTPTIME = @MAKE_NTPTIME@
-MAKE_NTP_KEYGEN = @MAKE_NTP_KEYGEN@
-MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
-MAKE_SNTP = @MAKE_SNTP@
-MAKE_TICKADJ = @MAKE_TICKADJ@
-MAKE_TIMETRIM = @MAKE_TIMETRIM@
-OBJEXT = @OBJEXT@
-OPENSSL = @OPENSSL@
-OPENSSL_INC = @OPENSSL_INC@
-OPENSSL_LIB = @OPENSSL_LIB@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_PERL = @PATH_PERL@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PATH_SH = @PATH_SH@
-PROPDELAY = @PROPDELAY@
-RANLIB = @RANLIB@
-READLINE_LIBS = @READLINE_LIBS@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-TESTDCF = @TESTDCF@
-U = @U@
-VERSION = @VERSION@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_RANLIB = @ac_ct_RANLIB@
-ac_ct_STRIP = @ac_ct_STRIP@
-am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
-am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-datadir = @datadir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-oldincludedir = @oldincludedir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-subdirs = @subdirs@
-sysconfdir = @sysconfdir@
-target = @target@
-target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
-
-#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
-AUTOMAKE_OPTIONS = ../util/ansi2knr
-bin_PROGRAMS = ntpd @MAKE_NTPDSIM@
-noinst_LIBRARIES = libntpd.a
-INCLUDES = -I$(top_srcdir)/include -I../include
-# LDADD might need RESLIB and ADJLIB.
-# If LIBPARSE, we need libntpd.a 2wagain afterwards...
-LDADD = version.o libntpd.a @LIBPARSE@ libntpd.a
-# ntpd may need:
-# log10 refclock_wwv.o
-# sqrt ntp_control.o
-# floor refclock_wwv.o
-# which are (usually) provided by -lm.
-ntpd_LDADD = $(LDADD) ../libntp/libntp.a -lm @LCRYPTO@
-ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@
-ntpdsim_CFLAGS = $(CFLAGS) -DSIM
-check_y2k_LDADD = $(LDADD) ../libntp/libntp.a
-DISTCLEANFILES = .version version.c
-#EXTRA_DIST = ntpd.mak
-ETAGS_ARGS = Makefile.am
-### Y2Kfixes
-check_PROGRAMS = @MAKE_CHECK_Y2K@
-EXTRA_PROGRAMS = check_y2k ntpdsim
-
-# SIM: cmd_args.c ntp_config.c ntp_io.c ntpd.c + ntpsim.c (include/ntpsim.h)
-# ntp_resolver.c is presently unused...
-ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c
-ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c
-libntpd_a_SOURCES = jupiter.h map_vme.c ntp_control.c \
- ntp_crypto.c ntp_filegen.c \
- ntp_intres.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_util.c \
- refclock_acts.c refclock_arbiter.c refclock_arc.c refclock_as2201.c \
- refclock_atom.c refclock_bancomm.c refclock_chronolog.c \
- refclock_chu.c refclock_conf.c refclock_datum.c refclock_dumbclock.c \
- refclock_fg.c refclock_gpsvme.c refclock_heath.c refclock_hopfser.c \
- refclock_hopfpci.c refclock_hpgps.c refclock_irig.c refclock_jjy.c \
- refclock_jupiter.c refclock_leitch.c refclock_local.c \
- refclock_msfees.c refclock_mx4200.c refclock_nmea.c refclock_oncore.c \
- refclock_palisade.c refclock_palisade.h refclock_parse.c \
- refclock_pcf.c refclock_pst.c refclock_ptbacts.c refclock_shm.c \
- refclock_tpro.c refclock_trak.c refclock_true.c refclock_tt560.c \
- refclock_ulink.c refclock_usno.c refclock_wwv.c refclock_wwvb.c \
- refclock_zyfer.c refclock_ripencc.c refclock_neoclock4x.c
-
-subdir = ntpd
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-LIBRARIES = $(noinst_LIBRARIES)
-
-libntpd_a_AR = $(AR) cru
-libntpd_a_LIBADD =
-am_libntpd_a_OBJECTS = map_vme$U.$(OBJEXT) ntp_control$U.$(OBJEXT) \
- ntp_crypto$U.$(OBJEXT) ntp_filegen$U.$(OBJEXT) \
- ntp_intres$U.$(OBJEXT) ntp_loopfilter$U.$(OBJEXT) \
- ntp_monitor$U.$(OBJEXT) ntp_peer$U.$(OBJEXT) \
- ntp_proto$U.$(OBJEXT) ntp_refclock$U.$(OBJEXT) \
- ntp_request$U.$(OBJEXT) ntp_restrict$U.$(OBJEXT) \
- ntp_timer$U.$(OBJEXT) ntp_util$U.$(OBJEXT) \
- refclock_acts$U.$(OBJEXT) refclock_arbiter$U.$(OBJEXT) \
- refclock_arc$U.$(OBJEXT) refclock_as2201$U.$(OBJEXT) \
- refclock_atom$U.$(OBJEXT) refclock_bancomm$U.$(OBJEXT) \
- refclock_chronolog$U.$(OBJEXT) refclock_chu$U.$(OBJEXT) \
- refclock_conf$U.$(OBJEXT) refclock_datum$U.$(OBJEXT) \
- refclock_dumbclock$U.$(OBJEXT) refclock_fg$U.$(OBJEXT) \
- refclock_gpsvme$U.$(OBJEXT) refclock_heath$U.$(OBJEXT) \
- refclock_hopfser$U.$(OBJEXT) refclock_hopfpci$U.$(OBJEXT) \
- refclock_hpgps$U.$(OBJEXT) refclock_irig$U.$(OBJEXT) \
- refclock_jjy$U.$(OBJEXT) refclock_jupiter$U.$(OBJEXT) \
- refclock_leitch$U.$(OBJEXT) refclock_local$U.$(OBJEXT) \
- refclock_msfees$U.$(OBJEXT) refclock_mx4200$U.$(OBJEXT) \
- refclock_nmea$U.$(OBJEXT) refclock_oncore$U.$(OBJEXT) \
- refclock_palisade$U.$(OBJEXT) refclock_parse$U.$(OBJEXT) \
- refclock_pcf$U.$(OBJEXT) refclock_pst$U.$(OBJEXT) \
- refclock_ptbacts$U.$(OBJEXT) refclock_shm$U.$(OBJEXT) \
- refclock_tpro$U.$(OBJEXT) refclock_trak$U.$(OBJEXT) \
- refclock_true$U.$(OBJEXT) refclock_tt560$U.$(OBJEXT) \
- refclock_ulink$U.$(OBJEXT) refclock_usno$U.$(OBJEXT) \
- refclock_wwv$U.$(OBJEXT) refclock_wwvb$U.$(OBJEXT) \
- refclock_zyfer$U.$(OBJEXT) refclock_ripencc$U.$(OBJEXT) \
- refclock_neoclock4x$U.$(OBJEXT)
-libntpd_a_OBJECTS = $(am_libntpd_a_OBJECTS)
-EXTRA_PROGRAMS = check_y2k$(EXEEXT) ntpdsim$(EXEEXT)
-bin_PROGRAMS = ntpd$(EXEEXT) @MAKE_NTPDSIM@
-check_PROGRAMS = @MAKE_CHECK_Y2K@
-PROGRAMS = $(bin_PROGRAMS)
-
-check_y2k_SOURCES = check_y2k.c
-check_y2k_OBJECTS = check_y2k$U.$(OBJEXT)
-check_y2k_DEPENDENCIES = version.o libntpd.a libntpd.a \
- ../libntp/libntp.a
-check_y2k_LDFLAGS =
-am_ntpd_OBJECTS = cmd_args$U.$(OBJEXT) ntp_config$U.$(OBJEXT) \
- ntp_io$U.$(OBJEXT) ntpd$U.$(OBJEXT)
-ntpd_OBJECTS = $(am_ntpd_OBJECTS)
-ntpd_DEPENDENCIES = version.o libntpd.a libntpd.a ../libntp/libntp.a
-ntpd_LDFLAGS =
-am__objects_1 = ntpdsim-cmd_args$U.$(OBJEXT) \
- ntpdsim-ntp_config$U.$(OBJEXT) ntpdsim-ntp_io$U.$(OBJEXT) \
- ntpdsim-ntpd$U.$(OBJEXT)
-am_ntpdsim_OBJECTS = $(am__objects_1) ntpdsim-ntpsim$U.$(OBJEXT)
-ntpdsim_OBJECTS = $(am_ntpdsim_OBJECTS)
-ntpdsim_DEPENDENCIES = version.o libntpd.a libntpd.a \
- ../libntp/libntpsim.a
-ntpdsim_LDFLAGS =
-
-DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/check_y2k$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/cmd_args$U.Po ./$(DEPDIR)/map_vme$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_config$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_control$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_crypto$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_filegen$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_intres$U.Po ./$(DEPDIR)/ntp_io$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_loopfilter$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_monitor$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_peer$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_proto$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_refclock$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_request$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_restrict$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_timer$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_util$U.Po ./$(DEPDIR)/ntpd$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-cmd_args$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntp_config$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntp_io$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntpd$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntpsim$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_acts$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_arbiter$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_arc$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_as2201$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_atom$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_bancomm$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_chronolog$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_chu$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_conf$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_datum$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_dumbclock$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_fg$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_gpsvme$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_heath$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_hopfpci$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_hopfser$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_hpgps$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_irig$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_jjy$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_jupiter$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_leitch$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_local$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_msfees$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_mx4200$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_neoclock4x$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_nmea$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_oncore$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_palisade$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_parse$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_pcf$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_pst$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_ptbacts$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_ripencc$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_shm$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_tpro$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_trak$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_true$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_tt560$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_ulink$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_usno$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_wwv$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_wwvb$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_zyfer$U.Po
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-DIST_SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) \
- $(ntpdsim_SOURCES)
-DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
-SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) $(ntpdsim_SOURCES)
-
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu ntpd/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
-
-AR = ar
-
-clean-noinstLIBRARIES:
- -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
-libntpd.a: $(libntpd_a_OBJECTS) $(libntpd_a_DEPENDENCIES)
- -rm -f libntpd.a
- $(libntpd_a_AR) libntpd.a $(libntpd_a_OBJECTS) $(libntpd_a_LIBADD)
- $(RANLIB) libntpd.a
-binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
-install-binPROGRAMS: $(bin_PROGRAMS)
- @$(NORMAL_INSTALL)
- $(mkinstalldirs) $(DESTDIR)$(bindir)
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
- $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \
- else :; fi; \
- done
-
-uninstall-binPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
- rm -f $(DESTDIR)$(bindir)/$$f; \
- done
-
-clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-clean-checkPROGRAMS:
- -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
-check_y2k$(EXEEXT): $(check_y2k_OBJECTS) $(check_y2k_DEPENDENCIES)
- @rm -f check_y2k$(EXEEXT)
- $(LINK) $(check_y2k_LDFLAGS) $(check_y2k_OBJECTS) $(check_y2k_LDADD) $(LIBS)
-ntpd$(EXEEXT): $(ntpd_OBJECTS) $(ntpd_DEPENDENCIES)
- @rm -f ntpd$(EXEEXT)
- $(LINK) $(ntpd_LDFLAGS) $(ntpd_OBJECTS) $(ntpd_LDADD) $(LIBS)
-ntpdsim$(EXEEXT): $(ntpdsim_OBJECTS) $(ntpdsim_DEPENDENCIES)
- @rm -f ntpdsim$(EXEEXT)
- $(LINK) $(ntpdsim_LDFLAGS) $(ntpdsim_OBJECTS) $(ntpdsim_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT) core *.core
-
-distclean-compile:
- -rm -f *.tab.c
-
-ANSI2KNR = ../util/ansi2knr
-../util/ansi2knr:
- cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr
-
-mostlyclean-kr:
- -test "$U" = "" || rm -f *_.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_y2k$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd_args$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_vme$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_config$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_control$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_crypto$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_filegen$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_intres$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_io$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_loopfilter$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_monitor$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_peer$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_proto$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_refclock$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_request$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_restrict$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_timer$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntp_util$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpd$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-cmd_args$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_config$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntp_io$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpd$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpsim$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_acts$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_arbiter$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_arc$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_as2201$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_atom$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_bancomm$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_chronolog$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_chu$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_conf$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_datum$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_dumbclock$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_fg$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_gpsvme$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_heath$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hopfpci$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hopfser$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_hpgps$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_irig$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_jjy$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_jupiter$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_leitch$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_local$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_msfees$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_mx4200$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_neoclock4x$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_nmea$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_oncore$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_palisade$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_parse$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pcf$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pst$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ptbacts$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ripencc$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_shm$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tpro$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_trak$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_true$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tt560$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ulink$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_usno$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwv$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwvb$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_zyfer$U.Po@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
-@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
-
-.c.obj:
-@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
-@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
-
-ntpdsim-cmd_args$U.o: cmd_args$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-cmd_args$U.o -MD -MP -MF "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-cmd_args$U.o `test -f 'cmd_args$U.c' || echo '$(srcdir)/'`cmd_args$U.c; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo" "$(DEPDIR)/ntpdsim-cmd_args$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cmd_args$U.c' object='ntpdsim-cmd_args$U.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-cmd_args$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-cmd_args$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-cmd_args$U.o `test -f 'cmd_args$U.c' || echo '$(srcdir)/'`cmd_args$U.c
-
-ntpdsim-cmd_args$U.obj: cmd_args$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-cmd_args$U.obj -MD -MP -MF "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-cmd_args$U.obj `if test -f 'cmd_args$U.c'; then $(CYGPATH_W) 'cmd_args$U.c'; else $(CYGPATH_W) '$(srcdir)/cmd_args$U.c'; fi`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo" "$(DEPDIR)/ntpdsim-cmd_args$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cmd_args$U.c' object='ntpdsim-cmd_args$U.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-cmd_args$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-cmd_args$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-cmd_args$U.obj `if test -f 'cmd_args$U.c'; then $(CYGPATH_W) 'cmd_args$U.c'; else $(CYGPATH_W) '$(srcdir)/cmd_args$U.c'; fi`
-
-ntpdsim-ntp_config$U.o: ntp_config$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_config$U.o -MD -MP -MF "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntp_config$U.o `test -f 'ntp_config$U.c' || echo '$(srcdir)/'`ntp_config$U.c; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo" "$(DEPDIR)/ntpdsim-ntp_config$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_config$U.c' object='ntpdsim-ntp_config$U.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntp_config$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntp_config$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_config$U.o `test -f 'ntp_config$U.c' || echo '$(srcdir)/'`ntp_config$U.c
-
-ntpdsim-ntp_config$U.obj: ntp_config$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_config$U.obj -MD -MP -MF "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntp_config$U.obj `if test -f 'ntp_config$U.c'; then $(CYGPATH_W) 'ntp_config$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_config$U.c'; fi`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo" "$(DEPDIR)/ntpdsim-ntp_config$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_config$U.c' object='ntpdsim-ntp_config$U.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntp_config$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntp_config$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_config$U.obj `if test -f 'ntp_config$U.c'; then $(CYGPATH_W) 'ntp_config$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_config$U.c'; fi`
-
-ntpdsim-ntp_io$U.o: ntp_io$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_io$U.o -MD -MP -MF "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntp_io$U.o `test -f 'ntp_io$U.c' || echo '$(srcdir)/'`ntp_io$U.c; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo" "$(DEPDIR)/ntpdsim-ntp_io$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_io$U.c' object='ntpdsim-ntp_io$U.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntp_io$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntp_io$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_io$U.o `test -f 'ntp_io$U.c' || echo '$(srcdir)/'`ntp_io$U.c
-
-ntpdsim-ntp_io$U.obj: ntp_io$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntp_io$U.obj -MD -MP -MF "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntp_io$U.obj `if test -f 'ntp_io$U.c'; then $(CYGPATH_W) 'ntp_io$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_io$U.c'; fi`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo" "$(DEPDIR)/ntpdsim-ntp_io$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntp_io$U.c' object='ntpdsim-ntp_io$U.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntp_io$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntp_io$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntp_io$U.obj `if test -f 'ntp_io$U.c'; then $(CYGPATH_W) 'ntp_io$U.c'; else $(CYGPATH_W) '$(srcdir)/ntp_io$U.c'; fi`
-
-ntpdsim-ntpd$U.o: ntpd$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd$U.o -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpd$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntpd$U.o `test -f 'ntpd$U.c' || echo '$(srcdir)/'`ntpd$U.c; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpd$U.Tpo" "$(DEPDIR)/ntpdsim-ntpd$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntpd$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd$U.c' object='ntpdsim-ntpd$U.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntpd$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntpd$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd$U.o `test -f 'ntpd$U.c' || echo '$(srcdir)/'`ntpd$U.c
-
-ntpdsim-ntpd$U.obj: ntpd$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd$U.obj -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpd$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntpd$U.obj `if test -f 'ntpd$U.c'; then $(CYGPATH_W) 'ntpd$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd$U.c'; fi`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpd$U.Tpo" "$(DEPDIR)/ntpdsim-ntpd$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntpd$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd$U.c' object='ntpdsim-ntpd$U.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntpd$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntpd$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd$U.obj `if test -f 'ntpd$U.c'; then $(CYGPATH_W) 'ntpd$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd$U.c'; fi`
-
-ntpdsim-ntpsim$U.o: ntpsim$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpsim$U.o -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntpsim$U.o `test -f 'ntpsim$U.c' || echo '$(srcdir)/'`ntpsim$U.c; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo" "$(DEPDIR)/ntpdsim-ntpsim$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpsim$U.c' object='ntpdsim-ntpsim$U.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntpsim$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntpsim$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpsim$U.o `test -f 'ntpsim$U.c' || echo '$(srcdir)/'`ntpsim$U.c
-
-ntpdsim-ntpsim$U.obj: ntpsim$U.c
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpsim$U.obj -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo" \
-@am__fastdepCC_TRUE@ -c -o ntpdsim-ntpsim$U.obj `if test -f 'ntpsim$U.c'; then $(CYGPATH_W) 'ntpsim$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpsim$U.c'; fi`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo" "$(DEPDIR)/ntpdsim-ntpsim$U.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpsim$U.c' object='ntpdsim-ntpsim$U.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/ntpdsim-ntpsim$U.Po' tmpdepfile='$(DEPDIR)/ntpdsim-ntpsim$U.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpsim$U.obj `if test -f 'ntpsim$U.c'; then $(CYGPATH_W) 'ntpsim$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpsim$U.c'; fi`
-check_y2k_.c: check_y2k.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/check_y2k.c; then echo $(srcdir)/check_y2k.c; else echo check_y2k.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-cmd_args_.c: cmd_args.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/cmd_args.c; then echo $(srcdir)/cmd_args.c; else echo cmd_args.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-map_vme_.c: map_vme.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/map_vme.c; then echo $(srcdir)/map_vme.c; else echo map_vme.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_config_.c: ntp_config.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_config.c; then echo $(srcdir)/ntp_config.c; else echo ntp_config.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_control_.c: ntp_control.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_control.c; then echo $(srcdir)/ntp_control.c; else echo ntp_control.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_crypto_.c: ntp_crypto.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_crypto.c; then echo $(srcdir)/ntp_crypto.c; else echo ntp_crypto.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_filegen_.c: ntp_filegen.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_filegen.c; then echo $(srcdir)/ntp_filegen.c; else echo ntp_filegen.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_intres_.c: ntp_intres.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_intres.c; then echo $(srcdir)/ntp_intres.c; else echo ntp_intres.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_io_.c: ntp_io.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_io.c; then echo $(srcdir)/ntp_io.c; else echo ntp_io.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_loopfilter_.c: ntp_loopfilter.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_loopfilter.c; then echo $(srcdir)/ntp_loopfilter.c; else echo ntp_loopfilter.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_monitor_.c: ntp_monitor.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_monitor.c; then echo $(srcdir)/ntp_monitor.c; else echo ntp_monitor.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_peer_.c: ntp_peer.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_peer.c; then echo $(srcdir)/ntp_peer.c; else echo ntp_peer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_proto_.c: ntp_proto.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_proto.c; then echo $(srcdir)/ntp_proto.c; else echo ntp_proto.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_refclock_.c: ntp_refclock.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_refclock.c; then echo $(srcdir)/ntp_refclock.c; else echo ntp_refclock.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_request_.c: ntp_request.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_request.c; then echo $(srcdir)/ntp_request.c; else echo ntp_request.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_restrict_.c: ntp_restrict.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_restrict.c; then echo $(srcdir)/ntp_restrict.c; else echo ntp_restrict.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_timer_.c: ntp_timer.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_timer.c; then echo $(srcdir)/ntp_timer.c; else echo ntp_timer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntp_util_.c: ntp_util.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_util.c; then echo $(srcdir)/ntp_util.c; else echo ntp_util.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntpd_.c: ntpd.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpd.c; then echo $(srcdir)/ntpd.c; else echo ntpd.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-ntpsim_.c: ntpsim.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpsim.c; then echo $(srcdir)/ntpsim.c; else echo ntpsim.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_acts_.c: refclock_acts.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_acts.c; then echo $(srcdir)/refclock_acts.c; else echo refclock_acts.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_arbiter_.c: refclock_arbiter.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_arbiter.c; then echo $(srcdir)/refclock_arbiter.c; else echo refclock_arbiter.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_arc_.c: refclock_arc.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_arc.c; then echo $(srcdir)/refclock_arc.c; else echo refclock_arc.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_as2201_.c: refclock_as2201.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_as2201.c; then echo $(srcdir)/refclock_as2201.c; else echo refclock_as2201.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_atom_.c: refclock_atom.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_atom.c; then echo $(srcdir)/refclock_atom.c; else echo refclock_atom.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_bancomm_.c: refclock_bancomm.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_bancomm.c; then echo $(srcdir)/refclock_bancomm.c; else echo refclock_bancomm.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_chronolog_.c: refclock_chronolog.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_chronolog.c; then echo $(srcdir)/refclock_chronolog.c; else echo refclock_chronolog.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_chu_.c: refclock_chu.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_chu.c; then echo $(srcdir)/refclock_chu.c; else echo refclock_chu.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_conf_.c: refclock_conf.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_conf.c; then echo $(srcdir)/refclock_conf.c; else echo refclock_conf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_datum_.c: refclock_datum.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_datum.c; then echo $(srcdir)/refclock_datum.c; else echo refclock_datum.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_dumbclock_.c: refclock_dumbclock.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_dumbclock.c; then echo $(srcdir)/refclock_dumbclock.c; else echo refclock_dumbclock.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_fg_.c: refclock_fg.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_fg.c; then echo $(srcdir)/refclock_fg.c; else echo refclock_fg.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_gpsvme_.c: refclock_gpsvme.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_gpsvme.c; then echo $(srcdir)/refclock_gpsvme.c; else echo refclock_gpsvme.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_heath_.c: refclock_heath.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_heath.c; then echo $(srcdir)/refclock_heath.c; else echo refclock_heath.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_hopfpci_.c: refclock_hopfpci.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hopfpci.c; then echo $(srcdir)/refclock_hopfpci.c; else echo refclock_hopfpci.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_hopfser_.c: refclock_hopfser.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hopfser.c; then echo $(srcdir)/refclock_hopfser.c; else echo refclock_hopfser.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_hpgps_.c: refclock_hpgps.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hpgps.c; then echo $(srcdir)/refclock_hpgps.c; else echo refclock_hpgps.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_irig_.c: refclock_irig.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_irig.c; then echo $(srcdir)/refclock_irig.c; else echo refclock_irig.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_jjy_.c: refclock_jjy.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_jjy.c; then echo $(srcdir)/refclock_jjy.c; else echo refclock_jjy.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_jupiter_.c: refclock_jupiter.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_jupiter.c; then echo $(srcdir)/refclock_jupiter.c; else echo refclock_jupiter.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_leitch_.c: refclock_leitch.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_leitch.c; then echo $(srcdir)/refclock_leitch.c; else echo refclock_leitch.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_local_.c: refclock_local.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_local.c; then echo $(srcdir)/refclock_local.c; else echo refclock_local.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_msfees_.c: refclock_msfees.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_msfees.c; then echo $(srcdir)/refclock_msfees.c; else echo refclock_msfees.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_mx4200_.c: refclock_mx4200.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_mx4200.c; then echo $(srcdir)/refclock_mx4200.c; else echo refclock_mx4200.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_neoclock4x_.c: refclock_neoclock4x.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_neoclock4x.c; then echo $(srcdir)/refclock_neoclock4x.c; else echo refclock_neoclock4x.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_nmea_.c: refclock_nmea.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_nmea.c; then echo $(srcdir)/refclock_nmea.c; else echo refclock_nmea.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_oncore_.c: refclock_oncore.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_oncore.c; then echo $(srcdir)/refclock_oncore.c; else echo refclock_oncore.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_palisade_.c: refclock_palisade.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_palisade.c; then echo $(srcdir)/refclock_palisade.c; else echo refclock_palisade.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_parse_.c: refclock_parse.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_parse.c; then echo $(srcdir)/refclock_parse.c; else echo refclock_parse.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_pcf_.c: refclock_pcf.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pcf.c; then echo $(srcdir)/refclock_pcf.c; else echo refclock_pcf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_pst_.c: refclock_pst.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pst.c; then echo $(srcdir)/refclock_pst.c; else echo refclock_pst.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_ptbacts_.c: refclock_ptbacts.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ptbacts.c; then echo $(srcdir)/refclock_ptbacts.c; else echo refclock_ptbacts.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_ripencc_.c: refclock_ripencc.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ripencc.c; then echo $(srcdir)/refclock_ripencc.c; else echo refclock_ripencc.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_shm_.c: refclock_shm.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_shm.c; then echo $(srcdir)/refclock_shm.c; else echo refclock_shm.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_tpro_.c: refclock_tpro.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_tpro.c; then echo $(srcdir)/refclock_tpro.c; else echo refclock_tpro.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_trak_.c: refclock_trak.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_trak.c; then echo $(srcdir)/refclock_trak.c; else echo refclock_trak.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_true_.c: refclock_true.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_true.c; then echo $(srcdir)/refclock_true.c; else echo refclock_true.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_tt560_.c: refclock_tt560.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_tt560.c; then echo $(srcdir)/refclock_tt560.c; else echo refclock_tt560.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_ulink_.c: refclock_ulink.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ulink.c; then echo $(srcdir)/refclock_ulink.c; else echo refclock_ulink.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_usno_.c: refclock_usno.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_usno.c; then echo $(srcdir)/refclock_usno.c; else echo refclock_usno.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_wwv_.c: refclock_wwv.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwv.c; then echo $(srcdir)/refclock_wwv.c; else echo refclock_wwv.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_wwvb_.c: refclock_wwvb.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwvb.c; then echo $(srcdir)/refclock_wwvb.c; else echo refclock_wwvb.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_zyfer_.c: refclock_zyfer.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_zyfer.c; then echo $(srcdir)/refclock_zyfer.c; else echo refclock_zyfer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-check_y2k_.$(OBJEXT) cmd_args_.$(OBJEXT) map_vme_.$(OBJEXT) \
-ntp_config_.$(OBJEXT) ntp_control_.$(OBJEXT) ntp_crypto_.$(OBJEXT) \
-ntp_filegen_.$(OBJEXT) ntp_intres_.$(OBJEXT) ntp_io_.$(OBJEXT) \
-ntp_loopfilter_.$(OBJEXT) ntp_monitor_.$(OBJEXT) ntp_peer_.$(OBJEXT) \
-ntp_proto_.$(OBJEXT) ntp_refclock_.$(OBJEXT) ntp_request_.$(OBJEXT) \
-ntp_restrict_.$(OBJEXT) ntp_timer_.$(OBJEXT) ntp_util_.$(OBJEXT) \
-ntpd_.$(OBJEXT) ntpsim_.$(OBJEXT) refclock_acts_.$(OBJEXT) \
-refclock_arbiter_.$(OBJEXT) refclock_arc_.$(OBJEXT) \
-refclock_as2201_.$(OBJEXT) refclock_atom_.$(OBJEXT) \
-refclock_bancomm_.$(OBJEXT) refclock_chronolog_.$(OBJEXT) \
-refclock_chu_.$(OBJEXT) refclock_conf_.$(OBJEXT) \
-refclock_datum_.$(OBJEXT) refclock_dumbclock_.$(OBJEXT) \
-refclock_fg_.$(OBJEXT) refclock_gpsvme_.$(OBJEXT) \
-refclock_heath_.$(OBJEXT) refclock_hopfpci_.$(OBJEXT) \
-refclock_hopfser_.$(OBJEXT) refclock_hpgps_.$(OBJEXT) \
-refclock_irig_.$(OBJEXT) refclock_jjy_.$(OBJEXT) \
-refclock_jupiter_.$(OBJEXT) refclock_leitch_.$(OBJEXT) \
-refclock_local_.$(OBJEXT) refclock_msfees_.$(OBJEXT) \
-refclock_mx4200_.$(OBJEXT) refclock_neoclock4x_.$(OBJEXT) \
-refclock_nmea_.$(OBJEXT) refclock_oncore_.$(OBJEXT) \
-refclock_palisade_.$(OBJEXT) refclock_parse_.$(OBJEXT) \
-refclock_pcf_.$(OBJEXT) refclock_pst_.$(OBJEXT) \
-refclock_ptbacts_.$(OBJEXT) refclock_ripencc_.$(OBJEXT) \
-refclock_shm_.$(OBJEXT) refclock_tpro_.$(OBJEXT) \
-refclock_trak_.$(OBJEXT) refclock_true_.$(OBJEXT) \
-refclock_tt560_.$(OBJEXT) refclock_ulink_.$(OBJEXT) \
-refclock_usno_.$(OBJEXT) refclock_wwv_.$(OBJEXT) \
-refclock_wwvb_.$(OBJEXT) refclock_zyfer_.$(OBJEXT) : $(ANSI2KNR)
-uninstall-info-am:
-
-ETAGS = etags
-ETAGSFLAGS =
-
-CTAGS = ctags
-CTAGSFLAGS =
-
-tags: TAGS
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- mkid -fID $$unique
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(ETAGS_ARGS)$$tags$$unique" \
- || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique
-
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-
-top_distdir = ..
-distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
- list='$(DISTFILES)'; for file in $$list; do \
- case $$file in \
- $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
- $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
- esac; \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test "$$dir" != "$$file" && test "$$dir" != "."; then \
- dir="/$$dir"; \
- $(mkinstalldirs) "$(distdir)$$dir"; \
- else \
- dir=''; \
- fi; \
- if test -d $$d/$$file; then \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
- $(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-am
-all-am: Makefile $(LIBRARIES) $(PROGRAMS)
-
-installdirs:
- $(mkinstalldirs) $(DESTDIR)$(bindir)
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -rm -f $(CONFIG_CLEAN_FILES)
- -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
- clean-noinstLIBRARIES mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-exec-am: install-binPROGRAMS
-
-install-info: install-info-am
-
-install-man:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic mostlyclean-kr
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-binPROGRAMS uninstall-info-am
-
-.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
- clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
- clean-noinstLIBRARIES ctags distclean distclean-compile \
- distclean-generic distclean-tags distdir dvi dvi-am info \
- info-am install install-am install-binPROGRAMS install-data \
- install-data-am install-exec install-exec-am install-info \
- install-info-am install-man install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-kr pdf pdf-am ps ps-am tags \
- uninstall uninstall-am uninstall-binPROGRAMS uninstall-info-am
-
-
-check-local: @MAKE_CHECK_Y2K@
- test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
-
-$(PROGRAMS): $(LDADD)
-
-../libntp/libntp.a:
- cd ../libntp && $(MAKE)
-
-../libparse/libparse.a:
- cd ../libparse && $(MAKE)
-
-version.o: $(ntpd_OBJECTS) ../libntp/libntp.a @LIBPARSE@ Makefile $(top_srcdir)/version
- env CSET=`cat $(top_srcdir)/version` $(top_builddir)/scripts/mkver ntpd
- $(COMPILE) -c version.c
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/contrib/ntp/ntpd/check_y2k.c b/contrib/ntp/ntpd/check_y2k.c
deleted file mode 100644
index 6b83115..0000000
--- a/contrib/ntp/ntpd/check_y2k.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/* check_y2k.c -- test ntp code constructs for Y2K correctness Y2KFixes [*/
-
- /*
- Code invoked by `make check`. Not part of ntpd and not to be
- installed.
-
- On any code I even wonder about, I've cut and pasted the code
- here and ran it as a test case just to be sure.
-
- For code not in "ntpd" proper, we have tried to call most
- repaired functions from herein to properly test them
- (something never done before!). This has found several bugs,
- not normal Y2K bugs, that will strike in Y2K so repair them
- we did.
-
- Program exits with 0 on success, 1 on Y2K failure (stdout messages).
- Exit of 2 indicates internal logic bug detected OR failure of
- what should be our correct formulas.
-
- While "make check" should only check logic for source within that
- specific directory, this check goes outside the scope of the local
- directory. It's not a perfect world (besides, there is a lot of
- interdependence here, and it really needs to be tested in
- a controled order).
- */
-
-/* { definitions lifted from ntpd.c to allow us to complie with
- "#include ntp.h". I have not taken the time to reduce the clutter. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntpd.h"
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#include <stdio.h>
-#include <errno.h>
-#ifndef SYS_WINNT
-# if !defined(VMS) /*wjm*/
-# include <sys/param.h>
-# endif /* VMS */
-# if HAVE_SYS_SIGNAL_H
-# include <sys/signal.h>
-# endif /* HAVE_SYS_SIGNAL_H */
-# include <sys/signal.h>
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-# endif /* HAVE_SYS_IOCTL_H */
-# if !defined(VMS) /*wjm*/
-# include <sys/resource.h>
-# endif /* VMS */
-#else
-# include <signal.h>
-# include <process.h>
-# include <io.h>
-# include "../libntp/log.h"
-#endif /* SYS_WINNT */
-#if defined(HAVE_RTPRIO)
-# ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-# endif
-# ifdef HAVE_SYS_LOCK_H
-# include <sys/lock.h>
-# endif
-# include <sys/rtprio.h>
-#else
-# ifdef HAVE_PLOCK
-# ifdef HAVE_SYS_LOCK_H
-# include <sys/lock.h>
-# endif
-# endif
-#endif
-#if defined(HAVE_SCHED_SETSCHEDULER)
-# ifdef HAVE_SCHED_H
-# include <sched.h>
-# else
-# ifdef HAVE_SYS_SCHED_H
-# include <sys/sched.h>
-# endif
-# endif
-#endif
-#if defined(HAVE_SYS_MMAN_H)
-# include <sys/mman.h>
-#endif
-
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
-#endif
-
-#ifdef SYS_DOMAINOS
-# include <apollo/base.h>
-#endif /* SYS_DOMAINOS */
-
-/* } end definitions lifted from ntpd.c */
-
-#include "ntp_calendar.h"
-#include "parse.h"
-
-#define GoodLeap(Year) (((Year)%4 || (!((Year)%100) && (Year)%400)) ? 0 : 13 )
-
-volatile int debug = 0; /* debugging requests for parse stuff */
-char const *progname = "check_y2k";
-
-long
-Days ( int Year ) /* return number of days since year "0" */
-{
- long Return;
- /* this is a known to be good algorithm */
- Return = Year * 365; /* first aproximation to the value */
- if ( Year >= 1 )
- { /* see notes in libparse/parse.c if you want a PROPER
- * **generic algorithm. */
- Return += (Year+3) / 4; /* add in (too many) leap days */
- Return -= (Year-1) / 100; /* reduce by (too many) centurys */
- Return += (Year-1) / 400; /* get final answer */
- }
-
- return Return;
-}
-
-static int year0 = 1900; /* sarting year for NTP time */
-static int yearend; /* ending year we test for NTP time.
- * 32-bit systems: through 2036, the
- **year in which NTP time overflows.
- * 64-bit systems: a reasonable upper
- **limit (well, maybe somewhat beyond
- **reasonable, but well before the
- **max time, by which time the earth
- **will be dead.) */
-static time_t Time;
-static struct tm LocalTime;
-
-#define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \
- Warnings++; else Fatals++
-
-int
-main( void )
-{
- int Fatals;
- int Warnings;
- int year;
-
- Time = time( (time_t *)NULL )
-#ifdef TESTTIMEOFFSET
- + test_time_offset
-#endif
- ;
- LocalTime = *localtime( &Time );
-
- year = ( sizeof( u_long ) > 4 ) /* save max span using year as temp */
- ? ( 400 * 3 ) /* three greater gregorian cycles */
- : ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/
- /* NOTE: will automacially expand test years on
- * 64 bit machines.... this may cause some of the
- * existing ntp logic to fail for years beyond
- * 2036 (the current 32-bit limit). If all checks
- * fail ONLY beyond year 2036 you may ignore such
- * errors, at least for a decade or so. */
- yearend = year0 + year;
-
- puts( " internal self check" );
- { /* verify our own logic used to verify repairs */
- unsigned long days;
-
- if ( year0 >= yearend )
- {
- fprintf( stdout, "year0=%d NOT LESS THAN yearend=%d (span=%d)\n",
- (int)year0, (int)yearend, (int)year );
- exit(2);
- }
-
- {
- int save_year;
-
- save_year = LocalTime.tm_year; /* save current year */
-
- year = 1980;
- LocalTime.tm_year = year - 1900;
- Fatals = Warnings = 0;
- Error(year); /* should increment Fatals */
- if ( Fatals == 0 )
- {
- fprintf( stdout,
- "%4d: %s(%d): FATAL DID NOT INCREMENT (Fatals=%d Warnings=%d)\n",
- (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
- exit(2);
- }
-
- year = 2100; /* test year > limit but CURRENT year < limit */
- Fatals = Warnings = 0;
- Error(year); /* should increment Fatals */
- if ( Warnings == 0 )
- {
- fprintf( stdout,
- "%4d: %s(%d): WARNING DID NOT INCREMENT (Fatals=%d Warnings=%d)\n",
- (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
- exit(2);
- }
- Fatals = Warnings = 0;
- LocalTime.tm_year = year - 1900; /* everything > limit */
- Error(1980); /* should increment Fatals */
- if ( Fatals == 0 )
- {
- fprintf( stdout,
- "%4d: %s(%d): FATALS DID NOT INCREMENT (Fatals=%d Warnings=%d)\n",
- (int)year, __FILE__, __LINE__, (int)Fatals, (int)Warnings );
- exit(2);
- }
-
- LocalTime.tm_year = save_year;
- }
-
- days = 365+1; /* days in year 0 + 1 more day */
- for ( year = 1; year <= 2500; year++ )
- {
- long Test;
- Test = Days( year );
- if ( days != Test )
- {
- fprintf( stdout, "%04d: Days() DAY COUNT ERROR: s/b=%ld was=%ld\n",
- year, (long)days, (long)Test );
- exit(2); /* would throw off many other tests */
- }
-
- Test = julian0(year); /* compare with julian0() macro */
- if ( days != Test )
- {
- fprintf( stdout, "%04d: julian0() DAY COUNT ERROR: s/b=%ld was=%ld\n",
- year, (long)days, (long)Test );
- exit(2); /* would throw off many other tests */
- }
-
- days += 365;
- if ( isleap_4(year) ) days++;
- }
-
- if ( isleap_4(1999) )
- {
- fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" );
- exit(2);
- }
- if ( !isleap_4(2000) )
- {
- fprintf( stdout, "isleap_4(2000) REPORTED FALSE\n" );
- exit(2);
- }
- if ( isleap_4(2001) )
- {
- fprintf( stdout, "isleap_4(1999) REPORTED TRUE\n" );
- exit(2);
- }
-
- if ( !isleap_tm(2000-1900) )
- {
- fprintf( stdout, "isleap_tm(100) REPORTED FALSE\n" );
- exit(2);
- }
- }
-
- Fatals = Warnings = 0;
-
- puts( " include/ntp.h" );
- { /* test our new isleap_*() #define "functions" */
-
- for ( year = 1400; year <= 2200; year++ )
- {
- int LeapSw;
- int IsLeapSw;
-
- LeapSw = GoodLeap(year);
- IsLeapSw = isleap_4(year);
-
- if ( !!LeapSw != !!IsLeapSw )
- {
- Error(year);
- fprintf( stdout,
- " %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw );
- break;
- }
-
- IsLeapSw = isleap_tm(year-1900);
-
- if ( !!LeapSw != !!IsLeapSw )
- {
- Error(year);
- fprintf( stdout,
- " %4d %2d %3d *** ERROR\n", year, LeapSw, IsLeapSw );
- break;
- }
- }
- }
-
- puts( " include/ntp_calendar.h" );
- { /* I belive this is good, but just to be sure... */
-
- /* we are testing this #define */
-#define is_leapyear(y) (y%4 == 0 && !(y%100 == 0 && !(y%400 == 0)))
-
- for ( year = 1400; year <= 2200; year++ )
- {
- int LeapSw;
-
- LeapSw = GoodLeap(year);
-
- if ( !(!LeapSw) != !(!is_leapyear(year)) )
- {
- Error(year);
- fprintf( stdout,
- " %4d %2d *** ERROR\n", year, LeapSw );
- break;
- }
- }
- }
-
-
- puts( " libparse/parse.c" );
- {
- long Days1970; /* days from 1900 to 1970 */
-
- struct ParseTime /* womp up a test structure to all cut/paste code */
- {
- int year;
- } Clock_Time, *clock_time;
-
- clock_time = &Clock_Time;
-
- /* first test this #define */
-#define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
-
- for ( year = 1400; year <= 2200; year++ )
- {
- int LeapSw;
- int DayCnt;
-
- LeapSw = GoodLeap(year);
- DayCnt = (int)days_per_year(year);
-
- if ( ( LeapSw ? 366 : 365 ) != DayCnt )
- {
- Error(year);
- fprintf( stdout,
- " days_per_year() %4d %2d %3d *** ERROR\n",
- year, LeapSw, DayCnt );
- break;
- }
- }
-
- /* test (what is now julian0) calculations */
-
- Days1970 = Days( 1970 ); /* get days since 1970 using a known good */
-
- for ( year = 1970; year < yearend; year++ )
- {
- unsigned long t;
- long DaysYear ;
-
- clock_time->year = year;
-
- /* here is the code we are testing, cut and pasted out of the source */
-#if 0 /* old BUGGY code that has Y2K (and many other) failures */
- /* ghealton: this logic FAILED with great frequency when run
- * over a period of time, including for year 2000. True, it
- * had more successes than failures, but that's not really good
- * enough for critical time distribution software.
- * It is so awful I wonder if it has had a history of failure
- * and fixes? */
- t = (clock_time->year - 1970) * 365;
- t += (clock_time->year >> 2) - (1970 >> 2);
- t -= clock_time->year / 100 - 1970 / 100;
- t += clock_time->year / 400 - 1970 / 400;
-
- /* (immediate feare of rounding errors on integer
- * **divisions proved well founded) */
-
-#else
- /* my replacement, based on Days() above */
- t = julian0(year) - julian0(1970);
-#endif
-
- /* compare result in t against trusted calculations */
- DaysYear = Days( year ); /* get days to this year */
- if ( t != DaysYear - Days1970 )
- {
- Error(year);
- fprintf( stdout,
- " %4d 1970=%-8ld %4d=%-8ld %-3ld t=%-8ld *** ERROR ***\n",
- year, (long)Days1970,
- year,
- (long)DaysYear,
- (long)(DaysYear - Days1970),
- (long)t );
- }
- }
-
-#if 1 /* { */
- {
- debug = 1; /* enable debugging */
- for ( year = 1970; year < yearend; year++ )
- { /* (limited by theory unix 2038 related bug lives by, but
- * ends in yearend) */
- clocktime_t ct;
- time_t Observed;
- time_t Expected;
- u_long Flag;
- unsigned long t;
-
- ct.day = 1;
- ct.month = 1;
- ct.year = year;
- ct.hour = ct.minute = ct.second = ct.usecond = 0;
- ct.utcoffset = 0;
- ct.utctime = 0;
- ct.flags = 0;
-
- Flag = 0;
- Observed = parse_to_unixtime( &ct, &Flag );
- if ( ct.year != year )
- {
- fprintf( stdout,
- "%04d: parse_to_unixtime(,%d) CORRUPTED ct.year: was %d\n",
- (int)year, (int)Flag, (int)ct.year );
- Error(year);
- break;
- }
- t = julian0(year) - julian0(1970); /* Julian day from 1970 */
- Expected = t * 24 * 60 * 60;
- if ( Observed != Expected || Flag )
- { /* time difference */
- fprintf( stdout,
- "%04d: parse_to_unixtime(,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
- year, (int)Flag,
- (unsigned long)Observed, (unsigned long)Expected,
- ((long)Observed - (long)Expected) );
- Error(year);
- break;
- }
-
- if ( year >= YEAR_PIVOT+1900 )
- {
- /* check year % 100 code we put into parse_to_unixtime() */
- ct.utctime = 0;
- ct.year = year % 100;
- Flag = 0;
-
- Observed = parse_to_unixtime( &ct, &Flag );
-
- if ( Observed != Expected || Flag )
- { /* time difference */
- fprintf( stdout,
-"%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
- year, (int)ct.year, (int)Flag,
- (unsigned long)Observed, (unsigned long)Expected,
- ((long)Observed - (long)Expected) );
- Error(year);
- break;
- }
-
- /* check year - 1900 code we put into parse_to_unixtime() */
- ct.utctime = 0;
- ct.year = year - 1900;
- Flag = 0;
-
- Observed = parse_to_unixtime( &ct, &Flag );
-
- if ( Observed != Expected || Flag )
- { /* time difference */
- fprintf( stdout,
-"%04d: parse_to_unixtime(%d,%d) FAILURE: was=%lu s/b=%lu (%ld)\n",
- year, (int)ct.year, (int)Flag,
- (unsigned long)Observed, (unsigned long)Expected,
- ((long)Observed - (long)Expected) );
- Error(year);
- break;
- }
-
-
- }
- }
-#endif /* } */
- }
- }
-
- puts( " libntp/caljulian.c" );
- { /* test caljulian() */
- struct calendar ot;
- u_long ntp_time; /* NTP time */
-
- year = year0; /* calculate the basic year */
- printf( " starting year %04d\n", (int)year0 );
- printf( " ending year %04d\n", (int)yearend );
-
-
- ntp_time = julian0( year0 ); /* NTP starts in 1900-01-01 */
-#if DAY_NTP_STARTS == 693596
- ntp_time -= 365; /* BIAS required for successful test */
-#endif
- if ( DAY_NTP_STARTS != ntp_time )
- {
- Error(year);
- fprintf( stdout,
- "%04d: DAY_NTP_STARTS (%ld) NOT TRUE VALUE OF %ld (%ld)\n",
- (int)year0,
- (long)DAY_NTP_STARTS, (long)ntp_time,
- (long)DAY_NTP_STARTS - (long)ntp_time );
- }
-
- for ( ; year < yearend; year++ )
- {
-
- /* 01-01 for the current year */
- ntp_time = Days( year ) - Days( year0 ); /* days into NTP time */
- ntp_time *= 24 * 60 * 60; /* convert into seconds */
- caljulian( ntp_time, &ot ); /* convert January 1 */
- if ( ot.year != year
- || ot.month != 1
- || ot.monthday != 1 )
- {
- Error(year);
- fprintf( stdout, "%lu: EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n",
- (unsigned long)ntp_time,
- year,
- (int)ot.year, (int)ot.month, (int)ot.monthday );
- break;
- }
-
- ntp_time += (31 + 28-1) * ( 24 * 60 * 60 ); /* advance to 02-28 */
- caljulian( ntp_time, &ot ); /* convert Feb 28 */
- if ( ot.year != year
- || ot.month != 2
- || ot.monthday != 28 )
- {
- Error(year);
- fprintf( stdout, "%lu: EXPECTED %04d-02-28: FOUND %04d-%02d-%02d\n",
- (unsigned long)ntp_time,
- year,
- (int)ot.year, (int)ot.month, (int)ot.monthday );
- break;
- }
-
- {
- int m; /* expected month */
- int d; /* expected day */
-
- m = isleap_4(year) ? 2 : 3;
- d = isleap_4(year) ? 29 : 1;
-
- ntp_time += ( 24 * 60 * 60 ); /* advance to the next day */
- caljulian( ntp_time, &ot ); /* convert this day */
- if ( ot.year != year
- || ot.month != m
- || ot.monthday != d )
- {
- Error(year);
- fprintf( stdout, "%lu: EXPECTED %04d-%02d-%02d: FOUND %04d-%02d-%02d\n",
- (unsigned long)ntp_time,
- year, m, d,
- (int)ot.year, (int)ot.month, (int)ot.monthday );
- break;
- }
-
- }
- }
- }
-
- puts( " libntp/caltontp.c" );
- { /* test caltontp() */
- struct calendar ot;
- u_long ntp_time; /* NTP time */
-
- year = year0; /* calculate the basic year */
- printf( " starting year %04d\n", (int)year0 );
- printf( " ending year %04d\n", (int)yearend );
-
-
- for ( ; year < yearend; year++ )
- {
- u_long ObservedNtp;
-
- /* 01-01 for the current year */
- ot.year = year;
- ot.month = ot.monthday = 1; /* unused, but set anyway JIC */
- ot.yearday = 1; /* this is the magic value used by caltontp() */
- ot.hour = ot.minute = ot.second = 0;
-
- ntp_time = Days( year ) - Days( year0 ); /* days into NTP time */
- ntp_time *= 24 * 60 * 60; /* convert into seconds */
- ObservedNtp = caltontp( &ot );
- if ( ntp_time != ObservedNtp )
- {
- Error(year);
- fprintf( stdout, "%d: EXPECTED %lu: FOUND %lu (%ld)\n",
- (int)year,
- (unsigned long)ntp_time, (unsigned long)ObservedNtp ,
- (long)ntp_time - (long)ObservedNtp );
-
- break;
- }
-
- /* now call caljulian as a type of failsafe supercheck */
- caljulian( ObservedNtp, &ot ); /* convert January 1 */
- if ( ot.year != year
- || ot.month != 1
- || ot.monthday != 1 )
- {
- Error(year);
- fprintf( stdout, "%lu: caljulian FAILSAFE EXPECTED %04d-01-01: FOUND %04d-%02d-%02d\n",
- (unsigned long)ObservedNtp,
- year,
- (int)ot.year, (int)ot.month, (int)ot.monthday );
- break;
- }
- }
- }
-
- if ( Warnings > 0 )
- fprintf( stdout, "%d WARNINGS\n", Warnings );
- if ( Fatals > 0 )
- fprintf( stdout, "%d FATAL ERRORS\n", Fatals );
- return Fatals ? 1 : 0;
-}
- /* Y2KFixes ] */
diff --git a/contrib/ntp/ntpd/cmd_args.c b/contrib/ntp/ntpd/cmd_args.c
deleted file mode 100644
index 3ed9b66..0000000
--- a/contrib/ntp/ntpd/cmd_args.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * cmd_args.c = command-line argument processing
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_stdlib.h"
-#include "ntp_cmdargs.h"
-
-#ifdef SIM
-#include "ntpsim.h"
-#endif /* SIM */
-
-/*
- * Definitions of things either imported from or exported to outside
- */
-extern char const *progname;
-int listen_to_virtual_ips = 1;
-
-#ifdef SYS_WINNT
-extern BOOL NoWinService;
-#endif
-
-static const char *ntp_options = "aAbB:c:C:dD:f:gi:k:l:LmnNO:p:P:qr:s:S:t:T:W:u:v:V:xY:Z:-:";
-
-#ifdef HAVE_NETINFO
-extern int check_netinfo;
-#endif
-
-
-/*
- * getstartup - search through the options looking for a debugging flag
- */
-void
-getstartup(
- int argc,
- char *argv[]
- )
-{
- int errflg;
- extern int priority_done;
- int c;
-
-#ifdef DEBUG
- debug = 0; /* no debugging by default */
-#endif
-
- /*
- * This is a big hack. We don't really want to read command line
- * configuration until everything else is initialized, since
- * the ability to configure the system may depend on storage
- * and the like having been initialized. Except that we also
- * don't want to initialize anything until after detaching from
- * the terminal, but we won't know to do that until we've
- * parsed the command line. Do that now, crudely, and do it
- * again later. Our ntp_getopt() is explicitly reusable, by the
- * way. Your own mileage may vary.
- *
- * This hack is even called twice (to allow complete logging to file)
- */
- errflg = 0;
- progname = argv[0];
-
- /*
- * Decode argument list
- */
- while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF)
- switch (c) {
-#ifdef DEBUG
- case 'd':
- ++debug;
- break;
- case 'D':
- debug = (int)atol(ntp_optarg);
- printf("Debug1: %s -> %x = %d\n", ntp_optarg, debug, debug);
- break;
-#else
- case 'd':
- case 'D':
- msyslog(LOG_ERR, "ntpd not compiled with -DDEBUG option - no DEBUG support");
- fprintf(stderr, "ntpd not compiled with -DDEBUG option - no DEBUG support\n");
- ++errflg;
- break;
-#endif
- case 'L':
- listen_to_virtual_ips = 0;
- break;
- case 'l':
- {
- FILE *new_file;
-
- if(strcmp(ntp_optarg, "stderr") == 0)
- new_file = stderr;
- else if(strcmp(ntp_optarg, "stdout") == 0)
- new_file = stdout;
- else
- new_file = fopen(ntp_optarg, "a");
- if (new_file != NULL) {
- NLOG(NLOG_SYSINFO)
- msyslog(LOG_NOTICE, "logging to file %s", ntp_optarg);
- if (syslog_file != NULL &&
- fileno(syslog_file) != fileno(new_file))
- (void)fclose(syslog_file);
-
- syslog_file = new_file;
- syslogit = 0;
- }
- else
- msyslog(LOG_ERR,
- "Cannot open log file %s",
- ntp_optarg);
- }
- break;
-
- case 'n':
- case 'q':
- ++nofork;
-#ifdef SYS_WINNT
- NoWinService = TRUE;
-#endif
- break;
-
- case 'N':
- priority_done = 0;
- break;
-
- case '?':
- ++errflg;
- break;
-
- case '-':
- if ( ! strcmp(ntp_optarg, "version") ) {
- printf("%.80s: %.80s\n", progname, Version);
- exit(0);
- } else if ( ! strcmp(ntp_optarg, "help") ) {
- /* usage(); */
- /* exit(0); */
- ++errflg;
- } else if ( ! strcmp(ntp_optarg, "copyright") ) {
- printf("unknown\n");
- exit(0);
- } else {
- fprintf(stderr, "%.80s: Error unknown argument '--%.80s'\n",
- progname,
- ntp_optarg);
- exit(12);
- }
- break;
-
- default:
- break;
- }
-
- if (errflg || ntp_optind != argc) {
- (void) fprintf(stderr, "usage: %s [ -abdgmnqx ] [ -c config_file ] [ -e e_delay ]\n", progname);
- (void) fprintf(stderr, "\t\t[ -f freq_file ] [ -k key_file ] [ -l log_file ]\n");
- (void) fprintf(stderr, "\t\t[ -p pid_file ] [ -r broad_delay ] [ -s statdir ]\n");
- (void) fprintf(stderr, "\t\t[ -t trust_key ] [ -v sys_var ] [ -V default_sysvar ]\n");
-#if defined(HAVE_SCHED_SETSCHEDULER)
- (void) fprintf(stderr, "\t\t[ -P fixed_process_priority ]\n");
-#endif
-#ifdef HAVE_CLOCKCTL
- (void) fprintf(stderr, "\t\t[ -u user[:group] ] [ -i chrootdir ]\n");
-#endif
- exit(2);
- }
- ntp_optind = 0; /* reset ntp_optind to restart ntp_getopt */
-
-#ifdef DEBUG
- if (debug) {
-#ifdef HAVE_SETVBUF
- static char buf[BUFSIZ];
- setvbuf(stdout, buf, _IOLBF, BUFSIZ);
-#else
- setlinebuf(stdout);
-#endif
- }
-#endif
-}
-
-/*
- * getCmdOpts - get command line options
- */
-void
-getCmdOpts(
- int argc,
- char *argv[]
- )
-{
- extern char *config_file;
- struct sockaddr_in inaddrntp;
- int errflg;
- int c;
-
- /*
- * Initialize, initialize
- */
- errflg = 0;
-#ifdef DEBUG
- debug = 0;
-#endif /* DEBUG */
-
- progname = argv[0];
-
- /*
- * Decode argument list
- */
- while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF) {
- switch (c) {
- case 'a':
- proto_config(PROTO_AUTHENTICATE, 1, 0., NULL);
- break;
-
- case 'A':
- proto_config(PROTO_AUTHENTICATE, 0, 0., NULL);
- break;
-
- case 'b':
- proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
- break;
-
- case 'c':
- config_file = ntp_optarg;
-#ifdef HAVE_NETINFO
- check_netinfo = 0;
-#endif
- break;
-
- case 'd':
-#ifdef DEBUG
- debug++;
-#else
- errflg++;
-#endif /* DEBUG */
- break;
-
- case 'D':
-#ifdef DEBUG
- debug = (int)atol(ntp_optarg);
- printf("Debug2: %s -> %x = %d\n", ntp_optarg, debug, debug);
-#else
- errflg++;
-#endif /* DEBUG */
- break;
-
- case 'f':
- stats_config(STATS_FREQ_FILE, ntp_optarg);
- break;
-
- case 'g':
- allow_panic = TRUE;
- break;
-
- case 'i':
-#ifdef HAVE_CLOCKCTL
- if (!ntp_optarg)
- errflg++;
- else
- chrootdir = ntp_optarg;
- break;
-#else
- errflg++;
-#endif
- case 'k':
- getauthkeys(ntp_optarg);
- break;
-
- case 'L': /* already done at pre-scan */
- case 'l': /* already done at pre-scan */
- break;
-
- case 'm':
- inaddrntp.sin_family = AF_INET;
- inaddrntp.sin_port = htons(NTP_PORT);
- inaddrntp.sin_addr.s_addr = htonl(INADDR_NTP);
- proto_config(PROTO_MULTICAST_ADD, 0, 0., (struct sockaddr_storage*)&inaddrntp);
- sys_bclient = 1;
- break;
-
- case 'n': /* already done at pre-scan */
- break;
-
- case 'N': /* already done at pre-scan */
- break;
-
- case 'p':
- stats_config(STATS_PID_FILE, ntp_optarg);
- break;
-
- case 'P':
-#if defined(HAVE_SCHED_SETSCHEDULER)
- config_priority = (int)atol(ntp_optarg);
- config_priority_override = 1;
-#else
- errflg++;
-#endif
- break;
-
- case 'q':
- mode_ntpdate = TRUE;
- break;
-
- case 'r':
- do {
- double tmp;
-
- if (sscanf(ntp_optarg, "%lf", &tmp) != 1) {
- msyslog(LOG_ERR,
- "command line broadcast delay value %s undecodable",
- ntp_optarg);
- } else {
- proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
- }
- } while (0);
- break;
-
- case 'u':
-#ifdef HAVE_CLOCKCTL
- user = malloc(strlen(ntp_optarg) + 1);
- if ((user == NULL) || (ntp_optarg == NULL))
- errflg++;
- (void)strncpy(user, ntp_optarg, strlen(ntp_optarg) + 1);
- group = rindex(user, ':');
- if (group)
- *group++ = '\0'; /* get rid of the ':' */
-#else
- errflg++;
-#endif
- break;
- case 's':
- stats_config(STATS_STATSDIR, ntp_optarg);
- break;
-
- case 't':
- do {
- u_long tkey;
-
- tkey = (int)atol(ntp_optarg);
- if (tkey <= 0 || tkey > NTP_MAXKEY) {
- msyslog(LOG_ERR,
- "command line trusted key %s is invalid",
- ntp_optarg);
- } else {
- authtrust(tkey, 1);
- }
- } while (0);
- break;
-
- case 'v':
- case 'V':
- set_sys_var(ntp_optarg, strlen(ntp_optarg)+1,
- (u_short) (RW | ((c == 'V') ? DEF : 0)));
- break;
-
- case 'x':
- clock_max = 600;
- break;
-#ifdef SIM
- case 'B':
- sscanf(ntp_optarg, "%lf", &ntp_node.bdly);
- break;
-
- case 'C':
- sscanf(ntp_optarg, "%lf", &ntp_node.snse);
- break;
-
- case 'H':
- sscanf(ntp_optarg, "%lf", &ntp_node.slew);
- break;
-
- case 'O':
- sscanf(ntp_optarg, "%lf", &ntp_node.clk_time);
- break;
-
- case 'S':
- sscanf(ntp_optarg, "%lf", &ntp_node.sim_time);
- break;
-
- case 'T':
- sscanf(ntp_optarg, "%lf", &ntp_node.ferr);
- break;
-
- case 'W':
- sscanf(ntp_optarg, "%lf", &ntp_node.fnse);
- break;
-
- case 'Y':
- sscanf(ntp_optarg, "%lf", &ntp_node.ndly);
- break;
-
- case 'Z':
- sscanf(ntp_optarg, "%lf", &ntp_node.pdly);
- break;
-
-#endif /* SIM */
- default:
- errflg++;
- break;
- }
- }
-
- if (errflg || ntp_optind != argc) {
- (void) fprintf(stderr, "usage: %s [ -abdgmnx ] [ -c config_file ] [ -e e_delay ]\n", progname);
- (void) fprintf(stderr, "\t\t[ -f freq_file ] [ -k key_file ] [ -l log_file ]\n");
- (void) fprintf(stderr, "\t\t[ -p pid_file ] [ -r broad_delay ] [ -s statdir ]\n");
- (void) fprintf(stderr, "\t\t[ -t trust_key ] [ -v sys_var ] [ -V default_sysvar ]\n");
-#if defined(HAVE_SCHED_SETSCHEDULER)
- (void) fprintf(stderr, "\t\t[ -P fixed_process_priority ]\n");
-#endif
-#ifdef HAVE_CLOCKCTL
- (void) fprintf(stderr, "\t\t[ -u user[:group] ] [ -i chrootdir ]\n");
-#endif
- exit(2);
- }
- return;
-}
diff --git a/contrib/ntp/ntpd/jupiter.h b/contrib/ntp/ntpd/jupiter.h
deleted file mode 100644
index ed80b0c..0000000
--- a/contrib/ntp/ntpd/jupiter.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/* @(#) $Header$ (LBL) */
-
-/*
- * Rockwell Jupiter GPS receiver definitions
- *
- * This is all based on the "Zodiac GPS Receiver Family Designer's
- * Guide" (dated 12/96)
- */
-
-#define JUPITER_SYNC 0x81ff /* sync word (book says 0xff81 !?!?) */
-#define JUPITER_ALL 0xffff /* disable all output messages */
-
-/* Output messages (sent by the Jupiter board) */
-#define JUPITER_O_GPOS 1000 /* geodetic position status */
-#define JUPITER_O_EPOS 1001 /* ECEF position status */
-#define JUPITER_O_CHAN 1002 /* channel summary */
-#define JUPITER_O_VIS 1003 /* visible satellites */
-#define JUPITER_O_DGPS 1005 /* differential GPS status */
-#define JUPITER_O_MEAS 1007 /* channel measurement */
-#define JUPITER_O_ID 1011 /* receiver id */
-#define JUPITER_O_USER 1012 /* user-settings output */
-#define JUPITER_O_TEST 1100 /* built-in test results */
-#define JUPITER_O_MARK 1102 /* measurement time mark */
-#define JUPITER_O_PULSE 1108 /* UTC time mark pulse output */
-#define JUPITER_O_PORT 1130 /* serial port com parameters in use */
-#define JUPITER_O_EUP 1135 /* EEPROM update */
-#define JUPITER_O_ESTAT 1136 /* EEPROM status */
-
-/* Input messages (sent to the Jupiter board) */
-#define JUPITER_I_PVTINIT 1200 /* geodetic position and velocity */
-#define JUPITER_I_USER 1210 /* user-defined datum */
-#define JUPITER_I_MAPSEL 1211 /* map datum select */
-#define JUPITER_I_ELEV 1212 /* satellite elevation mask control */
-#define JUPITER_I_CAND 1213 /* satellite candidate select */
-#define JUPITER_I_DGPS 1214 /* differential GPS control */
-#define JUPITER_I_COLD 1216 /* cold start control */
-#define JUPITER_I_VALID 1217 /* solution validity criteria */
-#define JUPITER_I_ALT 1219 /* user-entered altitude input */
-#define JUPITER_I_PLAT 1220 /* application platform control */
-#define JUPITER_I_NAV 1221 /* nav configuration */
-#define JUPITER_I_TEST 1300 /* preform built-in test command */
-#define JUPITER_I_RESTART 1303 /* restart command */
-#define JUPITER_I_PORT 1330 /* serial port com parameters */
-#define JUPITER_I_PROTO 1331 /* message protocol control */
-#define JUPITER_I_RDGPS 1351 /* raw DGPS RTCM SC-104 data */
-
-struct jheader {
- u_short sync; /* (JUPITER_SYNC) */
- u_short id; /* message id */
- u_short len; /* number of data short wordss (w/o cksum) */
- u_char reqid; /* JUPITER_REQID_MASK bits available as id */
- u_char flags; /* flags */
- u_short hsum; /* header cksum */
-};
-
-#define JUPITER_REQID_MASK 0x3f /* bits available as id */
-#define JUPITER_FLAG_NAK 0x01 /* negative acknowledgement */
-#define JUPITER_FLAG_ACK 0x02 /* acknowledgement */
-#define JUPITER_FLAG_REQUEST 0x04 /* request ACK or NAK */
-#define JUPITER_FLAG_QUERY 0x08 /* request one shot output message */
-#define JUPITER_FLAG_LOG 0x20 /* request periodic output message */
-#define JUPITER_FLAG_CONN 0x40 /* enable periodic message */
-#define JUPITER_FLAG_DISC 0x80 /* disable periodic message */
-
-#define JUPITER_H_FLAG_BITS \
- "\020\1NAK\2ACK\3REQUEST\4QUERY\5MBZ\6LOG\7CONN\10DISC"
-
-/* Log request messages (data payload when using JUPITER_FLAG_LOG) */
-struct jrequest {
- u_short trigger; /* if 0, trigger on time trigger on
- update (e.g. new almanac) */
- u_short interval; /* frequency in seconds */
- u_short offset; /* offset into minute */
- u_short dsum; /* checksum */
-};
-
-/* JUPITER_O_GPOS (1000) */
-struct jgpos {
- u_short stime[2]; /* set time (10 ms ticks) */
- u_short seq; /* sequence number */
- u_short sseq; /* sat measurement sequence number */
- u_short navval; /* navigation soltuion validity */
- u_short navtype; /* navigation solution type */
- u_short nmeas; /* # of measurements used in solution */
- u_short polar; /* if 1 then polar navigation */
- u_short gweek; /* GPS week number */
- u_short sweek[2]; /* GPS seconds into week */
- u_short nsweek[2]; /* GPS nanoseconds into second */
- u_short utcday; /* 1 to 31 */
- u_short utcmon; /* 1 to 12 */
- u_short utcyear; /* 1980 to 2079 */
- u_short utchour; /* 0 to 23 */
- u_short utcmin; /* 0 to 59 */
- u_short utcsec; /* 0 to 59 */
- u_short utcnsec[2]; /* 0 to 999999999 */
- u_short lat[2]; /* latitude (radians) */
- u_short lon[2]; /* longitude (radians) */
- u_short height[2]; /* height (meters) */
- u_short gsep; /* geoidal separation */
- u_short speed[2]; /* ground speed (meters/sec) */
- u_short course; /* true course (radians) */
- u_short mvar;
- u_short climb;
- u_short mapd;
- u_short herr[2];
- u_short verr[2];
- u_short terr[2];
- u_short hverr;
- u_short bias[2];
- u_short biassd[2];
- u_short drift[2];
- u_short driftsd[2];
- u_short dsum; /* checksum */
-};
-#define JUPITER_O_GPOS_NAV_NOALT 0x01 /* altitude used */
-#define JUPITER_O_GPOS_NAV_NODGPS 0x02 /* no differential GPS */
-#define JUPITER_O_GPOS_NAV_NOSAT 0x04 /* not enough satellites */
-#define JUPITER_O_GPOS_NAV_MAXH 0x08 /* exceeded max EHPE */
-#define JUPITER_O_GPOS_NAV_MAXV 0x10 /* exceeded max EVPE */
-
-/* JUPITER_O_CHAN (1002) */
-struct jchan {
- u_short stime[2]; /* set time (10 ms ticks) */
- u_short seq; /* sequence number */
- u_short sseq; /* sat measurement sequence number */
- u_short gweek; /* GPS week number */
- u_short sweek[2]; /* GPS seconds into week */
- u_short gpsns[2]; /* GPS nanoseconds from epoch */
- struct jchan2 {
- u_short flags; /* flags */
- u_short prn; /* satellite PRN */
- u_short chan; /* channel number */
- } sat[12];
- u_short dsum;
-};
-
-/* JUPITER_O_VIS (1003) */
-struct jvis {
- u_short stime[2]; /* set time (10 ms ticks) */
- u_short seq; /* sequence number */
- u_short gdop; /* best possible GDOP */
- u_short pdop; /* best possible PDOP */
- u_short hdop; /* best possible HDOP */
- u_short vdop; /* best possible VDOP */
- u_short tdop; /* best possible TDOP */
- u_short nvis; /* number of visible satellites */
- struct jvis2 {
- u_short prn; /* satellite PRN */
- u_short azi; /* satellite azimuth (radians) */
- u_short elev; /* satellite elevation (radians) */
- } sat[12];
- u_short dsum; /* checksum */
-};
-
-/* JUPITER_O_ID (1011) */
-struct jid {
- u_short stime[2]; /* set time (10 ms ticks) */
- u_short seq; /* sequence number */
- char chans[20]; /* number of channels (ascii) */
- char vers[20]; /* software version (ascii) */
- char date[20]; /* software date (ascii) */
- char opts[20]; /* software options (ascii) */
- char reserved[20];
- u_short dsum; /* checksum */
-};
-
-/* JUPITER_O_USER (1012) */
-struct juser {
- u_short stime[2]; /* set time (10 ms ticks) */
- u_short seq; /* sequence number */
- u_short status; /* operatinoal status */
- u_short coldtmo; /* cold start time-out */
- u_short dgpstmo; /* DGPS correction time-out*/
- u_short emask; /* elevation mask */
- u_short selcand[2]; /* selected candidate */
- u_short solflags; /* solution validity criteria */
- u_short nsat; /* number of satellites in track */
- u_short herr[2]; /* minimum expected horizontal error */
- u_short verr[2]; /* minimum expected vertical error */
- u_short platform; /* application platform */
- u_short dsum; /* checksum */
-};
-
-/* JUPITER_O_PULSE (1108) */
-struct jpulse {
- u_short stime[2]; /* set time (10 ms ticks) */
- u_short seq; /* sequence number */
- u_short reserved[5];
- u_short sweek[2]; /* GPS seconds into week */
- short offs; /* GPS to UTC time offset (seconds) */
- u_short offns[2]; /* GPS to UTC offset (nanoseconds) */
- u_short flags; /* flags */
- u_short dsum; /* checksum */
-};
-#define JUPITER_O_PULSE_VALID 0x1 /* time mark validity */
-#define JUPITER_O_PULSE_UTC 0x2 /* GPS/UTC sync */
-
-/* JUPITER_O_EUP (1135) */
-struct jeup {
- u_short stime[2]; /* set time (10 ms ticks) */
- u_short seq; /* sequence number */
- u_char dataid; /* data id */
- u_char prn; /* satellite PRN */
- u_short dsum; /* checksum */
-};
-
-/* JUPITER_I_RESTART (1303) */
-struct jrestart {
- u_short seq; /* sequence number */
- u_short flags;
- u_short dsum; /* checksum */
-};
-#define JUPITER_I_RESTART_INVRAM 0x01
-#define JUPITER_I_RESTART_INVEEPROM 0x02
-#define JUPITER_I_RESTART_INVRTC 0x04
-#define JUPITER_I_RESTART_COLD 0x80
-
-/* JUPITER_I_PVTINIT (1200) */
-struct jpvtinit {
- u_short flags;
- u_short gweek; /* GPS week number */
- u_short sweek[2]; /* GPS seconds into week */
- u_short utcday; /* 1 to 31 */
- u_short utcmon; /* 1 to 12 */
- u_short utcyear; /* 1980 to 2079 */
- u_short utchour; /* 0 to 23 */
- u_short utcmin; /* 0 to 59 */
- u_short utcsec; /* 0 to 59 */
- u_short lat[2]; /* latitude (radians) */
- u_short lon[2]; /* longitude (radians) */
- u_short height[2]; /* height (meters) */
- u_short speed[2]; /* ground speed (meters/sec) */
- u_short course; /* true course (radians) */
- u_short climb;
- u_short dsum;
-};
-#define JUPITER_I_PVTINIT_FORCE 0x01
-#define JUPITER_I_PVTINIT_GPSVAL 0x02
-#define JUPITER_I_PVTINIT_UTCVAL 0x04
-#define JUPITER_I_PVTINIT_POSVAL 0x08
-#define JUPITER_I_PVTINIT_ALTVAL 0x10
-#define JUPITER_I_PVTINIT_SPDVAL 0x12
-#define JUPITER_I_PVTINIT_MAGVAL 0x14
-#define JUPITER_I_PVTINIT_CLIMBVAL 0x18
-
-/* JUPITER_I_PLAT (1220) */
-struct jplat {
- u_short seq; /* sequence number */
- u_short platform; /* application platform */
- u_short dsum;
-};
-#define JUPITER_I_PLAT_DEFAULT 0 /* default dynamics */
-#define JUPITER_I_PLAT_LOW 2 /* pedestrian */
-#define JUPITER_I_PLAT_MED 5 /* land (e.g. automobile) */
-#define JUPITER_I_PLAT_HIGH 6 /* air */
diff --git a/contrib/ntp/ntpd/map_vme.c b/contrib/ntp/ntpd/map_vme.c
deleted file mode 100644
index e4569ce..0000000
--- a/contrib/ntp/ntpd/map_vme.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/********************************************************/
-/* map_vme.c */
-/* VME control of TrueTime VME-SG sync gen card */
-/* and TrueTime GPS-VME receiver card */
-/* Version for 700 series HPUX 9.0 */
-/* Richard E.Schmidt, US Naval Observatory, Washington */
-/* 27 March 94 */
-/********************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_GPSVME)
-#include <stdio.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <sys/rtprio.h> /* for rtprio */
-#include <sys/lock.h> /* for plock */
-#include "/etc/conf/machine/vme2.h"
-#include "/etc/conf/h/io.h"
-#include "gps.h"
-
-/* GLOBALS */
-void *gps_base;
-unsigned short *greg[NREGS];
-struct vme2_map_addr ma; /* memory mapped structure */
-int fd; /* file descriptor for VME */
-
-void unmap_vme ();
-
-caddr_t
-map_vme (
- char *filename
- )
-{
- int ret;
- caddr_t base;
- struct vme2_io_testx tx;
- caddr_t cp;
-
-#define VME_START_ADDR 0x00000 /* Starting address in A16N VME Space */
-#define VMESIZE 0xFF /* 256 bytes of A16N space length */
-
- /*
- To create the HP9000/700 series device file, /dev/vme2:
- mknod /dev/vme2 c 44 0x0; chmod 600 /dev/vme2
-
- Then must create /etc/vme.CFG and run /etc/vme_config and reboot.
- */
- if ((fd = open (filename, O_RDWR)) < 0) {
- printf("ERROR: VME bus adapter open failed. errno:%d\n",
- errno);
- if(errno == ENODEV) {
- printf("ENODEV. Is driver in kernel? vme2 in dfile?\n");
- }
- exit(errno);
- }
- tx.card_type = VME_A16;
- tx.vme_addr = VME_START_ADDR;
- tx.width = SHORT_WIDE;
-
- if(ioctl(fd, VME2_IO_TESTR, &tx)) {
- printf("ioctl to test VME space failed. Errno: %d\n",
- errno);
- exit(errno);
- }
- if(tx.error)
- printf("io_testr failed internal error %d\n",tx.error);
- if(tx.access_result < 0) {
- printf("io_testr failed\n");
- exit(2);
- }
-
- /* If successful mmap the device */
- /* NOW MAP THE CARD */
- ma.card_type = VME_A16;
- ma.vme_addr = VME_START_ADDR;
- ma.size = VMESIZE;
-
- if(ioctl(fd, VME2_MAP_ADDR, &ma)) {
- printf("ioctl to map VME space failed. Errno: %d\n",
- errno);
- exit(errno);
- }
- if(ma.error) {
- printf("ioctl to map VME failed\n");
- exit(ENOMEM);
- }
- base = ma.user_addr;
- return(base);
-}
-
-
-void
-unmap_vme(void)
-{
- if(ioctl(fd, VME2_UNMAP_ADDR, &ma))
- printf("ioctl to unmap VME space failed. Errno: %d\n",
- errno);
- close(fd);
- return;
-}
-
-
-int
-init_vme(boid)
-{
- /* set up address offsets */
-
- gps_base = map_vme (GPS_VME);
-
-/* offsets from base address: */
-
- greg[0] = (unsigned short *)gps_base + GFRZ1;
- greg[1] = (unsigned short *)gps_base + GUFRZ1;
- greg[2] = (unsigned short *)gps_base + GREG1A;
- greg[3] = (unsigned short *)gps_base + GREG1B;
- greg[4] = (unsigned short *)gps_base + GREG1C;
- greg[5] = (unsigned short *)gps_base + GREG1D;
- greg[6] = (unsigned short *)gps_base + GREG1E;
-
- return (0);
-}
-
-#else /* not (REFCLOCK && CLOCK_GPSVME) */
-int map_vme_bs;
-#endif /* not (REFCLOCK && CLOCK_GPSVME) */
diff --git a/contrib/ntp/ntpd/ntp_config.c b/contrib/ntp/ntpd/ntp_config.c
deleted file mode 100644
index f1428b1..0000000
--- a/contrib/ntp/ntpd/ntp_config.c
+++ /dev/null
@@ -1,2371 +0,0 @@
-/*
- * ntp_config.c - read and apply configuration information
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef HAVE_NETINFO
-# include <netinfo/ni.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_filegen.h"
-#include "ntp_stdlib.h"
-#include "ntp_config.h"
-#include "ntp_cmdargs.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <signal.h>
-#ifndef SIGCHLD
-# define SIGCHLD SIGCLD
-#endif
-#if !defined(VMS)
-# ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-# endif
-#endif /* VMS */
-
-#ifdef SYS_WINNT
-# include <io.h>
-extern HANDLE ResolverThreadHandle;
-#endif /* SYS_WINNT */
-
-#include <netdb.h>
-
-extern int priority_done;
-
-/*
- * These routines are used to read the configuration file at
- * startup time. An entry in the file must fit on a single line.
- * Entries are processed as multiple tokens separated by white space
- * Lines are considered terminated when a '#' is encountered. Blank
- * lines are ignored.
- */
-/*
- * Translation table - keywords to function index
- */
-struct keyword {
- const char *text;
- int keytype;
-};
-
-/*
- * Command keywords
- */
-static struct keyword keywords[] = {
- { "automax", CONFIG_AUTOMAX },
- { "broadcast", CONFIG_BROADCAST },
- { "broadcastclient", CONFIG_BROADCASTCLIENT },
- { "broadcastdelay", CONFIG_BDELAY },
- { "calldelay", CONFIG_CDELAY},
-#ifdef OPENSSL
- { "crypto", CONFIG_CRYPTO },
-#endif /* OPENSSL */
- { "controlkey", CONFIG_CONTROLKEY },
- { "disable", CONFIG_DISABLE },
- { "driftfile", CONFIG_DRIFTFILE },
- { "enable", CONFIG_ENABLE },
- { "filegen", CONFIG_FILEGEN },
- { "fudge", CONFIG_FUDGE },
- { "includefile", CONFIG_INCLUDEFILE },
- { "keys", CONFIG_KEYS },
- { "keysdir", CONFIG_KEYSDIR },
- { "logconfig", CONFIG_LOGCONFIG },
- { "logfile", CONFIG_LOGFILE },
- { "manycastclient", CONFIG_MANYCASTCLIENT },
- { "manycastserver", CONFIG_MANYCASTSERVER },
- { "multicastclient", CONFIG_MULTICASTCLIENT },
- { "peer", CONFIG_PEER },
- { "phone", CONFIG_PHONE },
- { "pidfile", CONFIG_PIDFILE },
- { "discard", CONFIG_DISCARD },
- { "requestkey", CONFIG_REQUESTKEY },
- { "restrict", CONFIG_RESTRICT },
- { "revoke", CONFIG_REVOKE },
- { "server", CONFIG_SERVER },
- { "setvar", CONFIG_SETVAR },
- { "statistics", CONFIG_STATISTICS },
- { "statsdir", CONFIG_STATSDIR },
- { "tick", CONFIG_ADJ },
- { "tinker", CONFIG_TINKER },
- { "tos", CONFIG_TOS },
- { "trap", CONFIG_TRAP },
- { "trustedkey", CONFIG_TRUSTEDKEY },
- { "ttl", CONFIG_TTL },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "peer", "server", "broadcast" modifier keywords
- */
-static struct keyword mod_keywords[] = {
- { "autokey", CONF_MOD_SKEY },
- { "burst", CONF_MOD_BURST },
- { "iburst", CONF_MOD_IBURST },
- { "key", CONF_MOD_KEY },
- { "maxpoll", CONF_MOD_MAXPOLL },
- { "minpoll", CONF_MOD_MINPOLL },
- { "mode", CONF_MOD_MODE }, /* refclocks */
- { "noselect", CONF_MOD_NOSELECT },
- { "prefer", CONF_MOD_PREFER },
- { "ttl", CONF_MOD_TTL }, /* NTP peers */
- { "version", CONF_MOD_VERSION },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "restrict" modifier keywords
- */
-static struct keyword res_keywords[] = {
- { "ignore", CONF_RES_IGNORE },
- { "limited", CONF_RES_LIMITED },
- { "kod", CONF_RES_DEMOBILIZE },
- { "lowpriotrap", CONF_RES_LPTRAP },
- { "mask", CONF_RES_MASK },
- { "nomodify", CONF_RES_NOMODIFY },
- { "nopeer", CONF_RES_NOPEER },
- { "noquery", CONF_RES_NOQUERY },
- { "noserve", CONF_RES_NOSERVE },
- { "notrap", CONF_RES_NOTRAP },
- { "notrust", CONF_RES_NOTRUST },
- { "ntpport", CONF_RES_NTPPORT },
- { "version", CONF_RES_VERSION },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "trap" modifier keywords
- */
-static struct keyword trap_keywords[] = {
- { "port", CONF_TRAP_PORT },
- { "interface", CONF_TRAP_INTERFACE },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "fudge" modifier keywords
- */
-static struct keyword fudge_keywords[] = {
- { "flag1", CONF_FDG_FLAG1 },
- { "flag2", CONF_FDG_FLAG2 },
- { "flag3", CONF_FDG_FLAG3 },
- { "flag4", CONF_FDG_FLAG4 },
- { "refid", CONF_FDG_REFID },
- { "stratum", CONF_FDG_STRATUM },
- { "time1", CONF_FDG_TIME1 },
- { "time2", CONF_FDG_TIME2 },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "filegen" modifier keywords
- */
-static struct keyword filegen_keywords[] = {
- { "disable", CONF_FGEN_FLAG_DISABLE },
- { "enable", CONF_FGEN_FLAG_ENABLE },
- { "file", CONF_FGEN_FILE },
- { "link", CONF_FGEN_FLAG_LINK },
- { "nolink", CONF_FGEN_FLAG_NOLINK },
- { "type", CONF_FGEN_TYPE },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "type" modifier keywords
- */
-static struct keyword fgen_types[] = {
- { "age", FILEGEN_AGE },
- { "day", FILEGEN_DAY },
- { "month", FILEGEN_MONTH },
- { "none", FILEGEN_NONE },
- { "pid", FILEGEN_PID },
- { "week", FILEGEN_WEEK },
- { "year", FILEGEN_YEAR },
- { "", CONFIG_UNKNOWN}
-};
-
-/*
- * "enable", "disable" modifier keywords
- */
-static struct keyword flags_keywords[] = {
- { "auth", PROTO_AUTHENTICATE },
- { "bclient", PROTO_BROADCLIENT },
- { "calibrate", PROTO_CAL },
- { "kernel", PROTO_KERNEL },
- { "monitor", PROTO_MONITOR },
- { "ntp", PROTO_NTP },
- { "pps", PROTO_PPS },
- { "stats", PROTO_FILEGEN },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "discard" modifier keywords
- */
-static struct keyword discard_keywords[] = {
- { "average", CONF_DISCARD_AVERAGE },
- { "minimum", CONF_DISCARD_MINIMUM },
- { "monitor", CONF_DISCARD_MONITOR },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "tinker" modifier keywords
- */
-static struct keyword tinker_keywords[] = {
- { "step", CONF_CLOCK_MAX },
- { "panic", CONF_CLOCK_PANIC },
- { "dispersion", CONF_CLOCK_PHI },
- { "stepout", CONF_CLOCK_MINSTEP },
- { "allan", CONF_CLOCK_ALLAN },
- { "huffpuff", CONF_CLOCK_HUFFPUFF },
- { "freq", CONF_CLOCK_FREQ },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "tos" modifier keywords
- */
-static struct keyword tos_keywords[] = {
- { "minclock", CONF_TOS_MINCLOCK },
- { "minsane", CONF_TOS_MINSANE },
- { "floor", CONF_TOS_FLOOR },
- { "ceiling", CONF_TOS_CEILING },
- { "cohort", CONF_TOS_COHORT },
- { "", CONFIG_UNKNOWN }
-};
-
-#ifdef OPENSSL
-/*
- * "crypto" modifier keywords
- */
-static struct keyword crypto_keywords[] = {
- { "cert", CONF_CRYPTO_CERT },
- { "gqpar", CONF_CRYPTO_GQPAR },
- { "host", CONF_CRYPTO_RSA },
- { "iffpar", CONF_CRYPTO_IFFPAR },
- { "leap", CONF_CRYPTO_LEAP },
- { "mvpar", CONF_CRYPTO_MVPAR },
- { "pw", CONF_CRYPTO_PW },
- { "randfile", CONF_CRYPTO_RAND },
- { "sign", CONF_CRYPTO_SIGN },
- { "", CONFIG_UNKNOWN }
-};
-#endif /* OPENSSL */
-
-/*
- * Address type selection, IPv4 or IPv4.
- * Used on various lines.
- */
-static struct keyword addr_type[] = {
- { "-4", CONF_ADDR_IPV4 },
- { "-6", CONF_ADDR_IPV6 },
- { "", CONFIG_UNKNOWN }
-};
-
-/*
- * "logconfig" building blocks
- */
-struct masks {
- const char *name;
- unsigned long mask;
-};
-
-static struct masks logcfg_class[] = {
- { "clock", NLOG_OCLOCK },
- { "peer", NLOG_OPEER },
- { "sync", NLOG_OSYNC },
- { "sys", NLOG_OSYS },
- { (char *)0, 0 }
-};
-
-static struct masks logcfg_item[] = {
- { "info", NLOG_INFO },
- { "allinfo", NLOG_SYSINFO|NLOG_PEERINFO|NLOG_CLOCKINFO|NLOG_SYNCINFO },
- { "events", NLOG_EVENT },
- { "allevents", NLOG_SYSEVENT|NLOG_PEEREVENT|NLOG_CLOCKEVENT|NLOG_SYNCEVENT },
- { "status", NLOG_STATUS },
- { "allstatus", NLOG_SYSSTATUS|NLOG_PEERSTATUS|NLOG_CLOCKSTATUS|NLOG_SYNCSTATUS },
- { "statistics", NLOG_STATIST },
- { "allstatistics", NLOG_SYSSTATIST|NLOG_PEERSTATIST|NLOG_CLOCKSTATIST|NLOG_SYNCSTATIST },
- { "allclock", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OCLOCK },
- { "allpeer", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OPEER },
- { "allsys", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS },
- { "allsync", (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC },
- { "all", NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK },
- { (char *)0, 0 }
-};
-
-/*
- * 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 MAXPPS 20 /* maximum length of PPS device string */
-#define MAXINCLUDELEVEL 5 /* maximum include file levels */
-
-/*
- * Miscellaneous macros
- */
-#define STRSAME(s1, s2) (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
-#define ISEOL(c) ((c) == '#' || (c) == '\n' || (c) == '\0')
-#define ISSPACE(c) ((c) == ' ' || (c) == '\t')
-#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
-
-#define KEY_TYPE_MD5 4
-
-/*
- * File descriptor used by the resolver save routines, and temporary file
- * name.
- */
-int call_resolver = 1; /* ntp-genkeys sets this to 0, for example */
-static FILE *res_fp;
-#ifndef SYS_WINNT
-static char res_file[20]; /* enough for /tmp/ntpXXXXXX\0 */
-#define RES_TEMPFILE "/tmp/ntpXXXXXX"
-#else
-static char res_file[MAX_PATH];
-#endif /* SYS_WINNT */
-
-/*
- * Definitions of things either imported from or exported to outside
- */
-char const *progname;
-char sys_phone[MAXPHONE][MAXDIAL]; /* ACTS phone numbers */
-char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
-char pps_device[MAXPPS + 1]; /* PPS device name */
-#if defined(HAVE_SCHED_SETSCHEDULER)
-int config_priority_override = 0;
-int config_priority;
-#endif
-
-const char *config_file;
-#ifdef HAVE_NETINFO
- struct netinfo_config_state *config_netinfo = NULL;
- int check_netinfo = 1;
-#endif /* HAVE_NETINFO */
-#ifdef SYS_WINNT
- char *alt_config_file;
- LPTSTR temp;
- char config_file_storage[MAX_PATH];
- char alt_config_file_storage[MAX_PATH];
-#endif /* SYS_WINNT */
-
-#ifdef HAVE_NETINFO
-/*
- * NetInfo configuration state
- */
-struct netinfo_config_state {
- void *domain; /* domain with config */
- ni_id config_dir; /* ID config dir */
- int prop_index; /* current property */
- int val_index; /* current value */
- char **val_list; /* value list */
-};
-#endif
-
-/*
- * Function prototypes
- */
-static unsigned long get_pfxmatch P((char **, struct masks *));
-static unsigned long get_match P((char *, struct masks *));
-static unsigned long get_logmask P((char *));
-#ifdef HAVE_NETINFO
-static struct netinfo_config_state *get_netinfo_config P((void));
-static void free_netinfo_config P((struct netinfo_config_state *));
-static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
-#endif
-static int gettokens P((FILE *, char *, char **, int *));
-static int matchkey P((char *, struct keyword *, int));
-static int getnetnum P((const char *, struct sockaddr_storage *, int));
-static void save_resolve P((char *, int, int, int, int, u_int, int,
- keyid_t, u_char *));
-static void do_resolve_internal P((void));
-static void abort_resolve P((void));
-#if !defined(VMS) && !defined(SYS_WINNT)
-static RETSIGTYPE catchchild P((int));
-#endif /* VMS */
-
-/*
- * get_pfxmatch - find value for prefixmatch
- * and update char * accordingly
- */
-static unsigned long
-get_pfxmatch(
- char ** s,
- struct masks *m
- )
-{
- while (m->name) {
- if (strncmp(*s, m->name, strlen(m->name)) == 0) {
- *s += strlen(m->name);
- return m->mask;
- } else {
- m++;
- }
- }
- return 0;
-}
-
-/*
- * get_match - find logmask value
- */
-static unsigned long
-get_match(
- char *s,
- struct masks *m
- )
-{
- while (m->name) {
- if (strcmp(s, m->name) == 0) {
- return m->mask;
- } else {
- m++;
- }
- }
- return 0;
-}
-
-/*
- * get_logmask - build bitmask for ntp_syslogmask
- */
-static unsigned long
-get_logmask(
- char *s
- )
-{
- char *t;
- unsigned long offset;
- unsigned long mask;
-
- t = s;
- offset = get_pfxmatch(&t, logcfg_class);
- mask = get_match(t, logcfg_item);
-
- if (mask)
- return mask << offset;
- else
- msyslog(LOG_ERR, "logconfig: illegal argument %s - ignored", s);
-
- return 0;
-}
-
-
-/*
- * getconfig - get command line options and read the configuration file
- */
-void
-getconfig(
- int argc,
- char *argv[]
- )
-{
- register int i;
- int c;
- int errflg;
- int istart;
- int peerversion;
- int minpoll;
- int maxpoll;
- int ttl;
- long stratum;
- unsigned long ul;
- keyid_t peerkey;
- u_char *peerkeystr;
- u_long fudgeflag;
- u_int peerflags;
- int hmode;
- struct sockaddr_storage peeraddr;
- struct sockaddr_storage maskaddr;
- FILE *fp[MAXINCLUDELEVEL+1];
- FILE *includefile;
- int includelevel = 0;
- char line[MAXLINE];
- char *(tokens[MAXTOKENS]);
- int ntokens = 0;
- int tok = CONFIG_UNKNOWN;
- struct interface *localaddr;
- struct refclockstat clock_stat;
- FILEGEN *filegen;
-
- /*
- * Initialize, initialize
- */
- errflg = 0;
- /* HMS: don't initialize debug to 0 here! */
-#ifndef SYS_WINNT
- config_file = CONFIG_FILE;
-#else
- temp = CONFIG_FILE;
- if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)config_file_storage, (DWORD)sizeof(config_file_storage))) {
- msyslog(LOG_ERR, "ExpandEnvironmentStrings CONFIG_FILE failed: %m\n");
- exit(1);
- }
- config_file = config_file_storage;
-
- temp = ALT_CONFIG_FILE;
- if (!ExpandEnvironmentStrings((LPCTSTR)temp, (LPTSTR)alt_config_file_storage, (DWORD)sizeof(alt_config_file_storage))) {
- msyslog(LOG_ERR, "ExpandEnvironmentStrings ALT_CONFIG_FILE failed: %m\n");
- exit(1);
- }
- alt_config_file = alt_config_file_storage;
-
-#endif /* SYS_WINNT */
- progname = argv[0];
- res_fp = NULL;
- memset((char *)sys_phone, 0, sizeof(sys_phone));
- ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
-
- /*
- * install a non default variable with this daemon version
- */
- (void) sprintf(line, "daemon_version=\"%s\"", Version);
- set_sys_var(line, strlen(line)+1, RO);
-
- /*
- * Say how we're setting the time of day
- */
- (void) sprintf(line, "settimeofday=\"%s\"", set_tod_using);
- set_sys_var(line, strlen(line)+1, RO);
-
- /*
- * Initialize the loop.
- */
- loop_config(LOOP_DRIFTINIT, 0.);
-
- getCmdOpts(argc, argv);
-
- if (
- (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
-#ifdef HAVE_NETINFO
- /* If there is no config_file, try NetInfo. */
- && check_netinfo && !(config_netinfo = get_netinfo_config())
-#endif /* HAVE_NETINFO */
- ) {
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(config_file));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(config_file));
-#ifdef SYS_WINNT
- /* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
-
- if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
-
- /*
- * Broadcast clients can sometimes run without
- * a configuration file.
- */
-
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(alt_config_file));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(alt_config_file));
- return;
- }
-#else /* not SYS_WINNT */
- return;
-#endif /* not SYS_WINNT */
- }
-
- for (;;) {
- if (fp[includelevel])
- tok = gettokens(fp[includelevel], line, tokens, &ntokens);
-#ifdef HAVE_NETINFO
- else
- tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
-#endif /* HAVE_NETINFO */
-
- if (tok == CONFIG_UNKNOWN) {
- if (includelevel > 0) {
- fclose(fp[includelevel--]);
- continue;
- } else {
- break;
- }
- }
-
- switch(tok) {
- case CONFIG_PEER:
- case CONFIG_SERVER:
- case CONFIG_MANYCASTCLIENT:
- case CONFIG_BROADCAST:
- if (tok == CONFIG_PEER)
- hmode = MODE_ACTIVE;
- else if (tok == CONFIG_SERVER)
- hmode = MODE_CLIENT;
- else if (tok == CONFIG_MANYCASTCLIENT)
- hmode = MODE_CLIENT;
- else
- hmode = MODE_BROADCAST;
-
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "No address for %s, line ignored",
- tokens[0]);
- break;
- }
-
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
- break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
- break;
- }
-
- if (!getnetnum(tokens[istart], &peeraddr, 0)) {
- errflg = -1;
- } else {
- errflg = 0;
-
- if (
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- ISBADADR(&peeraddr)) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
- break;
- }
- /*
- * Shouldn't be able to specify multicast
- * address for server/peer!
- * and unicast address for manycastclient!
- */
- if (peeraddr.ss_family == AF_INET) {
- if (((tok == CONFIG_SERVER) ||
- (tok == CONFIG_PEER)) &&
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
- break;
- }
- if ((tok == CONFIG_MANYCASTCLIENT) &&
- !IN_CLASSD(ntohl(((struct sockaddr_in*)&peeraddr)->sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- stoa(&peeraddr));
- break;
- }
- }
- else if(peeraddr.ss_family == AF_INET6) {
- if (((tok == CONFIG_SERVER) ||
- (tok == CONFIG_PEER)) &&
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
- msyslog(LOG_ERR,
- "attempt to configure in valid address %s",
- stoa(&peeraddr));
- break;
- }
- if ((tok == CONFIG_MANYCASTCLIENT) &&
- !IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)&peeraddr)->sin6_addr)) {
- msyslog(LOG_ERR,
- "attempt to configure in valid address %s",
- stoa(&peeraddr));
- break;
- }
- }
- }
-
- peerversion = NTP_VERSION;
- minpoll = NTP_MINDPOLL;
- maxpoll = NTP_MAXDPOLL;
- peerkey = 0;
- peerkeystr = (u_char *)"*";
- peerflags = 0;
- ttl = 0;
- istart++;
- for (i = istart; i < ntokens; i++)
- switch (matchkey(tokens[i], mod_keywords, 1)) {
- case CONF_MOD_VERSION:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "peer/server version requires an argument");
- errflg = 1;
- break;
- }
- peerversion = atoi(tokens[++i]);
- if ((u_char)peerversion > NTP_VERSION
- || (u_char)peerversion < NTP_OLDVERSION) {
- msyslog(LOG_ERR,
- "inappropriate version number %s, line ignored",
- tokens[i]);
- errflg = 1;
- }
- break;
-
- case CONF_MOD_KEY:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "key: argument required");
- errflg = 1;
- break;
- }
- peerkey = (int)atol(tokens[++i]);
- peerflags |= FLAG_AUTHENABLE;
- break;
-
- case CONF_MOD_MINPOLL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "minpoll: argument required");
- errflg = 1;
- break;
- }
- minpoll = atoi(tokens[++i]);
- if (minpoll < NTP_MINPOLL) {
- msyslog(LOG_INFO,
- "minpoll: provided value (%d) is below minimum (%d)",
- minpoll, NTP_MINPOLL);
- minpoll = NTP_MINPOLL;
- }
- break;
-
- case CONF_MOD_MAXPOLL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "maxpoll: argument required"
- );
- errflg = 1;
- break;
- }
- maxpoll = atoi(tokens[++i]);
- if (maxpoll > NTP_MAXPOLL) {
- msyslog(LOG_INFO,
- "maxpoll: provided value (%d) is above maximum (%d)",
- maxpoll, NTP_MAXPOLL);
- maxpoll = NTP_MAXPOLL;
- }
- break;
-
- case CONF_MOD_PREFER:
- peerflags |= FLAG_PREFER;
- break;
-
- case CONF_MOD_NOSELECT:
- peerflags |= FLAG_NOSELECT;
- break;
-
- case CONF_MOD_BURST:
- peerflags |= FLAG_BURST;
- break;
-
- case CONF_MOD_IBURST:
- peerflags |= FLAG_IBURST;
- break;
-#ifdef OPENSSL
- case CONF_MOD_SKEY:
- peerflags |= FLAG_SKEY |
- FLAG_AUTHENABLE;
- break;
-#endif /* OPENSSL */
-
- case CONF_MOD_TTL:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "ttl: argument required");
- errflg = 1;
- break;
- }
- ttl = atoi(tokens[++i]);
- if (ttl >= MAX_TTL) {
- msyslog(LOG_ERR,
- "ttl: invalid argument");
- errflg = 1;
- }
- break;
-
- case CONF_MOD_MODE:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "mode: argument required");
- errflg = 1;
- break;
- }
- ttl = atoi(tokens[++i]);
- break;
-
- case CONFIG_UNKNOWN:
- errflg = 1;
- break;
- }
- if (minpoll > maxpoll) {
- msyslog(LOG_ERR,
- "config error: minpoll > maxpoll");
- errflg = 1;
- }
- if (errflg == 0) {
- if (peer_config(&peeraddr,
- ANY_INTERFACE_CHOOSE(&peeraddr), hmode,
- peerversion, minpoll, maxpoll, peerflags,
- ttl, peerkey, peerkeystr) == 0) {
- msyslog(LOG_ERR,
- "configuration of %s failed",
- stoa(&peeraddr));
- }
- if (tok == CONFIG_MANYCASTCLIENT)
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., &peeraddr);
-
- } else if (errflg == -1) {
- save_resolve(tokens[1], hmode, peerversion,
- minpoll, maxpoll, peerflags, ttl,
- peerkey, peerkeystr);
- }
- break;
-
- case CONFIG_DRIFTFILE:
- if (ntokens >= 2)
- stats_config(STATS_FREQ_FILE, tokens[1]);
- else
- stats_config(STATS_FREQ_FILE, (char *)0);
- break;
-
- case CONFIG_PIDFILE:
- if (ntokens >= 2)
- stats_config(STATS_PID_FILE, tokens[1]);
- else
- stats_config(STATS_PID_FILE, (char *)0);
- break;
-
- case CONFIG_INCLUDEFILE:
- if (ntokens < 2) {
- msyslog(LOG_ERR, "includefile needs one argument");
- break;
- }
- if (includelevel >= MAXINCLUDELEVEL) {
- fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
- msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
- break;
- }
- includefile = fopen(FindConfig(tokens[1]), "r");
- if (includefile == NULL) {
- fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
- break;
- }
- fp[++includelevel] = includefile;
- break;
-
- case CONFIG_LOGFILE:
- if (ntokens >= 2) {
- FILE *new_file;
-
- new_file = fopen(tokens[1], "a");
- if (new_file != NULL) {
- NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "logging to file %s", tokens[1]);
- if (syslog_file != NULL &&
- fileno(syslog_file) != fileno(new_file))
- (void)fclose(syslog_file);
-
- syslog_file = new_file;
- syslogit = 0;
- }
- else
- msyslog(LOG_ERR,
- "Cannot open log file %s",
- tokens[1]);
- }
- else
- msyslog(LOG_ERR, "logfile needs one argument");
- break;
-
- case CONFIG_LOGCONFIG:
- for (i = 1; i < ntokens; i++)
- {
- int add = 1;
- int equals = 0;
- char * s = &tokens[i][0];
-
- switch (*s) {
- case '+':
- case '-':
- case '=':
- add = *s == '+';
- equals = *s == '=';
- s++;
- break;
-
- default:
- break;
- }
- if (equals) {
- ntp_syslogmask = get_logmask(s);
- } else {
- if (add) {
- ntp_syslogmask |= get_logmask(s);
- } else {
- ntp_syslogmask &= ~get_logmask(s);
- }
- }
-#ifdef DEBUG
- if (debug)
- printf("ntp_syslogmask = 0x%08lx (%s)\n", ntp_syslogmask, tokens[i]);
-#endif
- }
- break;
-
- case CONFIG_BROADCASTCLIENT:
- proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
- break;
-
- case CONFIG_MULTICASTCLIENT:
- case CONFIG_MANYCASTSERVER:
- if (ntokens > 1) {
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- switch (matchkey(tokens[istart],
- addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
- break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
- break;
- }
- /*
- * Abuse maskaddr to store the prefered ip
- * version.
- */
- memset((char *)&maskaddr, 0, sizeof(maskaddr));
- maskaddr.ss_family = peeraddr.ss_family;
-
- for (i = istart; i < ntokens; i++) {
- memset((char *)&peeraddr, 0,
- sizeof(peeraddr));
- peeraddr.ss_family = maskaddr.ss_family;
- if (getnetnum(tokens[i], &peeraddr, 1))
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., &peeraddr);
- }
- } else
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., NULL);
- if (tok == CONFIG_MULTICASTCLIENT)
- sys_bclient = 1;
- else if (tok == CONFIG_MANYCASTSERVER)
- sys_manycastserver = 1;
- break;
-
- case CONFIG_KEYS:
- if (ntokens >= 2) {
- getauthkeys(tokens[1]);
- }
- break;
-
- case CONFIG_KEYSDIR:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "Keys directory name required");
- break;
- }
- keysdir = emalloc(strlen(tokens[1]) + 1);
- strcpy(keysdir, tokens[1]);
- break;
-
- case CONFIG_TINKER:
- for (i = 1; i < ntokens; i++) {
- int temp;
- double ftemp;
-
- temp = matchkey(tokens[i++], tinker_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "tinker: missing argument");
- errflg++;
- break;
- }
- sscanf(tokens[i], "%lf", &ftemp);
- switch(temp) {
-
- case CONF_CLOCK_MAX:
- loop_config(LOOP_MAX, ftemp);
- break;
-
- case CONF_CLOCK_PANIC:
- loop_config(LOOP_PANIC, ftemp);
- break;
-
- case CONF_CLOCK_PHI:
- loop_config(LOOP_PHI, ftemp);
- break;
-
- case CONF_CLOCK_MINSTEP:
- loop_config(LOOP_MINSTEP, ftemp);
- break;
-
- case CONF_CLOCK_ALLAN:
- loop_config(LOOP_ALLAN, ftemp);
- break;
-
- case CONF_CLOCK_HUFFPUFF:
- loop_config(LOOP_HUFFPUFF, ftemp);
- break;
-
- case CONF_CLOCK_FREQ:
- loop_config(LOOP_FREQ, ftemp);
- break;
- }
- }
- break;
-
- case CONFIG_TOS:
- for (i = 1; i < ntokens; i++) {
- int temp;
- double ftemp;
-
- temp = matchkey(tokens[i++], tos_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "tinker: missing argument");
- errflg++;
- break;
- }
- sscanf(tokens[i], "%lf", &ftemp);
- switch(temp) {
-
- case CONF_TOS_MINCLOCK:
- proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
- break;
-
- case CONF_TOS_MINSANE:
- proto_config(PROTO_MINSANE, 0, ftemp, NULL);
- break;
-
- case CONF_TOS_FLOOR:
- proto_config(PROTO_FLOOR, 0, ftemp, NULL);
- break;
-
- case CONF_TOS_CEILING:
- proto_config(PROTO_CEILING, 0, ftemp, NULL);
- break;
-
- case CONF_TOS_COHORT:
- proto_config(PROTO_COHORT, 0, ftemp, NULL);
- break;
- }
- }
- break;
-
- case CONFIG_TTL:
- for (i = 1; i < ntokens && i < MAX_TTL; i++) {
- sys_ttl[i - 1] = (u_char) atoi(tokens[i]);
- sys_ttlmax = i - 1;
- }
- break;
-
- case CONFIG_DISCARD:
- for (i = 1; i < ntokens; i++) {
- int temp;
-
- temp = matchkey(tokens[i++],
- discard_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "discard: missing argument");
- errflg++;
- break;
- }
- switch(temp) {
- case CONF_DISCARD_AVERAGE:
- res_avg_interval = atoi(tokens[i++]);
- break;
-
- case CONF_DISCARD_MINIMUM:
- res_min_interval = atoi(tokens[i++]);
- break;
-
- case CONF_DISCARD_MONITOR:
- mon_age = atoi(tokens[i++]);
- break;
-
- default:
- msyslog(LOG_ERR,
- "discard: unknown keyword");
- break;
- }
- }
- break;
-
-#ifdef OPENSSL
- case CONFIG_REVOKE:
- if (ntokens >= 2)
- sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
- break;
-
- case CONFIG_AUTOMAX:
- if (ntokens >= 2)
- sys_automax = 1 << max(atoi(tokens[1]), 10);
- break;
-
- case CONFIG_CRYPTO:
- if (ntokens == 1) {
- crypto_config(CRYPTO_CONF_NONE, NULL);
- break;
- }
- for (i = 1; i < ntokens; i++) {
- int temp;
-
- temp = matchkey(tokens[i++],
- crypto_keywords, 1);
- if (i > ntokens - 1) {
- msyslog(LOG_ERR,
- "crypto: missing argument");
- errflg++;
- break;
- }
- switch(temp) {
-
- case CONF_CRYPTO_CERT:
- crypto_config(CRYPTO_CONF_CERT,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_RSA:
- crypto_config(CRYPTO_CONF_PRIV,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_IFFPAR:
- crypto_config(CRYPTO_CONF_IFFPAR,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_GQPAR:
- crypto_config(CRYPTO_CONF_GQPAR,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_MVPAR:
- crypto_config(CRYPTO_CONF_MVPAR,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_LEAP:
- crypto_config(CRYPTO_CONF_LEAP,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_PW:
- crypto_config(CRYPTO_CONF_PW,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_RAND:
- crypto_config(CRYPTO_CONF_RAND,
- tokens[i]);
- break;
-
- case CONF_CRYPTO_SIGN:
- crypto_config(CRYPTO_CONF_SIGN,
- tokens[i]);
- break;
-
- default:
- msyslog(LOG_ERR,
- "crypto: unknown keyword");
- break;
- }
- }
- break;
-#endif /* OPENSSL */
-
- case CONFIG_RESTRICT:
- if (ntokens < 2) {
- msyslog(LOG_ERR, "restrict requires an address");
- break;
- }
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
- break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
- break;
- }
-
- /*
- * Assume default means an IPv4 address, except
- * if forced by a -4 or -6.
- */
- if (STREQ(tokens[istart], "default")) {
- if (peeraddr.ss_family == 0)
- peeraddr.ss_family = AF_INET;
- } else if (!getnetnum(tokens[istart], &peeraddr, 1))
- break;
-
- /*
- * Use peerversion as flags, peerkey as mflags. Ick.
- */
- peerversion = 0;
- peerkey = 0;
- errflg = 0;
- SET_HOSTMASK(&maskaddr, peeraddr.ss_family);
- istart++;
- for (i = istart; i < ntokens; i++) {
- switch (matchkey(tokens[i], res_keywords, 1)) {
- case CONF_RES_MASK:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "mask keyword needs argument");
- errflg++;
- break;
- }
- i++;
- if (!getnetnum(tokens[i], &maskaddr, 1))
- errflg++;
- break;
-
- case CONF_RES_IGNORE:
- peerversion |= RES_IGNORE;
- break;
-
- case CONF_RES_NOSERVE:
- peerversion |= RES_DONTSERVE;
- break;
-
- case CONF_RES_NOTRUST:
- peerversion |= RES_DONTTRUST;
- break;
-
- case CONF_RES_NOQUERY:
- peerversion |= RES_NOQUERY;
- break;
-
- case CONF_RES_NOMODIFY:
- peerversion |= RES_NOMODIFY;
- break;
-
- case CONF_RES_NOPEER:
- peerversion |= RES_NOPEER;
- break;
-
- case CONF_RES_NOTRAP:
- peerversion |= RES_NOTRAP;
- break;
-
- case CONF_RES_LPTRAP:
- peerversion |= RES_LPTRAP;
- break;
-
- case CONF_RES_NTPPORT:
- peerkey |= RESM_NTPONLY;
- break;
-
- case CONF_RES_VERSION:
- peerversion |= RES_VERSION;
- break;
-
- case CONF_RES_DEMOBILIZE:
- peerversion |= RES_DEMOBILIZE;
- break;
-
- case CONF_RES_LIMITED:
- peerversion |= RES_LIMITED;
- break;
-
- case CONFIG_UNKNOWN:
- errflg++;
- break;
- }
- }
- if (SOCKNUL(&peeraddr))
- ANYSOCK(&maskaddr);
- if (!errflg)
- hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
- (int)peerkey, peerversion);
- break;
-
- case CONFIG_BDELAY:
- if (ntokens >= 2) {
- double tmp;
-
- if (sscanf(tokens[1], "%lf", &tmp) != 1) {
- msyslog(LOG_ERR,
- "broadcastdelay value %s undecodable",
- tokens[1]);
- } else {
- proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
- }
- }
- break;
-
- case CONFIG_CDELAY:
- if (ntokens >= 2) {
- u_long ui;
-
- if (sscanf(tokens[1], "%ld", &ui) != 1)
- msyslog(LOG_ERR,
- "illegal value - line ignored");
- else
- proto_config(PROTO_CALLDELAY, ui, 0, NULL);
- }
- break;
-
- case CONFIG_TRUSTEDKEY:
- for (i = 1; i < ntokens; i++) {
- keyid_t tkey;
-
- tkey = atol(tokens[i]);
- if (tkey == 0) {
- msyslog(LOG_ERR,
- "trusted key %s unlikely",
- tokens[i]);
- } else {
- authtrust(tkey, 1);
- }
- }
- break;
-
- case CONFIG_REQUESTKEY:
- if (ntokens >= 2) {
- if (!atouint(tokens[1], &ul)) {
- msyslog(LOG_ERR,
- "%s is undecodable as request key",
- tokens[1]);
- } else if (ul == 0) {
- msyslog(LOG_ERR,
- "%s makes a poor request keyid",
- tokens[1]);
- } else {
-#ifdef DEBUG
- if (debug > 3)
- printf(
- "set info_auth_key to %08lx\n", ul);
-#endif
- info_auth_keyid = (keyid_t)ul;
- }
- }
- break;
-
- case CONFIG_CONTROLKEY:
- if (ntokens >= 2) {
- keyid_t ckey;
-
- ckey = atol(tokens[1]);
- if (ckey == 0) {
- msyslog(LOG_ERR,
- "%s makes a poor control keyid",
- tokens[1]);
- } else {
- ctl_auth_keyid = ckey;
- }
- }
- break;
-
- case CONFIG_TRAP:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no address for trap command, line ignored");
- break;
- }
- istart = 1;
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- switch (matchkey(tokens[istart], addr_type, 0)) {
- case CONF_ADDR_IPV4:
- peeraddr.ss_family = AF_INET;
- istart++;
- break;
- case CONF_ADDR_IPV6:
- peeraddr.ss_family = AF_INET6;
- istart++;
- break;
- }
-
- if (!getnetnum(tokens[istart], &peeraddr, 1))
- break;
-
- /*
- * Use peerversion for port number. Barf.
- */
- errflg = 0;
- peerversion = 0;
- localaddr = 0;
- istart++;
- for (i = istart; i < ntokens-1; i++)
- switch (matchkey(tokens[i], trap_keywords, 1)) {
- case CONF_TRAP_PORT:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "trap port requires an argument");
- errflg = 1;
- break;
- }
- peerversion = atoi(tokens[++i]);
- if (peerversion <= 0
- || peerversion > 32767) {
- msyslog(LOG_ERR,
- "invalid port number %s, trap ignored",
- tokens[i]);
- errflg = 1;
- }
- break;
-
- case CONF_TRAP_INTERFACE:
- if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "trap interface requires an argument");
- errflg = 1;
- break;
- }
-
- memset((char *)&maskaddr, 0,
- sizeof(maskaddr));
- maskaddr.ss_family = peeraddr.ss_family;
- if (!getnetnum(tokens[++i],
- &maskaddr, 1)) {
- errflg = 1;
- break;
- }
-
- localaddr = findinterface(&maskaddr);
- if (localaddr == NULL) {
- msyslog(LOG_ERR,
- "can't find interface with address %s",
- stoa(&maskaddr));
- errflg = 1;
- }
- break;
-
- case CONFIG_UNKNOWN:
- errflg++;
- break;
- }
-
- if (!errflg) {
- if (peerversion != 0)
- ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
- else
- ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
- if (localaddr == NULL)
- localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
- if (!ctlsettrap(&peeraddr, localaddr, 0,
- NTP_VERSION))
- msyslog(LOG_ERR,
- "can't set trap for %s, no resources",
- stoa(&peeraddr));
- }
- break;
-
- case CONFIG_FUDGE:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no address for fudge command, line ignored");
- break;
- }
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (!getnetnum(tokens[1], &peeraddr, 1))
- break;
-
- if (!ISREFCLOCKADR(&peeraddr)) {
- msyslog(LOG_ERR,
- "%s is inappropriate address for the fudge command, line ignored",
- stoa(&peeraddr));
- break;
- }
-
- memset((void *)&clock_stat, 0, sizeof clock_stat);
- fudgeflag = 0;
- errflg = 0;
- for (i = 2; i < ntokens-1; i++) {
- switch (c = matchkey(tokens[i],
- fudge_keywords, 1)) {
- case CONF_FDG_TIME1:
- if (sscanf(tokens[++i], "%lf",
- &clock_stat.fudgetime1) != 1) {
- msyslog(LOG_ERR,
- "fudge %s time1 value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.haveflags |= CLK_HAVETIME1;
- break;
-
- case CONF_FDG_TIME2:
- if (sscanf(tokens[++i], "%lf",
- &clock_stat.fudgetime2) != 1) {
- msyslog(LOG_ERR,
- "fudge %s time2 value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.haveflags |= CLK_HAVETIME2;
- break;
-
-
- case CONF_FDG_STRATUM:
- if (!atoint(tokens[++i], &stratum))
- {
- msyslog(LOG_ERR,
- "fudge %s stratum value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- clock_stat.fudgeval1 = stratum;
- clock_stat.haveflags |= CLK_HAVEVAL1;
- break;
-
- case CONF_FDG_REFID:
- /* HMS: Endianness and 0 bytes? */
- /* XXX */
- strncpy((char *)&clock_stat.fudgeval2,
- tokens[++i], 4);
- clock_stat.haveflags |= CLK_HAVEVAL2;
- break;
-
- case CONF_FDG_FLAG1:
- case CONF_FDG_FLAG2:
- case CONF_FDG_FLAG3:
- case CONF_FDG_FLAG4:
- if (!atouint(tokens[++i], &fudgeflag)
- || fudgeflag > 1) {
- msyslog(LOG_ERR,
- "fudge %s flag value in error",
- stoa(&peeraddr));
- errflg = i;
- break;
- }
- switch(c) {
- case CONF_FDG_FLAG1:
- c = CLK_FLAG1;
- clock_stat.haveflags|=CLK_HAVEFLAG1;
- break;
- case CONF_FDG_FLAG2:
- c = CLK_FLAG2;
- clock_stat.haveflags|=CLK_HAVEFLAG2;
- break;
- case CONF_FDG_FLAG3:
- c = CLK_FLAG3;
- clock_stat.haveflags|=CLK_HAVEFLAG3;
- break;
- case CONF_FDG_FLAG4:
- c = CLK_FLAG4;
- clock_stat.haveflags|=CLK_HAVEFLAG4;
- break;
- }
- if (fudgeflag == 0)
- clock_stat.flags &= ~c;
- else
- clock_stat.flags |= c;
- break;
-
- case CONFIG_UNKNOWN:
- errflg = -1;
- break;
- }
- }
-
-#ifdef REFCLOCK
- /*
- * If reference clock support isn't defined the
- * fudge line will still be accepted and syntax
- * checked, but will essentially do nothing.
- */
- if (!errflg) {
- refclock_control(&peeraddr, &clock_stat,
- (struct refclockstat *)0);
- }
-#endif
- break;
-
- case CONFIG_STATSDIR:
- if (ntokens >= 2)
- stats_config(STATS_STATSDIR,tokens[1]);
- break;
-
- case CONFIG_STATISTICS:
- for (i = 1; i < ntokens; i++) {
- filegen = filegen_get(tokens[i]);
-
- if (filegen == NULL) {
- msyslog(LOG_ERR,
- "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);
-#endif
- filegen->flag |= FGEN_FLAG_ENABLED;
- }
- break;
-
- case CONFIG_FILEGEN:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no id for filegen command, line ignored");
- break;
- }
-
- filegen = filegen_get(tokens[1]);
- if (filegen == NULL) {
- msyslog(LOG_ERR,
- "unknown filegen \"%s\" ignored",
- tokens[1]);
- break;
- }
- /*
- * peerversion is (ab)used for filegen file (index)
- * peerkey is (ab)used for filegen type
- * peerflags is (ab)used for filegen flags
- */
- peerversion = 0;
- peerkey = filegen->type;
- peerflags = filegen->flag;
- errflg = 0;
-
- for (i = 2; i < ntokens; i++) {
- switch (matchkey(tokens[i],
- filegen_keywords, 1)) {
- case CONF_FGEN_FILE:
- if (i >= ntokens - 1) {
- msyslog(LOG_ERR,
- "filegen %s file requires argument",
- tokens[1]);
- errflg = i;
- break;
- }
- peerversion = ++i;
- break;
- case CONF_FGEN_TYPE:
- if (i >= ntokens -1) {
- msyslog(LOG_ERR,
- "filegen %s type requires argument",
- tokens[1]);
- errflg = i;
- break;
- }
- peerkey = matchkey(tokens[++i],
- fgen_types, 1);
- if (peerkey == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "filegen %s unknown type \"%s\"",
- tokens[1], tokens[i]);
- errflg = i;
- break;
- }
- break;
-
- case CONF_FGEN_FLAG_LINK:
- peerflags |= FGEN_FLAG_LINK;
- break;
-
- case CONF_FGEN_FLAG_NOLINK:
- peerflags &= ~FGEN_FLAG_LINK;
- break;
-
- case CONF_FGEN_FLAG_ENABLE:
- peerflags |= FGEN_FLAG_ENABLED;
- break;
-
- case CONF_FGEN_FLAG_DISABLE:
- peerflags &= ~FGEN_FLAG_ENABLED;
- break;
- }
- }
- if (!errflg)
- filegen_config(filegen, tokens[peerversion],
- (u_char)peerkey, (u_char)peerflags);
- break;
-
- case CONFIG_SETVAR:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no value for setvar command - line ignored");
- } else {
- set_sys_var(tokens[1], strlen(tokens[1])+1,
- (u_short) (RW |
- ((((ntokens > 2)
- && !strcmp(tokens[2],
- "default")))
- ? DEF
- : 0)));
- }
- break;
-
- case CONFIG_ENABLE:
- for (i = 1; i < ntokens; i++) {
- int flag;
-
- flag = matchkey(tokens[i], flags_keywords, 1);
- if (flag == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "enable unknown flag %s",
- tokens[i]);
- errflg = 1;
- break;
- }
- proto_config(flag, 1, 0., NULL);
- }
- break;
-
- case CONFIG_DISABLE:
- for (i = 1; i < ntokens; i++) {
- int flag;
-
- flag = matchkey(tokens[i], flags_keywords, 1);
- if (flag == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "disable unknown flag %s",
- tokens[i]);
- errflg = 1;
- break;
- }
- proto_config(flag, 0, 0., NULL);
- }
- 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;
-
- case CONFIG_ADJ: {
- double ftemp;
-
- sscanf(tokens[1], "%lf", &ftemp);
- proto_config(PROTO_ADJ, 0, ftemp, NULL);
- }
- break;
-
- }
- }
- if (fp[0])
- (void)fclose(fp[0]);
-
-#ifdef HAVE_NETINFO
- if (config_netinfo)
- free_netinfo_config(config_netinfo);
-#endif /* HAVE_NETINFO */
-
-#if !defined(VMS) && !defined(SYS_VXWORKS)
- /* 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];
- int j;
-
- for (i = 0; i < 8; i++)
- for (j = 1; j < 100; ++j) {
- rankey[i] = (char) (RANDOM & 0xff);
- if (rankey[i] != 0) break;
- }
- rankey[8] = 0;
- authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
- authtrust(req_keyid, 1);
- if (!authhavekey(req_keyid)) {
- msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
- /* HMS: Should this be fatal? */
- }
- }
-
- /* save keyid so we will accept config requests with it */
- info_auth_keyid = req_keyid;
-#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
-
- if (res_fp != NULL) {
- if (call_resolver) {
- /*
- * Need name resolution
- */
- do_resolve_internal();
- }
- }
-}
-
-
-#ifdef HAVE_NETINFO
-
-/*
- * get_netinfo_config - find the nearest NetInfo domain with an ntp
- * configuration and initialize the configuration state.
- */
-static struct netinfo_config_state *
-get_netinfo_config()
-{
- ni_status status;
- void *domain;
- ni_id config_dir;
- struct netinfo_config_state *config;
-
- if (ni_open(NULL, ".", &domain) != NI_OK) return NULL;
-
- while ((status = ni_pathsearch(domain, &config_dir, NETINFO_CONFIG_DIR)) == NI_NODIR) {
- void *next_domain;
- if (ni_open(domain, "..", &next_domain) != NI_OK) {
- ni_free(next_domain);
- break;
- }
- ni_free(domain);
- domain = next_domain;
- }
- if (status != NI_OK) {
- ni_free(domain);
- return NULL;
- }
-
- config = (struct netinfo_config_state *)malloc(sizeof(struct netinfo_config_state));
- config->domain = domain;
- config->config_dir = config_dir;
- config->prop_index = 0;
- config->val_index = 0;
- config->val_list = NULL;
-
- return config;
-}
-
-
-
-/*
- * free_netinfo_config - release NetInfo configuration state
- */
-static void
-free_netinfo_config(struct netinfo_config_state *config)
-{
- ni_free(config->domain);
- free(config);
-}
-
-
-
-/*
- * gettokens_netinfo - return tokens from NetInfo
- */
-static int
-gettokens_netinfo (
- struct netinfo_config_state *config,
- char **tokenlist,
- int *ntokens
- )
-{
- int prop_index = config->prop_index;
- int val_index = config->val_index;
- char **val_list = config->val_list;
-
- /*
- * Iterate through each keyword and look for a property that matches it.
- */
- again:
- if (!val_list) {
- for (; prop_index < (sizeof(keywords)/sizeof(keywords[0])); prop_index++)
- {
- ni_namelist namelist;
- struct keyword current_prop = keywords[prop_index];
-
- /*
- * For each value associated in the property, we're going to return
- * a separate line. We squirrel away the values in the config state
- * so the next time through, we don't need to do this lookup.
- */
- NI_INIT(&namelist);
- if (ni_lookupprop(config->domain, &config->config_dir, current_prop.text, &namelist) == NI_OK) {
- ni_index index;
-
- /* Found the property, but it has no values */
- if (namelist.ni_namelist_len == 0) continue;
-
- if (! (val_list = config->val_list = (char**)malloc(sizeof(char*) * (namelist.ni_namelist_len + 1))))
- { msyslog(LOG_ERR, "out of memory while configuring"); break; }
-
- for (index = 0; index < namelist.ni_namelist_len; index++) {
- char *value = namelist.ni_namelist_val[index];
-
- if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
- { msyslog(LOG_ERR, "out of memory while configuring"); break; }
-
- strcpy(val_list[index], value);
- }
- val_list[index] = NULL;
-
- break;
- }
- ni_namelist_free(&namelist);
- }
- config->prop_index = prop_index;
- }
-
- /* No list; we're done here. */
- if (!val_list) return CONFIG_UNKNOWN;
-
- /*
- * We have a list of values for the current property.
- * Iterate through them and return each in order.
- */
- if (val_list[val_index])
- {
- int ntok = 1;
- int quoted = 0;
- char *tokens = val_list[val_index];
-
- msyslog(LOG_INFO, "%s %s", keywords[prop_index].text, val_list[val_index]);
-
- (const char*)tokenlist[0] = keywords[prop_index].text;
- for (ntok = 1; ntok < MAXTOKENS; ntok++) {
- tokenlist[ntok] = tokens;
- while (!ISEOL(*tokens) && (!ISSPACE(*tokens) || quoted))
- quoted ^= (*tokens++ == '"');
-
- if (ISEOL(*tokens)) {
- *tokens = '\0';
- break;
- } else { /* must be space */
- *tokens++ = '\0';
- while (ISSPACE(*tokens)) tokens++;
- if (ISEOL(*tokens)) break;
- }
- }
- *ntokens = ntok + 1;
-
- config->val_index++;
-
- return keywords[prop_index].keytype;
- }
-
- /* We're done with the current property. */
- prop_index = ++config->prop_index;
-
- /* Free val_list and reset counters. */
- for (val_index = 0; val_list[val_index]; val_index++)
- free(val_list[val_index]);
- free(val_list); val_list = config->val_list = NULL; val_index = config->val_index = 0;
-
- goto again;
-}
-
-#endif /* HAVE_NETINFO */
-
-
-/*
- * gettokens - read a line and return tokens
- */
-static int
-gettokens (
- FILE *fp,
- char *line,
- char **tokenlist,
- int *ntokens
- )
-{
- register char *cp;
- register int ntok;
- register int quoted = 0;
-
- /*
- * Find start of first token
- */
- again:
- while ((cp = fgets(line, MAXLINE, fp)) != NULL) {
- cp = line;
- while (ISSPACE(*cp))
- cp++;
- if (!ISEOL(*cp))
- break;
- }
- if (cp == NULL) {
- *ntokens = 0;
- return CONFIG_UNKNOWN; /* hack. Is recognized as EOF */
- }
-
- /*
- * Now separate out the tokens
- */
- for (ntok = 0; ntok < MAXTOKENS; ntok++) {
- tokenlist[ntok] = cp;
- while (!ISEOL(*cp) && (!ISSPACE(*cp) || quoted))
- quoted ^= (*cp++ == '"');
-
- if (ISEOL(*cp)) {
- *cp = '\0';
- break;
- } else { /* must be space */
- *cp++ = '\0';
- while (ISSPACE(*cp))
- cp++;
- if (ISEOL(*cp))
- break;
- }
- }
-
- /*
- * Return the match
- */
- *ntokens = ntok + 1;
- ntok = matchkey(tokenlist[0], keywords, 1);
- if (ntok == CONFIG_UNKNOWN)
- goto again;
- return ntok;
-}
-
-
-
-/*
- * matchkey - match a keyword to a list
- */
-static int
-matchkey(
- register char *word,
- register struct keyword *keys,
- int complain
- )
-{
- for (;;) {
- if (keys->keytype == CONFIG_UNKNOWN) {
- if (complain)
- msyslog(LOG_ERR,
- "configure: keyword \"%s\" unknown, line ignored",
- word);
- return CONFIG_UNKNOWN;
- }
- if (STRSAME(word, keys->text))
- return keys->keytype;
- keys++;
- }
-}
-
-
-/*
- * getnetnum - return a net number (this is crude, but careful)
- */
-static int
-getnetnum(
- const char *num,
- struct sockaddr_storage *addr,
- int complain
- )
-{
- struct addrinfo hints;
- struct addrinfo *ptr;
-
- /* Get host address. Looking for UDP datagram connection */
- memset(&hints, 0, sizeof (hints));
- if (addr->ss_family == AF_INET || addr->ss_family == AF_INET6)
- hints.ai_family = addr->ss_family;
- else
- hints.ai_family = AF_UNSPEC;
-
- hints.ai_socktype = SOCK_DGRAM;
-#ifdef DEBUG
- if (debug > 3)
- printf("getaddrinfo %s\n", num);
-#endif
- if (getaddrinfo(num, "ntp", &hints, &ptr)!=0) {
- if (complain)
- msyslog(LOG_ERR,
- "getaddrinfo: \"%s\" invalid host address, line ignored",
- num);
-#ifdef DEBUG
- if (debug > 3)
- printf(
- "getaddrinfo: \"%s\" invalid host address%s.\n",
- num, (complain)
- ? ", line ignored"
- : "");
-#endif
- return 0;
- }
-
- memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
-#ifdef DEBUG
- if (debug > 1)
- printf("getnetnum given %s, got %s \n",
- num, stoa(addr));
-#endif
- freeaddrinfo(ptr);
- return 1;
-}
-
-
-#if !defined(VMS) && !defined(SYS_WINNT)
-/*
- * catchchild - receive the resolver's exit status
- */
-static RETSIGTYPE
-catchchild(
- int sig
- )
-{
- /*
- * We only start up one child, and if we're here
- * it should have already exited. Hence the following
- * shouldn't hang. If it does, please tell me.
- */
-#if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
- (void) wait(0);
-#endif /* SYS_WINNT && VXWORKS*/
-}
-#endif /* VMS */
-
-
-/*
- * save_resolve - save configuration info into a file for later name resolution
- */
-static void
-save_resolve(
- char *name,
- int mode,
- int version,
- int minpoll,
- int maxpoll,
- u_int flags,
- int ttl,
- keyid_t keyid,
- u_char *keystr
- )
-{
-#ifndef SYS_VXWORKS
- if (res_fp == NULL) {
-#ifndef SYS_WINNT
- (void) strcpy(res_file, RES_TEMPFILE);
-#else
- /* no /tmp directory under NT */
- {
- if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
- msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
- return;
- }
- (void) strcat(res_file, "ntpdXXXXXX");
- }
-#endif /* SYS_WINNT */
-#ifdef HAVE_MKSTEMP
- {
- int fd;
-
- res_fp = NULL;
- if ((fd = mkstemp(res_file)) != -1)
- res_fp = fdopen(fd, "r+");
- }
-#else
- (void) mktemp(res_file);
- res_fp = fopen(res_file, "w");
-#endif
- if (res_fp == NULL) {
- msyslog(LOG_ERR, "open failed for %s: %m", res_file);
- return;
- }
- }
-#ifdef DEBUG
- if (debug) {
- printf("resolving %s\n", name);
- }
-#endif
-
- (void)fprintf(res_fp, "%s %d %d %d %d %d %d %u %s\n", name,
- mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
-#ifdef DEBUG
- if (debug > 1)
- printf("config: %s %d %d %d %d %x %d %u %s\n", name, mode,
- version, minpoll, maxpoll, flags, ttl, keyid, keystr);
-#endif
-
-#else /* SYS_VXWORKS */
- /* save resolve info to a struct */
-#endif /* SYS_VXWORKS */
-}
-
-
-/*
- * abort_resolve - terminate the resolver stuff and delete the file
- */
-static void
-abort_resolve(void)
-{
- /*
- * In an ideal world we would might reread the file and
- * log the hosts which aren't getting configured. Since
- * this is too much work, however, just close and delete
- * the temp file.
- */
- if (res_fp != NULL)
- (void) fclose(res_fp);
- res_fp = NULL;
-
-#ifndef SYS_VXWORKS /* we don't open the file to begin with */
-#if !defined(VMS)
- (void) unlink(res_file);
-#else
- (void) delete(res_file);
-#endif /* VMS */
-#endif /* SYS_VXWORKS */
-}
-
-
-/*
- * do_resolve_internal - start up the resolver function (not program)
- */
-/*
- * On VMS, this routine will simply refuse to resolve anything.
- *
- * Possible implementation: keep `res_file' in memory, do async
- * name resolution via QIO, update from within completion AST.
- * I'm unlikely to find the time for doing this, though. -wjm
- */
-static void
-do_resolve_internal(void)
-{
- int i;
-
- if (res_fp == NULL) {
- /* belch */
- msyslog(LOG_ERR,
- "do_resolve_internal: Fatal: res_fp == NULL");
- exit(1);
- }
-
- /* we are done with this now */
- (void) fclose(res_fp);
- res_fp = NULL;
-
-#if !defined(VMS) && !defined (SYS_VXWORKS)
- req_file = res_file; /* set up pointer to res file */
-#ifndef SYS_WINNT
- (void) signal_no_reset(SIGCHLD, catchchild);
-
-#ifndef SYS_VXWORKS
- i = fork();
- if (i == 0) {
- /*
- * this used to close everything
- * I don't think this is necessary
- */
- /*
- * To the unknown commenter above:
- * Well, I think it's better to clean up
- * after oneself. I have had problems with
- * refclock-io when intres was running - things
- * where fine again when ntpintres was gone.
- * So some systems react erratic at least.
- *
- * Frank Kardel
- *
- * 94-11-16:
- * Further debugging has proven that the above is
- * absolutely harmful. The internal resolver
- * is still in the SIGIO process group and the lingering
- * async io information causes it to process requests from
- * all file decriptor causing a race between the NTP daemon
- * and the resolver. which then eats data when it wins 8-(.
- * It is absolutly necessary to kill any IO associations
- * shared with the NTP daemon.
- *
- * We also block SIGIO (currently no ports means to
- * disable the signal handle for IO).
- *
- * Thanks to wgstuken@informatik.uni-erlangen.de to notice
- * that it is the ntp-resolver child running into trouble.
- *
- * THUS:
- */
-
- closelog();
- kill_asyncio(0);
-
- (void) signal_no_reset(SIGCHLD, SIG_DFL);
-
-#ifdef DEBUG
- if (0)
- debug = 2;
-#endif
-
-# ifndef LOG_DAEMON
- openlog("ntpd_initres", LOG_PID);
-# else /* LOG_DAEMON */
-
-# ifndef LOG_NTP
-# define LOG_NTP LOG_DAEMON
-# endif
- openlog("ntpd_initres", LOG_PID | LOG_NDELAY, LOG_NTP);
-#ifndef SYS_CYGWIN32
-# ifdef DEBUG
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
- else
-# endif /* DEBUG */
- setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
-# endif /* LOG_DAEMON */
-#endif
-
- ntp_intres();
-
- /*
- * If we got here, the intres code screwed up.
- * Print something so we don't die without complaint
- */
- msyslog(LOG_ERR, "call to ntp_intres lost");
- abort_resolve();
- exit(1);
- }
-#else
- /* vxWorks spawns a thread... -casey */
- i = sp (ntp_intres);
- /*i = taskSpawn("ntp_intres",100,VX_FP_TASK,20000,ntp_intres);*/
-#endif
- if (i == -1) {
- msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
- (void) signal_no_reset(SIGCHLD, SIG_DFL);
- abort_resolve();
- }
-#else /* SYS_WINNT */
- {
- /* NT's equivalent of fork() is _spawn(), but the start point
- * of the new process is an executable filename rather than
- * a function name as desired here.
- */
- DWORD dwThreadId;
- fflush(stdout);
- ResolverThreadHandle = CreateThread(
- NULL, /* no security attributes */
- 0, /* use default stack size */
- (LPTHREAD_START_ROUTINE) ntp_intres, /* thread function */
- NULL, /* argument to thread function */
- 0, /* use default creation flags */
- &dwThreadId); /* returns the thread identifier */
- if (ResolverThreadHandle == NULL) {
- msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
- abort_resolve();
- }
- }
-#endif /* SYS_WINNT */
-#else /* VMS VX_WORKS */
- msyslog(LOG_ERR,
- "Name resolution not implemented for VMS - use numeric addresses");
- abort_resolve();
-#endif /* VMS VX_WORKS */
-}
diff --git a/contrib/ntp/ntpd/ntp_control.c b/contrib/ntp/ntpd/ntp_control.c
deleted file mode 100644
index 0ac0404..0000000
--- a/contrib/ntp/ntpd/ntp_control.c
+++ /dev/null
@@ -1,2928 +0,0 @@
-/*
- * ntp_control.c - respond to control messages and send async traps
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_control.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-/*
- * Structure to hold request procedure information
- */
-#define NOAUTH 0
-#define AUTH 1
-
-#define NO_REQUEST (-1)
-
-struct ctl_proc {
- short control_code; /* defined request code */
- u_short flags; /* flags word */
- void (*handler) P((struct recvbuf *, int)); /* handle request */
-};
-
-/*
- * Only one flag. Authentication required or not.
- */
-#define NOAUTH 0
-#define AUTH 1
-
-/*
- * Request processing routines
- */
-static void ctl_error P((int));
-#ifdef REFCLOCK
-static u_short ctlclkstatus P((struct refclockstat *));
-#endif
-static void ctl_flushpkt P((int));
-static void ctl_putdata P((const char *, unsigned int, int));
-static void ctl_putstr P((const char *, const char *,
- unsigned int));
-static void ctl_putdbl P((const char *, double));
-static void ctl_putuint P((const char *, u_long));
-static void ctl_puthex P((const char *, u_long));
-static void ctl_putint P((const char *, long));
-static void ctl_putts P((const char *, l_fp *));
-static void ctl_putadr P((const char *, u_int32, struct sockaddr_storage*));
-static void ctl_putid P((const char *, char *));
-static void ctl_putarray P((const char *, double *, int));
-static void ctl_putsys P((int));
-static void ctl_putpeer P((int, struct peer *));
-#ifdef REFCLOCK
-static void ctl_putclock P((int, struct refclockstat *, int));
-#endif /* REFCLOCK */
-static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
-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));
-static void write_variables P((struct recvbuf *, int));
-static void read_clock_status P((struct recvbuf *, int));
-static void write_clock_status P((struct recvbuf *, int));
-static void set_trap P((struct recvbuf *, int));
-static void unset_trap P((struct recvbuf *, int));
-static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
- struct interface *));
-
-static struct ctl_proc control_codes[] = {
- { CTL_OP_UNSPEC, NOAUTH, control_unspec },
- { CTL_OP_READSTAT, NOAUTH, read_status },
- { CTL_OP_READVAR, NOAUTH, read_variables },
- { CTL_OP_WRITEVAR, AUTH, write_variables },
- { CTL_OP_READCLOCK, NOAUTH, read_clock_status },
- { CTL_OP_WRITECLOCK, NOAUTH, write_clock_status },
- { CTL_OP_SETTRAP, NOAUTH, set_trap },
- { CTL_OP_UNSETTRAP, NOAUTH, unset_trap },
- { NO_REQUEST, 0 }
-};
-
-/*
- * System variable values. The array can be indexed by the variable
- * index to find the textual name.
- */
-static struct ctl_var sys_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CS_LEAP, RW, "leap" }, /* 1 */
- { CS_STRATUM, RO, "stratum" }, /* 2 */
- { CS_PRECISION, RO, "precision" }, /* 3 */
- { CS_ROOTDELAY, RO, "rootdelay" }, /* 4 */
- { CS_ROOTDISPERSION, RO, "rootdispersion" }, /* 5 */
- { CS_REFID, RO, "refid" }, /* 6 */
- { CS_REFTIME, RO, "reftime" }, /* 7 */
- { CS_POLL, RO, "poll" }, /* 8 */
- { CS_PEERID, RO, "peer" }, /* 9 */
- { CS_STATE, RO, "state" }, /* 10 */
- { CS_OFFSET, RO, "offset" }, /* 11 */
- { CS_DRIFT, RO, "frequency" }, /* 12 */
- { CS_JITTER, RO, "jitter" }, /* 13 */
- { CS_CLOCK, RO, "clock" }, /* 14 */
- { CS_PROCESSOR, RO, "processor" }, /* 15 */
- { CS_SYSTEM, RO, "system" }, /* 16 */
- { CS_VERSION, RO, "version" }, /* 17 */
- { CS_STABIL, RO, "stability" }, /* 18 */
- { CS_VARLIST, RO, "sys_var_list" }, /* 19 */
-#ifdef OPENSSL
- { CS_FLAGS, RO, "flags" }, /* 20 */
- { CS_HOST, RO, "hostname" }, /* 21 */
- { CS_PUBLIC, RO, "hostkey" }, /* 22 */
- { CS_CERTIF, RO, "cert" }, /* 23 */
- { CS_REVTIME, RO, "refresh" }, /* 24 */
- { CS_LEAPTAB, RO, "leapseconds" }, /* 25 */
- { CS_TAI, RO, "tai" }, /* 26 */
- { CS_DIGEST, RO, "signature" }, /* 27 */
-#endif /* OPENSSL */
- { 0, EOV, "" } /* 28 */
-};
-
-static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
-
-/*
- * System variables we print by default (in fuzzball order,
- * more-or-less)
- */
-static u_char def_sys_var[] = {
- CS_VERSION,
- CS_PROCESSOR,
- CS_SYSTEM,
- CS_LEAP,
- CS_STRATUM,
- CS_PRECISION,
- CS_ROOTDELAY,
- CS_ROOTDISPERSION,
- CS_PEERID,
- CS_REFID,
- CS_REFTIME,
- CS_POLL,
- CS_CLOCK,
- CS_STATE,
- CS_OFFSET,
- CS_DRIFT,
- CS_JITTER,
- CS_STABIL,
-#ifdef OPENSSL
- CS_HOST,
- CS_DIGEST,
- CS_FLAGS,
- CS_PUBLIC,
- CS_REVTIME,
- CS_LEAPTAB,
- CS_CERTIF,
-#endif /* OPENSSL */
- 0
-};
-
-
-/*
- * Peer variable list
- */
-static struct ctl_var peer_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CP_CONFIG, RO, "config" }, /* 1 */
- { CP_AUTHENABLE, RO, "authenable" }, /* 2 */
- { CP_AUTHENTIC, RO, "authentic" }, /* 3 */
- { CP_SRCADR, RO, "srcadr" }, /* 4 */
- { CP_SRCPORT, RO, "srcport" }, /* 5 */
- { CP_DSTADR, RO, "dstadr" }, /* 6 */
- { CP_DSTPORT, RO, "dstport" }, /* 7 */
- { CP_LEAP, RO, "leap" }, /* 8 */
- { CP_HMODE, RO, "hmode" }, /* 9 */
- { CP_STRATUM, RO, "stratum" }, /* 10 */
- { CP_PPOLL, RO, "ppoll" }, /* 11 */
- { CP_HPOLL, RO, "hpoll" }, /* 12 */
- { CP_PRECISION, RO, "precision" }, /* 13 */
- { CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
- { CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
- { CP_REFID, RO, "refid" }, /* 16 */
- { CP_REFTIME, RO, "reftime" }, /* 17 */
- { CP_ORG, RO, "org" }, /* 18 */
- { CP_REC, RO, "rec" }, /* 19 */
- { CP_XMT, RO, "xmt" }, /* 20 */
- { CP_REACH, RO, "reach" }, /* 21 */
- { CP_VALID, RO, "unreach" }, /* 22 */
- { CP_TIMER, RO, "timer" }, /* 23 */
- { CP_DELAY, RO, "delay" }, /* 24 */
- { CP_OFFSET, RO, "offset" }, /* 25 */
- { CP_JITTER, RO, "jitter" }, /* 26 */
- { CP_DISPERSION, RO, "dispersion" }, /* 27 */
- { CP_KEYID, RO, "keyid" }, /* 28 */
- { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */
- { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */
- { CP_PMODE, RO, "pmode" }, /* 31 */
- { CP_RECEIVED, RO, "received"}, /* 32 */
- { CP_SENT, RO, "sent" }, /* 33 */
- { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
- { CP_FLASH, RO, "flash" }, /* 35 */
- { CP_TTL, RO, "ttl" }, /* 36 */
- { CP_RANK, RO, "rank" }, /* 37 */
- { CP_VARLIST, RO, "peer_var_list" }, /* 38 */
-#ifdef OPENSSL
- { CP_FLAGS, RO, "flags" }, /* 39 */
- { CP_HOST, RO, "hostname" }, /* 40 */
- { CP_INITSEQ, RO, "initsequence" }, /* 41 */
- { CP_INITKEY, RO, "initkey" }, /* 42 */
- { CP_INITTSP, RO, "timestamp" }, /* 43 */
- { CP_DIGEST, RO, "signature" }, /* 44 */
- { CP_IDENT, RO, "identity" }, /* 45 */
-#endif /* OPENSSL */
- { 0, EOV, "" } /* 39/46 */
-};
-
-
-/*
- * Peer variables we print by default
- */
-static u_char def_peer_var[] = {
- CP_SRCADR,
- CP_SRCPORT,
- CP_DSTADR,
- CP_DSTPORT,
- CP_LEAP,
- CP_STRATUM,
- CP_PRECISION,
- CP_ROOTDELAY,
- CP_ROOTDISPERSION,
- CP_REFID,
- CP_REACH,
- CP_VALID,
- CP_HMODE,
- CP_PMODE,
- CP_HPOLL,
- CP_PPOLL,
- CP_FLASH,
- CP_KEYID,
- CP_TTL,
- CP_OFFSET,
- CP_DELAY,
- CP_DISPERSION,
- CP_JITTER,
- CP_REFTIME,
- CP_ORG,
- CP_REC,
- CP_XMT,
- CP_FILTDELAY,
- CP_FILTOFFSET,
- CP_FILTERROR,
-#ifdef OPENSSL
- CP_HOST,
- CP_DIGEST,
- CP_FLAGS,
- CP_IDENT,
- CP_INITSEQ,
-#endif /* OPENSSL */
- 0
-};
-
-
-#ifdef REFCLOCK
-/*
- * Clock variable list
- */
-static struct ctl_var clock_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CC_TYPE, RO, "type" }, /* 1 */
- { CC_TIMECODE, RO, "timecode" }, /* 2 */
- { CC_POLL, RO, "poll" }, /* 3 */
- { CC_NOREPLY, RO, "noreply" }, /* 4 */
- { CC_BADFORMAT, RO, "badformat" }, /* 5 */
- { CC_BADDATA, RO, "baddata" }, /* 6 */
- { CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */
- { CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */
- { 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 */
- { 0, EOV, "" } /* 14 */
-};
-
-
-/*
- * Clock variables printed by default
- */
-static u_char def_clock_var[] = {
- CC_DEVICE,
- CC_TYPE, /* won't be output if device = known */
- CC_TIMECODE,
- CC_POLL,
- CC_NOREPLY,
- CC_BADFORMAT,
- CC_BADDATA,
- CC_FUDGETIME1,
- CC_FUDGETIME2,
- CC_FUDGEVAL1,
- CC_FUDGEVAL2,
- CC_FLAGS,
- 0
-};
-#endif
-
-
-/*
- * System and processor definitions.
- */
-#ifndef HAVE_UNAME
-# ifndef STR_SYSTEM
-# define STR_SYSTEM "UNIX"
-# endif
-# ifndef STR_PROCESSOR
-# define STR_PROCESSOR "unknown"
-# endif
-
-static char str_system[] = STR_SYSTEM;
-static char str_processor[] = STR_PROCESSOR;
-#else
-# include <sys/utsname.h>
-static struct utsname utsnamebuf;
-#endif /* HAVE_UNAME */
-
-/*
- * Trap structures. We only allow a few of these, and send a copy of
- * each async message to each live one. Traps time out after an hour, it
- * is up to the trap receipient to keep resetting it to avoid being
- * timed out.
- */
-/* ntp_request.c */
-struct ctl_trap ctl_trap[CTL_MAXTRAPS];
-int num_ctl_traps;
-
-/*
- * Type bits, for ctlsettrap() call.
- */
-#define TRAP_TYPE_CONFIG 0 /* used by configuration code */
-#define TRAP_TYPE_PRIO 1 /* priority trap */
-#define TRAP_TYPE_NONPRIO 2 /* nonpriority trap */
-
-
-/*
- * List relating reference clock types to control message time sources.
- * Index by the reference clock type. This list will only be used iff
- * the reference clock driver doesn't set peer->sstclktype to something
- * different than CTL_SST_TS_UNSPEC.
- */
-static u_char clocktypes[] = {
- 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_TRUETIME (5) */
- CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) */
- CTL_SST_TS_HF, /* REFCLK_CHU (7) */
- CTL_SST_TS_LF, /* REFCLOCK_PARSE (default) (8) */
- CTL_SST_TS_LF, /* REFCLK_GPS_MX4200 (9) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_AS2201 (10) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_ARBITER (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_TRUETIME (15) */
- CTL_SST_TS_UHF, /* REFCLK_IRIG_BANCOMM (16) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_DATU (17) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_NIST_ACTS (18) */
- CTL_SST_TS_HF, /* REFCLK_WWV_HEATH (19) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_NMEA (20) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_VME (21) */
- CTL_SST_TS_ATOM, /* REFCLK_ATOM_PPS (22) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_PTB_ACTS (23) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_USNO (24) */
- CTL_SST_TS_UHF, /* REFCLK_TRUETIME (25) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */
- CTL_SST_TS_UHF, /* REFCLK_PALISADE (29) */
- CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */
- CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */
- CTL_SST_TS_LF, /* REFCLK_CHRONOLOG (32) */
- CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (32) */
- CTL_SST_TS_LF, /* REFCLK_ULINK (33) */
- CTL_SST_TS_LF, /* REFCLK_PCF (35) */
- CTL_SST_TS_LF, /* REFCLK_WWV (36) */
- CTL_SST_TS_LF, /* REFCLK_FG (37) */
- CTL_SST_TS_UHF, /* REFCLK_HOPF_SERIAL (38) */
- CTL_SST_TS_UHF, /* REFCLK_HOPF_PCI (39) */
- CTL_SST_TS_LF, /* REFCLK_JJY (40) */
- CTL_SST_TS_UHF, /* REFCLK_TT560 (41) */
- CTL_SST_TS_UHF, /* REFCLK_ZYFER (42) */
- CTL_SST_TS_UHF, /* REFCLK_RIPENCC (43) */
- CTL_SST_TS_UHF, /* REFCLK_NEOCLOCK4X (44) */
-};
-
-
-/*
- * Keyid used for authenticating write requests.
- */
-keyid_t ctl_auth_keyid;
-
-/*
- * We keep track of the last error reported by the system internally
- */
-static u_char ctl_sys_last_event;
-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 */
-
-/*
- * Response packet used by these routines. Also some state information
- * so that we can handle packet formatting within a common set of
- * subroutines. Note we try to enter data in place whenever possible,
- * but the need to set the more bit correctly means we occasionally
- * use the extra buffer and copy.
- */
-static struct ntp_control rpkt;
-static u_char res_version;
-static u_char res_opcode;
-static associd_t res_associd;
-static int res_offset;
-static u_char * datapt;
-static u_char * dataend;
-static int datalinelen;
-static int datanotbinflag;
-static struct sockaddr_storage *rmt_addr;
-static struct interface *lcl_inter;
-
-static u_char res_authenticate;
-static u_char res_authokay;
-static keyid_t res_keyid;
-
-#define MAXDATALINELEN (72)
-
-static u_char res_async; /* set to 1 if this is async trap response */
-
-/*
- * Pointers for saving state when decoding request packets
- */
-static char *reqpt;
-static char *reqend;
-
-/*
- * init_control - initialize request data
- */
-void
-init_control(void)
-{
- int i;
-
-#ifdef HAVE_UNAME
- uname(&utsnamebuf);
-#endif /* HAVE_UNAME */
-
- ctl_clr_stats();
-
- ctl_auth_keyid = 0;
- ctl_sys_last_event = EVNT_UNSPEC;
- ctl_sys_num_events = 0;
-
- num_ctl_traps = 0;
- for (i = 0; i < CTL_MAXTRAPS; i++)
- ctl_trap[i].tr_flags = 0;
-}
-
-
-/*
- * ctl_error - send an error response for the current request
- */
-static void
-ctl_error(
- int errcode
- )
-{
-#ifdef DEBUG
- if (debug >= 4)
- printf("sending control error %d\n", errcode);
-#endif
- /*
- * Fill in the fields. We assume rpkt.sequence and rpkt.associd
- * have already been filled in.
- */
- rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode &
- CTL_OP_MASK));
- rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
- rpkt.count = 0;
-
- /*
- * send packet and bump counters
- */
- if (res_authenticate && sys_authenticate) {
- int maclen;
-
- *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
- htonl(res_keyid);
- maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
- CTL_HEADER_LEN);
- sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
- CTL_HEADER_LEN + maclen);
- } else {
- sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
- CTL_HEADER_LEN);
- }
- numctlerrors++;
-}
-
-
-/*
- * process_control - process an incoming control message
- */
-void
-process_control(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register struct ntp_control *pkt;
- register int req_count;
- register int req_data;
- register struct ctl_proc *cc;
- int properlen;
- int maclen;
-
-#ifdef DEBUG
- if (debug > 2)
- printf("in process_control()\n");
-#endif
-
- /*
- * Save the addresses for error responses
- */
- numctlreq++;
- rmt_addr = &rbufp->recv_srcadr;
- lcl_inter = rbufp->dstadr;
- pkt = (struct ntp_control *)&rbufp->recv_pkt;
-
- /*
- * If the length is less than required for the header, or
- * it is a response or a fragment, ignore this.
- */
- if (rbufp->recv_length < CTL_HEADER_LEN
- || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
- || pkt->offset != 0) {
-#ifdef DEBUG
- if (debug)
- printf("invalid format in control packet\n");
-#endif
- if (rbufp->recv_length < CTL_HEADER_LEN)
- numctltooshort++;
- if (pkt->r_m_e_op & CTL_RESPONSE)
- numctlinputresp++;
- if (pkt->r_m_e_op & CTL_MORE)
- numctlinputfrag++;
- if (pkt->r_m_e_op & CTL_ERROR)
- numctlinputerr++;
- if (pkt->offset != 0)
- numctlbadoffset++;
- return;
- }
- res_version = PKT_VERSION(pkt->li_vn_mode);
- if (res_version > NTP_VERSION || res_version < NTP_OLDVERSION) {
-#ifdef DEBUG
- if (debug)
- printf("unknown version %d in control packet\n",
- res_version);
-#endif
- numctlbadversion++;
- return;
- }
-
- /*
- * Pull enough data from the packet to make intelligent
- * responses
- */
- rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
- MODE_CONTROL);
- res_opcode = pkt->r_m_e_op;
- rpkt.sequence = pkt->sequence;
- rpkt.associd = pkt->associd;
- rpkt.status = 0;
- res_offset = 0;
- res_associd = htons(pkt->associd);
- res_async = 0;
- res_authenticate = 0;
- res_keyid = 0;
- res_authokay = 0;
- req_count = (int)htons(pkt->count);
- datanotbinflag = 0;
- datalinelen = 0;
- datapt = rpkt.data;
- dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
-
- /*
- * We're set up now. Make sure we've got at least enough
- * incoming data space to match the count.
- */
- req_data = rbufp->recv_length - CTL_HEADER_LEN;
- if (req_data < req_count || rbufp->recv_length & 0x3) {
- ctl_error(CERR_BADFMT);
- numctldatatooshort++;
- return;
- }
-
- properlen = req_count + CTL_HEADER_LEN;
-#ifdef DEBUG
- if (debug > 2 && (rbufp->recv_length & 0x3) != 0)
- printf("Packet length %d unrounded\n",
- rbufp->recv_length);
-#endif
- /* round up proper len to a 8 octet boundary */
-
- properlen = (properlen + 7) & ~7;
- maclen = rbufp->recv_length - properlen;
- if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 &&
- maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
- sys_authenticate) {
- res_authenticate = 1;
- res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
- properlen));
-
-#ifdef DEBUG
- if (debug > 2)
- printf(
- "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
- rbufp->recv_length, properlen, res_keyid, maclen);
-#endif
- if (!authistrusted(res_keyid)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("invalid keyid %08x\n",
- res_keyid);
-#endif
- } else if (authdecrypt(res_keyid, (u_int32 *)pkt,
- rbufp->recv_length - maclen, maclen)) {
-#ifdef DEBUG
- if (debug > 2)
- printf("authenticated okay\n");
-#endif
- res_authokay = 1;
- } else {
-#ifdef DEBUG
- if (debug > 2)
- printf("authentication failed\n");
-#endif
- res_keyid = 0;
- }
- }
-
- /*
- * Set up translate pointers
- */
- reqpt = (char *)pkt->data;
- reqend = reqpt + req_count;
-
- /*
- * Look for the opcode processor
- */
- for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
- if (cc->control_code == res_opcode) {
-#ifdef DEBUG
- if (debug > 2)
- printf("opcode %d, found command handler\n",
- res_opcode);
-#endif
- if (cc->flags == AUTH && (!res_authokay ||
- res_keyid != ctl_auth_keyid)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
- (cc->handler)(rbufp, restrict_mask);
- return;
- }
- }
-
- /*
- * Can't find this one, return an error.
- */
- numctlbadop++;
- ctl_error(CERR_BADOP);
- return;
-}
-
-
-/*
- * ctlpeerstatus - return a status word for this peer
- */
-u_short
-ctlpeerstatus(
- register struct peer *peer
- )
-{
- register u_short status;
-
- status = peer->status;
- if (peer->flags & FLAG_CONFIG)
- status |= CTL_PST_CONFIG;
- if (peer->flags & FLAG_AUTHENABLE)
- status |= CTL_PST_AUTHENABLE;
- if (peer->flags & FLAG_AUTHENTIC)
- status |= CTL_PST_AUTHENTIC;
- if (peer->reach != 0)
- status |= CTL_PST_REACH;
- return (u_short)CTL_PEER_STATUS(status, peer->num_events,
- peer->last_event);
-}
-
-
-/*
- * ctlclkstatus - return a status word for this clock
- */
-#ifdef REFCLOCK
-static u_short
-ctlclkstatus(
- struct refclockstat *this_clock
- )
-{
- return ((u_short)(((this_clock->currentstatus) << 8) |
- (this_clock->lastevent)));
-}
-#endif
-
-
-/*
- * ctlsysstatus - return the system status word
- */
-u_short
-ctlsysstatus(void)
-{
- register u_char this_clock;
-
- this_clock = CTL_SST_TS_UNSPEC;
- if (sys_peer != 0) {
- if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
- this_clock = sys_peer->sstclktype;
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
- } else {
- if (sys_peer->refclktype < sizeof(clocktypes))
- this_clock =
- clocktypes[sys_peer->refclktype];
- if (pps_control)
- this_clock |= CTL_SST_TS_PPS;
- }
- }
- return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
- ctl_sys_num_events, ctl_sys_last_event);
-}
-
-
-/*
- * ctl_flushpkt - write out the current packet and prepare
- * another if necessary.
- */
-static void
-ctl_flushpkt(
- int more
- )
-{
- int dlen;
- int sendlen;
-
- if (!more && datanotbinflag) {
- /*
- * Big hack, output a trailing \r\n
- */
- *datapt++ = '\r';
- *datapt++ = '\n';
- }
- dlen = datapt - (u_char *)rpkt.data;
- sendlen = dlen + CTL_HEADER_LEN;
-
- /*
- * Pad to a multiple of 32 bits
- */
- while (sendlen & 0x3) {
- *datapt++ = '\0';
- sendlen++;
- }
-
- /*
- * Fill in the packet with the current info
- */
- rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode &
- CTL_OP_MASK));
- rpkt.count = htons((u_short) dlen);
- rpkt.offset = htons( (u_short) res_offset);
- if (res_async) {
- register int i;
-
- for (i = 0; i < CTL_MAXTRAPS; i++) {
- if (ctl_trap[i].tr_flags & TRAP_INUSE) {
- rpkt.li_vn_mode =
- PKT_LI_VN_MODE(sys_leap,
- ctl_trap[i].tr_version,
- MODE_CONTROL);
- 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++;
- numasyncmsgs++;
- }
- }
- } else {
- if (res_authenticate && sys_authenticate) {
- int maclen;
- int totlen = sendlen;
- keyid_t keyid = htonl(res_keyid);
-
- /*
- * If we are going to authenticate, then there
- * is an additional requirement that the MAC
- * begin on a 64 bit boundary.
- */
- while (totlen & 7) {
- *datapt++ = '\0';
- totlen++;
- }
- memcpy(datapt, &keyid, sizeof keyid);
- maclen = authencrypt(res_keyid,
- (u_int32 *)&rpkt, totlen);
- sendpkt(rmt_addr, lcl_inter, -5,
- (struct pkt *)&rpkt, totlen + maclen);
- } else {
- sendpkt(rmt_addr, lcl_inter, -6,
- (struct pkt *)&rpkt, sendlen);
- }
- if (more)
- numctlfrags++;
- else
- numctlresponses++;
- }
-
- /*
- * Set us up for another go around.
- */
- res_offset += dlen;
- datapt = (u_char *)rpkt.data;
-}
-
-
-/*
- * ctl_putdata - write data into the packet, fragmenting and starting
- * another if this one is full.
- */
-static void
-ctl_putdata(
- const char *dp,
- unsigned int dlen,
- int bin /* set to 1 when data is binary */
- )
-{
- int overhead;
-
- overhead = 0;
- if (!bin) {
- datanotbinflag = 1;
- overhead = 3;
- if (datapt != rpkt.data) {
- *datapt++ = ',';
- datalinelen++;
- if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
- {
- *datapt++ = '\r';
- *datapt++ = '\n';
- datalinelen = 0;
- } else {
- *datapt++ = ' ';
- datalinelen++;
- }
- }
- }
-
- /*
- * Save room for trailing junk
- */
- if (dlen + overhead + datapt > dataend) {
- /*
- * Not enough room in this one, flush it out.
- */
- ctl_flushpkt(CTL_MORE);
- }
- memmove((char *)datapt, dp, (unsigned)dlen);
- datapt += dlen;
- datalinelen += dlen;
-}
-
-
-/*
- * ctl_putstr - write a tagged string into the response packet
- */
-static void
-ctl_putstr(
- const char *tag,
- const char *data,
- unsigned int len
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[400];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
- if (len > 0) {
- *cp++ = '=';
- *cp++ = '"';
- if (len > (int) (sizeof(buffer) - (cp - buffer) - 1))
- len = sizeof(buffer) - (cp - buffer) - 1;
- memmove(cp, data, (unsigned)len);
- cp += len;
- *cp++ = '"';
- }
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putdbl - write a tagged, signed double into the response packet
- */
-static void
-ctl_putdbl(
- const char *tag,
- double ts
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
- *cp++ = '=';
- (void)sprintf(cp, "%.3f", ts);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-/*
- * ctl_putuint - write a tagged unsigned integer into the response
- */
-static void
-ctl_putuint(
- const char *tag,
- u_long uval
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "%lu", uval);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_puthex - write a tagged unsigned integer, in hex, into the response
- */
-static void
-ctl_puthex(
- const char *tag,
- u_long uval
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "0x%lx", uval);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putint - write a tagged signed integer into the response
- */
-static void
-ctl_putint(
- const char *tag,
- long ival
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "%ld", ival);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putts - write a tagged timestamp, in hex, into the response
- */
-static void
-ctl_putts(
- const char *tag,
- l_fp *ts
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- (void) sprintf(cp, "0x%08lx.%08lx", ts->l_ui & 0xffffffffL,
- ts->l_uf & 0xffffffffL);
- while (*cp != '\0')
- cp++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putadr - write an IP address into the response
- */
-static void
-ctl_putadr(
- const char *tag,
- u_int32 addr32,
- struct sockaddr_storage* addr
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- if (addr == NULL)
- cq = numtoa(addr32);
- else
- cq = stoa(addr);
- while (*cq != '\0')
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putid - write a tagged clock ID into the response
- */
-static void
-ctl_putid(
- const char *tag,
- char *id
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
-
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
-
- *cp++ = '=';
- cq = id;
- while (*cq != '\0' && (cq - id) < 4)
- *cp++ = *cq++;
- ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
-}
-
-
-/*
- * ctl_putarray - write a tagged eight element double array into the response
- */
-static void
-ctl_putarray(
- const char *tag,
- double *arr,
- int start
- )
-{
- register char *cp;
- register const char *cq;
- char buffer[200];
- int i;
- cp = buffer;
- cq = tag;
- while (*cq != '\0')
- *cp++ = *cq++;
- i = start;
- do {
- if (i == 0)
- i = NTP_SHIFT;
- i--;
- (void)sprintf(cp, " %.2f", arr[i] * 1e3);
- while (*cp != '\0')
- cp++;
- } while(i != start);
- ctl_putdata(buffer, (unsigned)(cp - buffer), 0);
-}
-
-
-/*
- * ctl_putsys - output a system variable
- */
-static void
-ctl_putsys(
- int varid
- )
-{
- l_fp tmp;
- char str[256];
-#ifdef OPENSSL
- struct cert_info *cp;
- char cbuf[256];
-#endif /* OPENSSL */
-
- switch (varid) {
-
- case CS_LEAP:
- ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
- break;
-
- case CS_STRATUM:
- ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
- break;
-
- case CS_PRECISION:
- ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
- break;
-
- case CS_ROOTDELAY:
- ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
- 1e3);
- break;
-
- case CS_ROOTDISPERSION:
- ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
- sys_rootdispersion * 1e3);
- break;
-
- case CS_REFID:
- if (sys_stratum > 1 && sys_stratum < STRATUM_UNSPEC)
- ctl_putadr(sys_var[CS_REFID].text, sys_refid, NULL);
- 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, sys_poll);
- break;
-
- case CS_PEERID:
- if (sys_peer == NULL)
- ctl_putuint(sys_var[CS_PEERID].text, 0);
- else
- ctl_putuint(sys_var[CS_PEERID].text,
- sys_peer->associd);
- break;
-
- case CS_STATE:
- ctl_putuint(sys_var[CS_STATE].text, (unsigned)state);
- break;
-
- case CS_OFFSET:
- ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3);
- break;
-
- case CS_DRIFT:
- ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
- break;
-
- case CS_JITTER:
- ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
- break;
-
- case CS_CLOCK:
- get_systime(&tmp);
- ctl_putts(sys_var[CS_CLOCK].text, &tmp);
- break;
-
- case CS_PROCESSOR:
-#ifndef HAVE_UNAME
- ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
- sizeof(str_processor) - 1);
-#else
- ctl_putstr(sys_var[CS_PROCESSOR].text,
- utsnamebuf.machine, strlen(utsnamebuf.machine));
-#endif /* HAVE_UNAME */
- break;
-
- case CS_SYSTEM:
-#ifndef HAVE_UNAME
- ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
- sizeof(str_system) - 1);
-#else
- sprintf(str, "%s/%s", utsnamebuf.sysname, utsnamebuf.release);
- ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
-#endif /* HAVE_UNAME */
- break;
-
- case CS_VERSION:
- ctl_putstr(sys_var[CS_VERSION].text, Version,
- strlen(Version));
- break;
-
- case CS_STABIL:
- ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
- 1e6);
- break;
-
- case CS_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) -
- strlen(sys_var[CS_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name */
-
- strcpy(s, sys_var[CS_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = sys_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
- i = strlen(k->text);
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
-
- for (k = ext_sys_var; k && !(k->flags &EOV);
- k++) {
- if (k->flags & PADDING)
- continue;
-
- ss = k->text;
- if (!ss)
- continue;
-
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text,
- (unsigned)i);
- s += i;
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
-
- ctl_putdata(buf, (unsigned)( s - buf ),
- 0);
- }
- break;
-
-#ifdef OPENSSL
- case CS_FLAGS:
- if (crypto_flags) {
- ctl_puthex(sys_var[CS_FLAGS].text, crypto_flags);
- }
- break;
-
- case CS_DIGEST:
- if (crypto_flags) {
- const EVP_MD *dp;
-
- dp = EVP_get_digestbynid(crypto_flags >> 16);
- strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(sys_var[CS_DIGEST].text, str,
- strlen(str));
- }
- break;
-
- case CS_HOST:
- if (sys_hostname != NULL)
- ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
- strlen(sys_hostname));
- break;
-
- case CS_CERTIF:
- for (cp = cinfo; cp != NULL; cp = cp->link) {
- sprintf(cbuf, "%s %s 0x%x %u", cp->subject,
- cp->issuer, cp->flags,
- ntohl(cp->cert.fstamp));
- ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
- strlen(cbuf));
- }
- break;
-
- case CS_PUBLIC:
- if (hostval.fstamp != 0)
- ctl_putuint(sys_var[CS_PUBLIC].text,
- ntohl(hostval.fstamp));
- break;
-
- case CS_REVTIME:
- if (hostval.tstamp != 0)
- ctl_putuint(sys_var[CS_REVTIME].text,
- ntohl(hostval.tstamp));
- break;
-
- case CS_LEAPTAB:
- if (tai_leap.fstamp != 0)
- ctl_putuint(sys_var[CS_LEAPTAB].text,
- ntohl(tai_leap.fstamp));
- if (sys_tai != 0)
- ctl_putuint(sys_var[CS_TAI].text, sys_tai);
- break;
-#endif /* OPENSSL */
- }
-}
-
-
-/*
- * ctl_putpeer - output a peer variable
- */
-static void
-ctl_putpeer(
- int varid,
- struct peer *peer
- )
-{
-#ifdef OPENSSL
- char str[256];
- struct autokey *ap;
-#endif /* OPENSSL */
-
- switch (varid) {
-
- case CP_CONFIG:
- ctl_putuint(peer_var[CP_CONFIG].text,
- (unsigned)((peer->flags & FLAG_CONFIG) != 0));
- break;
-
- case CP_AUTHENABLE:
- ctl_putuint(peer_var[CP_AUTHENABLE].text,
- (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
- break;
-
- case CP_AUTHENTIC:
- ctl_putuint(peer_var[CP_AUTHENTIC].text,
- (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
- break;
-
- case CP_SRCADR:
- ctl_putadr(peer_var[CP_SRCADR].text, 0,
- &peer->srcadr);
- break;
-
- case CP_SRCPORT:
- ctl_putuint(peer_var[CP_SRCPORT].text,
- ntohs(((struct sockaddr_in*)&peer->srcadr)->sin_port));
- break;
-
- case CP_DSTADR:
- ctl_putadr(peer_var[CP_DSTADR].text, 0,
- &(peer->dstadr->sin));
- break;
-
- case CP_DSTPORT:
- ctl_putuint(peer_var[CP_DSTPORT].text,
- (u_long)(peer->dstadr ?
- ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
- break;
-
- case CP_LEAP:
- ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
- break;
-
- case CP_HMODE:
- ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
- break;
-
- case CP_STRATUM:
- ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
- break;
-
- case CP_PPOLL:
- ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
- break;
-
- case CP_HPOLL:
- ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
- break;
-
- case CP_PRECISION:
- ctl_putint(peer_var[CP_PRECISION].text,
- peer->precision);
- break;
-
- case CP_ROOTDELAY:
- ctl_putdbl(peer_var[CP_ROOTDELAY].text,
- peer->rootdelay * 1e3);
- break;
-
- case CP_ROOTDISPERSION:
- ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
- peer->rootdispersion * 1e3);
- break;
-
- case CP_REFID:
- if (peer->flags & FLAG_REFCLOCK) {
- if (peer->stratum > 0 && peer->stratum <
- STRATUM_UNSPEC)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->refid, NULL);
- else
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
- } else {
- if (peer->stratum > 1 && peer->stratum <
- STRATUM_UNSPEC)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->refid, NULL);
- else
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
- }
- break;
-
- case CP_REFTIME:
- ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
- break;
-
- case CP_ORG:
- ctl_putts(peer_var[CP_ORG].text, &peer->org);
- break;
-
- case CP_REC:
- ctl_putts(peer_var[CP_REC].text, &peer->rec);
- break;
-
- case CP_XMT:
- ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
- break;
-
- case CP_REACH:
- ctl_puthex(peer_var[CP_REACH].text, peer->reach);
- break;
-
- case CP_FLASH:
- ctl_puthex(peer_var[CP_FLASH].text, peer->flash);
- break;
-
- case CP_TTL:
- ctl_putint(peer_var[CP_TTL].text, sys_ttl[peer->ttl]);
- break;
-
- case CP_VALID:
- ctl_putuint(peer_var[CP_VALID].text, peer->unreach);
- break;
-
- case CP_RANK:
- ctl_putuint(peer_var[CP_RANK].text, peer->rank);
- break;
-
- case CP_TIMER:
- ctl_putuint(peer_var[CP_TIMER].text,
- peer->nextdate - current_time);
- break;
-
- case CP_DELAY:
- ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3);
- break;
-
- case CP_OFFSET:
- ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
- 1e3);
- break;
-
- case CP_JITTER:
- ctl_putdbl(peer_var[CP_JITTER].text,
- SQRT(peer->jitter) * 1e3);
- break;
-
- case CP_DISPERSION:
- ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
- 1e3);
- break;
-
- case CP_KEYID:
- ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
- break;
-
- case CP_FILTDELAY:
- ctl_putarray(peer_var[CP_FILTDELAY].text,
- peer->filter_delay, (int)peer->filter_nextpt);
- break;
-
- case CP_FILTOFFSET:
- ctl_putarray(peer_var[CP_FILTOFFSET].text,
- peer->filter_offset, (int)peer->filter_nextpt);
- break;
-
- case CP_FILTERROR:
- ctl_putarray(peer_var[CP_FILTERROR].text,
- peer->filter_disp, (int)peer->filter_nextpt);
- break;
-
- case CP_PMODE:
- ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
- break;
-
- case CP_RECEIVED:
- ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
- break;
-
- case CP_SENT:
- ctl_putuint(peer_var[CP_SENT].text, peer->sent);
- break;
-
- case CP_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) -
- strlen(peer_var[CP_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name */
-
- strcpy(s, peer_var[CP_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
- for (k = peer_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)(s - buf), 0);
- }
- break;
-#ifdef OPENSSL
- case CP_FLAGS:
- if (peer->crypto)
- ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
- break;
-
- case CP_DIGEST:
- if (peer->crypto) {
- const EVP_MD *dp;
-
- dp = EVP_get_digestbynid(peer->crypto >> 16);
- strcpy(str, OBJ_nid2ln(EVP_MD_pkey_type(dp)));
- ctl_putstr(peer_var[CP_DIGEST].text, str,
- strlen(str));
- }
- break;
-
- case CP_HOST:
- if (peer->subject != NULL)
- ctl_putstr(peer_var[CP_HOST].text, peer->subject,
- strlen(peer->subject));
- break;
-
- case CP_IDENT:
- if (peer->issuer != NULL)
- ctl_putstr(peer_var[CP_IDENT].text, peer->issuer,
- strlen(peer->issuer));
- break;
-
- case CP_INITSEQ:
- if ((ap = (struct autokey *)peer->recval.ptr) == NULL)
- break;
- ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
- ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
- ctl_putuint(peer_var[CP_INITTSP].text,
- ntohl(peer->recval.tstamp));
- break;
-#endif /* OPENSSL */
- }
-}
-
-
-#ifdef REFCLOCK
-/*
- * ctl_putclock - output clock variables
- */
-static void
-ctl_putclock(
- int varid,
- struct refclockstat *clock_stat,
- int mustput
- )
-{
- switch(varid) {
-
- case CC_TYPE:
- if (mustput || clock_stat->clockdesc == NULL
- || *(clock_stat->clockdesc) == '\0') {
- ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
- }
- break;
- case CC_TIMECODE:
- ctl_putstr(clock_var[CC_TIMECODE].text,
- clock_stat->p_lastcode,
- (unsigned)clock_stat->lencode);
- break;
-
- case CC_POLL:
- ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls);
- break;
-
- case CC_NOREPLY:
- ctl_putuint(clock_var[CC_NOREPLY].text,
- clock_stat->noresponse);
- break;
-
- case CC_BADFORMAT:
- ctl_putuint(clock_var[CC_BADFORMAT].text,
- clock_stat->badformat);
- break;
-
- case CC_BADDATA:
- ctl_putuint(clock_var[CC_BADDATA].text,
- clock_stat->baddata);
- break;
-
- case CC_FUDGETIME1:
- if (mustput || (clock_stat->haveflags & CLK_HAVETIME1))
- ctl_putdbl(clock_var[CC_FUDGETIME1].text,
- clock_stat->fudgetime1 * 1e3);
- break;
-
- case CC_FUDGETIME2:
- if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) ctl_putdbl(clock_var[CC_FUDGETIME2].text,
- clock_stat->fudgetime2 * 1e3);
- break;
-
- case CC_FUDGEVAL1:
- if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1))
- ctl_putint(clock_var[CC_FUDGEVAL1].text,
- clock_stat->fudgeval1);
- break;
-
- case CC_FUDGEVAL2:
- if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
- if (clock_stat->fudgeval1 > 1)
- ctl_putadr(clock_var[CC_FUDGEVAL2].text,
- (u_int32)clock_stat->fudgeval2, NULL);
- else
- ctl_putid(clock_var[CC_FUDGEVAL2].text,
- (char *)&clock_stat->fudgeval2);
- }
- break;
-
- case CC_FLAGS:
- if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 |
- CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
- ctl_putuint(clock_var[CC_FLAGS].text,
- clock_stat->flags);
- break;
-
- case CC_DEVICE:
- if (clock_stat->clockdesc == NULL ||
- *(clock_stat->clockdesc) == '\0') {
- if (mustput)
- ctl_putstr(clock_var[CC_DEVICE].text,
- "", 0);
- } else {
- ctl_putstr(clock_var[CC_DEVICE].text,
- clock_stat->clockdesc,
- strlen(clock_stat->clockdesc));
- }
- break;
-
- case CC_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf);
- if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
- be)
- break; /* really long var name */
-
- strcpy(s, clock_var[CC_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
-
- for (k = clock_var; !(k->flags &EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- i = strlen(k->text);
- if (s + i + 1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
-
- for (k = clock_stat->kv_list; k && !(k->flags &
- EOV); k++) {
- if (k->flags & PADDING)
- continue;
-
- ss = k->text;
- if (!ss)
- continue;
-
- while (*ss && *ss != '=')
- ss++;
- i = ss - k->text;
- if (s+i+1 >= be)
- break;
-
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text, (unsigned)i);
- s += i;
- *s = '\0';
- }
- if (s+2 >= be)
- break;
-
- *s++ = '"';
- *s = '\0';
- ctl_putdata(buf, (unsigned)( s - buf ), 0);
- }
- break;
- }
-}
-#endif
-
-
-
-/*
- * ctl_getitem - get the next data item from the incoming packet
- */
-static struct ctl_var *
-ctl_getitem(
- struct ctl_var *var_list,
- char **data
- )
-{
- register struct ctl_var *v;
- register char *cp;
- register char *tp;
- static struct ctl_var eol = { 0, EOV, };
- static char buf[128];
-
- /*
- * Delete leading commas and white space
- */
- while (reqpt < reqend && (*reqpt == ',' ||
- isspace((int)*reqpt)))
- reqpt++;
- if (reqpt >= reqend)
- return (0);
-
- if (var_list == (struct ctl_var *)0)
- return (&eol);
-
- /*
- * Look for a first character match on the tag. If we find
- * one, see if it is a full match.
- */
- v = var_list;
- cp = reqpt;
- while (!(v->flags & EOV)) {
- if (!(v->flags & PADDING) && *cp == *(v->text)) {
- tp = v->text;
- while (*tp != '\0' && *tp != '=' && cp <
- reqend && *cp == *tp) {
- cp++;
- tp++;
- }
- if ((*tp == '\0') || (*tp == '=')) {
- while (cp < reqend && isspace((int)*cp))
- cp++;
- if (cp == reqend || *cp == ',') {
- buf[0] = '\0';
- *data = buf;
- if (cp < reqend)
- cp++;
- reqpt = cp;
- return v;
- }
- if (*cp == '=') {
- cp++;
- tp = buf;
- while (cp < reqend && isspace((int)*cp))
- cp++;
- while (cp < reqend && *cp != ',') {
- *tp++ = *cp++;
- if (tp >= buf + sizeof(buf)) {
- ctl_error(CERR_BADFMT);
- numctlbadpkts++;
- msyslog(LOG_WARNING,
- "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
- stoa(rmt_addr), SRCPORT(rmt_addr)
- );
- return (0);
- }
- }
- if (cp < reqend)
- cp++;
- *tp-- = '\0';
- while (tp >= buf) {
- if (!isspace((int)(*tp)))
- break;
- *tp-- = '\0';
- }
- reqpt = cp;
- *data = buf;
- return (v);
- }
- }
- cp = reqpt;
- }
- v++;
- }
- return v;
-}
-
-
-/*
- * control_unspec - response to an unspecified op-code
- */
-/*ARGSUSED*/
-static void
-control_unspec(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- struct peer *peer;
-
- /*
- * What is an appropriate response to an unspecified op-code?
- * I return no errors and no data, unless a specified assocation
- * doesn't exist.
- */
- if (res_associd != 0) {
- if ((peer = findpeerbyassoc(res_associd)) == 0) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- rpkt.status = htons(ctlpeerstatus(peer));
- } else {
- rpkt.status = htons(ctlsysstatus());
- }
- ctl_flushpkt(0);
-}
-
-
-/*
- * read_status - return either a list of associd's, or a particular
- * peer's status.
- */
-/*ARGSUSED*/
-static void
-read_status(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register int i;
- register struct peer *peer;
- u_short ass_stat[CTL_MAX_DATA_LEN / sizeof(u_short)];
-
-#ifdef DEBUG
- if (debug > 2)
- printf("read_status: ID %d\n", res_associd);
-#endif
- /*
- * Two choices here. If the specified association ID is
- * zero we return all known assocation ID's. Otherwise
- * we return a bunch of stuff about the particular peer.
- */
- if (res_associd == 0) {
- register int n;
-
- n = 0;
- rpkt.status = htons(ctlsysstatus());
- for (i = 0; i < HASH_SIZE; i++) {
- for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
- ass_stat[n++] = htons(peer->associd);
- ass_stat[n++] =
- htons(ctlpeerstatus(peer));
- if (n ==
- CTL_MAX_DATA_LEN/sizeof(u_short)) {
- ctl_putdata((char *)ass_stat,
- n * sizeof(u_short), 1);
- n = 0;
- }
- }
- }
-
- if (n != 0)
- ctl_putdata((char *)ass_stat, n *
- sizeof(u_short), 1);
- ctl_flushpkt(0);
- } else {
- peer = findpeerbyassoc(res_associd);
- if (peer == 0) {
- ctl_error(CERR_BADASSOC);
- } else {
- register u_char *cp;
-
- rpkt.status = htons(ctlpeerstatus(peer));
- if (res_authokay)
- peer->num_events = 0;
- /*
- * For now, output everything we know about the
- * peer. May be more selective later.
- */
- for (cp = def_peer_var; *cp != 0; cp++)
- ctl_putpeer((int)*cp, peer);
- ctl_flushpkt(0);
- }
- }
-}
-
-
-/*
- * read_variables - return the variables the caller asks for
- */
-/*ARGSUSED*/
-static void
-read_variables(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register struct ctl_var *v;
- register int i;
- char *valuep;
- u_char *wants;
- unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
- 1) : (CP_MAXCODE + 1);
- if (res_associd == 0) {
- /*
- * Wants system variables. Figure out which he wants
- * and give them to him.
- */
- rpkt.status = htons(ctlsysstatus());
- if (res_authokay)
- ctl_sys_num_events = 0;
- gotvar += count_var(ext_sys_var);
- wants = (u_char *)emalloc(gotvar);
- memset((char *)wants, 0, gotvar);
- gotvar = 0;
- while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
- if (v->flags & EOV) {
- if ((v = ctl_getitem(ext_sys_var,
- &valuep)) != 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- free((char *)wants);
- return;
- }
- wants[CS_MAXCODE + 1 +
- v->code] = 1;
- gotvar = 1;
- continue;
- } else {
- break; /* shouldn't happen ! */
- }
- }
- wants[v->code] = 1;
- gotvar = 1;
- }
- if (gotvar) {
- for (i = 1; i <= CS_MAXCODE; i++)
- if (wants[i])
- ctl_putsys(i);
- for (i = 0; ext_sys_var &&
- !(ext_sys_var[i].flags & EOV); i++)
- if (wants[i + CS_MAXCODE + 1])
- ctl_putdata(ext_sys_var[i].text,
- strlen(ext_sys_var[i].text),
- 0);
- } else {
- register u_char *cs;
- register struct ctl_var *kv;
-
- for (cs = def_sys_var; *cs != 0; cs++)
- ctl_putsys((int)*cs);
- for (kv = ext_sys_var; kv && !(kv->flags & EOV);
- kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- }
- free((char *)wants);
- } else {
- register struct peer *peer;
-
- /*
- * Wants info for a particular peer. See if we know
- * the guy.
- */
- peer = findpeerbyassoc(res_associd);
- if (peer == 0) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- rpkt.status = htons(ctlpeerstatus(peer));
- if (res_authokay)
- peer->num_events = 0;
- wants = (u_char *)emalloc(gotvar);
- memset((char*)wants, 0, gotvar);
- gotvar = 0;
- while ((v = ctl_getitem(peer_var, &valuep)) != 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- free((char *)wants);
- return;
- }
- wants[v->code] = 1;
- gotvar = 1;
- }
- if (gotvar) {
- for (i = 1; i <= CP_MAXCODE; i++)
- if (wants[i])
- ctl_putpeer(i, peer);
- } else {
- register u_char *cp;
-
- for (cp = def_peer_var; *cp != 0; cp++)
- ctl_putpeer((int)*cp, peer);
- }
- free((char *)wants);
- }
- ctl_flushpkt(0);
-}
-
-
-/*
- * write_variables - write into variables. We only allow leap bit
- * writing this way.
- */
-/*ARGSUSED*/
-static void
-write_variables(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- register struct ctl_var *v;
- register int ext_var;
- char *valuep;
- long val = 0;
-
- /*
- * If he's trying to write into a peer tell him no way
- */
- if (res_associd != 0) {
- ctl_error(CERR_PERMISSION);
- return;
- }
-
- /*
- * Set status
- */
- rpkt.status = htons(ctlsysstatus());
-
- /*
- * Look through the variables. Dump out at the first sign of
- * trouble.
- */
- while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
- ext_var = 0;
- if (v->flags & EOV) {
- if ((v = ctl_getitem(ext_sys_var, &valuep)) !=
- 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- return;
- }
- ext_var = 1;
- } else {
- break;
- }
- }
- if (!(v->flags & CAN_WRITE)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
- if (!ext_var && (*valuep == '\0' || !atoint(valuep,
- &val))) {
- ctl_error(CERR_BADFMT);
- return;
- }
- if (!ext_var && (val & ~LEAP_NOTINSYNC) != 0) {
- ctl_error(CERR_BADVALUE);
- return;
- }
-
- if (ext_var) {
- char *s = (char *)emalloc(strlen(v->text) +
- strlen(valuep) + 2);
- const char *t;
- char *tt = s;
-
- t = v->text;
- while (*t && *t != '=')
- *tt++ = *t++;
-
- *tt++ = '=';
- strcat(tt, valuep);
- set_sys_var(s, strlen(s)+1, v->flags);
- free(s);
- } else {
- /*
- * This one seems sane. Save it.
- */
- switch(v->code) {
-
- case CS_LEAP:
- default:
- ctl_error(CERR_UNSPEC); /* really */
- return;
- }
- }
- }
-
- /*
- * If we got anything, do it. xxx nothing to do ***
- */
- /*
- if (leapind != ~0 || leapwarn != ~0) {
- if (!leap_setleap((int)leapind, (int)leapwarn)) {
- ctl_error(CERR_PERMISSION);
- return;
- }
- }
- */
- ctl_flushpkt(0);
-}
-
-
-/*
- * read_clock_status - return clock radio status
- */
-/*ARGSUSED*/
-static void
-read_clock_status(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
-#ifndef REFCLOCK
- /*
- * If no refclock support, no data to return
- */
- ctl_error(CERR_BADASSOC);
-#else
- register struct ctl_var *v;
- register int i;
- register struct peer *peer;
- char *valuep;
- u_char *wants;
- unsigned int gotvar;
- struct refclockstat clock_stat;
-
- if (res_associd == 0) {
-
- /*
- * Find a clock for this jerk. If the system peer
- * is a clock use it, else search the hash tables
- * for one.
- */
- if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
- {
- peer = sys_peer;
- } else {
- peer = 0;
- for (i = 0; peer == 0 && i < HASH_SIZE; i++) {
- for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
- if (peer->flags & FLAG_REFCLOCK)
- break;
- }
- }
- if (peer == 0) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- }
- } else {
- peer = findpeerbyassoc(res_associd);
- if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) {
- ctl_error(CERR_BADASSOC);
- return;
- }
- }
-
- /*
- * If we got here we have a peer which is a clock. Get his
- * status.
- */
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr, (struct refclockstat *)0,
- &clock_stat);
-
- /*
- * Look for variables in the packet.
- */
- rpkt.status = htons(ctlclkstatus(&clock_stat));
- gotvar = CC_MAXCODE + 1 + count_var(clock_stat.kv_list);
- wants = (u_char *)emalloc(gotvar);
- memset((char*)wants, 0, gotvar);
- gotvar = 0;
- while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
- if (v->flags & EOV) {
- if ((v = ctl_getitem(clock_stat.kv_list,
- &valuep)) != 0) {
- if (v->flags & EOV) {
- ctl_error(CERR_UNKNOWNVAR);
- free((char*)wants);
- free_varlist(clock_stat.kv_list);
- return;
- }
- wants[CC_MAXCODE + 1 + v->code] = 1;
- gotvar = 1;
- continue;
- } else {
- break; /* shouldn't happen ! */
- }
- }
- wants[v->code] = 1;
- gotvar = 1;
- }
-
- if (gotvar) {
- for (i = 1; i <= CC_MAXCODE; i++)
- if (wants[i])
- ctl_putclock(i, &clock_stat, 1);
- for (i = 0; clock_stat.kv_list &&
- !(clock_stat.kv_list[i].flags & EOV); i++)
- if (wants[i + CC_MAXCODE + 1])
- ctl_putdata(clock_stat.kv_list[i].text,
- strlen(clock_stat.kv_list[i].text),
- 0);
- } else {
- register u_char *cc;
- register struct ctl_var *kv;
-
- for (cc = def_clock_var; *cc != 0; cc++)
- ctl_putclock((int)*cc, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV);
- kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text, strlen(kv->text),
- 0);
- }
-
- free((char*)wants);
- free_varlist(clock_stat.kv_list);
-
- ctl_flushpkt(0);
-#endif
-}
-
-
-/*
- * write_clock_status - we don't do this
- */
-/*ARGSUSED*/
-static void
-write_clock_status(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- ctl_error(CERR_PERMISSION);
-}
-
-/*
- * Trap support from here on down. We send async trap messages when the
- * upper levels report trouble. Traps can by set either by control
- * messages or by configuration.
- */
-/*
- * set_trap - set a trap in response to a control message
- */
-static void
-set_trap(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- int traptype;
-
- /*
- * See if this guy is allowed
- */
- if (restrict_mask & RES_NOTRAP) {
- ctl_error(CERR_PERMISSION);
- return;
- }
-
- /*
- * Determine his allowed trap type.
- */
- traptype = TRAP_TYPE_PRIO;
- if (restrict_mask & RES_LPTRAP)
- traptype = TRAP_TYPE_NONPRIO;
-
- /*
- * Call ctlsettrap() to do the work. Return
- * an error if it can't assign the trap.
- */
- if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
- (int)res_version))
- ctl_error(CERR_NORESOURCE);
- ctl_flushpkt(0);
-}
-
-
-/*
- * unset_trap - unset a trap in response to a control message
- */
-static void
-unset_trap(
- struct recvbuf *rbufp,
- int restrict_mask
- )
-{
- int traptype;
-
- /*
- * We don't prevent anyone from removing his own trap unless the
- * trap is configured. Note we also must be aware of the
- * possibility that restriction flags were changed since this
- * guy last set his trap. Set the trap type based on this.
- */
- traptype = TRAP_TYPE_PRIO;
- if (restrict_mask & RES_LPTRAP)
- traptype = TRAP_TYPE_NONPRIO;
-
- /*
- * Call ctlclrtrap() to clear this out.
- */
- if (!ctlclrtrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype))
- ctl_error(CERR_BADASSOC);
- ctl_flushpkt(0);
-}
-
-
-/*
- * ctlsettrap - called to set a trap
- */
-int
-ctlsettrap(
- struct sockaddr_storage *raddr,
- struct interface *linter,
- int traptype,
- int version
- )
-{
- register struct ctl_trap *tp;
- register struct ctl_trap *tptouse;
-
- /*
- * See if we can find this trap. If so, we only need update
- * the flags and the time.
- */
- if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
- switch (traptype) {
-
- case TRAP_TYPE_CONFIG:
- tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
- break;
-
- case TRAP_TYPE_PRIO:
- if (tp->tr_flags & TRAP_CONFIGURED)
- return (1); /* don't change anything */
- tp->tr_flags = TRAP_INUSE;
- break;
-
- case TRAP_TYPE_NONPRIO:
- if (tp->tr_flags & TRAP_CONFIGURED)
- return (1); /* don't change anything */
- tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
- break;
- }
- tp->tr_settime = current_time;
- tp->tr_resets++;
- return (1);
- }
-
- /*
- * First we heard of this guy. Try to find a trap structure
- * for him to use, clearing out lesser priority guys if we
- * have to. Clear out anyone who's expired while we're at it.
- */
- tptouse = NULL;
- for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
- if ((tp->tr_flags & TRAP_INUSE) &&
- !(tp->tr_flags & TRAP_CONFIGURED) &&
- ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
- tp->tr_flags = 0;
- num_ctl_traps--;
- }
- if (!(tp->tr_flags & TRAP_INUSE)) {
- tptouse = tp;
- } else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
- switch (traptype) {
-
- case TRAP_TYPE_CONFIG:
- if (tptouse == NULL) {
- tptouse = tp;
- break;
- }
- if (tptouse->tr_flags & TRAP_NONPRIO &&
- !(tp->tr_flags & TRAP_NONPRIO))
- break;
-
- if (!(tptouse->tr_flags & TRAP_NONPRIO)
- && tp->tr_flags & TRAP_NONPRIO) {
- tptouse = tp;
- break;
- }
- if (tptouse->tr_origtime <
- tp->tr_origtime)
- tptouse = tp;
- break;
-
- case TRAP_TYPE_PRIO:
- if (tp->tr_flags & TRAP_NONPRIO) {
- if (tptouse == NULL ||
- (tptouse->tr_flags &
- TRAP_INUSE &&
- tptouse->tr_origtime <
- tp->tr_origtime))
- tptouse = tp;
- }
- break;
-
- case TRAP_TYPE_NONPRIO:
- break;
- }
- }
- }
-
- /*
- * If we don't have room for him return an error.
- */
- if (tptouse == NULL)
- return (0);
-
- /*
- * Set up this structure for him.
- */
- tptouse->tr_settime = tptouse->tr_origtime = current_time;
- tptouse->tr_count = tptouse->tr_resets = 0;
- tptouse->tr_sequence = 1;
- tptouse->tr_addr = *raddr;
- tptouse->tr_localaddr = linter;
- tptouse->tr_version = (u_char) version;
- tptouse->tr_flags = TRAP_INUSE;
- if (traptype == TRAP_TYPE_CONFIG)
- tptouse->tr_flags |= TRAP_CONFIGURED;
- else if (traptype == TRAP_TYPE_NONPRIO)
- tptouse->tr_flags |= TRAP_NONPRIO;
- num_ctl_traps++;
- return (1);
-}
-
-
-/*
- * ctlclrtrap - called to clear a trap
- */
-int
-ctlclrtrap(
- struct sockaddr_storage *raddr,
- struct interface *linter,
- int traptype
- )
-{
- register struct ctl_trap *tp;
-
- if ((tp = ctlfindtrap(raddr, linter)) == NULL)
- return (0);
-
- if (tp->tr_flags & TRAP_CONFIGURED
- && traptype != TRAP_TYPE_CONFIG)
- return (0);
-
- tp->tr_flags = 0;
- num_ctl_traps--;
- return (1);
-}
-
-
-/*
- * ctlfindtrap - find a trap given the remote and local addresses
- */
-static struct ctl_trap *
-ctlfindtrap(
- struct sockaddr_storage *raddr,
- struct interface *linter
- )
-{
- register struct ctl_trap *tp;
-
- for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
- if ((tp->tr_flags & TRAP_INUSE)
- && (NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr))
- && SOCKCMP(raddr, &tp->tr_addr)
- && (linter == tp->tr_localaddr) )
- return (tp);
- }
- return (struct ctl_trap *)NULL;
-}
-
-
-/*
- * report_event - report an event to the trappers
- */
-void
-report_event(
- int err,
- struct peer *peer
- )
-{
- register int i;
-
- /*
- * Record error code in proper spots, but have mercy on the
- * log file.
- */
- if (!(err & (PEER_EVENT | CRPT_EVENT))) {
- if (ctl_sys_num_events < CTL_SYS_MAXEVENTS)
- ctl_sys_num_events++;
- if (ctl_sys_last_event != (u_char)err) {
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()), ctlsysstatus());
-#ifdef DEBUG
- if (debug)
- printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()),
- ctlsysstatus());
-#endif
- ctl_sys_last_event = (u_char)err;
- }
- } else if (peer != 0) {
- char *src;
-
-#ifdef REFCLOCK
- if (ISREFCLOCKADR(&peer->srcadr))
- src = refnumtoa(&peer->srcadr);
- else
-#endif
- src = stoa(&peer->srcadr);
-
- peer->last_event = (u_char)(err & ~PEER_EVENT);
- if (peer->num_events < CTL_PEER_MAXEVENTS)
- peer->num_events++;
- NLOG(NLOG_PEEREVENT)
- msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#ifdef DEBUG
- if (debug)
- printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)),
- ctlpeerstatus(peer));
-#endif
- } else {
- msyslog(LOG_ERR,
- "report_event: err '%s' (0x%02x), no peer",
- eventstr(err), err);
-#ifdef DEBUG
- printf(
- "report_event: peer event '%s' (0x%02x), no peer\n",
- eventstr(err), err);
-#endif
- return;
- }
-
- /*
- * If no trappers, return.
- */
- if (num_ctl_traps <= 0)
- return;
-
- /*
- * Set up the outgoing packet variables
- */
- res_opcode = CTL_OP_ASYNCMSG;
- res_offset = 0;
- res_async = 1;
- res_authenticate = 0;
- datapt = rpkt.data;
- dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
- if (!(err & PEER_EVENT)) {
- rpkt.associd = 0;
- rpkt.status = htons(ctlsysstatus());
-
- /*
- * For now, put everything we know about system
- * variables. Don't send crypto strings.
- */
- for (i = 1; i <= CS_MAXCODE; i++) {
-#ifdef OPENSSL
- if (i > CS_VARLIST)
- continue;
-#endif /* OPENSSL */
- ctl_putsys(i);
- }
-#ifdef REFCLOCK
- /*
- * for clock exception events: add clock variables to
- * reflect info on exception
- */
- if (err == EVNT_CLOCKEXCPT) {
- struct refclockstat clock_stat;
- struct ctl_var *kv;
-
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
- ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
- for (i = 1; i <= CC_MAXCODE; i++)
- ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv &&
- !(kv->flags & EOV); kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- free_varlist(clock_stat.kv_list);
- }
-#endif /* REFCLOCK */
- } else {
- rpkt.associd = htons(peer->associd);
- rpkt.status = htons(ctlpeerstatus(peer));
-
- /*
- * Dump it all. Later, maybe less.
- */
- for (i = 1; i <= CP_MAXCODE; i++) {
-#ifdef OPENSSL
- if (i > CP_VARLIST)
- continue;
-#endif /* OPENSSL */
- ctl_putpeer(i, peer);
- }
-#ifdef REFCLOCK
- /*
- * for clock exception events: add clock variables to
- * reflect info on exception
- */
- if (err == EVNT_PEERCLOCK) {
- struct refclockstat clock_stat;
- struct ctl_var *kv;
-
- clock_stat.kv_list = (struct ctl_var *)0;
- refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
-
- ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
-
- for (i = 1; i <= CC_MAXCODE; i++)
- ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv &&
- !(kv->flags & EOV); kv++)
- if (kv->flags & DEF)
- ctl_putdata(kv->text,
- strlen(kv->text), 0);
- free_varlist(clock_stat.kv_list);
- }
-#endif /* REFCLOCK */
- }
-
- /*
- * We're done, return.
- */
- ctl_flushpkt(0);
-}
-
-
-/*
- * ctl_clr_stats - clear stat counters
- */
-void
-ctl_clr_stats(void)
-{
- ctltimereset = current_time;
- numctlreq = 0;
- numctlbadpkts = 0;
- numctlresponses = 0;
- numctlfrags = 0;
- numctlerrors = 0;
- numctlfrags = 0;
- numctltooshort = 0;
- numctlinputresp = 0;
- numctlinputfrag = 0;
- numctlinputerr = 0;
- numctlbadoffset = 0;
- numctlbadversion = 0;
- numctldatatooshort = 0;
- numctlbadop = 0;
- numasyncmsgs = 0;
-}
-
-static u_long
-count_var(
- struct ctl_var *k
- )
-{
- register u_long c;
-
- if (!k)
- return (0);
-
- c = 0;
- while (!(k++->flags & EOV))
- c++;
- return (c);
-}
-
-char *
-add_var(
- struct ctl_var **kv,
- u_long size,
- u_short def
- )
-{
- register u_long c;
- register struct ctl_var *k;
-
- c = count_var(*kv);
-
- k = *kv;
- *kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
- if (k) {
- memmove((char *)*kv, (char *)k,
- sizeof(struct ctl_var)*c);
- free((char *)k);
- }
- (*kv)[c].code = (u_short) c;
- (*kv)[c].text = (char *)emalloc(size);
- (*kv)[c].flags = def;
- (*kv)[c+1].code = 0;
- (*kv)[c+1].text = (char *)0;
- (*kv)[c+1].flags = EOV;
- return (char *)(*kv)[c].text;
-}
-
-void
-set_var(
- struct ctl_var **kv,
- const char *data,
- u_long size,
- u_short def
- )
-{
- register struct ctl_var *k;
- register const char *s;
- register const char *t;
- char *td;
-
- if (!data || !size)
- return;
-
- k = *kv;
- if (k != NULL) {
- while (!(k->flags & EOV)) {
- s = data;
- t = k->text;
- if (t) {
- while (*t != '=' && *s - *t == 0) {
- s++;
- t++;
- }
- if (*s == *t && ((*t == '=') || !*t)) {
- free((void *)k->text);
- td = (char *)emalloc(size);
- memmove(td, data, size);
- k->text =td;
- k->flags = def;
- return;
- }
- } else {
- td = (char *)emalloc(size);
- memmove(td, data, size);
- k->text = td;
- k->flags = def;
- return;
- }
- k++;
- }
- }
- td = add_var(kv, size, def);
- memmove(td, data, size);
-}
-
-void
-set_sys_var(
- char *data,
- u_long size,
- u_short def
- )
-{
- set_var(&ext_sys_var, data, size, def);
-}
-
-void
-free_varlist(
- struct ctl_var *kv
- )
-{
- struct ctl_var *k;
- if (kv) {
- for (k = kv; !(k->flags & EOV); k++)
- free((void *)k->text);
- free((void *)kv);
- }
-}
diff --git a/contrib/ntp/ntpd/ntp_crypto.c b/contrib/ntp/ntpd/ntp_crypto.c
deleted file mode 100644
index 3e67703..0000000
--- a/contrib/ntp/ntpd/ntp_crypto.c
+++ /dev/null
@@ -1,4031 +0,0 @@
-/*
- * ntp_crypto.c - NTP version 4 public key routines
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef OPENSSL
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "ntpd.h"
-#include "ntp_stdlib.h"
-#include "ntp_unixtime.h"
-#include "ntp_string.h"
-
-#include "openssl/asn1_mac.h"
-#include "openssl/bn.h"
-#include "openssl/err.h"
-#include "openssl/evp.h"
-#include "openssl/pem.h"
-#include "openssl/rand.h"
-#include "openssl/x509v3.h"
-
-#ifdef KERNEL_PLL
-#include "ntp_syscall.h"
-#endif /* KERNEL_PLL */
-
-/*
- * Extension field message format
- *
- * These are always signed and saved before sending in network byte
- * order. They must be converted to and from host byte order for
- * processing.
- *
- * +-------+-------+
- * | op | len | <- extension pointer
- * +-------+-------+
- * | assocID |
- * +---------------+
- * | timestamp | <- value pointer
- * +---------------+
- * | filestamp |
- * +---------------+
- * | value len |
- * +---------------+
- * | |
- * = value =
- * | |
- * +---------------+
- * | signature len |
- * +---------------+
- * | |
- * = signature =
- * | |
- * +---------------+
- *
- * The CRYPTO_RESP bit is set to 0 for requests, 1 for responses.
- * Requests carry the association ID of the receiver; responses carry
- * the association ID of the sender. Some messages include only the
- * operation/length and association ID words and so have length 8
- * octets. Ohers include the value structure and associated value and
- * signature fields. These messages include the timestamp, filestamp,
- * value and signature words and so have length at least 24 octets. The
- * signature and/or value fields can be empty, in which case the
- * respective length words are zero. An empty value with nonempty
- * signature is syntactically valid, but semantically questionable.
- *
- * The filestamp represents the time when a cryptographic data file such
- * as a public/private key pair is created. It follows every reference
- * depending on that file and serves as a means to obsolete earlier data
- * of the same type. The timestamp represents the time when the
- * cryptographic data of the message were last signed. Creation of a
- * cryptographic data file or signing a message can occur only when the
- * creator or signor is synchronized to an authoritative source and
- * proventicated to a trusted authority.
- *
- * Note there are four conditions required for server trust. First, the
- * public key on the certificate must be verified, which involves a
- * number of format, content and consistency checks. Next, the server
- * identity must be confirmed by one of four schemes: private
- * certificate, IFF scheme, GQ scheme or certificate trail hike to a
- * self signed trusted certificate. Finally, the server signature must
- * be verified.
- */
-/*
- * Cryptodefines
- */
-#define TAI_1972 10 /* initial TAI offset (s) */
-#define MAX_LEAP 100 /* max UTC leapseconds (s) */
-#define VALUE_LEN (6 * 4) /* min response field length */
-#define YEAR (60 * 60 * 24 * 365) /* seconds in year */
-
-/*
- * Global cryptodata in host byte order
- */
-u_int32 crypto_flags = 0x0; /* status word */
-u_int sys_tai; /* current UTC offset from TAI */
-
-/*
- * Global cryptodata in network byte order
- */
-struct cert_info *cinfo = NULL; /* certificate info/value */
-struct value hostval; /* host value */
-struct value pubkey; /* public key */
-struct value tai_leap; /* leapseconds table */
-
-/*
- * Private cryptodata in host byte order
- */
-static char *passwd = NULL; /* private key password */
-static EVP_PKEY *host_pkey = NULL; /* host key */
-static EVP_PKEY *sign_pkey = NULL; /* sign key */
-static EVP_PKEY *iffpar_pkey = NULL; /* IFF parameters */
-static EVP_PKEY *gqpar_pkey = NULL; /* GQ parameters */
-static EVP_PKEY *mvpar_pkey = NULL; /* MV parameters */
-static const EVP_MD *sign_digest = NULL; /* sign digest */
-static u_int sign_siglen; /* sign key length */
-static char *rand_file = NULL; /* random seed file */
-static char *host_file = NULL; /* host key file */
-static char *sign_file = NULL; /* sign key file */
-static char *iffpar_file = NULL; /* IFF parameters file */
-static char *gqpar_file = NULL; /* GQ parameters file */
-static char *mvpar_file = NULL; /* MV parameters file */
-static char *cert_file = NULL; /* certificate file */
-static char *leap_file = NULL; /* leapseconds file */
-static tstamp_t if_fstamp = 0; /* IFF file stamp */
-static tstamp_t gq_fstamp = 0; /* GQ file stamp */
-static tstamp_t mv_fstamp = 0; /* MV file stamp */
-
-/*
- * Cryptotypes
- */
-static int crypto_verify P((struct exten *, struct value *,
- struct peer *));
-static int crypto_encrypt P((struct exten *, struct value *,
- keyid_t *));
-static int crypto_alice P((struct peer *, struct value *));
-static int crypto_alice2 P((struct peer *, struct value *));
-static int crypto_alice3 P((struct peer *, struct value *));
-static int crypto_bob P((struct exten *, struct value *));
-static int crypto_bob2 P((struct exten *, struct value *));
-static int crypto_bob3 P((struct exten *, struct value *));
-static int crypto_iff P((struct exten *, struct peer *));
-static int crypto_gq P((struct exten *, struct peer *));
-static int crypto_mv P((struct exten *, struct peer *));
-static u_int crypto_send P((struct exten *, struct value *));
-static tstamp_t crypto_time P((void));
-static u_long asn2ntp P((ASN1_TIME *));
-static struct cert_info *cert_parse P((u_char *, u_int, tstamp_t));
-static int cert_sign P((struct exten *, struct value *));
-static int cert_valid P((struct cert_info *, EVP_PKEY *));
-static int cert_install P((struct exten *, struct peer *));
-static void cert_free P((struct cert_info *));
-static EVP_PKEY *crypto_key P((char *, tstamp_t *));
-static int bighash P((BIGNUM *, BIGNUM *));
-static struct cert_info *crypto_cert P((char *));
-static void crypto_tai P((char *));
-
-#ifdef SYS_WINNT
-int
-readlink(char * link, char * file, int len) {
- return (-1);
-}
-#endif
-
-/*
- * session_key - generate session key
- *
- * This routine generates a session key from the source address,
- * destination address, key ID and private value. The value of the
- * session key is the MD5 hash of these values, while the next key ID is
- * the first four octets of the hash.
- *
- * Returns the next key ID
- */
-keyid_t
-session_key(
- struct sockaddr_storage *srcadr, /* source address */
- struct sockaddr_storage *dstadr, /* destination address */
- keyid_t keyno, /* key ID */
- keyid_t private, /* private value */
- u_long lifetime /* key lifetime */
- )
-{
- EVP_MD_CTX ctx; /* message digest context */
- u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
- keyid_t keyid; /* key identifer */
- u_int32 header[10]; /* data in network byte order */
- u_int hdlen, len;
-
- /*
- * Generate the session key and key ID. If the lifetime is
- * greater than zero, install the key and call it trusted.
- */
- hdlen = 0;
- switch(srcadr->ss_family) {
- case AF_INET:
- header[0] = ((struct sockaddr_in *)srcadr)->sin_addr.s_addr;
- header[1] = ((struct sockaddr_in *)dstadr)->sin_addr.s_addr;
- header[2] = htonl(keyno);
- header[3] = htonl(private);
- hdlen = 4 * sizeof(u_int32);
- break;
- case AF_INET6:
- memcpy(&header[0], &GET_INADDR6(*srcadr),
- sizeof(struct in6_addr));
- memcpy(&header[4], &GET_INADDR6(*dstadr),
- sizeof(struct in6_addr));
- header[8] = htonl(keyno);
- header[9] = htonl(private);
- hdlen = 10 * sizeof(u_int32);
- break;
- }
- EVP_DigestInit(&ctx, EVP_md5());
- EVP_DigestUpdate(&ctx, (u_char *)header, hdlen);
- EVP_DigestFinal(&ctx, dgst, &len);
- memcpy(&keyid, dgst, 4);
- keyid = ntohl(keyid);
- if (lifetime != 0) {
- MD5auth_setkey(keyno, dgst, len);
- authtrust(keyno, lifetime);
- }
-#ifdef DEBUG
- if (debug > 1)
- printf(
- "session_key: %s > %s %08x %08x hash %08x life %lu\n",
- stoa(srcadr), stoa(dstadr), keyno,
- private, keyid, lifetime);
-#endif
- return (keyid);
-}
-
-
-/*
- * make_keylist - generate key list
- *
- * This routine constructs a pseudo-random sequence by repeatedly
- * hashing the session key starting from a given source address,
- * destination address, private value and the next key ID of the
- * preceeding session key. The last entry on the list is saved along
- * with its sequence number and public signature.
- */
-void
-make_keylist(
- struct peer *peer, /* peer structure pointer */
- struct interface *dstadr /* interface */
- )
-{
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp; /* NTP timestamp */
- struct autokey *ap; /* autokey pointer */
- struct value *vp; /* value pointer */
- keyid_t keyid = 0; /* next key ID */
- keyid_t cookie; /* private value */
- u_long lifetime;
- u_int len;
- int i;
-
- /*
- * Allocate the key list if necessary.
- */
- tstamp = crypto_time();
- if (peer->keylist == NULL)
- peer->keylist = emalloc(sizeof(keyid_t) *
- NTP_MAXSESSION);
-
- /*
- * Generate an initial key ID which is unique and greater than
- * NTP_MAXKEY.
- */
- while (1) {
- keyid = (u_long)RANDOM & 0xffffffff;
- if (keyid <= NTP_MAXKEY)
- continue;
- if (authhavekey(keyid))
- continue;
- break;
- }
-
- /*
- * Generate up to NTP_MAXSESSION session keys. Stop if the
- * next one would not be unique or not a session key ID or if
- * it would expire before the next poll. The private value
- * included in the hash is zero if broadcast mode, the peer
- * cookie if client mode or the host cookie if symmetric modes.
- */
- lifetime = min(sys_automax, (unsigned long) NTP_MAXSESSION * (1 <<(peer->kpoll)));
- if (peer->hmode == MODE_BROADCAST)
- cookie = 0;
- else
- cookie = peer->pcookie;
- for (i = 0; i < NTP_MAXSESSION; i++) {
- peer->keylist[i] = keyid;
- peer->keynumber = i;
- keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
- cookie, lifetime);
- lifetime -= 1 << peer->kpoll;
- if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
- lifetime <= (unsigned long)(1 << (peer->kpoll)))
- break;
- }
-
- /*
- * Save the last session key ID, sequence number and timestamp,
- * then sign these values for later retrieval by the clients. Be
- * careful not to use invalid key media. Use the public values
- * timestamp as filestamp.
- */
- vp = &peer->sndval;
- if (vp->ptr == NULL)
- vp->ptr = emalloc(sizeof(struct autokey));
- ap = (struct autokey *)vp->ptr;
- ap->seq = htonl(peer->keynumber);
- ap->key = htonl(keyid);
- vp->tstamp = htonl(tstamp);
- vp->fstamp = hostval.tstamp;
- vp->vallen = htonl(sizeof(struct autokey));
- vp->siglen = 0;
- if (vp->tstamp != 0) {
- if (vp->sig == NULL)
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)vp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, sizeof(struct autokey));
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- else
- msyslog(LOG_ERR, "make_keys %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- peer->flags |= FLAG_ASSOC;
- }
-#ifdef DEBUG
- if (debug)
- printf("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
- ntohl(ap->seq), ntohl(ap->key), cookie,
- ntohl(vp->tstamp), ntohl(vp->fstamp), peer->kpoll);
-#endif
-}
-
-
-/*
- * crypto_recv - parse extension fields
- *
- * This routine is called when the packet has been matched to an
- * association and passed sanity, format and MAC checks. We believe the
- * extension field values only if the field has proper format and
- * length, the timestamp and filestamp are valid and the signature has
- * valid length and is verified. There are a few cases where some values
- * are believed even if the signature fails, but only if the proventic
- * bit is not set.
- */
-int
-crypto_recv(
- struct peer *peer, /* peer structure pointer */
- struct recvbuf *rbufp /* packet buffer pointer */
- )
-{
- const EVP_MD *dp; /* message digest algorithm */
- u_int32 *pkt; /* receive packet pointer */
- struct autokey *ap, *bp; /* autokey pointer */
- struct exten *ep, *fp; /* extension pointers */
- int has_mac; /* length of MAC field */
- int authlen; /* offset of MAC field */
- associd_t associd; /* association ID */
- tstamp_t tstamp = 0; /* timestamp */
- tstamp_t fstamp = 0; /* filestamp */
- u_int len; /* extension field length */
- u_int code; /* extension field opcode */
- u_int vallen = 0; /* value length */
- X509 *cert; /* X509 certificate */
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- keyid_t cookie; /* crumbles */
- int rval = XEVNT_OK;
- u_char *ptr;
- u_int32 temp32;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- struct timex ntv; /* kernel interface structure */
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
-
- /*
- * Initialize. Note that the packet has already been checked for
- * valid format and extension field lengths. First extract the
- * field length, command code and association ID in host byte
- * order. These are used with all commands and modes. Then check
- * the version number, which must be 2, and length, which must
- * be at least 8 for requests and VALUE_LEN (24) for responses.
- * Packets that fail either test sink without a trace. The
- * association ID is saved only if nonzero.
- */
- authlen = LEN_PKT_NOMAC;
- while ((has_mac = rbufp->recv_length - authlen) > MAX_MAC_LEN) {
- pkt = (u_int32 *)&rbufp->recv_pkt + authlen / 4;
- ep = (struct exten *)pkt;
- code = ntohl(ep->opcode) & 0xffff0000;
- len = ntohl(ep->opcode) & 0x0000ffff;
- associd = (associd_t) ntohl(pkt[1]);
- rval = XEVNT_OK;
-#ifdef DEBUG
- if (debug)
- printf(
- "crypto_recv: flags 0x%x ext offset %d len %u code %x assocID %d\n",
- peer->crypto, authlen, len, code >> 16,
- associd);
-#endif
-
- /*
- * Check version number and field length. If bad,
- * quietly ignore the packet.
- */
- if (((code >> 24) & 0x3f) != CRYPTO_VN || len < 8 ||
- (len < VALUE_LEN && (code & CRYPTO_RESP))) {
- sys_unknownversion++;
- code |= CRYPTO_ERROR;
- }
-
- /*
- * Little vulnerability bandage here. If a perp tosses a
- * fake association ID over the fence, we better toss it
- * out. Only the first one counts.
- */
- if (code & CRYPTO_RESP) {
- if (peer->assoc == 0)
- peer->assoc = associd;
- else if (peer->assoc != associd)
- code |= CRYPTO_ERROR;
- }
- if (len >= VALUE_LEN) {
- tstamp = ntohl(ep->tstamp);
- fstamp = ntohl(ep->fstamp);
- vallen = ntohl(ep->vallen);
- }
- switch (code) {
-
- /*
- * Install status word, host name, signature scheme and
- * association ID. In OpenSSL the signature algorithm is
- * bound to the digest algorithm, so the NID completely
- * defines the signature scheme. Note the request and
- * response are identical, but neither is validated by
- * signature. The request is processed here only in
- * symmetric modes. The server name field would be
- * useful to implement access controls in future.
- */
- case CRYPTO_ASSOC:
-
- /*
- * Pass the extension field to the transmit
- * side.
- */
- fp = emalloc(len);
- memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
- peer->cmmd = fp;
- /* fall through */
-
- case CRYPTO_ASSOC | CRYPTO_RESP:
-
- /*
- * Discard the message if it has already been
- * stored or the server is not synchronized.
- */
- if (peer->crypto || !fstamp)
- break;
-
- if (len < VALUE_LEN + vallen) {
- rval = XEVNT_LEN;
- break;
- }
-
- /*
- * Check the identity schemes are compatible. If
- * the client has PC, the server must have PC,
- * in which case the server public key and
- * identity are presumed valid, so we skip the
- * certificate and identity exchanges and move
- * immediately to the cookie exchange which
- * confirms the server signature. If the client
- * has IFF or GC or both, the server must have
- * the same one or both. Otherwise, the default
- * TC scheme is used.
- */
- if (crypto_flags & CRYPTO_FLAG_PRIV) {
- if (!(fstamp & CRYPTO_FLAG_PRIV))
- rval = XEVNT_KEY;
- else
- fstamp |= CRYPTO_FLAG_VALID |
- CRYPTO_FLAG_VRFY;
- } else if (crypto_flags & CRYPTO_FLAG_MASK &&
- !(crypto_flags & fstamp &
- CRYPTO_FLAG_MASK)) {
- rval = XEVNT_KEY;
- }
-
- /*
- * Discard the message if identity error.
- */
- if (rval != XEVNT_OK)
- break;
-
- /*
- * Discard the message if the host name length
- * is unreasonable or the signature digest NID
- * is not supported.
- */
- temp32 = (fstamp >> 16) & 0xffff;
- dp =
- (const EVP_MD *)EVP_get_digestbynid(temp32);
- if (vallen == 0 || vallen > MAXHOSTNAME)
- rval = XEVNT_LEN;
- else if (dp == NULL)
- rval = XEVNT_MD;
- if (rval != XEVNT_OK)
- break;
-
- /*
- * Save status word, host name and message
- * digest/signature type. If PC identity, be
- * sure not to sign the certificate.
- */
- if (crypto_flags & CRYPTO_FLAG_PRIV)
- fstamp |= CRYPTO_FLAG_SIGN;
- peer->crypto = fstamp;
- peer->digest = dp;
- peer->subject = emalloc(vallen + 1);
- memcpy(peer->subject, ep->pkt, vallen);
- peer->subject[vallen] = '\0';
- peer->issuer = emalloc(vallen + 1);
- strcpy(peer->issuer, peer->subject);
- temp32 = (fstamp >> 16) & 0xffff;
- sprintf(statstr,
- "flags 0x%x host %s signature %s", fstamp,
- peer->subject, OBJ_nid2ln(temp32));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * Decode X509 certificate in ASN.1 format and extract
- * the data containing, among other things, subject
- * name and public key. In the default identification
- * scheme, the certificate trail is followed to a self
- * signed trusted certificate.
- */
- case CRYPTO_CERT | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * already confirmed.
- */
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * Scan the certificate list to delete old
- * versions and link the newest version first on
- * the list.
- */
- if ((rval = cert_install(ep, peer)) != XEVNT_OK)
- break;
-
- /*
- * If we snatch the certificate before the
- * server certificate has been signed by its
- * server, it will be self signed. When it is,
- * we chase the certificate issuer, which the
- * server has, and keep going until a self
- * signed trusted certificate is found. Be sure
- * to update the issuer field, since it may
- * change.
- */
- if (peer->issuer != NULL)
- free(peer->issuer);
- peer->issuer = emalloc(strlen(cinfo->issuer) +
- 1);
- strcpy(peer->issuer, cinfo->issuer);
-
- /*
- * We plug in the public key and group key in
- * the first certificate received. However, note
- * that this certificate might not be signed by
- * the server, so we can't check the
- * signature/digest NID.
- */
- if (peer->pkey == NULL) {
- ptr = (u_char *)cinfo->cert.ptr;
- cert = d2i_X509(NULL, &ptr,
- ntohl(cinfo->cert.vallen));
- peer->pkey = X509_get_pubkey(cert);
- X509_free(cert);
- }
- peer->flash &= ~TEST10;
- temp32 = cinfo->nid;
- sprintf(statstr, "cert %s 0x%x %s (%u) fs %u",
- cinfo->subject, cinfo->flags,
- OBJ_nid2ln(temp32), temp32,
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * Schnorr (IFF)identity scheme. This scheme is designed
- * for use with shared secret group keys and where the
- * certificate may be generated by a third party. The
- * client sends a challenge to the server, which
- * performs a calculation and returns the result. A
- * positive result is possible only if both client and
- * server contain the same secret group key.
- */
- case CRYPTO_IFF | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * already confirmed.
- */
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * If the the challenge matches the response,
- * the certificate public key, as well as the
- * server public key, signatyre and identity are
- * all verified at the same time. The server is
- * declared trusted, so we skip further
- * certificate stages and move immediately to
- * the cookie stage.
- */
- if ((rval = crypto_iff(ep, peer)) != XEVNT_OK)
- break;
-
- peer->crypto |= CRYPTO_FLAG_VRFY |
- CRYPTO_FLAG_PROV;
- peer->flash &= ~TEST10;
- sprintf(statstr, "iff fs %u",
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * Guillou-Quisquater (GQ) identity scheme. This scheme
- * is designed for use with public certificates carrying
- * the GQ public key in an extension field. The client
- * sends a challenge to the server, which performs a
- * calculation and returns the result. A positive result
- * is possible only if both client and server contain
- * the same group key and the server has the matching GQ
- * private key.
- */
- case CRYPTO_GQ | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * already confirmed.
- */
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * If the the challenge matches the response,
- * the certificate public key, as well as the
- * server public key, signatyre and identity are
- * all verified at the same time. The server is
- * declared trusted, so we skip further
- * certificate stages and move immediately to
- * the cookie stage.
- */
- if ((rval = crypto_gq(ep, peer)) != XEVNT_OK)
- break;
-
- peer->crypto |= CRYPTO_FLAG_VRFY |
- CRYPTO_FLAG_PROV;
- peer->flash &= ~TEST10;
- sprintf(statstr, "gq fs %u",
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * MV
- */
- case CRYPTO_MV | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * already confirmed.
- */
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * If the the challenge matches the response,
- * the certificate public key, as well as the
- * server public key, signatyre and identity are
- * all verified at the same time. The server is
- * declared trusted, so we skip further
- * certificate stages and move immediately to
- * the cookie stage.
- */
- if ((rval = crypto_mv(ep, peer)) != XEVNT_OK)
- break;
-
- peer->crypto |= CRYPTO_FLAG_VRFY |
- CRYPTO_FLAG_PROV;
- peer->flash &= ~TEST10;
- sprintf(statstr, "mv fs %u",
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * X509 certificate sign response. Validate the
- * certificate signed by the server and install. Later
- * this can be provided to clients of this server in
- * lieu of the self signed certificate in order to
- * validate the public key.
- */
- case CRYPTO_SIGN | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * not confirmed.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * Scan the certificate list to delete old
- * versions and link the newest version first on
- * the list.
- */
- if ((rval = cert_install(ep, peer)) != XEVNT_OK) break;
-
- peer->crypto |= CRYPTO_FLAG_SIGN;
- peer->flash &= ~TEST10;
- temp32 = cinfo->nid;
- sprintf(statstr, "sign %s 0x%x %s (%u) fs %u",
- cinfo->issuer, cinfo->flags,
- OBJ_nid2ln(temp32), temp32,
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * Cookie request in symmetric modes. Roll a random
- * cookie and install in symmetric mode. Encrypt for the
- * response, which is transmitted later.
- */
- case CRYPTO_COOK:
-
- /*
- * Discard the message if invalid or identity
- * not confirmed.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * Pass the extension field to the transmit
- * side. If already agreed, walk away.
- */
- fp = emalloc(len);
- memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
- peer->cmmd = fp;
- if (peer->crypto & CRYPTO_FLAG_AGREE) {
- peer->flash &= ~TEST10;
- break;
- }
-
- /*
- * Install cookie values and light the cookie
- * bit. The transmit side will pick up and
- * encrypt it for the response.
- */
- key_expire(peer);
- peer->cookval.tstamp = ep->tstamp;
- peer->cookval.fstamp = ep->fstamp;
- RAND_bytes((u_char *)&peer->pcookie, 4);
- peer->crypto &= ~CRYPTO_FLAG_AUTO;
- peer->crypto |= CRYPTO_FLAG_AGREE;
- peer->flash &= ~TEST10;
- sprintf(statstr, "cook %x ts %u fs %u",
- peer->pcookie, ntohl(ep->tstamp),
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * Cookie response in client and symmetric modes. If the
- * cookie bit is set, the working cookie is the EXOR of
- * the current and new values.
- */
- case CRYPTO_COOK | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * not confirmed or signature not verified with
- * respect to the cookie values.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, &peer->cookval,
- peer)) != XEVNT_OK)
- break;
-
- /*
- * Decrypt the cookie, hunting all the time for
- * errors.
- */
- if (vallen == (u_int) EVP_PKEY_size(host_pkey)) {
- RSA_private_decrypt(vallen,
- (u_char *)ep->pkt,
- (u_char *)&temp32,
- host_pkey->pkey.rsa,
- RSA_PKCS1_OAEP_PADDING);
- cookie = ntohl(temp32);
- } else {
- rval = XEVNT_CKY;
- break;
- }
-
- /*
- * Install cookie values and light the cookie
- * bit. If this is not broadcast client mode, we
- * are done here.
- */
- key_expire(peer);
- peer->cookval.tstamp = ep->tstamp;
- peer->cookval.fstamp = ep->fstamp;
- if (peer->crypto & CRYPTO_FLAG_AGREE)
- peer->pcookie ^= cookie;
- else
- peer->pcookie = cookie;
- if (peer->hmode == MODE_CLIENT &&
- !(peer->cast_flags & MDF_BCLNT))
- peer->crypto |= CRYPTO_FLAG_AUTO;
- else
- peer->crypto &= ~CRYPTO_FLAG_AUTO;
- peer->crypto |= CRYPTO_FLAG_AGREE;
- peer->flash &= ~TEST10;
- sprintf(statstr, "cook %x ts %u fs %u",
- peer->pcookie, ntohl(ep->tstamp),
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * Install autokey values in broadcast client and
- * symmetric modes. We have to do this every time the
- * sever/peer cookie changes or a new keylist is
- * rolled. Ordinarily, this is automatic as this message
- * is piggybacked on the first NTP packet sent upon
- * either of these events. Note that a broadcast client
- * or symmetric peer can receive this response without a
- * matching request.
- */
- case CRYPTO_AUTO | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * not confirmed or signature not verified with
- * respect to the receive autokey values.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, &peer->recval,
- peer)) != XEVNT_OK)
- break;
-
- /*
- * Install autokey values and light the
- * autokey bit. This is not hard.
- */
- if (peer->recval.ptr == NULL)
- peer->recval.ptr =
- emalloc(sizeof(struct autokey));
- bp = (struct autokey *)peer->recval.ptr;
- peer->recval.tstamp = ep->tstamp;
- peer->recval.fstamp = ep->fstamp;
- ap = (struct autokey *)ep->pkt;
- bp->seq = ntohl(ap->seq);
- bp->key = ntohl(ap->key);
- peer->pkeyid = bp->key;
- peer->crypto |= CRYPTO_FLAG_AUTO;
- peer->flash &= ~TEST10;
- sprintf(statstr,
- "auto seq %d key %x ts %u fs %u", bp->seq,
- bp->key, ntohl(ep->tstamp),
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * Install leapseconds table in symmetric modes. This
- * table is proventicated to the NIST primary servers,
- * either by copying the file containing the table from
- * a NIST server to a trusted server or directly using
- * this protocol. While the entire table is installed at
- * the server, presently only the current TAI offset is
- * provided via the kernel to other applications.
- */
- case CRYPTO_TAI:
-
- /*
- * Discard the message if invalid or identity
- * not confirmed.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * Pass the extension field to the transmit
- * side. Continue below if a leapseconds table
- * accompanies the message.
- */
- fp = emalloc(len);
- memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
- peer->cmmd = fp;
- if (len <= VALUE_LEN) {
- peer->flash &= ~TEST10;
- break;
- }
- /* fall through */
-
- case CRYPTO_TAI | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * not confirmed or signature not verified with
- * respect to the leapsecond table values.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, &peer->tai_leap,
- peer)) != XEVNT_OK)
- break;
-
- /*
- * Initialize peer variables, leapseconds
- * structure and extension field in network byte
- * order. Since a filestamp may have changed,
- * recompute the signatures.
- */
- peer->tai_leap.tstamp = ep->tstamp;
- peer->tai_leap.fstamp = ep->fstamp;
- peer->tai_leap.vallen = ep->vallen;
-
- /*
- * Install the new table if there is no stored
- * table or the new table is more recent than
- * the stored table. Since a filestamp may have
- * changed, recompute the signatures.
- */
- if (ntohl(peer->tai_leap.fstamp) >
- ntohl(tai_leap.fstamp)) {
- tai_leap.fstamp = ep->fstamp;
- tai_leap.vallen = ep->vallen;
- if (tai_leap.ptr != NULL)
- free(tai_leap.ptr);
- tai_leap.ptr = emalloc(vallen);
- memcpy(tai_leap.ptr, ep->pkt, vallen);
- crypto_update();
- sys_tai = vallen / 4 + TAI_1972 - 1;
- }
- crypto_flags |= CRYPTO_FLAG_TAI;
- peer->crypto |= CRYPTO_FLAG_LEAP;
- peer->flash &= ~TEST10;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- /*
- * If the kernel cooperates, initialize the
- * current TAI offset.
- */
- ntv.modes = MOD_TAI;
- ntv.constant = sys_tai;
- (void)ntp_adjtime(&ntv);
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
- sprintf(statstr, "leap %u ts %u fs %u",
- vallen, ntohl(ep->tstamp),
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
-
- /*
- * We come here in symmetric modes for miscellaneous
- * commands that have value fields but are processed on
- * the transmit side. All we need do here is check for
- * valid field length. Remaining checks are below and on
- * the transmit side.
- */
- case CRYPTO_IFF:
- case CRYPTO_GQ:
- case CRYPTO_MV:
- case CRYPTO_SIGN:
- if (len < VALUE_LEN) {
- rval = XEVNT_LEN;
- break;
- }
-
- /* fall through */
-
- /*
- * We come here for miscellaneous requests and unknown
- * requests and responses. If an unknown response or
- * error, forget it. If a request, save the extension
- * field for later. Unknown requests will be caught on
- * the transmit side.
- */
- default:
- if (code & (CRYPTO_RESP | CRYPTO_ERROR)) {
- rval = XEVNT_LEN;
- } else if ((rval = crypto_verify(ep, NULL,
- peer)) == XEVNT_OK) {
- fp = emalloc(len);
- memcpy(fp, ep, len);
- temp32 = CRYPTO_RESP;
- fp->opcode |= htonl(temp32);
- peer->cmmd = fp;
- }
- }
-
- /*
- * We log everything except length/format errors and
- * duplicates, which are log clogging vulnerabilities.
- * The first error found terminates the extension field
- * scan and we return the laundry to the caller.
- */
- if (rval != XEVNT_OK) {
- sprintf(statstr,
- "error %x opcode %x ts %u fs %u", rval,
- code, tstamp, fstamp);
- if (rval > XEVNT_TSP)
- record_crypto_stats(&peer->srcadr,
- statstr);
- report_event(rval, peer);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
- }
- authlen += len;
- }
- return (rval);
-}
-
-
-/*
- * crypto_xmit - construct extension fields
- *
- * This routine is called both when an association is configured and
- * when one is not. The only case where this matters is to retrieve the
- * autokey information, in which case the caller has to provide the
- * association ID to match the association.
- *
- * Returns length of extension field.
- */
-int
-crypto_xmit(
- struct pkt *xpkt, /* transmit packet pointer */
- struct sockaddr_storage *srcadr_sin, /* active runway */
- int start, /* offset to extension field */
- struct exten *ep, /* extension pointer */
- keyid_t cookie /* session cookie */
- )
-{
- u_int32 *pkt; /* packet pointer */
- struct peer *peer; /* peer structure pointer */
- u_int opcode; /* extension field opcode */
- struct exten *fp; /* extension pointers */
- struct cert_info *cp; /* certificate info/value pointer */
- char certname[MAXHOSTNAME + 1]; /* subject name buffer */
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- u_int vallen;
- u_int len;
- struct value vtemp;
- associd_t associd;
- int rval;
- keyid_t tcookie;
-
- /*
- * Generate the requested extension field request code, length
- * and association ID. If this is a response and the host is not
- * synchronized, light the error bit and go home.
- */
- pkt = (u_int32 *)xpkt + start / 4;
- fp = (struct exten *)pkt;
- opcode = ntohl(ep->opcode);
- associd = (associd_t) ntohl(ep->associd);
- fp->associd = htonl(associd);
- len = 8;
- rval = XEVNT_OK;
- switch (opcode & 0xffff0000) {
-
- /*
- * Send association request and response with status word and
- * host name. Note, this message is not signed and the filestamp
- * contains only the status word. We check at this point whether
- * the identity schemes are compatible to save tears later on.
- */
- case CRYPTO_ASSOC | CRYPTO_RESP:
- case CRYPTO_ASSOC:
- len += crypto_send(fp, &hostval);
- if (crypto_time() == 0)
- fp->fstamp = 0;
- else
- fp->fstamp = htonl(crypto_flags);
- break;
-
- /*
- * Send certificate request. Use the values from the extension
- * field.
- */
- case CRYPTO_CERT:
- memset(&vtemp, 0, sizeof(vtemp));
- vtemp.tstamp = ep->tstamp;
- vtemp.fstamp = ep->fstamp;
- vtemp.vallen = ep->vallen;
- vtemp.ptr = (unsigned char *)ep->pkt;
- len += crypto_send(fp, &vtemp);
- break;
-
- /*
- * Send certificate response or sign request. Use the values
- * from the certificate. If the request contains no subject
- * name, assume the name of this host. This is for backwards
- * compatibility. Light the error bit if no certificate with
- * the given subject name is found. Of course, private
- * certificates are never sent.
- */
- case CRYPTO_SIGN:
- case CRYPTO_CERT | CRYPTO_RESP:
- vallen = ntohl(ep->vallen);
- if (vallen == 8) {
- strcpy(certname, sys_hostname);
- } else if (vallen == 0 || vallen > MAXHOSTNAME) {
- opcode |= CRYPTO_ERROR;
- break;
-
- } else {
- memcpy(certname, ep->pkt, vallen);
- certname[vallen] = '\0';
- }
- for (cp = cinfo; cp != NULL; cp = cp->link) {
- if (cp->flags & CERT_PRIV)
- continue;
- if (strcmp(certname, cp->subject) == 0) {
- len += crypto_send(fp, &cp->cert);
- break;
- }
- }
- if (cp == NULL)
- opcode |= CRYPTO_ERROR;
- break;
-
- /*
- * Send challenge in Schnorr (IFF) identity scheme.
- */
- case CRYPTO_IFF:
- if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- opcode |= CRYPTO_ERROR;
- break;
- }
- if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Send response in Schnorr (IFF) identity scheme.
- */
- case CRYPTO_IFF | CRYPTO_RESP:
- if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Send challenge in Guillou-Quisquater (GQ) identity scheme.
- */
- case CRYPTO_GQ:
- if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- opcode |= CRYPTO_ERROR;
- break;
- }
- if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Send response in Guillou-Quisquater (GQ) identity scheme.
- */
- case CRYPTO_GQ | CRYPTO_RESP:
- if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Send challenge in MV identity scheme.
- */
- case CRYPTO_MV:
- if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- opcode |= CRYPTO_ERROR;
- break;
- }
- if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Send response in MV identity scheme.
- */
- case CRYPTO_MV | CRYPTO_RESP:
- if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Send certificate sign response. The integrity of the request
- * certificate has already been verified on the receive side.
- * Sign the response using the local server key. Use the
- * filestamp from the request and use the timestamp as the
- * current time. Light the error bit if the certificate is
- * invalid or contains an unverified signature.
- */
- case CRYPTO_SIGN | CRYPTO_RESP:
- if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Send public key and signature. Use the values from the public
- * key.
- */
- case CRYPTO_COOK:
- len += crypto_send(fp, &pubkey);
- break;
-
- /*
- * Encrypt and send cookie and signature. Light the error bit if
- * anything goes wrong.
- */
- case CRYPTO_COOK | CRYPTO_RESP:
- if ((opcode & 0xffff) < VALUE_LEN) {
- opcode |= CRYPTO_ERROR;
- break;
- }
- if (PKT_MODE(xpkt->li_vn_mode) == MODE_SERVER) {
- tcookie = cookie;
- } else {
- if ((peer = findpeerbyassoc(associd)) == NULL) {
- opcode |= CRYPTO_ERROR;
- break;
- }
- tcookie = peer->pcookie;
- }
- if ((rval = crypto_encrypt(ep, &vtemp, &tcookie)) ==
- XEVNT_OK)
- len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
- break;
-
- /*
- * Find peer and send autokey data and signature in broadcast
- * server and symmetric modes. Use the values in the autokey
- * structure. If no association is found, either the server has
- * restarted with new associations or some perp has replayed an
- * old message, in which case light the error bit.
- */
- case CRYPTO_AUTO | CRYPTO_RESP:
- if ((peer = findpeerbyassoc(associd)) == NULL) {
- opcode |= CRYPTO_ERROR;
- break;
- }
- peer->flags &= ~FLAG_ASSOC;
- len += crypto_send(fp, &peer->sndval);
- break;
-
- /*
- * Send leapseconds table and signature. Use the values from the
- * tai structure. If no table has been loaded, just send a
- * request.
- */
- case CRYPTO_TAI:
- case CRYPTO_TAI | CRYPTO_RESP:
- if (crypto_flags & CRYPTO_FLAG_TAI)
- len += crypto_send(fp, &tai_leap);
- break;
-
- /*
- * Default - Fall through for requests; for unknown responses,
- * flag as error.
- */
- default:
- if (opcode & CRYPTO_RESP)
- opcode |= CRYPTO_ERROR;
- }
-
- /*
- * We ignore length/format errors and duplicates. Other errors
- * are reported to the log and deny further service. To really
- * persistent rascals we toss back a kiss-of-death grenade.
- */
- if (rval > XEVNT_TSP) {
- opcode |= CRYPTO_ERROR;
- sprintf(statstr, "error %x opcode %x", rval, opcode);
- record_crypto_stats(srcadr_sin, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_xmit: %s\n", statstr);
-#endif
- }
-
- /*
- * Round up the field length to a multiple of 8 bytes and save
- * the request code and length.
- */
- len = ((len + 7) / 8) * 8;
- fp->opcode = htonl((opcode & 0xffff0000) | len);
-#ifdef DEBUG
- if (debug)
- printf(
- "crypto_xmit: ext offset %d len %u code %x assocID %d\n",
- start, len, opcode>> 16, associd);
-#endif
- return (len);
-}
-
-
-/*
- * crypto_verify - parse and verify the extension field and value
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_LEN bad field format or length
- * XEVNT_TSP bad timestamp
- * XEVNT_FSP bad filestamp
- * XEVNT_PUB bad or missing public key
- * XEVNT_SGL bad signature length
- * XEVNT_SIG signature not verified
- */
-static int
-crypto_verify(
- struct exten *ep, /* extension pointer */
- struct value *vp, /* value pointer */
- struct peer *peer /* peer structure pointer */
- )
-{
- EVP_PKEY *pkey; /* server public key */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp; /* timestamp */
- tstamp_t fstamp; /* filestamp */
- u_int vallen; /* value length */
- u_int siglen; /* signature length */
- u_int opcode, len;
- int rval;
- int i;
-
- /*
- * We require valid opcode and field length, timestamp,
- * filestamp, public key, digest, signature length and
- * signature, where relevant. Note that preliminary length
- * checks are done in the main loop.
- */
- len = ntohl(ep->opcode) & 0x0000ffff;
- opcode = ntohl(ep->opcode) & 0xffff0000;
-
- /*
- * Check for valid operation code and protocol. The opcode must
- * not have the error bit set. If a response, it must have a
- * value header. If a request and does not contain a value
- * header, no need for further checking.
- */
- if (opcode & CRYPTO_ERROR)
- return (XEVNT_LEN);
- if (opcode & CRYPTO_RESP) {
- if (len < VALUE_LEN)
- return (XEVNT_LEN);
- } else {
- if (len < VALUE_LEN)
- return (XEVNT_OK);
- }
- /*
- * We have a value header. Check for valid field lengths. The
- * field length must be long enough to contain the value header,
- * value and signature. If a request and a previous request of
- * the same type is pending, discard the previous request. If a
- * request but no signature, there is no need for further
- * checking.
- */
- vallen = ntohl(ep->vallen);
- if (len < ((VALUE_LEN + vallen + 3) / 4) * 4)
- return (XEVNT_LEN);
-
- i = (vallen + 3) / 4;
- siglen = ntohl(ep->pkt[i++]);
- if (len < VALUE_LEN + vallen + siglen)
- return (XEVNT_LEN);
-
- if (!(opcode & CRYPTO_RESP)) {
- if (peer->cmmd != NULL) {
- if ((opcode | CRYPTO_RESP) ==
- (ntohl(peer->cmmd->opcode) & 0xffff0000)) {
- free(peer->cmmd);
- peer->cmmd = NULL;
- } else {
- return (XEVNT_LEN);
- }
- }
- if (siglen == 0)
- return (XEVNT_OK);
- }
-
- /*
- * We have a signature. Check for valid timestamp and filestamp.
- * The timestamp must not precede the filestamp. The timestamp
- * and filestamp must not precede the corresponding values in
- * the value structure. Once the autokey values have been
- * installed, the timestamp must always be later than the
- * corresponding value in the value structure. Duplicate
- * timestamps are illegal once the cookie has been validated.
- */
- rval = XEVNT_OK;
- if (crypto_flags & peer->crypto & CRYPTO_FLAG_PRIV)
- pkey = sign_pkey;
- else
- pkey = peer->pkey;
- tstamp = ntohl(ep->tstamp);
- fstamp = ntohl(ep->fstamp);
- if (tstamp == 0 || tstamp < fstamp) {
- rval = XEVNT_TSP;
- } else if (vp != NULL && (tstamp < ntohl(vp->tstamp) ||
- (tstamp == ntohl(vp->tstamp) && (peer->crypto &
- CRYPTO_FLAG_AUTO)))) {
- rval = XEVNT_TSP;
- } else if (vp != NULL && (tstamp < ntohl(vp->fstamp) || fstamp <
- ntohl(vp->fstamp))) {
- rval = XEVNT_FSP;
-
- /*
- * If a public key and digest is present, and if valid key
- * length, check for valid signature. Note that the first valid
- * signature lights the proventic bit.
- */
- } else if (pkey == NULL || peer->digest == NULL) {
- /* fall through */
- } else if (siglen != (u_int) EVP_PKEY_size(pkey)) {
- rval = XEVNT_SGL;
- } else {
- EVP_VerifyInit(&ctx, peer->digest);
- EVP_VerifyUpdate(&ctx, (u_char *)&ep->tstamp, vallen +
- 12);
- if (EVP_VerifyFinal(&ctx, (u_char *)&ep->pkt[i], siglen,
- pkey)) {
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- peer->crypto |= CRYPTO_FLAG_PROV;
- } else {
- rval = XEVNT_SIG;
- }
- }
-#ifdef DEBUG
- if (debug > 1)
- printf(
- "crypto_recv: verify %x vallen %u siglen %u ts %u fs %u\n",
- rval, vallen, siglen, tstamp, fstamp);
-#endif
- return (rval);
-}
-
-
-/*
- * crypto_encrypt - construct encrypted cookie and signature from
- * extension field and cookie
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_CKY bad or missing cookie
- */
-static int
-crypto_encrypt(
- struct exten *ep, /* extension pointer */
- struct value *vp, /* value pointer */
- keyid_t *cookie /* server cookie */
- )
-{
- EVP_PKEY *pkey; /* public key */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp; /* NTP timestamp */
- u_int32 temp32;
- u_int len;
- u_char *ptr;
-
- /*
- * Extract the public key from the request.
- */
- len = ntohl(ep->vallen);
- ptr = (u_char *)ep->pkt;
- pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &ptr, len);
- if (pkey == NULL) {
- msyslog(LOG_ERR, "crypto_encrypt %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_PUB);
- }
-
- /*
- * Encrypt the cookie, encode in ASN.1 and sign.
- */
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = hostval.tstamp;
- len = EVP_PKEY_size(pkey);
- vp->vallen = htonl(len);
- vp->ptr = emalloc(len);
- temp32 = htonl(*cookie);
- if (!RSA_public_encrypt(4, (u_char *)&temp32, vp->ptr,
- pkey->pkey.rsa, RSA_PKCS1_OAEP_PADDING)) {
- msyslog(LOG_ERR, "crypto_encrypt %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- EVP_PKEY_free(pkey);
- return (XEVNT_CKY);
- }
- EVP_PKEY_free(pkey);
- vp->siglen = 0;
- if (tstamp == 0)
- return (XEVNT_OK);
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- return (XEVNT_OK);
-}
-
-
-/*
- * crypto_ident - construct extension field for identity scheme
- *
- * This routine determines which identity scheme is in use and
- * constructs an extension field for that scheme.
- */
-u_int
-crypto_ident(
- struct peer *peer /* peer structure pointer */
- )
-{
- char filename[MAXFILENAME + 1];
-
- /*
- * If the server identity has already been verified, no further
- * action is necessary. Otherwise, try to load the identity file
- * of the certificate issuer. If the issuer file is not found,
- * try the host file. If nothing found, declare a cryptobust.
- * Note we can't get here unless the trusted certificate has
- * been found and the CRYPTO_FLAG_VALID bit is set, so the
- * certificate issuer is valid.
- */
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- return (0);
-
- if (peer->ident_pkey != NULL)
- EVP_PKEY_free(peer->ident_pkey);
- if (peer->crypto & CRYPTO_FLAG_GQ) {
- snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
- peer->issuer);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_GQ);
-
- snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
- sys_hostname);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_GQ);
- }
- if (peer->crypto & CRYPTO_FLAG_IFF) {
- snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
- peer->issuer);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_IFF);
-
- snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
- sys_hostname);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_IFF);
- }
- if (peer->crypto & CRYPTO_FLAG_MV) {
- snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
- peer->issuer);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_MV);
-
- snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
- sys_hostname);
- peer->ident_pkey = crypto_key(filename, &peer->fstamp);
- if (peer->ident_pkey != NULL)
- return (CRYPTO_MV);
- }
-
- /*
- * No compatible identity scheme is available. Use the default
- * TC scheme.
- */
- msyslog(LOG_INFO,
- "crypto_ident: no compatible identity scheme found");
- return (0);
-}
-
-
-/*
- * crypto_args - construct extension field from arguments
- *
- * This routine creates an extension field with current timestamps and
- * specified opcode, association ID and optional string. Note that the
- * extension field is created here, but freed after the crypto_xmit()
- * call in the protocol module.
- *
- * Returns extension field pointer (no errors).
- */
-struct exten *
-crypto_args(
- struct peer *peer, /* peer structure pointer */
- u_int opcode, /* operation code */
- char *str /* argument string */
- )
-{
- tstamp_t tstamp; /* NTP timestamp */
- struct exten *ep; /* extension field pointer */
- u_int len; /* extension field length */
-
- tstamp = crypto_time();
- len = sizeof(struct exten);
- if (str != NULL)
- len += strlen(str);
- ep = emalloc(len);
- memset(ep, 0, len);
- ep->opcode = htonl(opcode + len);
-
- /*
- * If a response, send our ID; if a request, send the
- * responder's ID.
- */
- if (opcode & CRYPTO_RESP)
- ep->associd = htonl(peer->associd);
- else
- ep->associd = htonl(peer->assoc);
- ep->tstamp = htonl(tstamp);
- ep->fstamp = hostval.tstamp;
- ep->vallen = 0;
- if (str != NULL) {
- ep->vallen = htonl(strlen(str));
- memcpy((char *)ep->pkt, str, strlen(str));
- } else {
- ep->pkt[0] = peer->associd;
- }
- return (ep);
-}
-
-
-/*
- * crypto_send - construct extension field from value components
- *
- * Returns extension field length. Note: it is not polite to send a
- * nonempty signature with zero timestamp or a nonzero timestamp with
- * empty signature, but these rules are not enforced here.
- */
-u_int
-crypto_send(
- struct exten *ep, /* extension field pointer */
- struct value *vp /* value pointer */
- )
-{
- u_int len, temp32;
- int i;
-
- /*
- * Copy data. If the data field is empty or zero length, encode
- * an empty value with length zero.
- */
- ep->tstamp = vp->tstamp;
- ep->fstamp = vp->fstamp;
- ep->vallen = vp->vallen;
- len = 12;
- temp32 = ntohl(vp->vallen);
- if (temp32 > 0 && vp->ptr != NULL)
- memcpy(ep->pkt, vp->ptr, temp32);
-
- /*
- * Copy signature. If the signature field is empty or zero
- * length, encode an empty signature with length zero.
- */
- i = (temp32 + 3) / 4;
- len += i * 4 + 4;
- ep->pkt[i++] = vp->siglen;
- temp32 = ntohl(vp->siglen);
- if (temp32 > 0 && vp->sig != NULL)
- memcpy(&ep->pkt[i], vp->sig, temp32);
- len += temp32;
- return (len);
-}
-
-
-/*
- * crypto_update - compute new public value and sign extension fields
- *
- * This routine runs periodically, like once a day, and when something
- * changes. It updates the timestamps on three value structures and one
- * value structure list, then signs all the structures:
- *
- * hostval host name (not signed)
- * pubkey public key
- * cinfo certificate info/value list
- * tai_leap leapseconds file
- *
- * Filestamps are proventicated data, so this routine is run only when
- * the host has been synchronized to a proventicated source. Thus, the
- * timestamp is proventicated, too, and can be used to deflect
- * clogging attacks and even cook breakfast.
- *
- * Returns void (no errors)
- */
-void
-crypto_update(void)
-{
- EVP_MD_CTX ctx; /* message digest context */
- struct cert_info *cp, *cpn, **zp; /* certificate info/value */
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- tstamp_t tstamp; /* NTP timestamp */
- u_int len;
-
- if ((tstamp = crypto_time()) == 0)
- return;
- hostval.tstamp = htonl(tstamp);
-
- /*
- * Sign public key and timestamps. The filestamp is derived from
- * the host key file extension from wherever the file was
- * generated.
- */
- if (pubkey.vallen != 0) {
- pubkey.tstamp = hostval.tstamp;
- pubkey.siglen = 0;
- if (pubkey.sig == NULL)
- pubkey.sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&pubkey, 12);
- EVP_SignUpdate(&ctx, pubkey.ptr, ntohl(pubkey.vallen));
- if (EVP_SignFinal(&ctx, pubkey.sig, &len, sign_pkey))
- pubkey.siglen = htonl(len);
- }
-
- /*
- * Sign certificates and timestamps. The filestamp is derived
- * from the certificate file extension from wherever the file
- * was generated. At the same time expired certificates are
- * expunged.
- */
- zp = &cinfo;
- for (cp = cinfo; cp != NULL; cp = cpn) {
- cpn = cp->link;
- if (tstamp > cp->last) {
- *zp = cpn;
- cert_free(cp);
- } else {
- cp->cert.tstamp = hostval.tstamp;
- cp->cert.siglen = 0;
- if (cp->cert.sig == NULL)
- cp->cert.sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&cp->cert, 12);
- EVP_SignUpdate(&ctx, cp->cert.ptr,
- ntohl(cp->cert.vallen));
- if (EVP_SignFinal(&ctx, cp->cert.sig, &len,
- sign_pkey))
- cp->cert.siglen = htonl(len);
- zp = &cp->link;
- }
- }
-
- /*
- * Sign leapseconds table and timestamps. The filestamp is
- * derived from the leapsecond file extension from wherever the
- * file was generated.
- */
- if (tai_leap.vallen != 0) {
- tai_leap.tstamp = hostval.tstamp;
- tai_leap.siglen = 0;
- if (tai_leap.sig == NULL)
- tai_leap.sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
- EVP_SignUpdate(&ctx, tai_leap.ptr,
- ntohl(tai_leap.vallen));
- if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))
- tai_leap.siglen = htonl(len);
- }
- sprintf(statstr, "update ts %u", ntohl(hostval.tstamp));
- record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_update: %s\n", statstr);
-#endif
-}
-
-
-/*
- * value_free - free value structure components.
- *
- * Returns void (no errors)
- */
-void
-value_free(
- struct value *vp /* value structure */
- )
-{
- if (vp->ptr != NULL)
- free(vp->ptr);
- if (vp->sig != NULL)
- free(vp->sig);
- memset(vp, 0, sizeof(struct value));
-}
-
-
-/*
- * crypto_time - returns current NTP time in seconds.
- */
-tstamp_t
-crypto_time()
-{
- l_fp tstamp; /* NTP time */ L_CLR(&tstamp);
-
- L_CLR(&tstamp);
- if (sys_leap != LEAP_NOTINSYNC)
- get_systime(&tstamp);
- return (tstamp.l_ui);
-}
-
-
-/*
- * asn2ntp - convert ASN1_TIME time structure to NTP time in seconds.
- */
-u_long
-asn2ntp (
- ASN1_TIME *asn1time /* pointer to ASN1_TIME structure */
- )
-{
- char *v; /* pointer to ASN1_TIME string */
- struct tm tm; /* used to convert to NTP time */
-
- /*
- * Extract time string YYMMDDHHMMSSZ from ASN1 time structure.
- * Note that the YY, MM, DD fields start with one, the HH, MM,
- * SS fiels start with zero and the Z character should be 'Z'
- * for UTC. Also note that years less than 50 map to years
- * greater than 100. Dontcha love ASN.1? Better than MIL-188.
- */
- if (asn1time->length > 13)
- return ((u_long)(~0)); /* We can't use -1 here. It's invalid */
- v = (char *)asn1time->data;
- tm.tm_year = (v[0] - '0') * 10 + v[1] - '0';
- if (tm.tm_year < 50)
- tm.tm_year += 100;
- tm.tm_mon = (v[2] - '0') * 10 + v[3] - '0' - 1;
- tm.tm_mday = (v[4] - '0') * 10 + v[5] - '0';
- tm.tm_hour = (v[6] - '0') * 10 + v[7] - '0';
- tm.tm_min = (v[8] - '0') * 10 + v[9] - '0';
- tm.tm_sec = (v[10] - '0') * 10 + v[11] - '0';
- tm.tm_wday = 0;
- tm.tm_yday = 0;
- tm.tm_isdst = 0;
- return (timegm(&tm) + JAN_1970);
-}
-
-
-/*
- * bigdig() - compute a BIGNUM MD5 hash of a BIGNUM number.
- */
-static int
-bighash(
- BIGNUM *bn, /* BIGNUM * from */
- BIGNUM *bk /* BIGNUM * to */
- )
-{
- EVP_MD_CTX ctx; /* message digest context */
- u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
- u_char *ptr; /* a BIGNUM as binary string */
- u_int len;
-
- len = BN_num_bytes(bn);
- ptr = emalloc(len);
- BN_bn2bin(bn, ptr);
- EVP_DigestInit(&ctx, EVP_md5());
- EVP_DigestUpdate(&ctx, ptr, len);
- EVP_DigestFinal(&ctx, dgst, &len);
- BN_bin2bn(dgst, len, bk);
- return (1);
-}
-
-
-/*
- ***********************************************************************
- * *
- * The following routines implement the Schnorr (IFF) identity scheme *
- * *
- ***********************************************************************
- *
- * The Schnorr (IFF) identity scheme is intended for use when
- * the ntp-genkeys program does not generate the certificates used in
- * the protocol and the group key cannot be conveyed in the certificate
- * itself. For this purpose, new generations of IFF values must be
- * securely transmitted to all members of the group before use. The
- * scheme is self contained and independent of new generations of host
- * keys, sign keys and certificates.
- *
- * The IFF identity scheme is based on DSA cryptography and algorithms
- * described in Stinson p. 285. The IFF values hide in a DSA cuckoo
- * structure, but only the primes and generator are used. The p is a
- * 512-bit prime, q a 160-bit prime that divides p - 1 and is a qth root
- * of 1 mod p; that is, g^q = 1 mod p. The TA rolls primvate random
- * group key b disguised as a DSA structure member, then computes public
- * key g^(q - b). These values are shared only among group members and
- * never revealed in messages. Alice challenges Bob to confirm identity
- * using the protocol described below.
- *
- * How it works
- *
- * The scheme goes like this. Both Alice and Bob have the public primes
- * p, q and generator g. The TA gives private key b to Bob and public
- * key v = g^(q - a) mod p to Alice.
- *
- * Alice rolls new random challenge r and sends to Bob in the IFF
- * request message. Bob rolls new random k, then computes y = k + b r
- * mod q and x = g^k mod p and sends (y, hash(x)) to Alice in the
- * response message. Besides making the response shorter, the hash makes
- * it effectivey impossible for an intruder to solve for b by observing
- * a number of these messages.
- *
- * Alice receives the response and computes g^y v^r mod p. After a bit
- * of algebra, this simplifies to g^k. If the hash of this result
- * matches hash(x), Alice knows that Bob has the group key b. The signed
- * response binds this knowledge to Bob's private key and the public key
- * previously received in his certificate.
- *
- * crypto_alice - construct Alice's challenge in IFF scheme
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing identity parameters
- */
-static int
-crypto_alice(
- struct peer *peer, /* peer pointer */
- struct value *vp /* value pointer */
- )
-{
- DSA *dsa; /* IFF parameters */
- BN_CTX *bctx; /* BIGNUM context */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp;
- u_int len;
-
- /*
- * The identity parameters must have correct format and content.
- */
- if (peer->ident_pkey == NULL)
- return (XEVNT_ID);
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_alice: defective key");
- return (XEVNT_PUB);
- }
-
- /*
- * Roll new random r (0 < r < q). The OpenSSL library has a bug
- * omitting BN_rand_range, so we have to do it the hard way.
- */
- bctx = BN_CTX_new();
- len = BN_num_bytes(dsa->q);
- if (peer->iffval != NULL)
- BN_free(peer->iffval);
- peer->iffval = BN_new();
- BN_rand(peer->iffval, len * 8, -1, 1); /* r */
- BN_mod(peer->iffval, peer->iffval, dsa->q, bctx);
- BN_CTX_free(bctx);
-
- /*
- * Sign and send to Bob. The filestamp is from the local file.
- */
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(peer->fstamp);
- vp->vallen = htonl(len);
- vp->ptr = emalloc(len);
- BN_bn2bin(peer->iffval, vp->ptr);
- vp->siglen = 0;
- if (tstamp == 0)
- return (XEVNT_OK);
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- return (XEVNT_OK);
-}
-
-
-/*
- * crypto_bob - construct Bob's response to Alice's challenge
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- */
-static int
-crypto_bob(
- struct exten *ep, /* extension pointer */
- struct value *vp /* value pointer */
- )
-{
- DSA *dsa; /* IFF parameters */
- DSA_SIG *sdsa; /* DSA signature context fake */
- BN_CTX *bctx; /* BIGNUM context */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp; /* NTP timestamp */
- BIGNUM *bn, *bk, *r;
- u_char *ptr;
- u_int len;
-
- /*
- * If the IFF parameters are not valid, something awful
- * happened or we are being tormented.
- */
- if (!(crypto_flags & CRYPTO_FLAG_IFF)) {
- msyslog(LOG_INFO, "crypto_bob: scheme unavailable");
- return (XEVNT_PUB);
- }
- dsa = iffpar_pkey->pkey.dsa;
-
- /*
- * Extract r from the challenge.
- */
- len = ntohl(ep->vallen);
- if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
- msyslog(LOG_ERR, "crypto_bob %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_PUB);
- }
-
- /*
- * Bob rolls random k (0 < k < q), computes y = k + b r mod q
- * and x = g^k mod p, then sends (y, hash(x)) to Alice.
- */
- bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
- sdsa = DSA_SIG_new();
- BN_rand(bk, len * 8, -1, 1); /* k */
- BN_mod_mul(bn, dsa->priv_key, r, dsa->q, bctx); /* b r mod q */
- BN_add(bn, bn, bk);
- BN_mod(bn, bn, dsa->q, bctx); /* k + b r mod q */
- sdsa->r = BN_dup(bn);
- BN_mod_exp(bk, dsa->g, bk, dsa->p, bctx); /* g^k mod p */
- bighash(bk, bk);
- sdsa->s = BN_dup(bk);
- BN_CTX_free(bctx);
- BN_free(r); BN_free(bn); BN_free(bk);
-
- /*
- * Encode the values in ASN.1 and sign.
- */
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(if_fstamp);
- len = i2d_DSA_SIG(sdsa, NULL);
- if (len <= 0) {
- msyslog(LOG_ERR, "crypto_bob %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- DSA_SIG_free(sdsa);
- return (XEVNT_PUB);
- }
- vp->vallen = htonl(len);
- ptr = emalloc(len);
- vp->ptr = ptr;
- i2d_DSA_SIG(sdsa, &ptr);
- DSA_SIG_free(sdsa);
- vp->siglen = 0;
- if (tstamp == 0)
- return (XEVNT_OK);
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- return (XEVNT_OK);
-}
-
-
-/*
- * crypto_iff - verify Bob's response to Alice's challenge
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_FSP bad filestamp
- * XEVNT_ID bad or missing identity parameters
- */
-int
-crypto_iff(
- struct exten *ep, /* extension pointer */
- struct peer *peer /* peer structure pointer */
- )
-{
- DSA *dsa; /* IFF parameters */
- BN_CTX *bctx; /* BIGNUM context */
- DSA_SIG *sdsa; /* DSA parameters */
- BIGNUM *bn, *bk;
- u_int len;
- const u_char *ptr;
- int temp;
-
- /*
- * If the IFF parameters are not valid or no challenge was sent,
- * something awful happened or we are being tormented.
- */
- if (peer->ident_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_iff: scheme unavailable");
- return (XEVNT_PUB);
- }
- if (ntohl(ep->fstamp) != peer->fstamp) {
- msyslog(LOG_INFO, "crypto_iff: invalid filestamp %u",
- ntohl(ep->fstamp));
- return (XEVNT_FSP);
- }
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_iff: defective key");
- return (XEVNT_PUB);
- }
- if (peer->iffval == NULL) {
- msyslog(LOG_INFO, "crypto_iff: missing challenge");
- return (XEVNT_PUB);
- }
-
- /*
- * Extract the k + b r and g^k values from the response.
- */
- bctx = BN_CTX_new(); bk = BN_new(); bn = BN_new();
- len = ntohl(ep->vallen);
- ptr = (const u_char *)ep->pkt;
- if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
- msyslog(LOG_ERR, "crypto_iff %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_PUB);
- }
-
- /*
- * Compute g^(k + b r) g^(q - b)r mod p.
- */
- BN_mod_exp(bn, dsa->pub_key, peer->iffval, dsa->p, bctx);
- BN_mod_exp(bk, dsa->g, sdsa->r, dsa->p, bctx);
- BN_mod_mul(bn, bn, bk, dsa->p, bctx);
-
- /*
- * Verify the hash of the result matches hash(x).
- */
- bighash(bn, bn);
- temp = BN_cmp(bn, sdsa->s);
- BN_free(bn); BN_free(bk); BN_CTX_free(bctx);
- BN_free(peer->iffval);
- peer->iffval = NULL;
- DSA_SIG_free(sdsa);
- if (temp == 0)
- return (XEVNT_OK);
- else
- return (XEVNT_ID);
-}
-
-
-/*
- ***********************************************************************
- * *
- * The following routines implement the Guillou-Quisquater (GQ) *
- * identity scheme *
- * *
- ***********************************************************************
- *
- * The Guillou-Quisquater (GQ) identity scheme is intended for use when
- * the ntp-genkeys program generates the certificates used in the
- * protocol and the group key can be conveyed in a certificate extension
- * field. The scheme is self contained and independent of new
- * generations of host keys, sign keys and certificates.
- *
- * The GQ identity scheme is based on RSA cryptography and algorithms
- * described in Stinson p. 300 (with errors). The GQ values hide in a
- * RSA cuckoo structure, but only the modulus is used. The 512-bit
- * public modulus is n = p q, where p and q are secret large primes. The
- * TA rolls random group key b disguised as a RSA structure member.
- * Except for the public key, these values are shared only among group
- * members and never revealed in messages.
- *
- * When rolling new certificates, Bob recomputes the private and
- * public keys. The private key u is a random roll, while the public key
- * is the inverse obscured by the group key v = (u^-1)^b. These values
- * replace the private and public keys normally generated by the RSA
- * scheme. Alice challenges Bob to confirm identity using the protocol
- * described below.
- *
- * How it works
- *
- * The scheme goes like this. Both Alice and Bob have the same modulus n
- * and some random b as the group key. These values are computed and
- * distributed in advance via secret means, although only the group key
- * b is truly secret. Each has a private random private key u and public
- * key (u^-1)^b, although not necessarily the same ones. Bob and Alice
- * can regenerate the key pair from time to time without affecting
- * operations. The public key is conveyed on the certificate in an
- * extension field; the private key is never revealed.
- *
- * Alice rolls new random challenge r and sends to Bob in the GQ
- * request message. Bob rolls new random k, then computes y = k u^r mod
- * n and x = k^b mod n and sends (y, hash(x)) to Alice in the response
- * message. Besides making the response shorter, the hash makes it
- * effectivey impossible for an intruder to solve for b by observing
- * a number of these messages.
- *
- * Alice receives the response and computes y^b v^r mod n. After a bit
- * of algebra, this simplifies to k^b. If the hash of this result
- * matches hash(x), Alice knows that Bob has the group key b. The signed
- * response binds this knowledge to Bob's private key and the public key
- * previously received in his certificate.
- *
- * crypto_alice2 - construct Alice's challenge in GQ scheme
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing identity parameters
- */
-static int
-crypto_alice2(
- struct peer *peer, /* peer pointer */
- struct value *vp /* value pointer */
- )
-{
- RSA *rsa; /* GQ parameters */
- BN_CTX *bctx; /* BIGNUM context */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp;
- u_int len;
-
- /*
- * The identity parameters must have correct format and content.
- */
- if (peer->ident_pkey == NULL)
- return (XEVNT_ID);
- if ((rsa = peer->ident_pkey->pkey.rsa) == NULL) {
- msyslog(LOG_INFO, "crypto_alice2: defective key");
- return (XEVNT_PUB);
- }
-
- /*
- * Roll new random r (0 < r < n). The OpenSSL library has a bug
- * omitting BN_rand_range, so we have to do it the hard way.
- */
- bctx = BN_CTX_new();
- len = BN_num_bytes(rsa->n);
- if (peer->iffval != NULL)
- BN_free(peer->iffval);
- peer->iffval = BN_new();
- BN_rand(peer->iffval, len * 8, -1, 1); /* r mod n */
- BN_mod(peer->iffval, peer->iffval, rsa->n, bctx);
- BN_CTX_free(bctx);
-
- /*
- * Sign and send to Bob. The filestamp is from the local file.
- */
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(peer->fstamp);
- vp->vallen = htonl(len);
- vp->ptr = emalloc(len);
- BN_bn2bin(peer->iffval, vp->ptr);
- vp->siglen = 0;
- if (tstamp == 0)
- return (XEVNT_OK);
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- return (XEVNT_OK);
-}
-
-
-/*
- * crypto_bob2 - construct Bob's response to Alice's challenge
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- */
-static int
-crypto_bob2(
- struct exten *ep, /* extension pointer */
- struct value *vp /* value pointer */
- )
-{
- RSA *rsa; /* GQ parameters */
- DSA_SIG *sdsa; /* DSA parameters */
- BN_CTX *bctx; /* BIGNUM context */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp; /* NTP timestamp */
- BIGNUM *r, *k, *g, *y;
- u_char *ptr;
- u_int len;
-
- /*
- * If the GQ parameters are not valid, something awful
- * happened or we are being tormented.
- */
- if (!(crypto_flags & CRYPTO_FLAG_GQ)) {
- msyslog(LOG_INFO, "crypto_bob2: scheme unavailable");
- return (XEVNT_PUB);
- }
- rsa = gqpar_pkey->pkey.rsa;
-
- /*
- * Extract r from the challenge.
- */
- len = ntohl(ep->vallen);
- if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
- msyslog(LOG_ERR, "crypto_bob2 %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_PUB);
- }
-
- /*
- * Bob rolls random k (0 < k < n), computes y = k u^r mod n and
- * x = k^b mod n, then sends (y, hash(x)) to Alice.
- */
- bctx = BN_CTX_new(); k = BN_new(); g = BN_new(); y = BN_new();
- sdsa = DSA_SIG_new();
- BN_rand(k, len * 8, -1, 1); /* k */
- BN_mod(k, k, rsa->n, bctx);
- BN_mod_exp(y, rsa->p, r, rsa->n, bctx); /* u^r mod n */
- BN_mod_mul(y, k, y, rsa->n, bctx); /* k u^r mod n */
- sdsa->r = BN_dup(y);
- BN_mod_exp(g, k, rsa->e, rsa->n, bctx); /* k^b mod n */
- bighash(g, g);
- sdsa->s = BN_dup(g);
- BN_CTX_free(bctx);
- BN_free(r); BN_free(k); BN_free(g); BN_free(y);
-
- /*
- * Encode the values in ASN.1 and sign.
- */
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(gq_fstamp);
- len = i2d_DSA_SIG(sdsa, NULL);
- if (len <= 0) {
- msyslog(LOG_ERR, "crypto_bob2 %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- DSA_SIG_free(sdsa);
- return (XEVNT_PUB);
- }
- vp->vallen = htonl(len);
- ptr = emalloc(len);
- vp->ptr = ptr;
- i2d_DSA_SIG(sdsa, &ptr);
- DSA_SIG_free(sdsa);
- vp->siglen = 0;
- if (tstamp == 0)
- return (XEVNT_OK);
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- return (XEVNT_OK);
-}
-
-
-/*
- * crypto_gq - verify Bob's response to Alice's challenge
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_FSP bad filestamp
- * XEVNT_ID bad or missing identity parameters
- */
-int
-crypto_gq(
- struct exten *ep, /* extension pointer */
- struct peer *peer /* peer structure pointer */
- )
-{
- RSA *rsa; /* GQ parameters */
- BN_CTX *bctx; /* BIGNUM context */
- DSA_SIG *sdsa; /* RSA signature context fake */
- BIGNUM *y, *v;
- const u_char *ptr;
- u_int len;
- int temp;
-
- /*
- * If the GQ parameters are not valid or no challenge was sent,
- * something awful happened or we are being tormented.
- */
- if (peer->ident_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_gq: scheme unavailable");
- return (XEVNT_PUB);
- }
- if (ntohl(ep->fstamp) != peer->fstamp) {
- msyslog(LOG_INFO, "crypto_gq: invalid filestamp %u",
- ntohl(ep->fstamp));
- return (XEVNT_FSP);
- }
- if ((rsa = peer->ident_pkey->pkey.rsa) == NULL) {
- msyslog(LOG_INFO, "crypto_gq: defective key");
- return (XEVNT_PUB);
- }
- if (peer->iffval == NULL) {
- msyslog(LOG_INFO, "crypto_gq: missing challenge");
- return (XEVNT_PUB);
- }
-
- /*
- * Extract the y = k u^r and hash(x = k^b) values from the
- * response.
- */
- bctx = BN_CTX_new(); y = BN_new(); v = BN_new();
- len = ntohl(ep->vallen);
- ptr = (const u_char *)ep->pkt;
- if ((sdsa = d2i_DSA_SIG(NULL, &ptr, len)) == NULL) {
- msyslog(LOG_ERR, "crypto_gq %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_PUB);
- }
-
- /*
- * Compute v^r y^b mod n.
- */
- BN_mod_exp(v, peer->grpkey, peer->iffval, rsa->n, bctx);
- /* v^r mod n */
- BN_mod_exp(y, sdsa->r, rsa->e, rsa->n, bctx); /* y^b mod n */
- BN_mod_mul(y, v, y, rsa->n, bctx); /* v^r y^b mod n */
-
- /*
- * Verify the hash of the result matches hash(x).
- */
- bighash(y, y);
- temp = BN_cmp(y, sdsa->s);
- BN_CTX_free(bctx); BN_free(y); BN_free(v);
- BN_free(peer->iffval);
- peer->iffval = NULL;
- DSA_SIG_free(sdsa);
- if (temp == 0)
- return (XEVNT_OK);
- else
- return (XEVNT_ID);
-}
-
-
-/*
- ***********************************************************************
- * *
- * The following routines implement the Mu-Varadharajan (MV) identity *
- * scheme *
- * *
- ***********************************************************************
- */
-/*
- * The Mu-Varadharajan (MV) cryptosystem was originally intended when
- * servers broadcast messages to clients, but clients never send
- * messages to servers. There is one encryption key for the server and a
- * separate decryption key for each client. It operated something like a
- * pay-per-view satellite broadcasting system where the session key is
- * encrypted by the broadcaster and the decryption keys are held in a
- * tamperproof set-top box.
- *
- * The MV parameters and private encryption key hide in a DSA cuckoo
- * structure which uses the same parameters, but generated in a
- * different way. The values are used in an encryption scheme similar to
- * El Gamal cryptography and a polynomial formed from the expansion of
- * product terms (x - x[j]), as described in Mu, Y., and V.
- * Varadharajan: Robust and Secure Broadcasting, Proc. Indocrypt 2001,
- * 223-231. The paper has significant errors and serious omissions.
- *
- * Let q be the product of n distinct primes s'[j] (j = 1...n), where
- * each s'[j] has m significant bits. Let p be a prime p = 2 * q + 1, so
- * that q and each s'[j] divide p - 1 and p has M = n * m + 1
- * significant bits. The elements x mod q of Zq with the elements 2 and
- * the primes removed form a field Zq* valid for polynomial arithetic.
- * Let g be a generator of Zp; that is, gcd(g, p - 1) = 1 and g^q = 1
- * mod p. We expect M to be in the 500-bit range and n relatively small,
- * like 25, so the likelihood of a randomly generated element of x mod q
- * of Zq colliding with a factor of p - 1 is very small and can be
- * avoided. Associated with each s'[j] is an element s[j] such that s[j]
- * s'[j] = s'[j] mod q. We find s[j] as the quotient (q + s'[j]) /
- * s'[j]. These are the parameters of the scheme and they are expensive
- * to compute.
- *
- * We set up an instance of the scheme as follows. A set of random
- * values x[j] mod q (j = 1...n), are generated as the zeros of a
- * polynomial of order n. The product terms (x - x[j]) are expanded to
- * form coefficients a[i] mod q (i = 0...n) in powers of x. These are
- * used as exponents of the generator g mod p to generate the private
- * encryption key A. The pair (gbar, ghat) of public server keys and the
- * pairs (xbar[j], xhat[j]) (j = 1...n) of private client keys are used
- * to construct the decryption keys. The devil is in the details.
- *
- * The distinguishing characteristic of this scheme is the capability to
- * revoke keys. Included in the calculation of E, gbar and ghat is the
- * product s = prod(s'[j]) (j = 1...n) above. If the factor s'[j] is
- * subsequently removed from the product and E, gbar and ghat
- * recomputed, the jth client will no longer be able to compute E^-1 and
- * thus unable to decrypt the block.
- *
- * How it works
- *
- * The scheme goes like this. Bob has the server values (p, A, q, gbar,
- * ghat) and Alice the client values (p, xbar, xhat).
- *
- * Alice rolls new random challenge r (0 < r < p) and sends to Bob in
- * the MV request message. Bob rolls new random k (0 < k < q), encrypts
- * y = A^k mod p (a permutation) and sends (hash(y), gbar^k, ghat^k) to
- * Alice.
- *
- * Alice receives the response and computes the decryption key (the
- * inverse permutation) from previously obtained (xbar, xhat) and
- * (gbar^k, ghat^k) in the message. She computes the inverse, which is
- * unique by reasons explained in the ntp-keygen.c program sources. If
- * the hash of this result matches hash(y), Alice knows that Bob has the
- * group key b. The signed response binds this knowledge to Bob's
- * private key and the public key previously received in his
- * certificate.
- *
- * crypto_alice3 - construct Alice's challenge in MV scheme
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing identity parameters
- */
-static int
-crypto_alice3(
- struct peer *peer, /* peer pointer */
- struct value *vp /* value pointer */
- )
-{
- DSA *dsa; /* MV parameters */
- BN_CTX *bctx; /* BIGNUM context */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp;
- u_int len;
-
- /*
- * The identity parameters must have correct format and content.
- */
- if (peer->ident_pkey == NULL)
- return (XEVNT_ID);
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_alice3: defective key");
- return (XEVNT_PUB);
- }
-
- /*
- * Roll new random r (0 < r < q). The OpenSSL library has a bug
- * omitting BN_rand_range, so we have to do it the hard way.
- */
- bctx = BN_CTX_new();
- len = BN_num_bytes(dsa->p);
- if (peer->iffval != NULL)
- BN_free(peer->iffval);
- peer->iffval = BN_new();
- BN_rand(peer->iffval, len * 8, -1, 1); /* r */
- BN_mod(peer->iffval, peer->iffval, dsa->p, bctx);
- BN_CTX_free(bctx);
-
- /*
- * Sign and send to Bob. The filestamp is from the local file.
- */
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(peer->fstamp);
- vp->vallen = htonl(len);
- vp->ptr = emalloc(len);
- BN_bn2bin(peer->iffval, vp->ptr);
- vp->siglen = 0;
- if (tstamp == 0)
- return (XEVNT_OK);
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- return (XEVNT_OK);
-}
-
-
-/*
- * crypto_bob3 - construct Bob's response to Alice's challenge
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- */
-static int
-crypto_bob3(
- struct exten *ep, /* extension pointer */
- struct value *vp /* value pointer */
- )
-{
- DSA *dsa; /* MV parameters */
- DSA *sdsa; /* DSA signature context fake */
- BN_CTX *bctx; /* BIGNUM context */
- EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp; /* NTP timestamp */
- BIGNUM *r, *k, *u;
- u_char *ptr;
- u_int len;
-
- /*
- * If the MV parameters are not valid, something awful
- * happened or we are being tormented.
- */
- if (!(crypto_flags & CRYPTO_FLAG_MV)) {
- msyslog(LOG_INFO, "crypto_bob3: scheme unavailable");
- return (XEVNT_PUB);
- }
- dsa = mvpar_pkey->pkey.dsa;
-
- /*
- * Extract r from the challenge.
- */
- len = ntohl(ep->vallen);
- if ((r = BN_bin2bn((u_char *)ep->pkt, len, NULL)) == NULL) {
- msyslog(LOG_ERR, "crypto_bob3 %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_PUB);
- }
-
- /*
- * Bob rolls random k (0 < k < q), making sure it is not a
- * factor of q. He then computes y = A^k r and sends (hash(y),
- * gbar^k, ghat^k) to Alice.
- */
- bctx = BN_CTX_new(); k = BN_new(); u = BN_new();
- sdsa = DSA_new();
- sdsa->p = BN_new(); sdsa->q = BN_new(); sdsa->g = BN_new();
- while (1) {
- BN_rand(k, BN_num_bits(dsa->q), 0, 0);
- BN_mod(k, k, dsa->q, bctx);
- BN_gcd(u, k, dsa->q, bctx);
- if (BN_is_one(u))
- break;
- }
- BN_mod_exp(u, dsa->g, k, dsa->p, bctx); /* A r */
- BN_mod_mul(u, u, r, dsa->p, bctx);
- bighash(u, sdsa->p);
- BN_mod_exp(sdsa->q, dsa->priv_key, k, dsa->p, bctx); /* gbar */
- BN_mod_exp(sdsa->g, dsa->pub_key, k, dsa->p, bctx); /* ghat */
- BN_CTX_free(bctx); BN_free(k); BN_free(r); BN_free(u);
-
- /*
- * Encode the values in ASN.1 and sign.
- */
- tstamp = crypto_time();
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = htonl(mv_fstamp);
- len = i2d_DSAparams(sdsa, NULL);
- if (len <= 0) {
- msyslog(LOG_ERR, "crypto_bob3 %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- DSA_free(sdsa);
- return (XEVNT_PUB);
- }
- vp->vallen = htonl(len);
- ptr = emalloc(len);
- vp->ptr = ptr;
- i2d_DSAparams(sdsa, &ptr);
- DSA_free(sdsa);
- vp->siglen = 0;
- if (tstamp == 0)
- return (XEVNT_OK);
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
- return (XEVNT_OK);
-}
-
-
-/*
- * crypto_mv - verify Bob's response to Alice's challenge
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_FSP bad filestamp
- * XEVNT_ID bad or missing identity parameters
- */
-int
-crypto_mv(
- struct exten *ep, /* extension pointer */
- struct peer *peer /* peer structure pointer */
- )
-{
- DSA *dsa; /* MV parameters */
- DSA *sdsa; /* DSA parameters */
- BN_CTX *bctx; /* BIGNUM context */
- BIGNUM *k, *u, *v;
- u_int len;
- const u_char *ptr;
- int temp;
-
- /*
- * If the MV parameters are not valid or no challenge was sent,
- * something awful happened or we are being tormented.
- */
- if (peer->ident_pkey == NULL) {
- msyslog(LOG_INFO, "crypto_mv: scheme unavailable");
- return (XEVNT_PUB);
- }
- if (ntohl(ep->fstamp) != peer->fstamp) {
- msyslog(LOG_INFO, "crypto_mv: invalid filestamp %u",
- ntohl(ep->fstamp));
- return (XEVNT_FSP);
- }
- if ((dsa = peer->ident_pkey->pkey.dsa) == NULL) {
- msyslog(LOG_INFO, "crypto_mv: defective key");
- return (XEVNT_PUB);
- }
- if (peer->iffval == NULL) {
- msyslog(LOG_INFO, "crypto_mv: missing challenge");
- return (XEVNT_PUB);
- }
-
- /*
- * Extract the (hash(y), gbar, ghat) values from the response.
- */
- bctx = BN_CTX_new(); k = BN_new(); u = BN_new(); v = BN_new();
- len = ntohl(ep->vallen);
- ptr = (const u_char *)ep->pkt;
- if ((sdsa = d2i_DSAparams(NULL, &ptr, len)) == NULL) {
- msyslog(LOG_ERR, "crypto_mv %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_PUB);
- }
-
- /*
- * Compute (gbar^xhat ghat^xbar)^-1 mod p.
- */
- BN_mod_exp(u, sdsa->q, dsa->pub_key, dsa->p, bctx);
- BN_mod_exp(v, sdsa->g, dsa->priv_key, dsa->p, bctx);
- BN_mod_mul(u, u, v, dsa->p, bctx);
- BN_mod_inverse(u, u, dsa->p, bctx);
- BN_mod_mul(v, u, peer->iffval, dsa->p, bctx);
-
- /*
- * The result should match the hash of r mod p.
- */
- bighash(v, v);
- temp = BN_cmp(v, sdsa->p);
- BN_CTX_free(bctx); BN_free(k); BN_free(u); BN_free(v);
- BN_free(peer->iffval);
- peer->iffval = NULL;
- DSA_free(sdsa);
- if (temp == 0)
- return (XEVNT_OK);
- else
- return (XEVNT_ID);
-}
-
-
-/*
- ***********************************************************************
- * *
- * The following routines are used to manipulate certificates *
- * *
- ***********************************************************************
- */
-/*
- * cert_parse - parse x509 certificate and create info/value structures.
- *
- * The server certificate includes the version number, issuer name,
- * subject name, public key and valid date interval. If the issuer name
- * is the same as the subject name, the certificate is self signed and
- * valid only if the server is configured as trustable. If the names are
- * different, another issuer has signed the server certificate and
- * vouched for it. In this case the server certificate is valid if
- * verified by the issuer public key.
- *
- * Returns certificate info/value pointer if valid, NULL if not.
- */
-struct cert_info * /* certificate information structure */
-cert_parse(
- u_char *asn1cert, /* X509 certificate */
- u_int len, /* certificate length */
- tstamp_t fstamp /* filestamp */
- )
-{
- X509 *cert; /* X509 certificate */
- X509_EXTENSION *ext; /* X509v3 extension */
- struct cert_info *ret; /* certificate info/value */
- BIO *bp;
- X509V3_EXT_METHOD *method;
- char pathbuf[MAXFILENAME];
- u_char *uptr;
- char *ptr;
- int temp, cnt, i;
-
- /*
- * Decode ASN.1 objects and construct certificate structure.
- */
- uptr = asn1cert;
- if ((cert = d2i_X509(NULL, &uptr, len)) == NULL) {
- msyslog(LOG_ERR, "cert_parse %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (NULL);
- }
-
- /*
- * Extract version, subject name and public key.
- */
- ret = emalloc(sizeof(struct cert_info));
- memset(ret, 0, sizeof(struct cert_info));
- if ((ret->pkey = X509_get_pubkey(cert)) == NULL) {
- msyslog(LOG_ERR, "cert_parse %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- ret->version = X509_get_version(cert);
- X509_NAME_oneline(X509_get_subject_name(cert), pathbuf,
- MAXFILENAME - 1);
- ptr = strstr(pathbuf, "CN=");
- if (ptr == NULL) {
- msyslog(LOG_INFO, "cert_parse: invalid subject %s",
- pathbuf);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- ret->subject = emalloc(strlen(ptr) + 1);
- strcpy(ret->subject, ptr + 3);
-
- /*
- * Extract remaining objects. Note that the NTP serial number is
- * the NTP seconds at the time of signing, but this might not be
- * the case for other authority. We don't bother to check the
- * objects at this time, since the real crunch can happen only
- * when the time is valid but not yet certificated.
- */
- ret->nid = OBJ_obj2nid(cert->cert_info->signature->algorithm);
- ret->digest = (const EVP_MD *)EVP_get_digestbynid(ret->nid);
- ret->serial =
- (u_long)ASN1_INTEGER_get(X509_get_serialNumber(cert));
- X509_NAME_oneline(X509_get_issuer_name(cert), pathbuf,
- MAXFILENAME);
- if ((ptr = strstr(pathbuf, "CN=")) == NULL) {
- msyslog(LOG_INFO, "cert_parse: invalid issuer %s",
- pathbuf);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- ret->issuer = emalloc(strlen(ptr) + 1);
- strcpy(ret->issuer, ptr + 3);
- ret->first = asn2ntp(X509_get_notBefore(cert));
- ret->last = asn2ntp(X509_get_notAfter(cert));
-
- /*
- * Extract extension fields. These are ad hoc ripoffs of
- * currently assigned functions and will certainly be changed
- * before prime time.
- */
- cnt = X509_get_ext_count(cert);
- for (i = 0; i < cnt; i++) {
- ext = X509_get_ext(cert, i);
- method = X509V3_EXT_get(ext);
- temp = OBJ_obj2nid(ext->object);
- switch (temp) {
-
- /*
- * If a key_usage field is present, we decode whether
- * this is a trusted or private certificate. This is
- * dorky; all we want is to compare NIDs, but OpenSSL
- * insists on BIO text strings.
- */
- case NID_ext_key_usage:
- bp = BIO_new(BIO_s_mem());
- X509V3_EXT_print(bp, ext, 0, 0);
- BIO_gets(bp, pathbuf, MAXFILENAME);
- BIO_free(bp);
-#if DEBUG
- if (debug)
- printf("cert_parse: %s: %s\n",
- OBJ_nid2ln(temp), pathbuf);
-#endif
- if (strcmp(pathbuf, "Trust Root") == 0)
- ret->flags |= CERT_TRUST;
- else if (strcmp(pathbuf, "Private") == 0)
- ret->flags |= CERT_PRIV;
- break;
-
- /*
- * If a NID_subject_key_identifier field is present, it
- * contains the GQ public key.
- */
- case NID_subject_key_identifier:
- ret->grplen = ext->value->length - 2;
- ret->grpkey = emalloc(ret->grplen);
- memcpy(ret->grpkey, &ext->value->data[2],
- ret->grplen);
- break;
- }
- }
-
- /*
- * If certificate is self signed, verify signature.
- */
- if (strcmp(ret->subject, ret->issuer) == 0) {
- if (!X509_verify(cert, ret->pkey)) {
- msyslog(LOG_INFO,
- "cert_parse: invalid signature not verified %s",
- pathbuf);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
- }
-
- /*
- * Verify certificate valid times. Note that certificates cannot
- * be retroactive.
- */
- if (ret->first > ret->last || ret->first < fstamp) {
- msyslog(LOG_INFO,
- "cert_parse: expired %s",
- ret->subject);
- cert_free(ret);
- X509_free(cert);
- return (NULL);
- }
-
- /*
- * Build the value structure to sign and send later.
- */
- ret->cert.fstamp = htonl(fstamp);
- ret->cert.vallen = htonl(len);
- ret->cert.ptr = emalloc(len);
- memcpy(ret->cert.ptr, asn1cert, len);
-#ifdef DEBUG
- if (debug > 1)
- X509_print_fp(stdout, cert);
-#endif
- X509_free(cert);
- return (ret);
-}
-
-
-/*
- * cert_sign - sign x509 certificate and update value structure.
- *
- * The certificate request is a copy of the client certificate, which
- * includes the version number, subject name and public key of the
- * client. The resulting certificate includes these values plus the
- * serial number, issuer name and validity interval of the server. The
- * validity interval extends from the current time to the same time one
- * year hence. For NTP purposes, it is convenient to use the NTP seconds
- * of the current time as the serial number.
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PUB bad or missing public key
- * XEVNT_CRT bad or missing certificate
- * XEVNT_VFY certificate not verified
- */
-static int
-cert_sign(
- struct exten *ep, /* extension field pointer */
- struct value *vp /* value pointer */
- )
-{
- X509 *req; /* X509 certificate request */
- X509 *cert; /* X509 certificate */
- X509_EXTENSION *ext; /* certificate extension */
- ASN1_INTEGER *serial; /* serial number */
- X509_NAME *subj; /* distinguished (common) name */
- EVP_PKEY *pkey; /* public key */
- EVP_MD_CTX ctx; /* message digest context */
- tstamp_t tstamp; /* NTP timestamp */
- u_int len;
- u_char *ptr;
- int i, temp;
-
- /*
- * Decode ASN.1 objects and construct certificate structure.
- */
- tstamp = crypto_time();
- if (tstamp == 0)
- return (XEVNT_TSP);
-
- ptr = (u_char *)ep->pkt;
- if ((req = d2i_X509(NULL, &ptr, ntohl(ep->vallen))) == NULL) {
- msyslog(LOG_ERR, "cert_sign %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (XEVNT_CRT);
- }
- /*
- * Extract public key and check for errors.
- */
- if ((pkey = X509_get_pubkey(req)) == NULL) {
- msyslog(LOG_ERR, "cert_sign %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- X509_free(req);
- return (XEVNT_PUB);
- }
-
- /*
- * Generate X509 certificate signed by this server. For this
- * prupose the issuer name is the server name. Also copy any
- * extensions that might be present.
- */
- cert = X509_new();
- X509_set_version(cert, X509_get_version(req));
- serial = ASN1_INTEGER_new();
- ASN1_INTEGER_set(serial, tstamp);
- X509_set_serialNumber(cert, serial);
- X509_gmtime_adj(X509_get_notBefore(cert), 0L);
- X509_gmtime_adj(X509_get_notAfter(cert), YEAR);
- subj = X509_get_issuer_name(cert);
- X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
- (unsigned char *) sys_hostname, strlen(sys_hostname), -1, 0);
- subj = X509_get_subject_name(req);
- X509_set_subject_name(cert, subj);
- X509_set_pubkey(cert, pkey);
- ext = X509_get_ext(req, 0);
- temp = X509_get_ext_count(req);
- for (i = 0; i < temp; i++) {
- ext = X509_get_ext(req, i);
- X509_add_ext(cert, ext, -1);
- }
- X509_free(req);
-
- /*
- * Sign and verify the certificate.
- */
- X509_sign(cert, sign_pkey, sign_digest);
- if (!X509_verify(cert, sign_pkey)) {
- printf("cert_sign\n%s\n",
- ERR_error_string(ERR_get_error(), NULL));
- X509_free(cert);
- return (XEVNT_VFY);
- }
- len = i2d_X509(cert, NULL);
-
- /*
- * Build and sign the value structure. We have to sign it here,
- * since the response has to be returned right away. This is a
- * clogging hazard.
- */
- memset(vp, 0, sizeof(struct value));
- vp->tstamp = htonl(tstamp);
- vp->fstamp = ep->fstamp;
- vp->vallen = htonl(len);
- vp->ptr = emalloc(len);
- ptr = vp->ptr;
- i2d_X509(cert, &ptr);
- vp->siglen = 0;
- vp->sig = emalloc(sign_siglen);
- EVP_SignInit(&ctx, sign_digest);
- EVP_SignUpdate(&ctx, (u_char *)vp, 12);
- EVP_SignUpdate(&ctx, vp->ptr, len);
- if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
- vp->siglen = htonl(len);
-#ifdef DEBUG
- if (debug > 1)
- X509_print_fp(stdout, cert);
-#endif
- X509_free(cert);
- return (XEVNT_OK);
-}
-
-
-/*
- * cert_valid - verify certificate with given public key
- *
- * This is pretty ugly, as the certificate has to be verified in the
- * OpenSSL X509 structure, not in the DER format in the info/value
- * structure.
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_VFY certificate not verified
- */
-int
-cert_valid(
- struct cert_info *cinf, /* certificate information structure */
- EVP_PKEY *pkey /* public key */
- )
-{
- X509 *cert; /* X509 certificate */
- u_char *ptr;
-
- if (cinf->flags & CERT_SIGN)
- return (XEVNT_OK);
- ptr = (u_char *)cinf->cert.ptr;
- cert = d2i_X509(NULL, &ptr, ntohl(cinf->cert.vallen));
- if (!X509_verify(cert, pkey))
- return (XEVNT_VFY);
- cinf->flags |= CERT_SIGN;
- X509_free(cert);
- return (XEVNT_OK);
-}
-
-
-/*
- * cert - install certificate in certificate list
- *
- * This routine encodes an extension field into a certificate info/value
- * structure. It searches the certificate list for duplicates and
- * expunges whichever is older. It then searches the list for other
- * certificates that might be verified by this latest one. Finally, it
- * inserts this certificate first on the list.
- *
- * Returns
- * XEVNT_OK success
- * XEVNT_PER certificate expired
- * XEVNT_CRT bad or missing certificate
- */
-int
-cert_install(
- struct exten *ep, /* cert info/value */
- struct peer *peer /* peer structure */
- )
-{
- struct cert_info *cp, *xp, *yp, **zp;
- int rval;
- tstamp_t tstamp;
-
- /*
- * Parse and validate the signed certificate. If valid,
- * construct the info/value structure; otherwise, scamper home.
- * Note this allows a certificate not-before time to be in the
- * future, but not a not-after time to be in the past.
- */
- if ((cp = cert_parse((u_char *)ep->pkt, ntohl(ep->vallen),
- ntohl(ep->fstamp))) == NULL)
- return (XEVNT_CRT);
-
- tstamp = crypto_time();
- if (tstamp > cp->last) {
- cert_free(cp);
- return (XEVNT_PER);
- }
-
- /*
- * Scan certificate list looking for another certificate with
- * the same subject and issuer. If another is found with the
- * same or older filestamp, unlink it and return the goodies to
- * the heap. If another is found with a later filetsamp, discard
- * the new one and leave the building.
- */
- rval = XEVNT_OK;
- yp = cp;
- zp = &cinfo;
- for (xp = cinfo; xp != NULL; xp = xp->link) {
- if (strcmp(cp->subject, xp->subject) == 0 &&
- strcmp(cp->issuer, xp->issuer) == 0) {
- if (ntohl(cp->cert.fstamp) <=
- ntohl(xp->cert.fstamp)) {
- *zp = xp->link;;
- cert_free(xp);
- } else {
- cert_free(cp);
- return (XEVNT_TSP);
- }
- break;
- }
- zp = &xp->link;
- }
- yp->link = cinfo;
- cinfo = yp;
-
- /*
- * Scan the certificate list to see if Y is signed by X.
- */
- for (yp = cinfo; yp != NULL; yp = yp->link) {
- for (xp = cinfo; xp != NULL; xp = xp->link) {
- if (yp->flags & CERT_ERROR)
- continue;
-
- /*
- * If issuer Y matches subject X and signature Y
- * is valid using public key X, then Y is valid.
- */
- if (strcmp(yp->issuer, xp->subject) != 0)
- continue;
-
- if (cert_valid(yp, xp->pkey) != XEVNT_OK) {
- yp->flags |= CERT_ERROR;
- continue;
- }
- xp->flags |= CERT_SIGN;
-
- /*
- * If X is trusted, then Y is trusted. Note that
- * we might stumble over a self signed
- * certificate that is not trusted, at least
- * temporarily. This can happen when a dude
- * first comes up, but has not synchronized the
- * clock and had its certificate signed by its
- * server. In case of broken certificate trail,
- * this might result in a loop that could
- * persist until timeout.
- */
- if (!(xp->flags & CERT_TRUST))
- continue;
-
- yp->flags |= CERT_TRUST;
-
- /*
- * If subject Y matches the server subject name,
- * then Y has completed the certificate trail.
- * Save the group key and light the valid bit.
- */
- if (strcmp(yp->subject, peer->subject) != 0)
- continue;
-
- if (yp->grpkey != NULL) {
- if (peer->grpkey != NULL)
- BN_free(peer->grpkey);
- peer->grpkey = BN_bin2bn(yp->grpkey,
- yp->grplen, NULL);
- }
- peer->crypto |= CRYPTO_FLAG_VALID;
-
- /*
- * If the server has an an identity scheme,
- * fetch the identity credentials. If not, the
- * identity is verified only by the trusted
- * certificate. The next signature will set the
- * server proventic.
- */
- if (peer->crypto & (CRYPTO_FLAG_GQ |
- CRYPTO_FLAG_IFF | CRYPTO_FLAG_MV))
- continue;
-
- peer->crypto |= CRYPTO_FLAG_VRFY;
- }
- }
-
- /*
- * That was awesome. Now update the timestamps and signatures.
- */
- crypto_update();
- return (rval);
-}
-
-
-/*
- * cert_free - free certificate information structure
- */
-void
-cert_free(
- struct cert_info *cinf /* certificate info/value structure */
- )
-{
- if (cinf->pkey != NULL)
- EVP_PKEY_free(cinf->pkey);
- if (cinf->subject != NULL)
- free(cinf->subject);
- if (cinf->issuer != NULL)
- free(cinf->issuer);
- if (cinf->grpkey != NULL)
- free(cinf->grpkey);
- value_free(&cinf->cert);
- free(cinf);
-}
-
-
-/*
- ***********************************************************************
- * *
- * The following routines are used only at initialization time *
- * *
- ***********************************************************************
- */
-/*
- * crypto_key - load cryptographic parameters and keys from files
- *
- * This routine loads a PEM-encoded public/private key pair and extracts
- * the filestamp from the file name.
- *
- * Returns public key pointer if valid, NULL if not. Side effect updates
- * the filestamp if valid.
- */
-static EVP_PKEY *
-crypto_key(
- char *cp, /* file name */
- tstamp_t *fstamp /* filestamp */
- )
-{
- FILE *str; /* file handle */
- EVP_PKEY *pkey = NULL; /* public/private key */
- char filename[MAXFILENAME]; /* name of key file */
- char linkname[MAXFILENAME]; /* filestamp buffer) */
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- char *ptr;
-
- /*
- * Open the key file. If the first character of the file name is
- * not '/', prepend the keys directory string. If something goes
- * wrong, abandon ship.
- */
- if (*cp == '/')
- strcpy(filename, cp);
- else
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
- str = fopen(filename, "r");
- if (str == NULL)
- return (NULL);
-
- /*
- * Read the filestamp, which is contained in the first line.
- */
- if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
- msyslog(LOG_ERR, "crypto_key: no data %s\n",
- filename);
- return (NULL);
- }
- if ((ptr = strrchr(ptr, '.')) == NULL) {
- msyslog(LOG_ERR, "crypto_key: no filestamp %s\n",
- filename);
- return (NULL);
- }
- if (sscanf(++ptr, "%u", fstamp) != 1) {
- msyslog(LOG_ERR, "crypto_key: invalid timestamp %s\n",
- filename);
- return (NULL);
- }
-
- /*
- * Read and decrypt PEM-encoded private key.
- */
- pkey = PEM_read_PrivateKey(str, NULL, NULL, passwd);
- fclose(str);
- if (pkey == NULL) {
- msyslog(LOG_ERR, "crypto_key %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (NULL);
- }
-
- /*
- * Leave tracks in the cryptostats.
- */
- if ((ptr = strrchr(linkname, '\n')) != NULL)
- *ptr = '\0';
- sprintf(statstr, "%s mod %d", &linkname[2],
- EVP_PKEY_size(pkey) * 8);
- record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_key: %s\n", statstr);
- if (debug > 1) {
- if (EVP_MD_type(pkey) == EVP_PKEY_DSA)
- DSA_print_fp(stdout, pkey->pkey.dsa, 0);
- else
- RSA_print_fp(stdout, pkey->pkey.rsa, 0);
- }
-#endif
- return (pkey);
-}
-
-
-/*
- * crypto_cert - load certificate from file
- *
- * This routine loads a X.509 RSA or DSA certificate from a file and
- * constructs a info/cert value structure for this machine. The
- * structure includes a filestamp extracted from the file name. Later
- * the certificate can be sent to another machine by request.
- *
- * Returns certificate info/value pointer if valid, NULL if not.
- */
-static struct cert_info * /* certificate information */
-crypto_cert(
- char *cp /* file name */
- )
-{
- struct cert_info *ret; /* certificate information */
- FILE *str; /* file handle */
- char filename[MAXFILENAME]; /* name of certificate file */
- char linkname[MAXFILENAME]; /* filestamp buffer */
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- tstamp_t fstamp; /* filestamp */
- long len;
- char *ptr;
- char *name, *header;
- u_char *data;
-
- /*
- * Open the certificate file. If the first character of the file
- * name is not '/', prepend the keys directory string. If
- * something goes wrong, abandon ship.
- */
- if (*cp == '/')
- strcpy(filename, cp);
- else
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
- str = fopen(filename, "r");
- if (str == NULL)
- return (NULL);
-
- /*
- * Read the filestamp, which is contained in the first line.
- */
- if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
- msyslog(LOG_ERR, "crypto_cert: no data %s\n",
- filename);
- return (NULL);
- }
- if ((ptr = strrchr(ptr, '.')) == NULL) {
- msyslog(LOG_ERR, "crypto_cert: no filestamp %s\n",
- filename);
- return (NULL);
- }
- if (sscanf(++ptr, "%u", &fstamp) != 1) {
- msyslog(LOG_ERR, "crypto_cert: invalid filestamp %s\n",
- filename);
- return (NULL);
- }
-
- /*
- * Read PEM-encoded certificate and install.
- */
- if (!PEM_read(str, &name, &header, &data, &len)) {
- msyslog(LOG_ERR, "crypto_cert %s\n",
- ERR_error_string(ERR_get_error(), NULL));
- return (NULL);
- }
- free(header);
- if (strcmp(name, "CERTIFICATE") !=0) {
- msyslog(LOG_INFO, "crypto_cert: wrong PEM type %s",
- name);
- free(name);
- free(data);
- return (NULL);
- }
- free(name);
-
- /*
- * Parse certificate and generate info/value structure.
- */
- ret = cert_parse(data, len, fstamp);
- free(data);
- if (ret == NULL)
- return (NULL);
- if ((ptr = strrchr(linkname, '\n')) != NULL)
- *ptr = '\0';
- sprintf(statstr, "%s 0x%x len %lu", &linkname[2], ret->flags,
- len);
- record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_cert: %s\n", statstr);
-#endif
- return (ret);
-}
-
-
-/*
- * crypto_tai - load leapseconds table from file
- *
- * This routine loads the ERTS leapsecond file in NIST text format,
- * converts to a value structure and extracts a filestamp from the file
- * name. The data are used to establish the TAI offset from UTC, which
- * is provided to the kernel if supported. Later the data can be sent to
- * another machine on request.
- */
-static void
-crypto_tai(
- char *cp /* file name */
- )
-{
- FILE *str; /* file handle */
- char buf[NTP_MAXSTRLEN]; /* file line buffer */
- u_int leapsec[MAX_LEAP]; /* NTP time at leaps */
- u_int offset; /* offset at leap (s) */
- char filename[MAXFILENAME]; /* name of leapseconds file */
- char linkname[MAXFILENAME]; /* file link (for filestamp) */
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
- tstamp_t fstamp; /* filestamp */
- u_int len;
- char *ptr;
- int rval, i;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- struct timex ntv; /* kernel interface structure */
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
-
- /*
- * Open the file and discard comment lines. If the first
- * character of the file name is not '/', prepend the keys
- * directory string. If the file is not found, not to worry; it
- * can be retrieved over the net. But, if it is found with
- * errors, we crash and burn.
- */
- if (*cp == '/')
- strcpy(filename, cp);
- else
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
- if ((str = fopen(filename, "r")) == NULL)
- return;
-
- /*
- * Extract filestamp if present.
- */
- rval = readlink(filename, linkname, MAXFILENAME - 1);
- if (rval > 0) {
- linkname[rval] = '\0';
- ptr = strrchr(linkname, '.');
- } else {
- ptr = strrchr(filename, '.');
- }
- if (ptr != NULL)
- sscanf(++ptr, "%u", &fstamp);
- else
- fstamp = 0;
- tai_leap.fstamp = htonl(fstamp);
-
- /*
- * We are rather paranoid here, since an intruder might cause a
- * coredump by infiltrating naughty values. Empty lines and
- * comments are ignored. Other lines must begin with two
- * integers followed by junk or comments. The first integer is
- * the NTP seconds of leap insertion, the second is the offset
- * of TAI relative to UTC after that insertion. The second word
- * must equal the initial insertion of ten seconds on 1 January
- * 1972 plus one second for each succeeding insertion.
- */
- i = 0;
- while (i < MAX_LEAP) {
- ptr = fgets(buf, NTP_MAXSTRLEN - 1, str);
- if (ptr == NULL)
- break;
- if (strlen(buf) < 1)
- continue;
- if (*buf == '#')
- continue;
- if (sscanf(buf, "%u %u", &leapsec[i], &offset) != 2)
- continue;
- if (i != (int)(offset - TAI_1972)) {
- break;
- }
- i++;
- }
- fclose(str);
- if (ptr != NULL) {
- msyslog(LOG_INFO,
- "crypto_tai: leapseconds file %s error %d", cp,
- rval);
- exit (-1);
- }
-
- /*
- * The extension field table entries consists of the NTP seconds
- * of leap insertion in reverse order, so that the most recent
- * insertion is the first entry in the table.
- */
- len = i * 4;
- tai_leap.vallen = htonl(len);
- ptr = emalloc(len);
- tai_leap.ptr = (unsigned char *) ptr;
- for (; i >= 0; i--) {
- *ptr++ = (char) htonl(leapsec[i]);
- }
- crypto_flags |= CRYPTO_FLAG_TAI;
- sys_tai = len / 4 + TAI_1972 - 1;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- ntv.modes = MOD_TAI;
- ntv.constant = sys_tai;
- if (ntp_adjtime(&ntv) == TIME_ERROR)
- msyslog(LOG_INFO,
- "crypto_tai: kernel TAI update failed");
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
- sprintf(statstr, "%s link %d fs %u offset %u", cp, rval, fstamp,
- ntohl(tai_leap.vallen) / 4 + TAI_1972 - 1);
- record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_tai: %s\n", statstr);
-#endif
-}
-
-
-/*
- * crypto_setup - load keys, certificate and leapseconds table
- *
- * This routine loads the public/private host key and certificate. If
- * available, it loads the public/private sign key, which defaults to
- * the host key, and leapseconds table. The host key must be RSA, but
- * the sign key can be either RSA or DSA. In either case, the public key
- * on the certificate must agree with the sign key.
- */
-void
-crypto_setup(void)
-{
- EVP_PKEY *pkey; /* private/public key pair */
- char filename[MAXFILENAME]; /* file name buffer */
- l_fp seed; /* crypto PRNG seed as NTP timestamp */
- tstamp_t fstamp; /* filestamp */
- tstamp_t sstamp; /* sign filestamp */
- u_int len, bytes;
- u_char *ptr;
-
- /*
- * Initialize structures.
- */
- if (!crypto_flags)
- return;
- gethostname(filename, MAXFILENAME);
- bytes = strlen(filename) + 1;
- sys_hostname = emalloc(bytes);
- memcpy(sys_hostname, filename, bytes);
- if (passwd == NULL)
- passwd = sys_hostname;
- memset(&hostval, 0, sizeof(hostval));
- memset(&pubkey, 0, sizeof(pubkey));
- memset(&tai_leap, 0, sizeof(tai_leap));
-
- /*
- * Load required random seed file and seed the random number
- * generator. Be default, it is found in the user home
- * directory. The root home directory may be / or /root,
- * depending on the system. Wiggle the contents a bit and write
- * it back so the sequence does not repeat when we next restart.
- */
- ERR_load_crypto_strings();
- if (rand_file == NULL) {
- if ((RAND_file_name(filename, MAXFILENAME)) != NULL) {
- rand_file = emalloc(strlen(filename) + 1);
- strcpy(rand_file, filename);
- }
- } else if (*rand_file != '/') {
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir,
- rand_file);
- free(rand_file);
- rand_file = emalloc(strlen(filename) + 1);
- strcpy(rand_file, filename);
- }
- if (rand_file == NULL) {
- msyslog(LOG_ERR,
- "crypto_setup: random seed file not specified");
- exit (-1);
- }
- if ((bytes = RAND_load_file(rand_file, -1)) == 0) {
- msyslog(LOG_ERR,
- "crypto_setup: random seed file %s not found\n",
- rand_file);
- exit (-1);
- }
- get_systime(&seed);
- RAND_seed(&seed, sizeof(l_fp));
- RAND_write_file(rand_file);
- OpenSSL_add_all_algorithms();
-#ifdef DEBUG
- if (debug)
- printf(
- "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n",
- SSLeay(), rand_file, bytes);
-#endif
-
- /*
- * Load required host key from file "ntpkey_host_<hostname>". It
- * also becomes the default sign key.
- */
- if (host_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_host_%s",
- sys_hostname);
- host_file = emalloc(strlen(filename) + 1);
- strcpy(host_file, filename);
- }
- pkey = crypto_key(host_file, &fstamp);
- if (pkey == NULL) {
- msyslog(LOG_ERR,
- "crypto_setup: host key file %s not found or corrupt",
- host_file);
- exit (-1);
- }
- host_pkey = pkey;
- sign_pkey = pkey;
- sstamp = fstamp;
- hostval.fstamp = htonl(fstamp);
- if (EVP_MD_type(host_pkey) != EVP_PKEY_RSA) {
- msyslog(LOG_ERR,
- "crypto_setup: host key is not RSA key type");
- exit (-1);
- }
- hostval.vallen = htonl(strlen(sys_hostname));
- hostval.ptr = (unsigned char *) sys_hostname;
-
- /*
- * Construct public key extension field for agreement scheme.
- */
- len = i2d_PublicKey(host_pkey, NULL);
- ptr = emalloc(len);
- pubkey.ptr = ptr;
- i2d_PublicKey(host_pkey, &ptr);
- pubkey.vallen = htonl(len);
- pubkey.fstamp = hostval.fstamp;
-
- /*
- * Load optional sign key from file "ntpkey_sign_<hostname>". If
- * loaded, it becomes the sign key.
- */
- if (sign_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_sign_%s",
- sys_hostname);
- sign_file = emalloc(strlen(filename) + 1);
- strcpy(sign_file, filename);
- }
- pkey = crypto_key(sign_file, &fstamp);
- if (pkey != NULL) {
- sign_pkey = pkey;
- sstamp = fstamp;
- }
- sign_siglen = EVP_PKEY_size(sign_pkey);
-
- /*
- * Load optional IFF parameters from file
- * "ntpkey_iff_<hostname>".
- */
- if (iffpar_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_iff_%s",
- sys_hostname);
- iffpar_file = emalloc(strlen(filename) + 1);
- strcpy(iffpar_file, filename);
- }
- iffpar_pkey = crypto_key(iffpar_file, &if_fstamp);
- if (iffpar_pkey != NULL)
- crypto_flags |= CRYPTO_FLAG_IFF;
-
- /*
- * Load optional GQ parameters from file "ntpkey_gq_<hostname>".
- */
- if (gqpar_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_gq_%s",
- sys_hostname);
- gqpar_file = emalloc(strlen(filename) + 1);
- strcpy(gqpar_file, filename);
- }
- gqpar_pkey = crypto_key(gqpar_file, &gq_fstamp);
- if (gqpar_pkey != NULL)
- crypto_flags |= CRYPTO_FLAG_GQ;
-
- /*
- * Load optional MV parameters from file "ntpkey_mv_<hostname>".
- */
- if (mvpar_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_mv_%s",
- sys_hostname);
- mvpar_file = emalloc(strlen(filename) + 1);
- strcpy(mvpar_file, filename);
- }
- mvpar_pkey = crypto_key(mvpar_file, &mv_fstamp);
- if (mvpar_pkey != NULL)
- crypto_flags |= CRYPTO_FLAG_MV;
-
- /*
- * Load required certificate from file "ntpkey_cert_<hostname>".
- */
- if (cert_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_cert_%s",
- sys_hostname);
- cert_file = emalloc(strlen(filename) + 1);
- strcpy(cert_file, filename);
- }
- if ((cinfo = crypto_cert(cert_file)) == NULL) {
- msyslog(LOG_ERR,
- "certificate file %s not found or corrupt",
- cert_file);
- exit (-1);
- }
-
- /*
- * The subject name must be the same as the host name, unless
- * the certificate is private, in which case it may have come
- * from another host.
- */
- if (!(cinfo->flags & CERT_PRIV) && strcmp(cinfo->subject,
- sys_hostname) != 0) {
- msyslog(LOG_ERR,
- "crypto_setup: certificate %s not for this host",
- cert_file);
- cert_free(cinfo);
- exit (-1);
- }
-
- /*
- * It the certificate is trusted, the subject must be the same
- * as the issuer, in other words it must be self signed.
- */
- if (cinfo->flags & CERT_PRIV && strcmp(cinfo->subject,
- cinfo->issuer) != 0) {
- if (cert_valid(cinfo, sign_pkey) != XEVNT_OK) {
- msyslog(LOG_ERR,
- "crypto_setup: certificate %s is trusted, but not self signed.",
- cert_file);
- cert_free(cinfo);
- exit (-1);
- }
- }
- sign_digest = cinfo->digest;
- if (cinfo->flags & CERT_PRIV)
- crypto_flags |= CRYPTO_FLAG_PRIV;
- crypto_flags |= cinfo->nid << 16;
-
- /*
- * Load optional leapseconds table from file "ntpkey_leap". If
- * the file is missing or defective, the values can later be
- * retrieved from a server.
- */
- if (leap_file == NULL)
- leap_file = "ntpkey_leap";
- crypto_tai(leap_file);
-#ifdef DEBUG
- if (debug)
- printf(
- "crypto_setup: flags 0x%x host %s signature %s\n",
- crypto_flags, sys_hostname, OBJ_nid2ln(cinfo->nid));
-#endif
-}
-
-
-/*
- * crypto_config - configure data from crypto configuration command.
- */
-void
-crypto_config(
- int item, /* configuration item */
- char *cp /* file name */
- )
-{
- switch (item) {
-
- /*
- * Set random seed file name.
- */
- case CRYPTO_CONF_RAND:
- rand_file = emalloc(strlen(cp) + 1);
- strcpy(rand_file, cp);
- break;
-
- /*
- * Set private key password.
- */
- case CRYPTO_CONF_PW:
- passwd = emalloc(strlen(cp) + 1);
- strcpy(passwd, cp);
- break;
-
- /*
- * Set host file name.
- */
- case CRYPTO_CONF_PRIV:
- host_file = emalloc(strlen(cp) + 1);
- strcpy(host_file, cp);
- break;
-
- /*
- * Set sign key file name.
- */
- case CRYPTO_CONF_SIGN:
- sign_file = emalloc(strlen(cp) + 1);
- strcpy(sign_file, cp);
- break;
-
- /*
- * Set iff parameters file name.
- */
- case CRYPTO_CONF_IFFPAR:
- iffpar_file = emalloc(strlen(cp) + 1);
- strcpy(iffpar_file, cp);
- break;
-
- /*
- * Set gq parameters file name.
- */
- case CRYPTO_CONF_GQPAR:
- gqpar_file = emalloc(strlen(cp) + 1);
- strcpy(gqpar_file, cp);
- break;
-
- /*
- * Set mv parameters file name.
- */
- case CRYPTO_CONF_MVPAR:
- mvpar_file = emalloc(strlen(cp) + 1);
- strcpy(mvpar_file, cp);
- break;
-
- /*
- * Set certificate file name.
- */
- case CRYPTO_CONF_CERT:
- cert_file = emalloc(strlen(cp) + 1);
- strcpy(cert_file, cp);
- break;
-
- /*
- * Set leapseconds file name.
- */
- case CRYPTO_CONF_LEAP:
- leap_file = emalloc(strlen(cp) + 1);
- strcpy(leap_file, cp);
- break;
- }
- crypto_flags |= CRYPTO_FLAG_ENAB;
-}
-# else
-int ntp_crypto_bs_pubkey;
-# endif /* OPENSSL */
diff --git a/contrib/ntp/ntpd/ntp_filegen.c b/contrib/ntp/ntpd/ntp_filegen.c
deleted file mode 100644
index 59a1d91..0000000
--- a/contrib/ntp/ntpd/ntp_filegen.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * ntp_filegen.c,v 3.12 1994/01/25 19:06:11 kardel Exp
- *
- * implements file generations support for NTP
- * logfiles and statistic files
- *
- *
- * Copyright (C) 1992, 1996 by Rainer Pruy
- * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
- *
- * This code may be modified and used freely
- * provided credits remain intact.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_string.h"
-#include "ntp_calendar.h"
-#include "ntp_filegen.h"
-#include "ntp_stdlib.h"
-
-/*
- * 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
- * to generating files using file generations
- *
- * the generation of a file is changed according to file generation type
- */
-
-
-/*
- * redefine this if your system dislikes filename suffixes like
- * X.19910101 or X.1992W50 or ....
- */
-#define SUFFIX_SEP '.'
-
-/*
- * other constants
- */
-#define FGEN_AGE_SECS (24*60*60) /* life time of FILEGEN_AGE in seconds */
-
-static void filegen_open P((FILEGEN *, u_long));
-static int valid_fileref P((char *, char *));
-#ifdef UNUSED
-static FILEGEN *filegen_unregister P((char *));
-#endif /* UNUSED */
-
-/*
- * open a file generation according to the current settings of gen
- * will also provide a link to basename if requested to do so
- */
-
-static void
-filegen_open(
- FILEGEN *gen,
- u_long newid
- )
-{
- char *filename;
- char *basename;
- u_int len;
- FILE *fp;
- struct calendar cal;
-
- len = strlen(gen->prefix) + strlen(gen->basename) + 1;
- basename = (char*)emalloc(len);
- sprintf(basename, "%s%s", gen->prefix, gen->basename);
-
- switch(gen->type) {
- default:
- msyslog(LOG_ERR, "unsupported file generations type %d for \"%s\" - reverting to FILEGEN_NONE",
- gen->type, basename);
- gen->type = FILEGEN_NONE;
-
- /*FALLTHROUGH*/
- case FILEGEN_NONE:
- filename = (char*)emalloc(len);
- sprintf(filename,"%s", basename);
- break;
-
- case FILEGEN_PID:
- filename = (char*)emalloc(len + 1 + 1 + 10);
- sprintf(filename,"%s%c#%ld", basename, SUFFIX_SEP, newid);
- break;
-
- case FILEGEN_DAY:
- /* You can argue here in favor of using MJD, but
- * I would assume it to be easier for humans to interpret dates
- * in a format they are used to in everyday life.
- */
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4 + 2 + 2);
- sprintf(filename, "%s%c%04d%02d%02d",
- basename, SUFFIX_SEP, cal.year, cal.month, cal.monthday);
- break;
-
- case FILEGEN_WEEK:
- /*
- * This is still a hack
- * - the term week is not correlated to week as it is used
- * normally - it just refers to a period of 7 days
- * starting at Jan 1 - 'weeks' are counted starting from zero
- */
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4 + 1 + 2);
- sprintf(filename, "%s%c%04dw%02d",
- basename, SUFFIX_SEP, cal.year, cal.yearday / 7);
- break;
-
- case FILEGEN_MONTH:
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4 + 2);
- sprintf(filename, "%s%c%04d%02d",
- basename, SUFFIX_SEP, cal.year, cal.month);
- break;
-
- case FILEGEN_YEAR:
- caljulian(newid,&cal);
- filename = (char*)emalloc(len + 1 + 4);
- sprintf(filename, "%s%c%04d", basename, SUFFIX_SEP, cal.year);
- break;
-
- case FILEGEN_AGE:
- filename = (char*)emalloc(len + 1 + 2 + 10);
- sprintf(filename, "%s%ca%08ld", basename, SUFFIX_SEP, newid);
- break;
- }
-
- if (gen->type != FILEGEN_NONE) {
- /*
- * check for existence of a file with name 'basename'
- * as we disallow such a file
- * if FGEN_FLAG_LINK is set create a link
- */
- struct stat stats;
- /*
- * try to resolve name collisions
- */
- static u_long conflicts = 0;
-
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
-#endif
- if (stat(basename, &stats) == 0) {
- /* Hm, file exists... */
- if (S_ISREG(stats.st_mode)) {
- if (stats.st_nlink <= 1) {
- /*
- * Oh, it is not linked - try to save it
- */
- char *savename = (char*)emalloc(len + 1 + 1 + 10 + 10);
- sprintf(savename, "%s%c%dC%lu",
- basename,
- SUFFIX_SEP,
- (int) getpid(),
- (u_long)conflicts++);
- if (rename(basename, savename) != 0)
- msyslog(LOG_ERR," couldn't save %s: %m", basename);
- free(savename);
- } else {
- /*
- * there is at least a second link tpo this file
- * just remove the conflicting one
- */
- if (
-#if !defined(VMS)
- unlink(basename) != 0
-#else
- delete(basename) != 0
-#endif
- )
- msyslog(LOG_ERR, "couldn't unlink %s: %m", basename);
- }
- } else {
- /*
- * Ehh? Not a regular file ?? strange !!!!
- */
- msyslog(LOG_ERR, "expected regular file for %s (found mode 0%lo)",
- basename, (unsigned long)stats.st_mode);
- }
- } else {
- /*
- * stat(..) failed, but it is absolutely correct for
- * 'basename' not to exist
- */
- if (errno != ENOENT)
- msyslog(LOG_ERR,"stat(%s) failed: %m", basename);
- }
- }
-
- /*
- * now, try to open new file generation...
- */
- fp = fopen(filename, "a");
-
-#ifdef DEBUG
- if (debug > 3)
- printf("opening filegen (type=%d/id=%lu) \"%s\"\n",
- gen->type, (u_long)newid, filename);
-#endif
-
- if (fp == NULL) {
- /* open failed -- keep previous state
- *
- * If the file was open before keep the previous generation.
- * This will cause output to end up in the 'wrong' file,
- * but I think this is still better than losing output
- *
- * ignore errors due to missing directories
- */
-
- if (errno != ENOENT)
- msyslog(LOG_ERR, "can't open %s: %m", filename);
- } else {
- if (gen->fp != NULL) {
- fclose(gen->fp);
- }
- gen->fp = fp;
- gen->id = newid;
-
- if (gen->flag & FGEN_FLAG_LINK) {
- /*
- * need to link file to basename
- * have to use hardlink for now as I want to allow
- * gen->basename spanning directory levels
- * this would make it more complex to get the correct
- * filename for symlink
- *
- * Ok, it would just mean taking the part following
- * the last '/' in the name.... Should add it later....
- */
-
- /* Windows NT does not support file links -Greg Schueman 1/18/97 */
-
-#if defined SYS_WINNT || defined SYS_VXWORKS
- SetLastError(0); /* On WinNT, don't support FGEN_FLAG_LINK */
-#elif defined(VMS)
- errno = 0; /* On VMS, don't support FGEN_FLAG_LINK */
-#else /* not (VMS) / VXWORKS / WINNT ; DO THE LINK) */
- if (link(filename, basename) != 0)
- if (errno != EEXIST)
- msyslog(LOG_ERR, "can't link(%s, %s): %m", filename, basename);
-#endif /* SYS_WINNT || VXWORKS */
- } /* flags & FGEN_FLAG_LINK */
- } /* else fp == NULL */
-
- free(basename);
- free(filename);
- return;
-}
-
-/*
- * this function sets up gen->fp to point to the correct
- * generation of the file for the time specified by 'now'
- *
- * 'now' usually is interpreted as second part of a l_fp as is in the cal...
- * library routines
- */
-
-void
-filegen_setup(
- FILEGEN *gen,
- u_long now
- )
-{
- u_long new_gen = ~ (u_long) 0;
- struct calendar cal;
-
- if (!(gen->flag & FGEN_FLAG_ENABLED)) {
- if (gen->fp != NULL)
- fclose(gen->fp);
- return;
- }
-
- switch (gen->type) {
- case FILEGEN_NONE:
- if (gen->fp != NULL) return; /* file already open */
- break;
-
- case FILEGEN_PID:
- new_gen = getpid();
- break;
-
- case FILEGEN_DAY:
- caljulian(now, &cal);
- cal.hour = cal.minute = cal.second = 0;
- new_gen = caltontp(&cal);
- break;
-
- case FILEGEN_WEEK:
- /* Would be nice to have a calweekstart() routine */
- /* so just use a hack ... */
- /* just round time to integral 7 day period for actual year */
- new_gen = now - (now - calyearstart(now)) % TIMES7(SECSPERDAY)
- + 60;
- /*
- * just to be sure -
- * the computation above would fail in the presence of leap seconds
- * so at least carry the date to the next day (+60 (seconds))
- * and go back to the start of the day via calendar computations
- */
- caljulian(new_gen, &cal);
- cal.hour = cal.minute = cal.second = 0;
- new_gen = caltontp(&cal);
- break;
-
- case FILEGEN_MONTH:
- caljulian(now, &cal);
- cal.yearday = (u_short) (cal.yearday - cal.monthday + 1);
- cal.monthday = 1;
- cal.hour = cal.minute = cal.second = 0;
- new_gen = caltontp(&cal);
- break;
-
- case FILEGEN_YEAR:
- new_gen = calyearstart(now);
- break;
-
- case FILEGEN_AGE:
- new_gen = current_time - (current_time % FGEN_AGE_SECS);
- break;
- }
- /*
- * try to open file if not yet open
- * reopen new file generation file on change of generation id
- */
- if (gen->fp == NULL || gen->id != new_gen) {
- filegen_open(gen, new_gen);
- }
-}
-
-
-/*
- * change settings for filegen files
- */
-void
-filegen_config(
- FILEGEN *gen,
- char *basename,
- u_int type,
- u_int flag
- )
-{
- /*
- * if nothing would be changed...
- */
- if ((basename == gen->basename || strcmp(basename,gen->basename) == 0) &&
- type == gen->type &&
- flag == gen->flag)
- return;
-
- /*
- * validate parameters
- */
- if (!valid_fileref(gen->prefix,basename))
- return;
-
- if (gen->fp != NULL)
- fclose(gen->fp);
-
-#ifdef DEBUG
- if (debug > 2)
- printf("configuring filegen:\n\tprefix:\t%s\n\tbasename:\t%s -> %s\n\ttype:\t%d -> %d\n\tflag: %x -> %x\n",
- gen->prefix, gen->basename, basename, gen->type, type, gen->flag, flag);
-#endif
- if (gen->basename != basename || strcmp(gen->basename, basename) != 0) {
- free(gen->basename);
- gen->basename = (char*)emalloc(strlen(basename) + 1);
- strcpy(gen->basename, basename);
- }
- gen->type = (u_char) type;
- gen->flag = (u_char) flag;
-
- /*
- * make filegen use the new settings
- * special action is only required when a generation file
- * is currently open
- * otherwise the new settings will be used anyway at the next open
- */
- if (gen->fp != NULL) {
- l_fp now;
-
- get_systime(&now);
- filegen_setup(gen, now.l_ui);
- }
-}
-
-
-/*
- * check whether concatenating prefix and basename
- * yields a legal filename
- */
-static int
-valid_fileref(
- char *prefix,
- char *basename
- )
-{
- /*
- * prefix cannot be changed dynamically
- * (within the context of filegen)
- * so just reject basenames containing '..'
- *
- * ASSUMPTION:
- * file system parts 'below' prefix may be
- * specified without infringement of security
- *
- * restricing prefix to legal values
- * has to be ensured by other means
- * (however, it would be possible to perform some checks here...)
- */
- register char *p = basename;
-
- /*
- * Just to catch, dumb errors opening up the world...
- */
- if (prefix == NULL || *prefix == '\0')
- return 0;
-
- if (basename == NULL)
- return 0;
-
- for (p = basename; p; p = strchr(p, '/')) {
- if (*p == '.' && *(p+1) == '.' && (*(p+2) == '\0' || *(p+2) == '/'))
- return 0;
- }
-
- return 1;
-}
-
-
-/*
- * filegen registry
- */
-
-static struct filegen_entry {
- char *name;
- FILEGEN *filegen;
- struct filegen_entry *next;
-} *filegen_registry = NULL;
-
-
-FILEGEN *
-filegen_get(
- char *name
- )
-{
- struct filegen_entry *f = filegen_registry;
-
- while(f) {
- if (f->name == name || strcmp(name, f->name) == 0) {
-#ifdef XXX /* this gives the Alpha compiler fits */
- if (debug > 3)
- printf("filegen_get(\"%s\") = %x\n", name,
- (u_int)f->filegen);
-#endif
- return f->filegen;
- }
- f = f->next;
- }
-#ifdef DEBUG
- if (debug > 3)
- printf("filegen_get(\"%s\") = NULL\n", name);
-#endif
- return NULL;
-}
-
-void
-filegen_register(
- const char *name,
- FILEGEN *filegen
- )
-{
- struct filegen_entry **f = &filegen_registry;
-
-#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 XXX /* this gives the Alpha compiler fits */
- if (debug > 4) {
- printf("replacing filegen %x\n", (u_int)(*f)->filegen);
- }
-#endif
- (*f)->filegen = filegen;
- return;
- }
- f = &((*f)->next);
- }
-
- *f = (struct filegen_entry *) emalloc(sizeof(struct filegen_entry));
- if (*f) {
- (*f)->next = NULL;
- (*f)->name = (char*)emalloc(strlen(name) + 1);
- strcpy((*f)->name, name);
- (*f)->filegen = filegen;
-#ifdef DEBUG
- if (debug > 5) {
- printf("adding new filegen\n");
- }
-#endif
- }
-
- return;
-}
-
-#ifdef UNUSED
-static FILEGEN *
-filegen_unregister(
- char *name
- )
-{
- struct filegen_entry **f = &filegen_registry;
-
-#ifdef DEBUG
- if (debug > 3)
- printf("filegen_unregister(\"%s\")\n", name);
-#endif
-
- while (*f) {
- if (strcmp((*f)->name,name) == 0) {
- struct filegen_entry *ff = *f;
- FILEGEN *fg;
-
- *f = (*f)->next;
- fg = ff->filegen;
- free(ff->name);
- free(ff);
- return fg;
- }
- f = &((*f)->next);
- }
- return NULL;
-}
-#endif /* UNUSED */
diff --git a/contrib/ntp/ntpd/ntp_intres.c b/contrib/ntp/ntpd/ntp_intres.c
deleted file mode 100644
index 7f27f21..0000000
--- a/contrib/ntp/ntpd/ntp_intres.c
+++ /dev/null
@@ -1,1065 +0,0 @@
-/*
- * ripped off from ../ntpres/ntpres.c by Greg Troxel 4/2/92
- * routine callable from ntpd, rather than separate program
- * also, key info passed in via a global, so no key file needed.
- */
-
-/*
- * ntpres - process configuration entries which require use of the resolver
- *
- * This is meant to be run by ntpd on the fly. It is not guaranteed
- * to work properly if run by hand. This is actually a quick hack to
- * stave off violence from people who hate using numbers in the
- * configuration file (at least I hope the rest of the daemon is
- * better than this). Also might provide some ideas about how one
- * might go about autoconfiguring an NTP distribution network.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_request.h"
-#include "ntp_stdlib.h"
-#include "ntp_syslog.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <netdb.h>
-#include <signal.h>
-
-/**/
-#include <netinet/in.h>
-#include <arpa/inet.h>
-/**/
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h> /* MAXHOSTNAMELEN (often) */
-#endif
-
-#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
-
-/*
- * Each item we are to resolve and configure gets one of these
- * structures defined for it.
- */
-struct conf_entry {
- struct conf_entry *ce_next;
- char *ce_name; /* name we are trying to resolve */
- struct conf_peer ce_config; /* configuration info for peer */
- struct sockaddr_storage peer_store; /* address info for both fams */
-};
-#define ce_peeraddr ce_config.peeraddr
-#define ce_peeraddr6 ce_config.peeraddr6
-#define ce_hmode ce_config.hmode
-#define ce_version ce_config.version
-#define ce_minpoll ce_config.minpoll
-#define ce_maxpoll ce_config.maxpoll
-#define ce_flags ce_config.flags
-#define ce_ttl ce_config.ttl
-#define ce_keyid ce_config.keyid
-#define ce_keystr ce_config.keystr
-
-/*
- * confentries is a pointer to the list of configuration entries
- * we have left to do.
- */
-static struct conf_entry *confentries = NULL;
-
-/*
- * We take an interrupt every thirty seconds, at which time we decrement
- * config_timer and resolve_timer. The former is set to 2, so we retry
- * unsucessful reconfigurations every minute. The latter is set to
- * an exponentially increasing value which starts at 2 and increases to
- * 32. When this expires we retry failed name resolutions.
- *
- * We sleep SLEEPTIME seconds before doing anything, to give the server
- * time to arrange itself.
- */
-#define MINRESOLVE 2
-#define MAXRESOLVE 32
-#define CONFIG_TIME 2
-#define ALARM_TIME 30
-#define SLEEPTIME 2
-
-static volatile int config_timer = 0;
-static volatile int resolve_timer = 0;
-
-static int resolve_value; /* next value of resolve timer */
-
-/*
- * Big hack attack
- */
-#define LOCALHOST 0x7f000001 /* 127.0.0.1, in hex, of course */
-#define SKEWTIME 0x08000000 /* 0.03125 seconds as a l_fp fraction */
-
-/*
- * Select time out. Set to 2 seconds. The server is on the local machine,
- * after all.
- */
-#define TIMEOUT_SEC 2
-#define TIMEOUT_USEC 0
-
-
-/*
- * Input processing. The data on each line in the configuration file
- * is supposed to consist of entries in the following order
- */
-#define TOK_HOSTNAME 0
-#define TOK_HMODE 1
-#define TOK_VERSION 2
-#define TOK_MINPOLL 3
-#define TOK_MAXPOLL 4
-#define TOK_FLAGS 5
-#define TOK_TTL 6
-#define TOK_KEYID 7
-#define TOK_KEYSTR 8
-#define NUMTOK 9
-
-#define MAXLINESIZE 512
-
-
-/*
- * File descriptor for ntp request code.
- */
-static SOCKET sockfd = INVALID_SOCKET; /* NT uses SOCKET */
-
-/* stuff to be filled in by caller */
-
-keyid_t req_keyid; /* request keyid */
-char *req_file; /* name of the file with configuration info */
-
-/* end stuff to be filled in */
-
-
-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, u_int,
- int, keyid_t, char *));
-static int findhostaddr P((struct conf_entry *));
-static void openntp P((void));
-static int request P((struct conf_peer *));
-static char * nexttoken P((char **));
-static void readconf P((FILE *, char *));
-static void doconfigure P((int));
-
-struct ntp_res_t_pkt { /* Tagged packet: */
- void *tag; /* For the caller */
- u_int32 paddr; /* IP to look up, or 0 */
- char name[MAXHOSTNAMELEN]; /* Name to look up (if 1st byte is not 0) */
-};
-
-struct ntp_res_c_pkt { /* Control packet: */
- char name[MAXHOSTNAMELEN];
- u_int32 paddr;
- int mode;
- int version;
- int minpoll;
- int maxpoll;
- u_int flags;
- int ttl;
- keyid_t keyid;
- u_char keystr[MAXFILENAME];
-};
-
-
-/*
- * ntp_res_recv: Process an answer from the resolver
- */
-
-void
-ntp_res_recv(void)
-{
- /*
- We have data ready on our descriptor.
- It may be an EOF, meaning the resolver process went away.
- Otherwise, it will be an "answer".
- */
-}
-
-
-/*
- * ntp_intres needs;
- *
- * req_key(???), req_keyid, req_file valid
- * syslog still open
- */
-
-void
-ntp_intres(void)
-{
- FILE *in;
-#ifdef HAVE_SIGSUSPEND
- sigset_t set;
-
- sigemptyset(&set);
-#endif /* HAVE_SIGSUSPEND */
-
-#ifdef DEBUG
- if (debug > 1) {
- msyslog(LOG_INFO, "NTP_INTRES running");
- }
-#endif
-
- /* check out auth stuff */
- if (sys_authenticate) {
- if (!authistrusted(req_keyid)) {
- msyslog(LOG_ERR, "invalid request keyid %08x",
- req_keyid );
- exit(1);
- }
- }
-
- /*
- * Read the configuration info
- * {this is bogus, since we are forked, but it is easier
- * to keep this code - gdt}
- */
- if ((in = fopen(req_file, "r")) == NULL) {
- msyslog(LOG_ERR, "can't open configuration file %s: %m",
- req_file);
- exit(1);
- }
- readconf(in, req_file);
- (void) fclose(in);
-
- if (!debug )
- (void) unlink(req_file);
-
- /*
- * Sleep a little to make sure the server is completely up
- */
-
- sleep(SLEEPTIME);
-
- /*
- * Make a first cut at resolving the bunch
- */
- doconfigure(1);
- if (confentries == NULL) {
-#if defined SYS_WINNT
- ExitThread(0); /* Don't want to kill whole NT process */
-#else
- exit(0); /* done that quick */
-#endif
- }
-
- /*
- * Here we've got some problem children. Set up the timer
- * and wait for it.
- */
- resolve_value = resolve_timer = MINRESOLVE;
- config_timer = CONFIG_TIME;
-#ifndef SYS_WINNT
- (void) signal_no_reset(SIGALRM, bong);
- alarm(ALARM_TIME);
-#endif /* SYS_WINNT */
-
- for (;;) {
- if (confentries == NULL)
- exit(0);
-
- checkparent();
-
- if (resolve_timer == 0) {
- if (resolve_value < MAXRESOLVE)
- resolve_value <<= 1;
- resolve_timer = resolve_value;
-#ifdef DEBUG
- if (debug > 2)
- msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
-#endif
- config_timer = CONFIG_TIME;
- doconfigure(1);
- continue;
- } else if (config_timer == 0) {
- config_timer = CONFIG_TIME;
-#ifdef DEBUG
- if (debug > 2)
- msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
-#endif
- doconfigure(0);
- continue;
- }
-#ifndef SYS_WINNT
- /*
- * There is a race in here. Is okay, though, since
- * all it does is delay things by 30 seconds.
- */
-# ifdef HAVE_SIGSUSPEND
- sigsuspend(&set);
-# else
- sigpause(0);
-# endif /* HAVE_SIGSUSPEND */
-#else
- if (config_timer > 0)
- config_timer--;
- if (resolve_timer > 0)
- resolve_timer--;
- sleep(ALARM_TIME);
-#endif /* SYS_WINNT */
- }
-}
-
-
-#ifndef SYS_WINNT
-/*
- * bong - service and reschedule an alarm() interrupt
- */
-static RETSIGTYPE
-bong(
- int sig
- )
-{
- if (config_timer > 0)
- config_timer--;
- if (resolve_timer > 0)
- resolve_timer--;
- alarm(ALARM_TIME);
-}
-#endif /* SYS_WINNT */
-
-/*
- * checkparent - see if our parent process is still running
- *
- * No need to worry in the Windows NT environment whether the
- * main thread is still running, because if it goes
- * down it takes the whole process down with it (in
- * which case we won't be running this thread either)
- * Turn function into NOP;
- */
-
-static void
-checkparent(void)
-{
-#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS)
-
- /*
- * If our parent (the server) has died we will have been
- * inherited by init. If so, exit.
- */
- if (getppid() == 1) {
- msyslog(LOG_INFO, "parent died before we finished, exiting");
- exit(0);
- }
-#endif /* SYS_WINNT && SYS_VXWORKS*/
-}
-
-
-
-/*
- * removeentry - we are done with an entry, remove it from the list
- */
-static void
-removeentry(
- struct conf_entry *entry
- )
-{
- register struct conf_entry *ce;
-
- ce = confentries;
- if (ce == entry) {
- confentries = ce->ce_next;
- return;
- }
-
- while (ce != NULL) {
- if (ce->ce_next == entry) {
- ce->ce_next = entry->ce_next;
- return;
- }
- ce = ce->ce_next;
- }
-}
-
-
-/*
- * addentry - add an entry to the configuration list
- */
-static void
-addentry(
- char *name,
- int mode,
- int version,
- int minpoll,
- int maxpoll,
- u_int flags,
- int ttl,
- keyid_t keyid,
- char *keystr
- )
-{
- register char *cp;
- register struct conf_entry *ce;
- unsigned int len;
-
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO,
- "intres: <%s> %d %d %d %d %x %d %x %s\n", name,
- mode, version, minpoll, maxpoll, flags, ttl, keyid,
- keystr);
-#endif
- len = strlen(name) + 1;
- cp = (char *)emalloc(len);
- memmove(cp, name, len);
-
- ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));
- ce->ce_name = cp;
- ce->ce_peeraddr = 0;
- ce->ce_peeraddr6 = in6addr_any;
- ANYSOCK(&ce->peer_store);
- ce->ce_hmode = (u_char)mode;
- ce->ce_version = (u_char)version;
- ce->ce_minpoll = (u_char)minpoll;
- ce->ce_maxpoll = (u_char)maxpoll;
- ce->ce_flags = (u_char)flags;
- ce->ce_ttl = (u_char)ttl;
- ce->ce_keyid = keyid;
- strncpy((char *)ce->ce_keystr, keystr, MAXFILENAME);
- ce->ce_next = NULL;
-
- if (confentries == NULL) {
- confentries = ce;
- } else {
- register struct conf_entry *cep;
-
- for (cep = confentries; cep->ce_next != NULL;
- cep = cep->ce_next)
- /* nothing */;
- cep->ce_next = ce;
- }
-}
-
-
-/*
- * findhostaddr - resolve a host name into an address (Or vice-versa)
- *
- * Given one of {ce_peeraddr,ce_name}, find the other one.
- * It returns 1 for "success" and 0 for an uncorrectable failure.
- * Note that "success" includes try again errors. You can tell that you
- * got a "try again" since {ce_peeraddr,ce_name} will still be zero.
- */
-static int
-findhostaddr(
- struct conf_entry *entry
- )
-{
- struct addrinfo *addr;
- int error;
-
- checkparent(); /* make sure our guy is still running */
-
- if (entry->ce_name != NULL && SOCKNUL(&entry->peer_store)) {
- /* HMS: Squawk? */
- msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");
- return 1;
- }
-
- if (entry->ce_name == NULL && !SOCKNUL(&entry->peer_store)) {
- msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
- return 0;
- }
-
- if (entry->ce_name) {
-#ifdef DEBUG
- if (debug > 2)
- msyslog(LOG_INFO, "findhostaddr: Resolving <%s>",
- entry->ce_name);
-#endif /* DEBUG */
- error = getaddrinfo(entry->ce_name, NULL, NULL, &addr);
- if (error == 0) {
- entry->peer_store = *((struct sockaddr_storage*)(addr->ai_addr));
- if (entry->peer_store.ss_family == AF_INET) {
- entry->ce_peeraddr =
- GET_INADDR(entry->peer_store);
- entry->ce_config.v6_flag = 0;
- } else {
- entry->ce_peeraddr6 =
- GET_INADDR6(entry->peer_store);
- entry->ce_config.v6_flag = 1;
- }
- }
- } else {
-#ifdef DEBUG
- if (debug > 2)
- msyslog(LOG_INFO, "findhostaddr: Resolving %s>",
- stoa(&entry->peer_store));
-#endif
- entry->ce_name = emalloc(MAXHOSTNAMELEN);
- error = getnameinfo((const struct sockaddr *)&entry->peer_store,
- SOCKLEN(&entry->peer_store),
- (char *)&entry->ce_name, MAXHOSTNAMELEN,
- NULL, 0, 0);
- }
-
- if (error != 0) {
- /*
- * If the resolver is in use, see if the failure is
- * temporary. If so, return success.
- */
- if (h_errno == TRY_AGAIN)
- return (1);
- return (0);
- }
-
- if (entry->ce_name) {
-#ifdef DEBUG
- if (debug > 2)
- msyslog(LOG_INFO, "findhostaddr: name resolved.");
-#endif
-
-#ifdef DEBUG
- if (debug > 2)
- msyslog(LOG_INFO, "findhostaddr: address resolved.");
-#endif
- }
-
- return (1);
-}
-
-
-/*
- * openntp - open a socket to the ntp server
- */
-static void
-openntp(void)
-{
- struct addrinfo hints;
- struct addrinfo *addrResult;
-
- if (sockfd >= 0)
- return;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM;
- if (getaddrinfo(NULL, "ntp", &hints, &addrResult)!=0) {
- msyslog(LOG_ERR, "getaddrinfo failed: %m");
- exit(1);
- }
- sockfd = socket(addrResult->ai_family, addrResult->ai_socktype, 0);
-
- if (sockfd == -1) {
- msyslog(LOG_ERR, "socket() failed: %m");
- exit(1);
- }
-
- /*
- * Make the socket non-blocking. We'll wait with select()
- */
-#ifndef SYS_WINNT
-#if defined(O_NONBLOCK)
- if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
- msyslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");
- exit(1);
- }
-#else
-#if defined(FNDELAY)
- if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
- msyslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
- exit(1);
- }
-#else
-# include "Bletch: NEED NON BLOCKING IO"
-#endif /* FNDDELAY */
-#endif /* O_NONBLOCK */
-#else /* SYS_WINNT */
- {
- int on = 1;
- if (ioctlsocket(sockfd,FIONBIO,(u_long *) &on) == SOCKET_ERROR) {
- msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
- exit(1); /* Windows NT - set socket in non-blocking mode */
- }
- }
-#endif /* SYS_WINNT */
- if (connect(sockfd, addrResult->ai_addr, addrResult->ai_addrlen) == -1) {
- msyslog(LOG_ERR, "openntp: connect() failed: %m");
- exit(1);
- }
- freeaddrinfo(addrResult);
-}
-
-
-/*
- * request - send a configuration request to the server, wait for a response
- */
-static int
-request(
- struct conf_peer *conf
- )
-{
- fd_set fdset;
- struct timeval tvout;
- struct req_pkt reqpkt;
- l_fp ts;
- int n;
-#ifdef SYS_WINNT
- HANDLE hReadWriteEvent = NULL;
- BOOL ret;
- DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait;
- OVERLAPPED overlap;
-#endif /* SYS_WINNT */
-
- checkparent(); /* make sure our guy is still running */
-
- if (sockfd < 0)
- openntp();
-
-#ifdef SYS_WINNT
- hReadWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-#endif /* SYS_WINNT */
-
- /*
- * Try to clear out any previously received traffic so it
- * doesn't fool us. Note the socket is nonblocking.
- */
- tvout.tv_sec = 0;
- tvout.tv_usec = 0;
- FD_ZERO(&fdset);
- FD_SET(sockfd, &fdset);
- while (select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout) >
- 0) {
- recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);
- FD_ZERO(&fdset);
- FD_SET(sockfd, &fdset);
- }
-
- /*
- * Make up a request packet with the configuration info
- */
- memset((char *)&reqpkt, 0, sizeof(reqpkt));
-
- reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
- reqpkt.auth_seq = AUTH_SEQ(1, 0); /* authenticated, no seq */
- reqpkt.implementation = IMPL_XNTPD; /* local implementation */
- reqpkt.request = REQ_CONFIG; /* configure a new peer */
- reqpkt.err_nitems = ERR_NITEMS(0, 1); /* one item */
- reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer));
- /* Make sure mbz_itemsize <= sizeof reqpkt.data */
- if (sizeof(struct conf_peer) > sizeof (reqpkt.data)) {
- msyslog(LOG_ERR, "Bletch: conf_peer is too big for reqpkt.data!");
- exit(1);
- }
- memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer));
- reqpkt.keyid = htonl(req_keyid);
-
- get_systime(&ts);
- L_ADDUF(&ts, SKEWTIME);
- HTONL_FP(&ts, &reqpkt.tstamp);
- n = 0;
- if (sys_authenticate)
- n = authencrypt(req_keyid, (u_int32 *)&reqpkt, REQ_LEN_NOMAC);
-
- /*
- * Done. Send it.
- */
-#ifndef SYS_WINNT
- n = send(sockfd, (char *)&reqpkt, (unsigned)(REQ_LEN_NOMAC + n), 0);
- if (n < 0) {
- msyslog(LOG_ERR, "send to NTP server failed: %m");
- return 0; /* maybe should exit */
- }
-#else
- /* In the NT world, documentation seems to indicate that there
- * exist _write and _read routines that can be used to do blocking
- * I/O on sockets. Problem is these routines require a socket
- * handle obtained through the _open_osf_handle C run-time API
- * of which there is no explanation in the documentation. We need
- * nonblocking write's and read's anyway for our purpose here.
- * We're therefore forced to deviate a little bit from the Unix
- * model here and use the ReadFile and WriteFile Win32 I/O API's
- * on the socket
- */
- overlap.Offset = overlap.OffsetHigh = (DWORD)0;
- overlap.hEvent = hReadWriteEvent;
- ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n,
- (LPDWORD)&NumberOfBytesWritten, (LPOVERLAPPED)&overlap);
- if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
- msyslog(LOG_ERR, "send to NTP server failed: %m");
- return 0;
- }
- dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
- if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
- if (dwWait == WAIT_FAILED)
- msyslog(LOG_ERR, "WaitForSingleObject failed: %m");
- return 0;
- }
-#endif /* SYS_WINNT */
-
-
- /*
- * Wait for a response. A weakness of the mode 7 protocol used
- * is that there is no way to associate a response with a
- * particular request, i.e. the response to this configuration
- * request is indistinguishable from that to any other. I should
- * fix this some day. In any event, the time out is fairly
- * pessimistic to make sure that if an answer is coming back
- * at all, we get it.
- */
- for (;;) {
- FD_ZERO(&fdset);
- FD_SET(sockfd, &fdset);
- tvout.tv_sec = TIMEOUT_SEC;
- tvout.tv_usec = TIMEOUT_USEC;
-
- n = select(sockfd + 1, &fdset, (fd_set *)0,
- (fd_set *)0, &tvout);
-
- if (n < 0)
- {
- if (errno != EINTR)
- msyslog(LOG_ERR, "select() fails: %m");
- return 0;
- }
- else if (n == 0)
- {
- if (debug)
- msyslog(LOG_INFO, "select() returned 0.");
- return 0;
- }
-
-#ifndef SYS_WINNT
- n = recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);
- if (n <= 0) {
- if (n < 0) {
- msyslog(LOG_ERR, "recv() fails: %m");
- return 0;
- }
- continue;
- }
-#else /* Overlapped I/O used on non-blocking sockets on Windows NT */
- ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, (DWORD)REQ_LEN_MAC,
- (LPDWORD)&NumberOfBytesRead, (LPOVERLAPPED)&overlap);
- if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
- msyslog(LOG_ERR, "ReadFile() fails: %m");
- return 0;
- }
- dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
- if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
- if (dwWait == WAIT_FAILED) {
- msyslog(LOG_ERR, "WaitForSingleObject fails: %m");
- return 0;
- }
- continue;
- }
- n = NumberOfBytesRead;
-#endif /* SYS_WINNT */
-
- /*
- * Got one. Check through to make sure it is what
- * we expect.
- */
- if (n < RESP_HEADER_SIZE) {
- msyslog(LOG_ERR, "received runt response (%d octets)",
- n);
- continue;
- }
-
- if (!ISRESPONSE(reqpkt.rm_vn_mode)) {
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO, "received non-response packet");
-#endif
- continue;
- }
-
- if (ISMORE(reqpkt.rm_vn_mode)) {
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO, "received fragmented packet");
-#endif
- continue;
- }
-
- if ( ( (INFO_VERSION(reqpkt.rm_vn_mode) < 2)
- || (INFO_VERSION(reqpkt.rm_vn_mode) > NTP_VERSION))
- || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO,
- "version (%d/%d) or mode (%d/%d) incorrect",
- INFO_VERSION(reqpkt.rm_vn_mode),
- NTP_VERSION,
- INFO_MODE(reqpkt.rm_vn_mode),
- MODE_PRIVATE);
-#endif
- continue;
- }
-
- if (INFO_SEQ(reqpkt.auth_seq) != 0) {
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO,
- "nonzero sequence number (%d)",
- INFO_SEQ(reqpkt.auth_seq));
-#endif
- continue;
- }
-
- if (reqpkt.implementation != IMPL_XNTPD ||
- reqpkt.request != REQ_CONFIG) {
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO,
- "implementation (%d) or request (%d) incorrect",
- reqpkt.implementation, reqpkt.request);
-#endif
- continue;
- }
-
- if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||
- INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||
- INFO_ITEMSIZE(reqpkt.mbz_itemsize) != 0) {
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO,
- "nitems (%d) mbz (%d) or itemsize (%d) nonzero",
- INFO_NITEMS(reqpkt.err_nitems),
- INFO_MBZ(reqpkt.mbz_itemsize),
- INFO_ITEMSIZE(reqpkt.mbz_itemsize));
-#endif
- continue;
- }
-
- n = INFO_ERR(reqpkt.err_nitems);
- switch (n) {
- case INFO_OKAY:
- /* success */
- return 1;
-
- case INFO_ERR_IMPL:
- msyslog(LOG_ERR,
- "ntpd reports implementation mismatch!");
- return 0;
-
- case INFO_ERR_REQ:
- msyslog(LOG_ERR,
- "ntpd says configuration request is unknown!");
- return 0;
-
- case INFO_ERR_FMT:
- msyslog(LOG_ERR,
- "ntpd indicates a format error occurred!");
- return 0;
-
- case INFO_ERR_NODATA:
- msyslog(LOG_ERR,
- "ntpd indicates no data available!");
- return 0;
-
- case INFO_ERR_AUTH:
- msyslog(LOG_ERR,
- "ntpd returns a permission denied error!");
- return 0;
-
- default:
- msyslog(LOG_ERR,
- "ntpd returns unknown error code %d!", n);
- return 0;
- }
- }
-}
-
-
-/*
- * nexttoken - return the next token from a line
- */
-static char *
-nexttoken(
- char **lptr
- )
-{
- register char *cp;
- register char *tstart;
-
- cp = *lptr;
-
- /*
- * Skip leading white space
- */
- while (*cp == ' ' || *cp == '\t')
- cp++;
-
- /*
- * If this is the end of the line, return nothing.
- */
- if (*cp == '\n' || *cp == '\0') {
- *lptr = cp;
- return NULL;
- }
-
- /*
- * Must be the start of a token. Record the pointer and look
- * for the end.
- */
- tstart = cp++;
- while (*cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0')
- cp++;
-
- /*
- * Terminate the token with a \0. If this isn't the end of the
- * line, space to the next character.
- */
- if (*cp == '\n' || *cp == '\0')
- *cp = '\0';
- else
- *cp++ = '\0';
-
- *lptr = cp;
- return tstart;
-}
-
-
-/*
- * readconf - read the configuration information out of the file we
- * were passed. Note that since the file is supposed to be
- * machine generated, we bail out at the first sign of trouble.
- */
-static void
-readconf(
- FILE *fp,
- char *name
- )
-{
- register int i;
- char *token[NUMTOK];
- u_long intval[NUMTOK];
- u_int flags;
- char buf[MAXLINESIZE];
- char *bp;
-
- while (fgets(buf, MAXLINESIZE, fp) != NULL) {
-
- bp = buf;
- for (i = 0; i < NUMTOK; i++) {
- if ((token[i] = nexttoken(&bp)) == NULL) {
- msyslog(LOG_ERR,
- "tokenizing error in file `%s', quitting",
- name);
- exit(1);
- }
- }
-
- for (i = 1; i < NUMTOK - 1; i++) {
- if (!atouint(token[i], &intval[i])) {
- msyslog(LOG_ERR,
- "format error for integer token `%s', file `%s', quitting",
- token[i], name);
- exit(1);
- }
- }
-
- if (intval[TOK_HMODE] != MODE_ACTIVE &&
- intval[TOK_HMODE] != MODE_CLIENT &&
- intval[TOK_HMODE] != MODE_BROADCAST) {
- msyslog(LOG_ERR, "invalid mode (%ld) in file %s",
- intval[TOK_HMODE], name);
- exit(1);
- }
-
- if (intval[TOK_VERSION] > NTP_VERSION ||
- intval[TOK_VERSION] < NTP_OLDVERSION) {
- msyslog(LOG_ERR, "invalid version (%ld) in file %s",
- intval[TOK_VERSION], name);
- exit(1);
- }
- if (intval[TOK_MINPOLL] < NTP_MINPOLL ||
- intval[TOK_MINPOLL] > NTP_MAXPOLL) {
- msyslog(LOG_ERR, "invalid MINPOLL value (%ld) in file %s",
- intval[TOK_MINPOLL], name);
- exit(1);
- }
-
- if (intval[TOK_MAXPOLL] < NTP_MINPOLL ||
- intval[TOK_MAXPOLL] > NTP_MAXPOLL) {
- msyslog(LOG_ERR, "invalid MAXPOLL value (%ld) in file %s",
- intval[TOK_MAXPOLL], name);
- exit(1);
- }
-
- if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE | FLAG_PREFER |
- FLAG_NOSELECT | FLAG_BURST | FLAG_IBURST | FLAG_SKEY))
- != 0) {
- msyslog(LOG_ERR, "invalid flags (%ld) in file %s",
- intval[TOK_FLAGS], name);
- exit(1);
- }
-
- flags = 0;
- if (intval[TOK_FLAGS] & FLAG_AUTHENABLE)
- flags |= CONF_FLAG_AUTHENABLE;
- if (intval[TOK_FLAGS] & FLAG_PREFER)
- flags |= CONF_FLAG_PREFER;
- if (intval[TOK_FLAGS] & FLAG_NOSELECT)
- flags |= CONF_FLAG_NOSELECT;
- if (intval[TOK_FLAGS] & FLAG_BURST)
- flags |= CONF_FLAG_BURST;
- if (intval[TOK_FLAGS] & FLAG_IBURST)
- flags |= CONF_FLAG_IBURST;
- if (intval[TOK_FLAGS] & FLAG_SKEY)
- flags |= CONF_FLAG_SKEY;
-
- /*
- * This is as good as we can check it. Add it in.
- */
- addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
- (int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
- (int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
- intval[TOK_KEYID], token[TOK_KEYSTR]);
- }
-}
-
-
-/*
- * doconfigure - attempt to resolve names and configure the server
- */
-static void
-doconfigure(
- int dores
- )
-{
- register struct conf_entry *ce;
- register struct conf_entry *ceremove;
-
- ce = confentries;
- while (ce != NULL) {
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO,
- "doconfigure: <%s> has peeraddr %s",
- ce->ce_name, stoa(&ce->peer_store));
-#endif
- if (dores && !SOCKNUL(&(ce->peer_store))) {
- if (!findhostaddr(ce)) {
- msyslog(LOG_ERR,
- "couldn't resolve `%s', giving up on it",
- ce->ce_name);
- ceremove = ce;
- ce = ceremove->ce_next;
- removeentry(ceremove);
- continue;
- }
- }
-
- if (!SOCKNUL(&ce->peer_store)) {
- if (request(&ce->ce_config)) {
- ceremove = ce;
- ce = ceremove->ce_next;
- removeentry(ceremove);
- continue;
- }
-#ifdef DEBUG
- if (debug > 1) {
- msyslog(LOG_INFO,
- "doconfigure: request() FAILED, maybe next time.");
- }
-#endif
- }
- ce = ce->ce_next;
- }
-}
diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c
deleted file mode 100644
index 9f2acea..0000000
--- a/contrib/ntp/ntpd/ntp_io.c
+++ /dev/null
@@ -1,2257 +0,0 @@
-/*
- * ntp_io.c - input/output routines for ntpd. The socket-opening code
- * was shamelessly stolen from ntpd.
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "iosignal.h"
-#include "ntp_refclock.h"
-#include "ntp_if.h"
-#include "ntp_stdlib.h"
-#include "ntp.h"
-
-/* Don't include ISC's version of IPv6 variables and structures */
-#define ISC_IPV6_H 1
-#include <isc/interfaceiter.h>
-#include <isc/list.h>
-#include <isc/result.h>
-
-#ifdef SIM
-#include "ntpsim.h"
-#endif
-
-#include <stdio.h>
-#include <signal.h>
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif /* HAVE_SYS_PARAM_H */
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET_IN_SYSTM_H
-# include <netinet/in_systm.h>
-#else /* Some old linux systems at least have in_system.h instead. */
-# ifdef HAVE_NETINET_IN_SYSTEM_H
-# include <netinet/in_system.h>
-# endif
-#endif /* HAVE_NETINET_IN_SYSTM_H */
-#ifdef HAVE_NETINET_IP_H
-# include <netinet/ip.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
-# include <sys/sockio.h>
-#endif
-#include <arpa/inet.h>
-
-extern int listen_to_virtual_ips;
-
-#if defined(SYS_WINNT)
-#include <transmitbuff.h>
-#include <isc/win32os.h>
-/*
- * Define this macro to control the behavior of connection
- * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823
- * for details.
- * NOTE: This requires that Windows 2000 systems install Service Pack 2
- * or later.
- */
-#ifndef SIO_UDP_CONNRESET
-#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
-#endif
-
-#endif
-
-/*
- * We do asynchronous input using the SIGIO facility. A number of
- * recvbuf buffers are preallocated for input. In the signal
- * handler we poll to see which sockets are ready and read the
- * packets from them into the recvbuf's along with a time stamp and
- * an indication of the source host and the interface it was received
- * through. This allows us to get as accurate receive time stamps
- * as possible independent of other processing going on.
- *
- * We watch the number of recvbufs available to the signal handler
- * and allocate more when this number drops below the low water
- * mark. If the signal handler should run out of buffers in the
- * interim it will drop incoming frames, the idea being that it is
- * better to drop a packet than to be inaccurate.
- */
-
-
-/*
- * Other statistics of possible interest
- */
-volatile u_long packets_dropped; /* total number of packets dropped on reception */
-volatile u_long packets_ignored; /* packets received on wild card interface */
-volatile 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 */
-
-volatile u_long handler_calls; /* number of calls to interrupt handler */
-volatile u_long handler_pkts; /* number of pkts received by handler */
-u_long io_timereset; /* time counters were reset */
-
-/*
- * Interface stuff
- */
-struct interface *any_interface; /* default ipv4 interface */
-struct interface *any6_interface; /* default ipv6 interface */
-struct interface *loopback_interface; /* loopback ipv4 interface */
-struct interface *loopback6_interface; /* loopback ipv6 interface */
-struct interface inter_list[MAXINTERFACES]; /* Interface list */
-int ninterfaces; /* Total number of interfaces */
-int nwilds; /* Total number of wildcard intefaces */
-int wildipv4 = -1; /* Index into inter_list for IPv4 wildcard */
-int wildipv6 = -1; /* Index into inter_list for IPv6 wildcard */
-
-#ifdef REFCLOCK
-/*
- * Refclock stuff. We keep a chain of structures with data concerning
- * the guys we are doing I/O for.
- */
-static struct refclockio *refio;
-#endif /* REFCLOCK */
-
-
-/*
- * Define what the possible "soft" errors can be. These are non-fatal returns
- * of various network related functions, like recv() and so on.
- *
- * For some reason, BSDI (and perhaps others) will sometimes return <0
- * from recv() but will have errno==0. This is broken, but we have to
- * work around it here.
- */
-#define SOFT_ERROR(e) ((e) == EAGAIN || \
- (e) == EWOULDBLOCK || \
- (e) == EINTR || \
- (e) == 0)
-
-/*
- * File descriptor masks etc. for call to select
- * Not needed for I/O Completion Ports
- */
-fd_set activefds;
-int maxactivefd;
-
-static int create_sockets P((u_short));
-static SOCKET open_socket P((struct sockaddr_storage *, int, int));
-static void close_socket P((SOCKET));
-#ifdef REFCLOCK
-static void close_file P((SOCKET));
-#endif
-static char * fdbits P((int, fd_set *));
-static void set_reuseaddr P((int));
-
-typedef struct vsock vsock_t;
-
-struct vsock {
- SOCKET fd;
- ISC_LINK(vsock_t) link;
-};
-
-ISC_LIST(vsock_t) sockets_list;
-
-typedef struct remaddr remaddr_t;
-
-struct remaddr {
- struct sockaddr_storage addr;
- int if_index;
- ISC_LINK(remaddr_t) link;
-};
-
-ISC_LIST(remaddr_t) remoteaddr_list;
-
-void add_socket_to_list P((SOCKET));
-void delete_socket_from_list P((SOCKET));
-void add_addr_to_list P((struct sockaddr_storage *, int));
-void delete_addr_from_list P((struct sockaddr_storage *));
-int find_addr_in_list P((struct sockaddr_storage *));
-int create_wildcards P((u_short));
-isc_boolean_t address_okay P((isc_interface_t *));
-void convert_isc_if P((isc_interface_t *, struct interface *, u_short));
-
-#ifdef SYS_WINNT
-/*
- * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
- * to not work correctly, returning a WSACONNRESET error when a WSASendTo
- * fails with an "ICMP port unreachable" response and preventing the
- * socket from using the WSARecvFrom in subsequent operations.
- * The function below fixes this, but requires that Windows 2000
- * Service Pack 2 or later be installed on the system. NT 4.0
- * systems are not affected by this and work correctly.
- * See Microsoft Knowledge Base Article Q263823 for details of this.
- */
-isc_result_t
-connection_reset_fix(SOCKET fd) {
- DWORD dwBytesReturned = 0;
- BOOL bNewBehavior = FALSE;
- DWORD status;
-
- if(isc_win32os_majorversion() < 5)
- return (ISC_R_SUCCESS); /* NT 4.0 has no problem */
-
- /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */
- status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
- sizeof(bNewBehavior), NULL, 0,
- &dwBytesReturned, NULL, NULL);
- if (status != SOCKET_ERROR)
- return (ISC_R_SUCCESS);
- else
- return (ISC_R_UNEXPECTED);
-}
-#endif
-/*
- * init_io - initialize I/O data structures and call socket creation routine
- */
-void
-init_io(void)
-{
-#ifdef SYS_WINNT
- init_transmitbuff();
-#endif /* SYS_WINNT */
-
- /*
- * Init buffer free list and stat counters
- */
- init_recvbuff(RECV_INIT);
-
- packets_dropped = packets_received = 0;
- packets_ignored = 0;
- packets_sent = packets_notsent = 0;
- handler_calls = handler_pkts = 0;
- io_timereset = 0;
- loopback_interface = NULL;
- loopback6_interface = NULL;
-
-#ifdef REFCLOCK
- refio = 0;
-#endif
-
-#if defined(HAVE_SIGNALED_IO)
- (void) set_signal();
-#endif
-
-#ifdef SYS_WINNT
- if (!Win32InitSockets())
- {
- netsyslog(LOG_ERR, "No useable winsock.dll: %m");
- exit(1);
- }
-#endif /* SYS_WINNT */
-
- ISC_LIST_INIT(sockets_list);
-
- ISC_LIST_INIT(remoteaddr_list);
-
- /*
- * Create the sockets
- */
- BLOCKIO();
- (void) create_sockets(htons(NTP_PORT));
- UNBLOCKIO();
-
-#ifdef DEBUG
- if (debug)
- printf("init_io: maxactivefd %d\n", maxactivefd);
-#endif
-}
-
-int
-create_wildcards(u_short port) {
-
- int idx = 0;
- /*
- * create pseudo-interface with wildcard IPv4 address
- */
- inter_list[idx].sin.ss_family = AF_INET;
- ((struct sockaddr_in*)&inter_list[idx].sin)->sin_addr.s_addr = htonl(INADDR_ANY);
- ((struct sockaddr_in*)&inter_list[idx].sin)->sin_port = port;
- (void) strncpy(inter_list[idx].name, "wildcard", sizeof(inter_list[idx].name));
- inter_list[idx].mask.ss_family = AF_INET;
- ((struct sockaddr_in*)&inter_list[idx].mask)->sin_addr.s_addr = htonl(~(u_int32)0);
- inter_list[idx].bfd = INVALID_SOCKET;
- inter_list[idx].num_mcast = 0;
- inter_list[idx].received = 0;
- inter_list[idx].sent = 0;
- inter_list[idx].notsent = 0;
- inter_list[idx].flags = INT_BROADCAST;
- any_interface = &inter_list[idx];
-#if defined(MCAST)
- /*
- * enable possible multicast reception on the broadcast socket
- */
- inter_list[idx].bcast.ss_family = AF_INET;
- ((struct sockaddr_in*)&inter_list[idx].bcast)->sin_port = port;
- ((struct sockaddr_in*)&inter_list[idx].bcast)->sin_addr.s_addr = htonl(INADDR_ANY);
-#endif /* MCAST */
- wildipv4 = idx;
- idx++;
-
-#ifdef HAVE_IPV6
- /*
- * create pseudo-interface with wildcard IPv6 address
- */
- if (isc_net_probeipv6() == ISC_R_SUCCESS) {
- inter_list[idx].sin.ss_family = AF_INET6;
- ((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_addr = in6addr_any;
- ((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_port = port;
- (void) strncpy(inter_list[idx].name, "wildcard", sizeof(inter_list[idx].name));
- inter_list[idx].mask.ss_family = AF_INET6;
- memset(&((struct sockaddr_in6*)&inter_list[idx].mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));
- inter_list[idx].bfd = INVALID_SOCKET;
- inter_list[idx].num_mcast = 0;
- inter_list[idx].received = 0;
- inter_list[idx].sent = 0;
- inter_list[idx].notsent = 0;
- inter_list[idx].flags = 0;
- any6_interface = &inter_list[idx];
- wildipv6 = idx;
- idx++;
- }
-#endif
- return (idx);
-}
-
-isc_boolean_t
-address_okay(isc_interface_t *isc_if) {
-
-#ifdef DEBUG
- if (debug > 2)
- printf("address_okay: listen Virtual: %d, IF name: %s, Up Flag: %d\n",
- listen_to_virtual_ips, isc_if->name, (isc_if->flags & INTERFACE_F_UP));
-#endif
-
- if (listen_to_virtual_ips == 0 && (strchr(isc_if->name, (int)':') != NULL))
- return (ISC_FALSE);
-
- /* XXXPDM This should be fixed later, but since we may not have set
- * the UP flag, we at least get to use the interface.
- * The UP flag is not always set so we don't do this right now.
- */
-/* if ((isc_if->flags & INTERFACE_F_UP) == 0)
- return (ISC_FALSE);
-*/
- return (ISC_TRUE);
-}
-void
-convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) {
-
- if(isc_if->af == AF_INET) {
- itf->sin.ss_family = (u_short) isc_if->af;
- strcpy(itf->name, isc_if->name);
- memcpy(&(((struct sockaddr_in*)&itf->sin)->sin_addr),
- &(isc_if->address.type.in),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&itf->sin)->sin_port = port;
-
- if((isc_if->flags & INTERFACE_F_BROADCAST) != 0) {
- itf->flags |= INT_BROADCAST;
- itf->bcast.ss_family = itf->sin.ss_family;
- memcpy(&(((struct sockaddr_in*)&itf->bcast)->sin_addr),
- &(isc_if->broadcast.type.in),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&itf->bcast)->sin_port = port;
- }
-
- itf->mask.ss_family = itf->sin.ss_family;
- memcpy(&(((struct sockaddr_in*)&itf->mask)->sin_addr),
- &(isc_if->netmask.type.in),
- sizeof(struct in_addr));
- ((struct sockaddr_in*)&itf->mask)->sin_port = port;
-
- if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback_interface == NULL))
- {
- loopback_interface = itf;
- }
- }
-#ifdef HAVE_IPV6
- else if (isc_if->af == AF_INET6) {
- itf->sin.ss_family = (u_short) isc_if->af;
- strcpy(itf->name, isc_if->name);
- memcpy(&(((struct sockaddr_in6 *)&itf->sin)->sin6_addr),
- &(isc_if->address.type.in6),
- sizeof(struct in6_addr));
- ((struct sockaddr_in6 *)&itf->sin)->sin6_port = port;
-
- itf->mask.ss_family = itf->sin.ss_family;
- memcpy(&(((struct sockaddr_in6 *)&itf->mask)->sin6_addr),
- &(isc_if->netmask.type.in6),
- sizeof(struct in6_addr));
- ((struct sockaddr_in6 *)&itf->mask)->sin6_port = port;
-
- if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback6_interface == NULL))
- {
- loopback6_interface = itf;
- }
- }
-#endif /* HAVE_IPV6 */
-
- /* Process the rest of the flags */
-
- if((isc_if->flags & INTERFACE_F_UP) != 0)
- itf->flags |= INT_UP;
- if((isc_if->flags & INTERFACE_F_LOOPBACK) != 0)
- itf->flags |= INT_LOOPBACK;
- if((isc_if->flags & INTERFACE_F_POINTTOPOINT) != 0)
- itf->flags |= INT_PPP;
-}
-/*
- * create_sockets - create a socket for each interface plus a default
- * socket for when we don't know where to send
- */
-static int
-create_sockets(
- u_short port
- )
-{
- struct sockaddr_storage resmask;
- int i;
- isc_mem_t *mctx = NULL;
- isc_interfaceiter_t *iter = NULL;
- isc_boolean_t scan_ipv4 = ISC_FALSE;
- isc_boolean_t scan_ipv6 = ISC_FALSE;
- isc_result_t result;
- int idx = 0;
-
-#ifdef DEBUG
- if (debug)
- printf("create_sockets(%d)\n", ntohs( (u_short) port));
-#endif
-
- if (isc_net_probeipv6() == ISC_R_SUCCESS)
- scan_ipv6 = ISC_TRUE;
-#ifdef HAVE_IPV6
- else
- netsyslog(LOG_ERR, "no IPv6 interfaces found");
-#endif
-
- if (isc_net_probeipv4() == ISC_R_SUCCESS)
- scan_ipv4 = ISC_TRUE;
- else
- netsyslog(LOG_ERR, "no IPv4 interfaces found");
-
- nwilds = create_wildcards(port);
- idx = nwilds;
-
- result = isc_interfaceiter_create(mctx, &iter);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- for (result = isc_interfaceiter_first(iter);
- result == ISC_R_SUCCESS;
- result = isc_interfaceiter_next(iter))
- {
- isc_interface_t isc_if;
- unsigned int family;
-
- result = isc_interfaceiter_current(iter, &isc_if);
- if (result != ISC_R_SUCCESS)
- break;
-
- /* See if we have a valid family to use */
- family = isc_if.address.family;
- if (family != AF_INET && family != AF_INET6)
- continue;
- if (scan_ipv4 == ISC_FALSE && family == AF_INET)
- continue;
- if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
- continue;
-
- /* Check to see if we are going to use the interface */
- if (address_okay(&isc_if) == ISC_TRUE) {
- convert_isc_if(&isc_if, &inter_list[idx], port);
- inter_list[idx].fd = INVALID_SOCKET;
- inter_list[idx].bfd = INVALID_SOCKET;
- inter_list[idx].num_mcast = 0;
- inter_list[idx].received = 0;
- inter_list[idx].sent = 0;
- inter_list[idx].notsent = 0;
- idx++;
- }
- }
- isc_interfaceiter_destroy(&iter);
-
- ninterfaces = idx;
- /*
- * I/O Completion Ports don't care about the select and FD_SET
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- maxactivefd = 0;
- FD_ZERO(&activefds);
-#endif
- for (i = 0; i < ninterfaces; i++) {
- inter_list[i].fd = open_socket(&inter_list[i].sin,
- inter_list[i].flags & INT_BROADCAST, 0);
- if (inter_list[i].bfd != INVALID_SOCKET)
- msyslog(LOG_INFO, "Listening on interface %s, %s#%d",
- inter_list[i].name,
- stoa((&inter_list[i].sin)),
- NTP_PORT);
- if ((inter_list[i].flags & INT_BROADCAST) &&
- inter_list[i].bfd != INVALID_SOCKET)
- msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
- stoa((&inter_list[i].bcast)),
- NTP_PORT);
-#if defined (HAVE_IO_COMPLETION_PORT)
- if (inter_list[i].fd != INVALID_SOCKET) {
- io_completion_port_add_socket(inter_list[i].fd, &inter_list[i]);
- }
-#endif
- }
-
- /*
- * Now that we have opened all the sockets, turn off the reuse
- * flag for security.
- */
- set_reuseaddr(0);
-
- /*
- * Blacklist all bound interface addresses
- * Wildcard interfaces are ignored.
- */
-
- for (i = nwilds; i < ninterfaces; i++) {
- SET_HOSTMASK(&resmask, inter_list[i].sin.ss_family);
- hack_restrict(RESTRICT_FLAGS, &inter_list[i].sin, &resmask,
- RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
- }
-
- /*
- * Calculate the address hash for each interface address.
- */
- for (i = 0; i < ninterfaces; i++) {
- inter_list[i].addr_refid = addr2refid(&inter_list[i].sin);
- }
-
-
-#ifdef DEBUG
- if (debug > 1) {
- 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",
- i,
- inter_list[i].fd,
- inter_list[i].bfd,
- inter_list[i].name,
- inter_list[i].flags);
- /* Leave these as three printf calls. */
- printf(" sin=%s",
- stoa((&inter_list[i].sin)));
- if (inter_list[i].flags & INT_BROADCAST)
- printf(" bcast=%s,",
- stoa((&inter_list[i].bcast)));
- printf(" mask=%s\n",
- stoa((&inter_list[i].mask)));
- }
- }
-#endif
- return ninterfaces;
-}
-
-/*
- * io_setbclient - open the broadcast client sockets
- */
-void
-io_setbclient(void)
-{
- int i;
-
-#ifdef OPEN_BCAST_SOCKET
- set_reuseaddr(1);
-#endif
- for (i = nwilds; i < ninterfaces; i++) {
- /* Only IPv4 addresses are valid for broadcast */
- if (inter_list[i].bcast.ss_family != AF_INET)
- continue;
-
- /* Is this a broadcast address? */
- if (!(inter_list[i].flags & INT_BROADCAST))
- continue;
-
- /* Do we already have the broadcast address open? */
- if (inter_list[i].flags & INT_BCASTOPEN)
- continue;
-
-#ifdef SYS_SOLARIS
- inter_list[i].bcast.sin_addr.s_addr = htonl(INADDR_ANY);
-#endif
-#ifdef OPEN_BCAST_SOCKET /* Was: !SYS_DOMAINOS && !SYS_LINUX */
- inter_list[i].bfd = open_socket(&inter_list[i].bcast,
- INT_BROADCAST, 1);
- if (inter_list[i].bfd != INVALID_SOCKET) {
- inter_list[i].flags |= INT_BCASTOPEN;
-#if defined (HAVE_IO_COMPLETION_PORT)
- io_completion_port_add_socket(inter_list[i].bfd, &inter_list[i]);
-#endif
- }
-#ifdef DEBUG
- if (debug) {
- if (inter_list[i].bfd != INVALID_SOCKET)
- printf("io_setbclient: Opened broadcast client on interface %d, socket: %d\n",
- i, inter_list[i].bfd);
- else
- printf("io_setbclient: Unable to Open broadcast client on interface %d\n",
- i);
- }
-#endif
-#endif
- }
-#ifdef OPEN_BCAST_SOCKET
- set_reuseaddr(0);
-#endif
-#ifdef DEBUG
- if (debug)
- printf("io_setbclient: Opened broadcast clients\n");
-#endif
-}
-
-/*
- * set_reuseaddr() - set/clear REUSEADDR on all sockets
- * NB possible hole - should we be doing this on broadcast
- * fd's also?
- */
-static void
-set_reuseaddr(int flag) {
- int i;
-
- for (i=0; i < ninterfaces; i++) {
- /*
- * if inter_list[ n ].fd is -1, we might have a adapter
- * configured but not present
- */
- if (inter_list[i].fd != INVALID_SOCKET) {
- if (setsockopt(inter_list[i].fd, SOL_SOCKET,
- SO_REUSEADDR, (char *)&flag,
- sizeof(flag))) {
- netsyslog(LOG_ERR, "set_reuseaddr: setsockopt(SO_REUSEADDR, %s) failed: %m", flag ? "on" : "off");
- }
- }
- }
-}
-
-
-/*
- * io_multicast_add() - add multicast group address
- */
-void
-io_multicast_add(
- struct sockaddr_storage addr
- )
-{
-#ifdef MCAST
- struct ip_mreq mreq;
- int i = ninterfaces; /* Use the next interface */
- u_int32 haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
- struct in_addr iaddr;
- SOCKET s;
- struct sockaddr_in *sinp;
-
-#ifdef HAVE_IPV6
- struct ipv6_mreq mreq6;
- struct in6_addr iaddr6;
- struct sockaddr_in6 *sin6p;
-#endif /* HAVE_IPV6 */
-
- switch (addr.ss_family)
- {
- case AF_INET :
- iaddr = (((struct sockaddr_in*)&addr)->sin_addr);
- if (!IN_CLASSD(haddr)) {
- netsyslog(LOG_ERR,
- "multicast address %s not class D",
- inet_ntoa(iaddr));
- return;
- }
- for (i = nwilds; i < ninterfaces; i++) {
- /* Be sure it's the correct family */
- if (inter_list[i].sin.ss_family != AF_INET)
- continue;
- /* Already have this address */
- if (SOCKCMP(&inter_list[i].sin, &addr))
- return;
- /* found a free slot */
- if (SOCKNUL(&inter_list[i].sin) &&
- inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
- inter_list[i].flags == 0)
- break;
- }
- sinp = (struct sockaddr_in*)&(inter_list[i].sin);
- memset((char *)&mreq, 0, sizeof(mreq));
- memset((char *)&inter_list[i], 0, sizeof(struct interface));
- sinp->sin_family = AF_INET;
- sinp->sin_addr = iaddr;
- sinp->sin_port = htons(NTP_PORT);
-
- /*
- * Try opening a socket for the specified class D address. This
- * works under SunOS 4.x, but not OSF1 .. :-(
- */
- set_reuseaddr(1);
- s = open_socket((struct sockaddr_storage*)sinp, 0, 1);
- set_reuseaddr(0);
- if (s == INVALID_SOCKET) {
- memset((char *)&inter_list[i], 0, sizeof(struct interface));
- if (wildipv4 >= 0) {
- i = wildipv4;
- /* HACK ! -- stuff in an address */
- inter_list[i].bcast = addr;
- netsyslog(LOG_ERR,
- "...multicast address %s using wildcard socket",
- inet_ntoa(iaddr));
- } else {
- netsyslog(LOG_ERR,
- "No wildcard socket available to use for address %s",
- inet_ntoa(iaddr));
- return;
- }
- } else {
- inter_list[i].fd = s;
- inter_list[i].bfd = INVALID_SOCKET;
- (void) strncpy(inter_list[i].name, "multicast",
- sizeof(inter_list[i].name));
- ((struct sockaddr_in*)&inter_list[i].mask)->sin_addr.s_addr = htonl(~(u_int32)0);
-#if defined (HAVE_IO_COMPLETION_PORT)
- io_completion_port_add_socket(inter_list[i].fd, &inter_list[i]);
-#endif
- }
-
- /*
- * enable reception of multicast packets
- */
- 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)
- netsyslog(LOG_ERR,
- "setsockopt IP_ADD_MEMBERSHIP fails: %m for %x / %x (%s)",
- mreq.imr_multiaddr.s_addr,
- mreq.imr_interface.s_addr, inet_ntoa(iaddr));
- inter_list[i].flags |= INT_MULTICAST;
- inter_list[i].num_mcast++;
- if (i >= ninterfaces)
- ninterfaces = i+1;
-
- add_addr_to_list(&addr, i);
- break;
-
-#ifdef HAVE_IPV6
- case AF_INET6 :
-
- iaddr6 = ((struct sockaddr_in6*)&addr)->sin6_addr;
- if (!IN6_IS_ADDR_MULTICAST(&iaddr6)) {
- netsyslog(LOG_ERR,
- "address %s not IPv6 multicast address",
- stoa(&addr));
- return;
- }
- for (i = nwilds; i < ninterfaces; i++) {
- /* Be sure it's the correct family */
- if(inter_list[i].sin.ss_family != AF_INET6)
- continue;
- /* Already have this address */
- if (SOCKCMP(&inter_list[i].sin, &addr))
- return;
- /* found a free slot */
- if (SOCKNUL(&inter_list[i].sin) &&
- inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
- inter_list[i].flags == 0)
- break;
- }
- sin6p = (struct sockaddr_in6*)&inter_list[i].sin;
- memset((char *)&mreq6, 0, sizeof(mreq6));
- memset((char *)&inter_list[i], 0, sizeof(struct interface));
- sin6p->sin6_family = AF_INET6;
- sin6p->sin6_addr = iaddr6;
- sin6p->sin6_port = htons(NTP_PORT);
-
- /*
- * Try opening a socket for the specified class D address. This
- * works under SunOS 4.x, but not OSF1 .. :-(
- */
- set_reuseaddr(1);
- s = open_socket((struct sockaddr_storage*)sin6p, 0, 1);
- set_reuseaddr(0);
- if(s == INVALID_SOCKET){
- memset((char *)&inter_list[i], 0, sizeof(struct interface));
- if (wildipv6 >= 0) {
- i = wildipv6;
- /* HACK ! -- stuff in an address */
- inter_list[i].bcast = addr;
- netsyslog(LOG_ERR,
- "...multicast address %s using wildcard socket",
- stoa(&addr));
- } else {
- netsyslog(LOG_ERR,
- "No wildcard socket available to use for address %s",
- stoa(&addr));
- return;
- }
- } else {
- inter_list[i].fd = s;
- inter_list[i].bfd = INVALID_SOCKET;
- (void)strncpy(inter_list[i].name, "multicast",
- sizeof(inter_list[i].name));
- memset(&(((struct sockaddr_in6*)&inter_list[i].mask)->sin6_addr), 1, sizeof(struct in6_addr));
-#if defined (HAVE_IO_COMPLETION_PORT)
- io_completion_port_add_socket(inter_list[i].fd, &inter_list[i]);
-#endif
- }
-
- /*
- * enable reception of multicast packets
- */
- mreq6.ipv6mr_multiaddr = iaddr6;
- mreq6.ipv6mr_interface = 0;
- if(setsockopt(inter_list[i].fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- (char *)&mreq6, sizeof(mreq6)) == -1)
- netsyslog(LOG_ERR,
- "setsockopt IPV6_JOIN_GROUP fails: %m on interface %d(%s)",
- mreq6.ipv6mr_interface, stoa(&addr));
- inter_list[i].flags |= INT_MULTICAST;
- inter_list[i].num_mcast++;
- if(i >= ninterfaces)
- ninterfaces = i+1;
-
- add_addr_to_list(&addr, i);
- break;
-#endif /* HAVE_IPV6 */
- }
-
-#ifdef DEBUG
- if (debug)
- printf("io_multicast_add %s\n", stoa(&addr));
-#endif
-#else /* MCAST */
- netsyslog(LOG_ERR,
- "cannot add multicast address %s as no MCAST support",
- stoa(&addr));
-#endif /* MCAST */
-}
-
-/*
- * io_unsetbclient - close the broadcast client sockets
- */
-void
-io_unsetbclient(void)
-{
- int i;
-
- for (i = nwilds; i < ninterfaces; i++)
- {
- if (!(inter_list[i].flags & INT_BCASTOPEN))
- continue;
- close_socket(inter_list[i].bfd);
- inter_list[i].bfd = INVALID_SOCKET;
- inter_list[i].flags &= ~INT_BCASTOPEN;
- }
-}
-
-
-/*
- * io_multicast_del() - delete multicast group address
- */
-void
-io_multicast_del(
- struct sockaddr_storage addr
- )
-{
-#ifdef MCAST
- int i;
- struct ip_mreq mreq;
- u_int32 haddr;
-
-#ifdef HAVE_IPV6
- struct ipv6_mreq mreq6;
- struct in6_addr haddr6;
-#endif /* HAVE_IPV6 */
-
- switch (addr.ss_family)
- {
- case AF_INET :
-
- haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
-
- if (!IN_CLASSD(haddr))
- {
- netsyslog(LOG_ERR,
- "invalid multicast address %s", stoa(&addr));
- return;
- }
-
- /*
- * Disable reception of multicast packets
- */
- mreq.imr_multiaddr = ((struct sockaddr_in*)&addr)->sin_addr;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- for (i = 0; i < ninterfaces; i++)
- {
- /* Be sure it's the correct family */
- if (inter_list[i].sin.ss_family != AF_INET)
- continue;
- if (!(inter_list[i].flags & INT_MULTICAST))
- continue;
- if (!(inter_list[i].fd < 0))
- continue;
- if (!SOCKCMP(&addr, &inter_list[i].sin))
- continue;
- if (i != wildipv4)
- {
- /* we have an explicit fd, so we can close it */
- close_socket(inter_list[i].fd);
- memset((char *)&inter_list[i], 0, sizeof(struct interface));
- inter_list[i].fd = INVALID_SOCKET;
- inter_list[i].bfd = INVALID_SOCKET;
- }
- 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)
- netsyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails on address: %s %m",
- stoa(&addr));
- inter_list[i].num_mcast--;
- /* If there are none left negate the Multicast flag */
- if(inter_list[i].num_mcast == 0)
- inter_list[i].flags &= ~INT_MULTICAST;
- }
- }
- break;
-
-#ifdef HAVE_IPV6
- case AF_INET6 :
- haddr6 = ((struct sockaddr_in6*)&addr)->sin6_addr;
-
- if (!IN6_IS_ADDR_MULTICAST(&haddr6))
- {
- netsyslog(LOG_ERR,
- "invalid multicast address %s", stoa(&addr));
- return;
- }
-
- /*
- * Disable reception of multicast packets
- */
- mreq6.ipv6mr_multiaddr = ((struct sockaddr_in6*)&addr)->sin6_addr;
- mreq6.ipv6mr_interface = 0;
- for (i = 0; i < ninterfaces; i++)
- {
- /* Be sure it's the correct family */
- if (inter_list[i].sin.ss_family != AF_INET6)
- continue;
- if (!(inter_list[i].flags & INT_MULTICAST))
- continue;
- if (!(inter_list[i].fd < 0))
- continue;
- if (!SOCKCMP(&addr, &inter_list[i].sin))
- continue;
- if (i != wildipv6)
- {
- /* we have an explicit fd, so we can close it */
- close_socket(inter_list[i].fd);
- memset((char *)&inter_list[i], 0, sizeof(struct interface));
- inter_list[i].fd = INVALID_SOCKET;
- inter_list[i].bfd = INVALID_SOCKET;
- }
- else
- {
- /* We are sharing "any address" port :-( Don't close it! */
- if (setsockopt(inter_list[i].fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- (char *)&mreq6, sizeof(mreq6)) == -1)
- netsyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails on address %s: %m",
- stoa(&addr));
- /* If there are none left negate the Multicast flag */
- if(inter_list[i].num_mcast == 0)
- inter_list[i].flags &= ~INT_MULTICAST;
- }
- }
- break;
-#endif /* HAVE_IPV6 */
- }/* switch */
- delete_addr_from_list(&addr);
-
-#else /* not MCAST */
- netsyslog(LOG_ERR, "this function requires multicast kernel");
-#endif /* not MCAST */
-}
-
-
-/*
- * open_socket - open a socket, returning the file descriptor
- */
-
-static SOCKET
-open_socket(
- struct sockaddr_storage *addr,
- int flags,
- int turn_off_reuse
- )
-{
- int errval;
- SOCKET fd;
- int on = 1, off = 0;
-#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
- int tos;
-#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
-
- if ((addr->ss_family == AF_INET6) && (isc_net_probeipv6() != ISC_R_SUCCESS))
- return (INVALID_SOCKET);
-
- /* create a datagram (UDP) socket */
-#ifndef SYS_WINNT
- if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) < 0) {
- errval = errno;
- if(addr->ss_family == AF_INET)
- netsyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed on address %s: %m",
- stoa(addr));
- else if(addr->ss_family == AF_INET6)
- netsyslog(LOG_ERR, "socket(AF_INET6, SOCK_DGRAM, 0) failed on address %s: %m",
- stoa(addr));
- if (errval == EPROTONOSUPPORT || errval == EAFNOSUPPORT ||
- errval == EPFNOSUPPORT)
- return (INVALID_SOCKET);
- exit(1);
- /*NOTREACHED*/
- }
-#else
- if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
- errval = WSAGetLastError();
- if(addr->ss_family == AF_INET)
- netsyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed on address %s: %m",
- stoa(addr));
- else if(addr->ss_family == AF_INET6)
- netsyslog(LOG_ERR, "socket(AF_INET6, SOCK_DGRAM, 0) failed on address %s: %m",
- stoa(addr));
- if (errval == WSAEPROTONOSUPPORT || errval == WSAEAFNOSUPPORT ||
- errval == WSAEPFNOSUPPORT)
- return (INVALID_SOCKET);
- exit(1);
- /*NOTREACHED*/
- }
- if (connection_reset_fix(fd) != ISC_R_SUCCESS) {
- netsyslog(LOG_ERR, "connection_reset_fix(fd) failed on address %s: %m",
- stoa(addr));
- }
-
-#endif /* SYS_WINNT */
-
- /* set SO_REUSEADDR since we will be binding the same port
- number on each interface */
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails on address %s: %m",
- stoa(addr));
- }
-
-#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
- /* set IP_TOS to minimize packet delay */
- tos = IPTOS_LOWDELAY;
- if (addr->ss_family == AF_INET)
- if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)) < 0)
- {
- netsyslog(LOG_ERR, "setsockopt IPTOS_LOWDELAY on fails on address %s: %m",
- stoa(addr));
- }
-
-#if defined(IPV6_V6ONLY)
- if (addr->ss_family == AF_INET6)
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
- (char*)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR, "setsockopt IPV6_V6ONLY on fails on address %s: %m",
- stoa(addr));
- }
-#else /* IPV6_V6ONLY */
-#if defined(IPV6_BINDV6ONLY)
- if (addr->ss_family == AF_INET6)
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
- (char*)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR,
- "setsockopt IPV6_BINDV6ONLY on fails on address %s: %m",
- stoa(addr));
- }
-#endif /* IPV6_BINDV6ONLY */
-#endif /* IPV6_V6ONLY */
-
-#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
-
- /*
- * bind the local address.
- */
- if (bind(fd, (struct sockaddr *)addr, SOCKLEN(addr)) < 0) {
- char buff[160];
-
- if(addr->ss_family == AF_INET)
- sprintf(buff,
- "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=%d fails: %%m",
- fd, addr->ss_family, (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
- stoa(addr),
- IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)), flags);
- else if(addr->ss_family == AF_INET6)
- sprintf(buff,
- "bind() fd %d, family %d, port %d, addr %s, in6_is_addr_multicast=%d flags=%d fails: %%m",
- fd, addr->ss_family, (int)ntohs(((struct sockaddr_in6*)addr)->sin6_port),
- stoa(addr),
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr), flags);
- else return INVALID_SOCKET;
-
- netsyslog(LOG_ERR, buff);
- closesocket(fd);
-
- /*
- * soft fail if opening a multicast address
- */
- if(addr->ss_family == AF_INET){
- if(IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)))
- return (INVALID_SOCKET);
- }
- else {
- if(IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr))
- return (INVALID_SOCKET);
- }
-#if 0
- exit(1);
-#else
- return INVALID_SOCKET;
-#endif
- }
-#ifdef DEBUG
- if (debug)
- printf("bind() fd %d, family %d, port %d, addr %s, flags=%d\n",
- fd,
- addr->ss_family,
- (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
- stoa(addr),
- flags);
-#endif
-
- /*
- * I/O Completion Ports don't care about the select and FD_SET
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- if (fd > maxactivefd)
- maxactivefd = fd;
- FD_SET(fd, &activefds);
-#endif
- add_socket_to_list(fd);
- /*
- * set non-blocking,
- */
-
-#ifdef USE_FIONBIO
- /* in vxWorks we use FIONBIO, but the others are defined for old systems, so
- * all hell breaks loose if we leave them defined
- */
-#undef O_NONBLOCK
-#undef FNDELAY
-#undef O_NDELAY
-#endif
-
-#if defined(O_NONBLOCK) /* POSIX */
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#elif defined(FNDELAY)
- if (fcntl(fd, F_SETFL, FNDELAY) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(FNDELAY) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#elif defined(O_NDELAY) /* generally the same as FNDELAY */
- if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(O_NDELAY) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#elif defined(FIONBIO)
-# if defined(VMS)
- if (ioctl(fd,FIONBIO,&on) < 0)
-# elif defined(SYS_WINNT)
- if (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
-# else
- if (ioctl(fd,FIONBIO,&on) < 0)
-# endif
- {
- netsyslog(LOG_ERR, "ioctl(FIONBIO) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#elif defined(FIOSNBIO)
- if (ioctl(fd,FIOSNBIO,&on) < 0)
- {
- netsyslog(LOG_ERR, "ioctl(FIOSNBIO) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#else
-# include "Bletch: Need non-blocking I/O!"
-#endif
-
-#ifdef HAVE_SIGNALED_IO
- init_socket_sig(fd);
-#endif /* not HAVE_SIGNALED_IO */
-
- /*
- * Turn off the SO_REUSEADDR socket option. It apparently
- * causes heartburn on systems with multicast IP installed.
- * On normal systems it only gets looked at when the address
- * is being bound anyway..
- */
- if (turn_off_reuse)
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&off, sizeof(off)))
- {
- netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails on address %s: %m",
- stoa(addr));
- }
-
-#ifdef SO_BROADCAST
- /* if this interface can support broadcast, set SO_BROADCAST */
- if (flags & INT_BROADCAST)
- {
- if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
- (char *)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) on address %s: %m",
- stoa(addr));
- }
- }
-#endif /* SO_BROADCAST */
-
-#if !defined(SYS_WINNT) && !defined(VMS)
-# ifdef DEBUG
- if (debug > 1)
- printf("flags for fd %d: 0%o\n", fd,
- fcntl(fd, F_GETFL, 0));
-# endif
-#endif /* SYS_WINNT || VMS */
-
- return fd;
-}
-
-
-/*
- * close_socket - close a socket and remove from the activefd list
- */
-static void
-close_socket(
- SOCKET fd
- )
-{
- SOCKET i, newmax;
-
- (void) closesocket(fd);
-
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- FD_CLR( (u_int) fd, &activefds);
-
- if (fd == maxactivefd) {
- newmax = 0;
- for (i = 0; i < maxactivefd; i++)
- if (FD_ISSET(i, &activefds))
- newmax = i;
- maxactivefd = newmax;
- }
-#endif
- delete_socket_from_list(fd);
-
-}
-
-
-/*
- * close_file - close a file and remove from the activefd list
- * added 1/31/1997 Greg Schueman for Windows NT portability
- */
-#ifdef REFCLOCK
-static void
-close_file(
- SOCKET fd
- )
-{
- int i, newmax;
-
- (void) close(fd);
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- FD_CLR( (u_int) fd, &activefds);
-
- if (fd == maxactivefd) {
- newmax = 0;
- for (i = 0; i < maxactivefd; i++)
- if (FD_ISSET(i, &activefds))
- newmax = i;
- maxactivefd = newmax;
- }
-#endif
- delete_socket_from_list(fd);
-
-}
-#endif
-
-
-/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
-/*
- * sendpkt - send a packet to the specified destination. Maintain a
- * send error cache so that only the first consecutive error for a
- * destination is logged.
- */
-void
-sendpkt(
- struct sockaddr_storage *dest,
- struct interface *inter,
- int ttl,
- struct pkt *pkt,
- int len
- )
-{
- int cc, slot;
-#ifdef SYS_WINNT
- DWORD err;
-#endif /* SYS_WINNT */
-
- /*
- * Send error caches. Empty slots have port == 0
- * Set ERRORCACHESIZE to 0 to disable
- */
- struct cache {
- u_short port;
- struct in_addr addr;
- };
-
-#ifdef HAVE_IPV6
- struct cache6 {
- u_short port;
- struct in6_addr addr;
- };
-#endif /* HAVE_IPV6 */
-
-#ifndef ERRORCACHESIZE
-#define ERRORCACHESIZE 8
-#endif
-#if ERRORCACHESIZE > 0
- static struct cache badaddrs[ERRORCACHESIZE];
-#ifdef HAVE_IPV6
- static struct cache6 badaddrs6[ERRORCACHESIZE];
-#endif /* HAVE_IPV6 */
-#else
-#define badaddrs ((struct cache *)0) /* Only used in empty loops! */
-#ifdef HAVE_IPV6
-#define badaddrs6 ((struct cache6 *)0) /* Only used in empty loops! */
-#endif /* HAVE_IPV6 */
-#endif
-#ifdef DEBUG
- if (debug > 1)
- printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n",
- (ttl >= 0) ? "\tMCAST\t*****" : "",
- inter->fd, stoa(dest),
- stoa(&inter->sin), ttl, len);
-#endif
-
-#ifdef MCAST
-
- switch (inter->sin.ss_family) {
-
- case AF_INET :
-
- /*
- * for the moment we use the bcast option to set multicast ttl
- */
- if (ttl > 0 && ttl != inter->last_ttl) {
-
- /*
- * set the multicast ttl for outgoing packets
- */
- if (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
- (char *) &ttl, sizeof(ttl)) != 0) {
- netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails on address %s: %m",
- stoa(&inter->sin));
- }
- else
- inter->last_ttl = ttl;
- }
- break;
-
-#ifdef HAVE_IPV6
- case AF_INET6 :
-
- /*
- * for the moment we use the bcast option to set
- * multicast max hops
- */
- if (ttl > 0 && ttl != inter->last_ttl) {
-
- /*
- * set the multicast ttl for outgoing packets
- */
- if (setsockopt(inter->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- &ttl, sizeof(ttl)) == -1)
- netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails on address %s: %m",
- stoa(&inter->sin));
- else
- inter->last_ttl = ttl;
- }
- break;
-#endif /* HAVE_IPV6 */
-
- default :
- exit(1);
-
- }
-
-
-#endif /* MCAST */
-
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if(dest->ss_family == AF_INET) {
- if (badaddrs[slot].port == ((struct sockaddr_in*)dest)->sin_port &&
- badaddrs[slot].addr.s_addr == ((struct sockaddr_in*)dest)->sin_addr.s_addr)
- break;
- }
-#ifdef HAVE_IPV6
- else if (dest->ss_family == AF_INET6) {
- if (badaddrs6[slot].port == ((struct sockaddr_in6*)dest)->sin6_port &&
- badaddrs6[slot].addr.s6_addr == ((struct sockaddr_in6*)dest)->sin6_addr.s6_addr)
- break;
- }
-#endif /* HAVE_IPV6 */
- else exit(1); /* address family not supported yet */
-
-#if defined(HAVE_IO_COMPLETION_PORT)
- err = io_completion_port_sendto(inter, pkt, len, dest);
- if (err != ERROR_SUCCESS)
-#else
-#ifdef SIM
- cc = srvr_rply(&ntp_node, dest, inter, pkt);
-#else /* SIM */
- cc = sendto(inter->fd, (char *)pkt, (unsigned int)len, 0, (struct sockaddr *)dest,
- SOCKLEN(dest));
-#endif /* SIM */
- if (cc == -1)
-#endif
- {
- inter->notsent++;
- packets_notsent++;
-#if defined(HAVE_IO_COMPLETION_PORT)
- err = WSAGetLastError();
- if (err != WSAEWOULDBLOCK && err != WSAENOBUFS && slot < 0)
-#else
- if (errno != EWOULDBLOCK && errno != ENOBUFS && slot < 0)
-#endif
- {
- /*
- * Remember this, if there's an empty slot
- */
- switch (dest->ss_family) {
-
- case AF_INET :
-
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if (badaddrs[slot].port == 0)
- {
- badaddrs[slot].port = SRCPORT(dest);
- badaddrs[slot].addr = ((struct sockaddr_in*)dest)->sin_addr;
- break;
- }
- break;
-
-#ifdef HAVE_IPV6
- case AF_INET6 :
-
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if (badaddrs6[slot].port == 0)
- {
- badaddrs6[slot].port = SRCPORT(dest);
- badaddrs6[slot].addr = ((struct sockaddr_in6*)dest)->sin6_addr;
- break;
- }
- break;
-#endif /* HAVE_IPV6 */
-
- default :
- exit(1);
- }
-
- netsyslog(LOG_ERR, "sendto(%s): %m", stoa(dest));
- }
- }
- else
- {
- inter->sent++;
- packets_sent++;
- /*
- * He's not bad any more
- */
- if (slot >= 0)
- {
- netsyslog(LOG_INFO, "Connection re-established to %s", stoa(dest));
- switch (dest->ss_family) {
- case AF_INET :
- badaddrs[slot].port = 0;
- break;
-#ifdef HAVE_IPV6
- case AF_INET6 :
- badaddrs6[slot].port = 0;
- break;
-#endif /* HAVE_IPV6 */
- }
- }
- }
-}
-
-#if !defined(HAVE_IO_COMPLETION_PORT)
-/*
- * fdbits - generate ascii representation of fd_set (FAU debug support)
- * HFDF format - highest fd first.
- */
-static char *
-fdbits(
- int count,
- fd_set *set
- )
-{
- static char buffer[256];
- char * buf = buffer;
-
- count = (count < 256) ? count : 255;
-
- while (count >= 0)
- {
- *buf++ = FD_ISSET(count, set) ? '#' : '-';
- count--;
- }
- *buf = '\0';
-
- return buffer;
-}
-
-/*
- * input_handler - receive packets asynchronously
- */
-void
-input_handler(
- l_fp *cts
- )
-{
- register int i, n;
- register struct recvbuf *rb;
- register int doing;
- register SOCKET fd;
- struct timeval tvzero;
- int fromlen;
- l_fp ts; /* Timestamp at BOselect() gob */
- l_fp ts_e; /* Timestamp at EOselect() gob */
- fd_set fds;
- int select_count = 0;
- static int handler_count = 0;
-
- ++handler_count;
- if (handler_count != 1)
- msyslog(LOG_ERR, "input_handler: handler_count is %d!", handler_count);
- handler_calls++;
- ts = *cts;
-
- for (;;)
- {
- /*
- * Do a poll to see who has data
- */
-
- fds = activefds;
- tvzero.tv_sec = tvzero.tv_usec = 0;
-
- /*
- * If we have something to do, freeze a timestamp.
- * See below for the other cases (nothing (left) to do or error)
- */
- while (0 < (n = select(maxactivefd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero)))
- {
- ++select_count;
- ++handler_pkts;
-
-#ifdef REFCLOCK
- /*
- * Check out the reference clocks first, if any
- */
- if (refio != 0)
- {
- register struct refclockio *rp;
-
- for (rp = refio; rp != 0 && n > 0; rp = rp->next)
- {
- fd = rp->fd;
- if (FD_ISSET(fd, &fds))
- {
- n--;
- if (free_recvbuffs() == 0)
- {
- char buf[RX_BUFF_SIZE];
-
- (void) read(fd, buf, sizeof buf);
- packets_dropped++;
- goto select_again;
- }
-
- rb = get_free_recv_buffer();
-
- i = (rp->datalen == 0
- || rp->datalen > sizeof(rb->recv_space))
- ? sizeof(rb->recv_space) : rp->datalen;
- rb->recv_length =
- read(fd, (char *)&rb->recv_space, (unsigned)i);
-
- if (rb->recv_length == -1)
- {
- netsyslog(LOG_ERR, "clock read fd %d: %m", fd);
- freerecvbuf(rb);
- goto select_again;
- }
-
- /*
- * Got one. Mark how
- * and when it got here,
- * put it on the full
- * list and do
- * bookkeeping.
- */
- rb->recv_srcclock = rp->srcclock;
- rb->dstadr = 0;
- rb->fd = fd;
- rb->recv_time = ts;
- rb->receiver = rp->clock_recv;
-
- if (rp->io_input)
- {
- /*
- * have direct
- * input routine
- * for refclocks
- */
- if (rp->io_input(rb) == 0)
- {
- /*
- * data
- * was
- * consumed
- * -
- * nothing
- * to
- * pass
- * up
- * into
- * block
- * input
- * machine
- */
- freerecvbuf(rb);
-#if 1
- goto select_again;
-#else
- continue;
-#endif
- }
- }
-
- add_full_recv_buffer(rb);
-
- rp->recvcount++;
- packets_received++;
- }
- }
- }
-#endif /* REFCLOCK */
-
- /*
- * Loop through the interfaces looking for data
- * to read.
- */
- for (i = ninterfaces - 1; (i >= 0) && (n > 0); i--)
- {
- for (doing = 0; (doing < 2) && (n > 0); doing++)
- {
- if (doing == 0)
- {
- fd = inter_list[i].fd;
- }
- else
- {
- if (!(inter_list[i].flags & INT_BCASTOPEN))
- 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.
- */
- if (
-#ifdef UDP_WILDCARD_DELIVERY
- /*
- * these guys manage to put properly addressed
- * packets into the wildcard queue
- */
- (free_recvbuffs() == 0)
-#else
- ((i == wildipv4) || (i == wildipv6)||
- (free_recvbuffs() == 0))
-#endif
- )
- {
- char buf[RX_BUFF_SIZE];
- struct sockaddr_storage from;
-
- fromlen = sizeof from;
- (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fromlen);
-#ifdef DEBUG
- if (debug)
- printf("%s on %d(%lu) fd=%d from %s\n",
- (i) ? "drop" : "ignore",
- i, free_recvbuffs(), fd,
- stoa(&from));
-#endif
- if (i == wildipv4 || i == wildipv6)
- packets_ignored++;
- else
- packets_dropped++;
- goto select_again;
- }
-
- rb = get_free_recv_buffer();
-
- fromlen = sizeof(struct sockaddr_storage);
- rb->recv_length = recvfrom(fd,
- (char *)&rb->recv_space,
- sizeof(rb->recv_space), 0,
- (struct sockaddr *)&rb->recv_srcadr,
- &fromlen);
- if (rb->recv_length == 0
-#ifdef EWOULDBLOCK
- || errno==EWOULDBLOCK
-#endif
-#ifdef EAGAIN
- || errno==EAGAIN
-#endif
- ) {
- freerecvbuf(rb);
- continue;
- }
- else if (rb->recv_length < 0)
- {
- netsyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
- stoa(&rb->recv_srcadr), fd);
-#ifdef DEBUG
- if (debug)
- printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd);
-#endif
- freerecvbuf(rb);
- continue;
- }
-#ifdef DEBUG
- if (debug > 2) {
- if(rb->recv_srcadr.ss_family == AF_INET)
- printf("input_handler: if=%d fd=%d length %d from %08lx %s\n",
- i, fd, rb->recv_length,
- (u_long)ntohl(((struct sockaddr_in*)&rb->recv_srcadr)->sin_addr.s_addr) &
- 0x00000000ffffffff,
- stoa(&rb->recv_srcadr));
- else
- printf("input_handler: if=%d fd=%d length %d from %s\n",
- i, fd, rb->recv_length,
- stoa(&rb->recv_srcadr));
- }
-#endif
-
- /*
- * Got one. Mark how and when it got here,
- * put it on the full list and do bookkeeping.
- */
- rb->dstadr = &inter_list[i];
- rb->fd = fd;
- rb->recv_time = ts;
- rb->receiver = receive;
-
- add_full_recv_buffer(rb);
-
- inter_list[i].received++;
- packets_received++;
- goto select_again;
- }
- /* Check more interfaces */
- }
- }
- select_again:;
- /*
- * Done everything from that select. Poll again.
- */
- }
-
- /*
- * If nothing more to do, try again.
- * If nothing to do, just return.
- * If an error occurred, complain and return.
- */
- if (n == 0)
- {
- if (select_count == 0) /* We really had nothing to do */
- {
- if (debug)
- netsyslog(LOG_DEBUG, "input_handler: select() returned 0");
- --handler_count;
- return;
- }
- /* We've done our work */
- get_systime(&ts_e);
- /*
- * (ts_e - ts) is the amount of time we spent
- * processing this gob of file descriptors. Log
- * it.
- */
- L_SUB(&ts_e, &ts);
- if (debug > 3)
- netsyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
-
- /* just bail. */
- --handler_count;
- return;
- }
- else if (n == -1)
- {
- int err = errno;
-
- /*
- * extended FAU debugging output
- */
- if (err != EINTR)
- netsyslog(LOG_ERR,
- "select(%d, %s, 0L, 0L, &0.0) error: %m",
- maxactivefd+1,
- fdbits(maxactivefd, &activefds));
- if (err == EBADF) {
- int j, b;
-
- fds = activefds;
- for (j = 0; j <= maxactivefd; j++)
- if (
- (FD_ISSET(j, &fds) && (read(j, &b, 0) == -1))
- )
- netsyslog(LOG_ERR, "Bad file descriptor %d", j);
- }
- --handler_count;
- return;
- }
- }
- msyslog(LOG_ERR, "input_handler: fell out of infinite for(;;) loop!");
- --handler_count;
- return;
-}
-
-#endif
-/*
- * findinterface - find interface corresponding to address
- */
-struct interface *
-findinterface(
- struct sockaddr_storage *addr
- )
-{
- SOCKET s;
- int rtn, i;
- struct sockaddr_storage saddr;
- int saddrlen = SOCKLEN(addr);
- /*
- * This is considerably hoke. We open a socket, connect to it
- * and slap a getsockname() on it. If anything breaks, as it
- * probably will in some j-random knockoff, we just return the
- * wildcard interface.
- */
- memset(&saddr, 0, sizeof(saddr));
- saddr.ss_family = addr->ss_family;
- if(addr->ss_family == AF_INET)
- memcpy(&((struct sockaddr_in*)&saddr)->sin_addr, &((struct sockaddr_in*)addr)->sin_addr, sizeof(struct in_addr));
- else if(addr->ss_family == AF_INET6)
- memcpy(&((struct sockaddr_in6*)&saddr)->sin6_addr, &((struct sockaddr_in6*)addr)->sin6_addr, sizeof(struct in6_addr));
- ((struct sockaddr_in*)&saddr)->sin_port = htons(2000);
- s = socket(addr->ss_family, SOCK_DGRAM, 0);
- if (s == INVALID_SOCKET)
- return ANY_INTERFACE_CHOOSE(addr);
-
- rtn = connect(s, (struct sockaddr *)&saddr, SOCKLEN(&saddr));
-#ifndef SYS_WINNT
- if (rtn < 0)
-#else
- if (rtn == SOCKET_ERROR)
-#endif
- {
- closesocket(s);
- return ANY_INTERFACE_CHOOSE(addr);
- }
-
- rtn = getsockname(s, (struct sockaddr *)&saddr, &saddrlen);
- closesocket(s);
-#ifndef SYS_WINNT
- if (rtn < 0)
-#else
- if (rtn == SOCKET_ERROR)
-#endif
- return ANY_INTERFACE_CHOOSE(addr);
-
- for (i = 0; i < ninterfaces; i++) {
- /*
- * First look if is the the correct family
- */
- if(inter_list[i].sin.ss_family != saddr.ss_family)
- continue;
- /*
- * We match the unicast address only.
- */
- if (SOCKCMP(&inter_list[i].sin, &saddr))
- return (&inter_list[i]);
- }
- return ANY_INTERFACE_CHOOSE(addr);
-}
-
-/*
- * findbcastinter - find broadcast interface corresponding to address
- */
-struct interface *
-findbcastinter(
- struct sockaddr_storage *addr
- )
-{
-#if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT))
- register int i;
-
- i = find_addr_in_list(addr);
- if(i >= 0)
- return (&inter_list[i]);
-
- for (i = 0; i < ninterfaces; i++) {
- /*
- * First look if this is the correct family
- */
- if(inter_list[i].sin.ss_family != addr->ss_family)
- continue;
- /*
- * We match only those interfaces marked as
- * broadcastable and either the explicit broadcast
- * address or the network portion of the IP address.
- * Sloppy.
- */
- if (!(inter_list[i].flags & INT_BROADCAST))
- continue;
- if(addr->ss_family == AF_INET) {
- if (SOCKCMP(&inter_list[i].bcast, addr))
- return (&inter_list[i]);
- if ((NSRCADR(&inter_list[i].sin) &
- NSRCADR(&inter_list[i].mask)) == (NSRCADR(addr) &
- NSRCADR(&inter_list[i].mask)))
- return (&inter_list[i]);
- }
- else if(addr->ss_family == AF_INET6) {
- if (SOCKCMP(&inter_list[i].bcast, addr))
- return (&inter_list[i]);
- if (SOCKCMP(netof(&inter_list[i].sin), netof(addr)))
- return (&inter_list[i]);
- }
- }
-#endif /* SIOCGIFCONF */
- return ANY_INTERFACE_CHOOSE(addr);
-}
-
-
-/*
- * io_clr_stats - clear I/O module statistics
- */
-void
-io_clr_stats(void)
-{
- packets_dropped = 0;
- packets_ignored = 0;
- packets_received = 0;
- packets_sent = 0;
- packets_notsent = 0;
-
- handler_calls = 0;
- handler_pkts = 0;
- io_timereset = current_time;
-}
-
-
-#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
- */
-int
-io_addclock_simple(
- struct refclockio *rio
- )
-{
- BLOCKIO();
- /*
- * Stuff the I/O structure in the list and mark the descriptor
- * in use. There is a harmless (I hope) race condition here.
- */
- rio->next = refio;
- refio = rio;
-
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- if (rio->fd > maxactivefd)
- maxactivefd = rio->fd;
- FD_SET(rio->fd, &activefds);
-#endif
- UNBLOCKIO();
- return 1;
-}
-
-/*
- * io_addclock - add a reference clock to the list and arrange that we
- * get SIGIO interrupts from it.
- */
-int
-io_addclock(
- struct refclockio *rio
- )
-{
- BLOCKIO();
- /*
- * Stuff the I/O structure in the list and mark the descriptor
- * in use. There is a harmless (I hope) race condition here.
- */
- rio->next = refio;
- refio = rio;
-
-# ifdef HAVE_SIGNALED_IO
- if (init_clock_sig(rio))
- {
- refio = rio->next;
- UNBLOCKIO();
- return 0;
- }
-# elif defined(HAVE_IO_COMPLETION_PORT)
- if (io_completion_port_add_clock_io(rio))
- {
- add_socket_to_list(rio->fd);
- refio = rio->next;
- UNBLOCKIO();
- return 0;
- }
-# endif
-
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- if (rio->fd > maxactivefd)
- maxactivefd = rio->fd;
- FD_SET(rio->fd, &activefds);
-#endif
- UNBLOCKIO();
- return 1;
-}
-
-/*
- * io_closeclock - close the clock in the I/O structure given
- */
-void
-io_closeclock(
- struct refclockio *rio
- )
-{
- /*
- * Remove structure from the list
- */
- if (refio == rio)
- {
- refio = rio->next;
- }
- else
- {
- register struct refclockio *rp;
-
- for (rp = refio; rp != 0; rp = rp->next)
- if (rp->next == rio)
- {
- rp->next = rio->next;
- break;
- }
-
- if (rp == 0)
- {
- /*
- * Internal error. Report it.
- */
- msyslog(LOG_ERR,
- "internal error: refclockio structure not found");
- return;
- }
- }
-
- /*
- * Close the descriptor.
- */
- close_file(rio->fd);
-}
-#endif /* REFCLOCK */
-
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
-void
-kill_asyncio(
- int startfd
- )
-{
- SOCKET i;
-
- BLOCKIO();
- for (i = startfd; i <= maxactivefd; i++)
- (void)close_socket(i);
-}
-#else
-/*
- * On NT a SOCKET is an unsigned int so we cannot possibly keep it in
- * an array. So we use one of the ISC_LIST functions to hold the
- * socket value and use that when we want to enumerate it.
- */
-void
-kill_asyncio(int startfd)
-{
- vsock_t *lsock;
- vsock_t *next;
-
- BLOCKIO();
-
- lsock = ISC_LIST_HEAD(sockets_list);
- while (lsock != NULL) {
- next = ISC_LIST_NEXT(lsock, link);
- close_socket(lsock->fd);
- lsock = next;
- }
-
-}
-#endif
-/*
- * Add and delete functions for the list of open sockets
- */
-void
-add_socket_to_list(SOCKET fd){
- vsock_t *lsock = malloc(sizeof(vsock_t));
- lsock->fd = fd;
-
- ISC_LIST_APPEND(sockets_list, lsock, link);
-}
-void
-delete_socket_from_list(SOCKET fd) {
-
- vsock_t *next;
- vsock_t *lsock = ISC_LIST_HEAD(sockets_list);
-
- while(lsock != NULL) {
- next = ISC_LIST_NEXT(lsock, link);
- if(lsock->fd == fd) {
- ISC_LIST_DEQUEUE(sockets_list, lsock, link);
- free(lsock);
- break;
- }
- else
- lsock = next;
- }
-}
-void
-add_addr_to_list(struct sockaddr_storage *addr, int if_index){
- remaddr_t *laddr = malloc(sizeof(remaddr_t));
- memcpy(&laddr->addr, addr, sizeof(addr));
- laddr->if_index = if_index;
-
- ISC_LIST_APPEND(remoteaddr_list, laddr, link);
-#ifdef DEBUG
- if (debug)
- printf("Added addr %s to list of addresses\n",
- stoa(addr));
-#endif
-
-
-}
-void
-delete_addr_from_list(struct sockaddr_storage *addr) {
-
- remaddr_t *next;
- remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
-
- while(laddr != NULL) {
- next = ISC_LIST_NEXT(laddr, link);
- if(SOCKCMP(&laddr->addr, addr)) {
- ISC_LIST_DEQUEUE(remoteaddr_list, laddr, link);
- free(laddr);
- break;
- }
- else
- laddr = next;
- }
-#ifdef DEBUG
- if (debug)
- printf("Deleted addr %s from list of addresses\n",
- stoa(addr));
-#endif
-}
-int
-find_addr_in_list(struct sockaddr_storage *addr) {
-
- remaddr_t *next;
- remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
-#ifdef DEBUG
- if (debug)
- printf("Finding addr %s in list of addresses\n",
- stoa(addr));
-#endif
-
- while(laddr != NULL) {
- next = ISC_LIST_NEXT(laddr, link);
- if(SOCKCMP(&laddr->addr, addr)) {
- return (laddr->if_index);
- break;
- }
- else
- laddr = next;
- }
- return (-1); /* Not found */
-}
diff --git a/contrib/ntp/ntpd/ntp_loopfilter.c b/contrib/ntp/ntpd/ntp_loopfilter.c
deleted file mode 100644
index 99d1cc4..0000000
--- a/contrib/ntp/ntpd/ntp_loopfilter.c
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*
- * ntp_loopfilter.c - implements the NTP loop filter algorithm
- *
- * ATTENTION: Get approval from Dave Mills on all changes to this file!
- *
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include <signal.h>
-#include <setjmp.h>
-
-#if defined(VMS) && defined(VMS_LOCALUNIT) /*wjm*/
-#include "ntp_refclock.h"
-#endif /* VMS */
-
-#ifdef KERNEL_PLL
-#include "ntp_syscall.h"
-#endif /* KERNEL_PLL */
-
-/*
- * This is an implementation of the clock discipline algorithm described
- * in UDel TR 97-4-3, as amended. It operates as an adaptive parameter,
- * hybrid phase/frequency-lock loop. A number of sanity checks are
- * included to protect against timewarps, timespikes and general mayhem.
- * All units are in s and s/s, unless noted otherwise.
- */
-#define CLOCK_MAX .128 /* default step threshold (s) */
-#define CLOCK_MINSTEP 900. /* default stepout threshold (s) */
-#define CLOCK_PANIC 1000. /* default panic threshold (s) */
-#define CLOCK_PHI 15e-6 /* max frequency error (s/s) */
-#define CLOCK_PLL 16. /* PLL loop gain */
-#define CLOCK_FLL 8. /* FLL loop gain */
-#define CLOCK_AVG 4. /* parameter averaging constant */
-#define CLOCK_ALLAN 1500. /* compromise Allan intercept (s) */
-#define CLOCK_DAY 86400. /* one day in seconds (s) */
-#define CLOCK_LIMIT 30 /* poll-adjust threshold */
-#define CLOCK_PGATE 4. /* poll-adjust gate */
-#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
-
-/*
- * Clock discipline state machine. This is used to control the
- * synchronization behavior during initialization and following a
- * timewarp.
- *
- * State < max > max Comments
- * ====================================================
- * NSET FREQ FREQ no ntp.drift
- *
- * FSET TSET if (allow) TSET, ntp.drift
- * else FREQ
- *
- * TSET SYNC FREQ time set
- *
- * FREQ SYNC if (mu < 900) FREQ calculate frequency
- * else if (allow) TSET
- * else FREQ
- *
- * SYNC SYNC if (mu < 900) SYNC normal state
- * else SPIK
- *
- * SPIK SYNC if (allow) TSET spike detector
- * else FREQ
- */
-#define S_NSET 0 /* clock never set */
-#define S_FSET 1 /* frequency set from the drift file */
-#define S_TSET 2 /* time set */
-#define S_FREQ 3 /* frequency mode */
-#define S_SYNC 4 /* clock synchronized */
-#define S_SPIK 5 /* spike detected */
-
-/*
- * Kernel PLL/PPS state machine. This is used with the kernel PLL
- * modifications described in the README.kernel file.
- *
- * If kernel support for the ntp_adjtime() system call is available, the
- * ntp_control flag is set. The ntp_enable and kern_enable flags can be
- * set at configuration time or run time using ntpdc. If ntp_enable is
- * false, the discipline loop is unlocked and no correctios of any kind
- * are made. If both ntp_control and kern_enable are set, the kernel
- * support is used as described above; if false, the kernel is bypassed
- * entirely and the daemon PLL used instead.
- *
- * Each update to a prefer peer sets pps_stratum 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_stratum 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.
- *
- * If an external clock is present, the clock driver sets STA_CLK in the
- * status word. When the local clock driver sees this bit, it updates
- * via this routine, which then calls ntp_adjtime() with the STA_PLL bit
- * set to zero, in which case the system clock is not adjusted. This is
- * also a signal for the external clock driver to discipline the system
- * clock.
- */
-/*
- * Program variables that can be tinkered.
- */
-double clock_max = CLOCK_MAX; /* step threshold (s) */
-double clock_minstep = CLOCK_MINSTEP; /* stepout threshold (s) */
-double clock_panic = CLOCK_PANIC; /* panic threshold (s) */
-double clock_phi = CLOCK_PHI; /* dispersion rate (s/s) */
-double allan_xpt = CLOCK_ALLAN; /* Allan intercept (s) */
-
-/*
- * Program variables
- */
-static double clock_offset; /* clock offset adjustment (s) */
-double drift_comp; /* clock frequency (s/s) */
-double clock_stability; /* clock stability (s/s) */
-u_long pps_control; /* last pps sample time */
-static void rstclock P((int, u_long, double)); /* transition function */
-
-#ifdef KERNEL_PLL
-struct timex ntv; /* kernel API parameters */
-int pll_status; /* status bits for kernel pll */
-int pll_nano; /* nanosecond kernel switch */
-#endif /* KERNEL_PLL */
-
-/*
- * Clock state machine control flags
- */
-int ntp_enable; /* clock discipline enabled */
-int pll_control; /* kernel support available */
-int kern_enable; /* kernel support enabled */
-int pps_enable; /* kernel PPS discipline enabled */
-int ext_enable; /* external clock enabled */
-int pps_stratum; /* pps stratum */
-int allow_panic = FALSE; /* allow panic correction */
-int mode_ntpdate = FALSE; /* exit on first clock set */
-
-/*
- * Clock state machine variables
- */
-u_char sys_poll = NTP_MINDPOLL; /* system poll interval (log2 s) */
-int state; /* clock discipline state */
-int tc_counter; /* hysteresis counter */
-u_long last_time; /* time of last clock update (s) */
-double last_offset; /* last clock offset (s) */
-double sys_jitter; /* system RMS jitter (s) */
-
-/*
- * Huff-n'-puff filter variables
- */
-static double *sys_huffpuff; /* huff-n'-puff filter */
-static int sys_hufflen; /* huff-n'-puff filter stages */
-static int sys_huffptr; /* huff-n'-puff filter pointer */
-static double sys_mindly; /* huff-n'-puff filter min delay */
-
-#if defined(KERNEL_PLL)
-/* Emacs cc-mode goes nuts if we split the next line... */
-#define MOD_BITS (MOD_OFFSET | MOD_MAXERROR | MOD_ESTERROR | \
- MOD_STATUS | MOD_TIMECONST)
-#ifdef SIGSYS
-static void pll_trap P((int)); /* configuration trap */
-static struct sigaction sigsys; /* current sigaction status */
-static struct sigaction newsigsys; /* new sigaction status */
-static sigjmp_buf env; /* environment var. for pll_trap() */
-#endif /* SIGSYS */
-#endif /* KERNEL_PLL */
-
-/*
- * init_loopfilter - initialize loop filter data
- */
-void
-init_loopfilter(void)
-{
- /*
- * Initialize state variables. Initially, we expect no drift
- * file, so set the state to S_NSET.
- */
- rstclock(S_NSET, current_time, 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.
- *
- * LOCKCLOCK: The only thing this routine does is set the
- * sys_rootdispersion variable equal to the peer dispersion.
- */
-int
-local_clock(
- struct peer *peer, /* synch source peer structure */
- double fp_offset, /* clock offset (s) */
- double epsil /* jittter (square s*s) */
- )
-{
- u_long mu; /* interval since last update (s) */
- double oerror; /* previous error estimate */
- double flladj; /* FLL frequency adjustment (ppm) */
- double plladj; /* PLL frequency adjustment (ppm) */
- double clock_frequency; /* clock frequency adjustment (ppm) */
- double dtemp, etemp; /* double temps */
- int retval; /* return value */
-
- /*
- * If the loop is opened, monitor and record the offsets
- * anyway in order to determine the open-loop response.
- */
-#ifdef DEBUG
- if (debug)
- printf(
- "local_clock: assocID %d offset %.9f jitter %.9f state %d\n",
- peer->associd, fp_offset, SQRT(epsil), state);
-#endif
-#ifdef LOCKCLOCK
- sys_rootdispersion = peer->rootdispersion;
- return (0);
-
-#else /* LOCKCLOCK */
- if (!ntp_enable) {
- record_loop_stats(fp_offset, drift_comp, SQRT(epsil),
- clock_stability, sys_poll);
- return (0);
- }
-
- /*
- * If the clock is way off, panic is declared. The clock_panic
- * defaults to 1000 s; if set to zero, the panic will never
- * occur. The allow_panic defaults to FALSE, so the first panic
- * will exit. It can be set TRUE by a command line option, in
- * which case the clock will be set anyway and time marches on.
- * But, allow_panic will be set it FALSE when the update is
- * within the step range; so, subsequent panics will exit.
- */
- if (fabs(fp_offset) > clock_panic && clock_panic > 0 &&
- !allow_panic) {
- msyslog(LOG_ERR,
- "time correction of %.0f seconds exceeds sanity limit (%.0f); set clock manually to the correct UTC time.",
- fp_offset, clock_panic);
- return (-1);
- }
-
- /*
- * If simulating ntpdate, set the clock directly, rather than
- * using the discipline. The clock_max defines the step
- * threshold, above which the clock will be stepped instead of
- * slewed. The value defaults to 128 ms, but can be set to even
- * unreasonable values. If set to zero, the clock will never be
- * stepped.
- *
- * Note that if ntpdate is active, the terminal does not detach,
- * so the termination comments print directly to the console.
- */
- if (mode_ntpdate) {
- if (fabs(fp_offset) > clock_max && clock_max > 0) {
- step_systime(fp_offset);
- msyslog(LOG_NOTICE, "time reset %+.6f s",
- fp_offset);
- printf("ntpd: time set %+.6fs\n", fp_offset);
- } else {
- adj_systime(fp_offset);
- msyslog(LOG_NOTICE, "time slew %+.6f s",
- fp_offset);
- printf("ntpd: time slew %+.6fs\n", fp_offset);
- }
- record_loop_stats(fp_offset, drift_comp, SQRT(epsil),
- clock_stability, sys_poll);
- exit (0);
- }
-
- /*
- * If the clock has never been set, set it and initialize the
- * discipline parameters. We then switch to frequency mode to
- * speed the inital convergence process. If lucky, after an hour
- * the ntp.drift file is created and initialized and we don't
- * get here again.
- */
- if (state == S_NSET) {
- if (fabs(fp_offset) > clock_max && clock_max > 0) {
- step_systime(fp_offset);
- msyslog(LOG_NOTICE, "time reset %+.6f s",
- fp_offset);
- reinit_timer();
- }
- rstclock(S_FREQ, peer->epoch, 0);
- return (1);
- }
-
- /*
- * Update the jitter estimate.
- */
- oerror = sys_jitter;
- dtemp = SQUARE(sys_jitter);
- sys_jitter = SQRT(dtemp + (epsil - dtemp) / CLOCK_AVG);
-
- /*
- * The huff-n'-puff filter finds the lowest delay in the recent
- * interval. This is used to correct the offset by one-half the
- * difference between the sample delay and minimum delay. This
- * is most effective if the delays are highly assymetric and
- * clockhopping is avoided and the clock frequency wander is
- * relatively small.
- */
- if (sys_huffpuff != NULL) {
- if (peer->delay < sys_huffpuff[sys_huffptr])
- sys_huffpuff[sys_huffptr] = peer->delay;
- if (peer->delay < sys_mindly)
- sys_mindly = peer->delay;
- if (fp_offset > 0)
- dtemp = -(peer->delay - sys_mindly) / 2;
- else
- dtemp = (peer->delay - sys_mindly) / 2;
- fp_offset += dtemp;
-#ifdef DEBUG
- if (debug)
- printf(
- "local_clock: size %d mindly %.6f huffpuff %.6f\n",
- sys_hufflen, sys_mindly, dtemp);
-#endif
- }
-
- /*
- * Clock state machine transition function. This is where the
- * action is and defines how the system reacts to large phase
- * and frequency errors. There are two main regimes: when the
- * offset exceeds the step threshold and when it does not.
- * However, if the step threshold is set to zero, a step will
- * never occur. See the instruction manual for the details how
- * these actions interact with the command line options.
- */
- retval = 0;
- if (sys_poll > peer->maxpoll)
- sys_poll = peer->maxpoll;
- else if (sys_poll < peer->minpoll)
- sys_poll = peer->minpoll;
- clock_frequency = flladj = plladj = 0;
- mu = peer->epoch - last_time;
- if (fabs(fp_offset) > clock_max && clock_max > 0) {
- switch (state) {
-
- /*
- * In S_TSET state the time has been set at the last
- * valid update and the offset at that time set to zero.
- * If following that we cruise outside the capture
- * range, assume a really bad frequency error and switch
- * to S_FREQ state.
- */
- case S_TSET:
- state = S_FREQ;
- break;
-
- /*
- * In S_SYNC state we ignore outlyers. At the first
- * outlyer after the stepout threshold, switch to S_SPIK
- * state.
- */
- case S_SYNC:
- if (mu < clock_minstep)
- return (0);
- state = S_SPIK;
- return (0);
-
- /*
- * In S_FREQ state we ignore outlyers. At the first
- * outlyer after 900 s, compute the apparent phase and
- * frequency correction.
- */
- case S_FREQ:
- if (mu < clock_minstep)
- return (0);
- /* fall through to S_SPIK */
-
- /*
- * In S_SPIK state a large correction is necessary.
- * Since the outlyer may be due to a large frequency
- * error, compute the apparent frequency correction.
- */
- case S_SPIK:
- clock_frequency = (fp_offset - clock_offset) /
- mu;
- /* fall through to default */
-
- /*
- * We get here directly in S_FSET state and indirectly
- * from S_FREQ and S_SPIK states. The clock is either
- * reset or shaken, but never stirred.
- */
- default:
- step_systime(fp_offset);
- msyslog(LOG_NOTICE, "time reset %+.6f s",
- fp_offset);
- reinit_timer();
- rstclock(S_TSET, peer->epoch, 0);
- retval = 1;
- break;
- }
- } else {
- switch (state) {
-
- /*
- * In S_FSET state this is the first update. Adjust the
- * phase, but don't adjust the frequency until the next
- * update.
- */
- case S_FSET:
- rstclock(S_TSET, peer->epoch, fp_offset);
- break;
-
- /*
- * In S_FREQ state ignore updates until the stepout
- * threshold. After that, correct the phase and
- * frequency and switch to S_SYNC state.
- */
- case S_FREQ:
- if (mu < clock_minstep)
- return (0);
- clock_frequency = (fp_offset - clock_offset) /
- mu;
- rstclock(S_SYNC, peer->epoch, fp_offset);
- break;
-
- /*
- * Either the clock has just been set or the previous
- * update was a spike and ignored. Since this update is
- * not an outlyer, fold the tent and resume life.
- */
- case S_TSET:
- case S_SPIK:
- state = S_SYNC;
- /* fall through to default */
-
- /*
- * We come here in the normal case for linear phase and
- * frequency adjustments. If the difference between the
- * last offset and the current one exceeds the jitter by
- * CLOCK_SGATE and the interval since the last update is
- * less than twice the system poll interval, consider
- * the update a popcorn spike and ignore it..
- */
- default:
- allow_panic = FALSE;
- dtemp = fabs(fp_offset - last_offset);
-/*
- if (dtemp > CLOCK_SGATE * oerror && mu <
- (u_long) ULOGTOD(sys_poll + 1)) {
-#ifdef DEBUG
- if (debug)
- printf(
- "local_clock: popcorn %.6f %.6f\n",
- dtemp, oerror);
-#endif
- last_offset = fp_offset;
- return (0);
- }
-*/
-
- /*
- * The FLL and PLL frequency gain constants
- * depend on the poll interval and Allan
- * intercept. The PLL constant is calculated
- * throughout the poll interval range, but the
- * update interval is clamped so as not to
- * exceed the poll interval. The FLL gain is
- * zero below one-half the Allan intercept and
- * unity at MAXPOLL. It decreases as 1 /
- * (MAXPOLL + 1 - poll interval) in a feeble
- * effort to match the loop stiffness to the
- * Allan wobble. Particularly for the PLL, these
- * measures allow oversampling, but not
- * undersampling and insure stability even when
- * the rules of fair engagement are broken.
- */
- if (ULOGTOD(sys_poll) > allan_xpt / 2) {
- dtemp = NTP_MAXPOLL + 1 - sys_poll;
- flladj = (fp_offset - clock_offset) /
- (max(mu, allan_xpt) * dtemp);
- }
- etemp = min(mu, (u_long)ULOGTOD(sys_poll));
- dtemp = 4 * CLOCK_PLL * ULOGTOD(sys_poll);
- plladj = fp_offset * etemp / (dtemp * dtemp);
- last_time = peer->epoch;
- last_offset = clock_offset = fp_offset;
- break;
- }
- }
-
-#ifdef KERNEL_PLL
- /*
- * This code segment works when clock adjustments are made using
- * precision time kernel support and the ntp_adjtime() system
- * call. This support is available in Solaris 2.6 and later,
- * Digital Unix 4.0 and later, FreeBSD, Linux and specially
- * modified kernels for HP-UX 9 and Ultrix 4. In the case of the
- * DECstation 5000/240 and Alpha AXP, additional kernel
- * modifications provide a true microsecond clock and nanosecond
- * clock, respectively.
- */
- if (pll_control && kern_enable) {
-
- /*
- * We initialize the structure for the ntp_adjtime()
- * system call. We have to convert everything to
- * microseconds or nanoseconds first. Do not update the
- * system variables if the ext_enable flag is set. In
- * this case, the external clock driver will update the
- * variables, which will be read later by the local
- * clock driver. Afterwards, remember the time and
- * frequency offsets for jitter and stability values and
- * to update the drift file.
- */
- memset(&ntv, 0, sizeof(ntv));
- if (ext_enable) {
- ntv.modes = MOD_STATUS;
- } else {
- ntv.modes = MOD_BITS;
- if (clock_offset < 0)
- dtemp = -.5;
- else
- dtemp = .5;
- if (pll_nano) {
- ntv.offset = (int32)(clock_offset *
- 1e9 + dtemp);
- ntv.constant = sys_poll;
- } else {
- ntv.offset = (int32)(clock_offset *
- 1e6 + dtemp);
- ntv.constant = sys_poll - 4;
- }
- if (clock_frequency != 0) {
- ntv.modes |= MOD_FREQUENCY;
- ntv.freq = (int32)((clock_frequency +
- drift_comp) * 65536e6);
- }
- ntv.esterror = (u_int32)(sys_jitter * 1e6);
- ntv.maxerror = (u_int32)((sys_rootdelay / 2 +
- sys_rootdispersion) * 1e6);
- ntv.status = STA_PLL;
-
- /*
- * Set the leap bits in the status word.
- */
- if (sys_leap == LEAP_NOTINSYNC) {
- ntv.status |= STA_UNSYNC;
- } else if (calleapwhen(sys_reftime.l_ui) <
- CLOCK_DAY) {
- if (sys_leap & LEAP_ADDSECOND)
- ntv.status |= STA_INS;
- else if (sys_leap & LEAP_DELSECOND)
- ntv.status |= STA_DEL;
- }
-
- /*
- * Switch to FLL mode if the poll interval is
- * greater than MAXDPOLL, so that the kernel
- * loop behaves as the daemon loop; viz.,
- * selects the FLL when necessary, etc. For
- * legacy only.
- */
- if (sys_poll > NTP_MAXDPOLL)
- ntv.status |= STA_FLL;
-
- /*
- * If the PPS signal is up and enabled, light
- * the frequency bit. If the PPS driver is
- * working, light the phase bit as well. If not,
- * douse the lights, since somebody else may
- * have left the switch on.
- */
- if (pps_enable && pll_status & STA_PPSSIGNAL) {
- ntv.status |= STA_PPSFREQ;
- if (pps_stratum < STRATUM_UNSPEC)
- ntv.status |= STA_PPSTIME;
- } else {
- ntv.status &= ~(STA_PPSFREQ |
- STA_PPSTIME);
- }
- }
-
- /*
- * Pass the stuff to the kernel. If it squeals, turn off
- * the pigs. In any case, fetch the kernel offset and
- * frequency and pretend we did it here.
- */
- if (ntp_adjtime(&ntv) == TIME_ERROR) {
- if (ntv.status != pll_status)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "kernel time sync disabled %04x",
- ntv.status);
- ntv.status &= ~(STA_PPSFREQ | STA_PPSTIME);
- } else {
- if (ntv.status != pll_status)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "kernel time sync enabled %04x",
- ntv.status);
- }
- pll_status = ntv.status;
- if (pll_nano)
- clock_offset = ntv.offset / 1e9;
- else
- clock_offset = ntv.offset / 1e6;
- clock_frequency = ntv.freq / 65536e6 - drift_comp;
- flladj = plladj = 0;
-
- /*
- * If the kernel PPS is lit, monitor its performance.
- */
- if (ntv.status & STA_PPSTIME) {
- pps_control = current_time;
- if (pll_nano)
- sys_jitter = ntv.jitter / 1e9;
- else
- sys_jitter = ntv.jitter / 1e6;
- }
- }
-#endif /* KERNEL_PLL */
-
- /*
- * Adjust the clock frequency and calculate the stability. If
- * kernel support is available, we use the results of the kernel
- * discipline instead of the PLL/FLL discipline. In this case,
- * drift_comp is a sham and used only for updating the drift
- * file and for billboard eye candy.
- */
- dtemp = clock_frequency + flladj + plladj;
- etemp = drift_comp + dtemp;
- if (etemp > NTP_MAXFREQ)
- drift_comp = NTP_MAXFREQ;
- else if (etemp <= -NTP_MAXFREQ)
- drift_comp = -NTP_MAXFREQ;
- else
- drift_comp = etemp;
- if (fabs(etemp) > NTP_MAXFREQ)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "frequency error %.0f PPM exceeds tolerance %.0f PPM",
- etemp * 1e6, NTP_MAXFREQ * 1e6);
-
- etemp = SQUARE(clock_stability);
- dtemp = SQUARE(dtemp);
- clock_stability = SQRT(etemp + (dtemp - etemp) / CLOCK_AVG);
-
- /*
- * In SYNC state, adjust the poll interval. The trick here is to
- * compare the apparent frequency change induced by the system
- * jitter over the poll interval, or fritter, to the frequency
- * stability. If the fritter is greater than the stability,
- * phase noise predominates and the averaging interval is
- * increased; otherwise, it is decreased. A bit of hysteresis
- * helps calm the dance. Works best using burst mode.
- */
- if (state == S_SYNC) {
- if (sys_jitter > ULOGTOD(sys_poll) * clock_stability &&
- fabs(clock_offset) < CLOCK_PGATE * sys_jitter) {
- tc_counter += sys_poll;
- if (tc_counter > CLOCK_LIMIT) {
- tc_counter = CLOCK_LIMIT;
- if (sys_poll < peer->maxpoll) {
- tc_counter = 0;
- sys_poll++;
- }
- }
- } else {
- tc_counter -= sys_poll << 1;
- if (tc_counter < -CLOCK_LIMIT) {
- tc_counter = -CLOCK_LIMIT;
- if (sys_poll > peer->minpoll) {
- tc_counter = 0;
- sys_poll--;
- }
- }
- }
- }
-
- /*
- * Update the system time variables.
- */
- dtemp = peer->disp + (current_time - peer->epoch) * clock_phi +
- sys_jitter + fabs(last_offset);
- if (!(peer->flags & FLAG_REFCLOCK) && dtemp < MINDISPERSE)
- dtemp = MINDISPERSE;
- sys_rootdispersion = peer->rootdispersion + dtemp;
- record_loop_stats(last_offset, drift_comp, sys_jitter,
- clock_stability, sys_poll);
-
-#ifdef DEBUG
- if (debug)
- printf(
- "local_clock: mu %lu rootjit %.6f stab %.3f poll %d count %d\n",
- mu, dtemp, clock_stability * 1e6, sys_poll,
- tc_counter);
-#endif /* DEBUG */
- return (retval);
-#endif /* LOCKCLOCK */
-}
-
-
-/*
- * adj_host_clock - Called once every second to update the local clock.
- *
- * LOCKCLOCK: The only thing this routine does is increment the
- * sys_rootdispersion variable.
- */
-void
-adj_host_clock(
- void
- )
-{
- double adjustment;
-
- /*
- * Update the dispersion since the last update. In contrast to
- * NTPv3, NTPv4 does not declare unsynchronized after one day,
- * since the dispersion check serves this function. Also,
- * since the poll interval can exceed one day, the old test
- * would be counterproductive. Note we do this even with
- * external clocks, since the clock driver will recompute the
- * maximum error and the local clock driver will pick it up and
- * pass to the common refclock routines. Very elegant.
- */
- sys_rootdispersion += clock_phi;
-
-#ifndef LOCKCLOCK
- /*
- * Declare PPS kernel unsync if the pps signal has not been
- * heard for a few minutes.
- */
- if (pps_control && current_time - pps_control > PPS_MAXAGE) {
- if (pps_control)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE, "pps sync disabled");
- pps_control = 0;
- }
-
- /*
- * If NTP is disabled or ntpdate mode enabled or the kernel
- * discipline enabled, we have no business going further.
- */
- if (!ntp_enable || mode_ntpdate || (pll_control && kern_enable))
- return;
-
- /*
- * Intricate wrinkle for legacy only. If the local clock driver
- * is in use and selected for synchronization, somebody else may
- * tinker the adjtime() syscall. If this is the case, the driver
- * is marked prefer and we have to avoid calling adjtime(),
- * since that may truncate the other guy's requests.
- */
- if (sys_peer != 0) {
- if (sys_peer->refclktype == REFCLK_LOCALCLOCK &&
- sys_peer->flags & FLAG_PREFER)
- return;
- }
-
- /*
- * Implement the phase and frequency adjustments. Note the
- * black art formerly practiced here has been whitewashed.
- */
- adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
- clock_offset -= adjustment;
- adj_systime(adjustment + drift_comp);
-#endif /* LOCKCLOCK */
-}
-
-
-/*
- * Clock state machine. Enter new state and set state variables.
- */
-static void
-rstclock(
- int trans, /* new state */
- u_long epoch, /* last time */
- double offset /* last offset */
- )
-{
- tc_counter = 0;
- sys_poll = NTP_MINPOLL;
- state = trans;
- last_time = epoch;
- last_offset = clock_offset = offset;
-#ifdef DEBUG
- if (debug)
- printf("local_clock: at %lu state %d\n", last_time,
- trans);
-#endif
-}
-
-
-/*
- * huff-n'-puff filter
- */
-void
-huffpuff()
-{
- int i;
-
- if (sys_huffpuff == NULL)
- return;
- sys_huffptr = (sys_huffptr + 1) % sys_hufflen;
- sys_huffpuff[sys_huffptr] = 1e9;
- sys_mindly = 1e9;
- for (i = 0; i < sys_hufflen; i++) {
- if (sys_huffpuff[i] < sys_mindly)
- sys_mindly = sys_huffpuff[i];
- }
-}
-
-
-/*
- * loop_config - configure the loop filter
- *
- * LOCKCLOCK: The LOOP_DRIFTINIT and LOOP_DRIFTCOMP cases are no-ops.
- */
-void
-loop_config(
- int item,
- double freq
- )
-{
- int i;
-
- switch (item) {
-
- case LOOP_DRIFTINIT:
-
-#ifndef LOCKCLOCK
-#ifdef KERNEL_PLL
- /*
- * Assume the kernel supports the ntp_adjtime() syscall.
- * If that syscall works, initialize the kernel
- * variables. Otherwise, continue leaving no harm
- * behind. While at it, ask to set nanosecond mode. If
- * the kernel agrees, rejoice; othewise, it does only
- * microseconds.
- *
- * Call out the safety patrol. If ntpdate mode or if the
- * step threshold has been changed by the -x option or
- * tinker command, kernel discipline is unsafe, so don't
- * do any of this stuff.
- */
- if (mode_ntpdate || clock_max != CLOCK_MAX)
- break;
-
- pll_control = 1;
- memset(&ntv, 0, sizeof(ntv));
-#ifdef STA_NANO
- ntv.modes = MOD_BITS | MOD_NANO;
-#else
- ntv.modes = MOD_BITS;
-#endif /* STA_NANO */
- ntv.maxerror = MAXDISPERSE;
- ntv.esterror = MAXDISPERSE;
- ntv.status = STA_UNSYNC;
-#ifdef SIGSYS
- /*
- * Use sigsetjmp() to save state and then call
- * ntp_adjtime(); if it fails, then siglongjmp() is used
- * to return control
- */
- newsigsys.sa_handler = pll_trap;
- newsigsys.sa_flags = 0;
- if (sigaction(SIGSYS, &newsigsys, &sigsys)) {
- msyslog(LOG_ERR,
- "sigaction() fails to save SIGSYS trap: %m");
- pll_control = 0;
- }
- if (sigsetjmp(env, 1) == 0)
- ntp_adjtime(&ntv);
- if ((sigaction(SIGSYS, &sigsys,
- (struct sigaction *)NULL))) {
- msyslog(LOG_ERR,
- "sigaction() fails to restore SIGSYS trap: %m");
- pll_control = 0;
- }
-#else /* SIGSYS */
- ntp_adjtime(&ntv);
-#endif /* SIGSYS */
- pll_status = ntv.status;
- if (pll_control) {
-#ifdef STA_NANO
- if (pll_status & STA_NANO)
- pll_nano = 1;
- if (pll_status & STA_CLK)
- ext_enable = 1;
-#endif /* STA_NANO */
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_INFO,
- "kernel time sync status %04x",
- pll_status);
- }
-#endif /* KERNEL_PLL */
-#endif /* LOCKCLOCK */
- break;
-
- case LOOP_DRIFTCOMP:
-
-#ifndef LOCKCLOCK
- /*
- * If the frequency value is reasonable, set the initial
- * frequency to the given value and the state to S_FSET.
- * Otherwise, the drift file may be missing or broken,
- * so set the frequency to zero. This erases past
- * history should somebody break something.
- */
- if (freq <= NTP_MAXFREQ && freq >= -NTP_MAXFREQ) {
- drift_comp = freq;
- rstclock(S_FSET, current_time, 0);
- } else {
- drift_comp = 0;
- }
-
-#ifdef KERNEL_PLL
- /*
- * Sanity check. If the kernel is enabled, load the
- * frequency and light up the loop. If not, set the
- * kernel frequency to zero and leave the loop dark. In
- * either case set the time to zero to cancel any
- * previous nonsense.
- */
- if (pll_control) {
- memset((char *)&ntv, 0, sizeof(ntv));
- ntv.modes = MOD_OFFSET | MOD_FREQUENCY;
- if (kern_enable) {
- ntv.modes |= MOD_STATUS;
- ntv.status = STA_PLL;
- ntv.freq = (int32)(drift_comp *
- 65536e6);
- }
- (void)ntp_adjtime(&ntv);
- }
-#endif /* KERNEL_PLL */
-#endif /* LOCKCLOCK */
- break;
-
- /*
- * Special tinker variables for Ulrich Windl. Very dangerous.
- */
- case LOOP_MAX: /* step threshold */
- clock_max = freq;
- break;
-
- case LOOP_PANIC: /* panic threshold */
- clock_panic = freq;
- break;
-
- case LOOP_PHI: /* dispersion rate */
- clock_phi = freq;
- break;
-
- case LOOP_MINSTEP: /* watchdog bark */
- clock_minstep = freq;
- break;
-
- case LOOP_ALLAN: /* Allan intercept */
- allan_xpt = freq;
- break;
-
- case LOOP_HUFFPUFF: /* huff-n'-puff filter length */
- if (freq < HUFFPUFF)
- freq = HUFFPUFF;
- sys_hufflen = (int)(freq / HUFFPUFF);
- sys_huffpuff = (double *)emalloc(sizeof(double) *
- sys_hufflen);
- for (i = 0; i < sys_hufflen; i++)
- sys_huffpuff[i] = 1e9;
- sys_mindly = 1e9;
- break;
-
- case LOOP_FREQ: /* initial frequency */
- drift_comp = freq / 1e6;
- rstclock(S_FSET, current_time, 0);
- break;
- }
-}
-
-
-#if defined(KERNEL_PLL) && defined(SIGSYS)
-/*
- * _trap - trap processor for undefined syscalls
- *
- * This nugget is called by the kernel when the SYS_ntp_adjtime()
- * syscall bombs because the silly thing has not been implemented in
- * the kernel. In this case the phase-lock loop is emulated by
- * the stock adjtime() syscall and a lot of indelicate abuse.
- */
-static RETSIGTYPE
-pll_trap(
- int arg
- )
-{
- pll_control = 0;
- siglongjmp(env, 1);
-}
-#endif /* KERNEL_PLL && SIGSYS */
diff --git a/contrib/ntp/ntpd/ntp_monitor.c b/contrib/ntp/ntpd/ntp_monitor.c
deleted file mode 100644
index 6b288fc..0000000
--- a/contrib/ntp/ntpd/ntp_monitor.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * ntp_monitor - monitor ntpd statistics
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_if.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <signal.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-
-/*
- * I'm still not sure I like what I've done here. It certainly consumes
- * memory like it is going out of style, and also may not be as low
- * overhead as I'd imagined.
- *
- * Anyway, we record statistics based on source address, mode and
- * version (for now, anyway. Check the code). The receive procedure
- * calls us with the incoming rbufp before it does anything else.
- *
- * Each entry is doubly linked into two lists, a hash table and a
- * most-recently-used list. When a packet arrives it is looked up in
- * the hash table. If found, the statistics are updated and the entry
- * relinked at the head of the MRU list. If not found, a new entry is
- * allocated, initialized and linked into both the hash table and at the
- * head of the MRU list.
- *
- * Memory is usually allocated by grabbing a big chunk of new memory and
- * cutting it up into littler pieces. The exception to this when we 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
- */
-/*
- * Limits on the number of structures allocated. This limit is picked
- * 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
- */
-#ifndef MAXMONMEM
-#define MAXMONMEM 600 /* we allocate up to 600 structures */
-#endif
-#ifndef MONMEMINC
-#define MONMEMINC 40 /* allocate them 40 at a time */
-#endif
-
-/*
- * Hashing stuff
- */
-#define MON_HASH_SIZE 128
-#define MON_HASH_MASK (MON_HASH_SIZE-1)
-#define MON_HASH(addr) sock_hash(addr)
-
-/*
- * 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[MON_HASH_SIZE]; /* list ptrs */
-struct mon_data mon_mru_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; /* free list or null if none */
-static int mon_total_mem; /* total structures allocated */
-static int mon_mem_increments; /* times called malloc() */
-
-/*
- * Initialization state. We may be monitoring, we may not. If
- * we aren't, we may not even have allocated any memory yet.
- */
-int mon_enabled; /* enable switch */
-u_long mon_age = 3000; /* preemption limit */
-static int mon_have_memory;
-static void mon_getmoremem P((void));
-static void remove_from_hash P((struct mon_data *));
-
-/*
- * init_mon - initialize monitoring global data
- */
-void
-init_mon(void)
-{
- /*
- * Don't do much of anything here. We don't allocate memory
- * until someone explicitly starts us.
- */
- mon_enabled = MON_OFF;
- mon_have_memory = 0;
-
- mon_total_mem = 0;
- mon_mem_increments = 0;
- mon_free = NULL;
- memset(&mon_hash[0], 0, sizeof mon_hash);
- memset(&mon_mru_list, 0, sizeof mon_mru_list);
-}
-
-
-/*
- * mon_start - start up the monitoring software
- */
-void
-mon_start(
- int mode
- )
-{
-
- if (mon_enabled != MON_OFF) {
- mon_enabled |= mode;
- return;
- }
- if (mode == MON_OFF)
- return;
-
- if (!mon_have_memory) {
- mon_total_mem = 0;
- mon_mem_increments = 0;
- mon_free = NULL;
- mon_getmoremem();
- mon_have_memory = 1;
- }
-
- mon_mru_list.mru_next = &mon_mru_list;
- mon_mru_list.mru_prev = &mon_mru_list;
- mon_enabled = mode;
-}
-
-
-/*
- * mon_stop - stop the monitoring software
- */
-void
-mon_stop(
- int mode
- )
-{
- register struct mon_data *md, *md_next;
- register int i;
-
- if (mon_enabled == MON_OFF)
- return;
- if ((mon_enabled & mode) == 0 || mode == MON_OFF)
- return;
-
- mon_enabled &= ~mode;
- if (mon_enabled != MON_OFF)
- return;
-
- /*
- * Put everything back on the free list
- */
- 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;
- }
- }
-
- mon_mru_list.mru_next = &mon_mru_list;
- mon_mru_list.mru_prev = &mon_mru_list;
-}
-
-
-/*
- * ntp_monitor - record stats about this packet
- */
-void
-ntp_monitor(
- struct recvbuf *rbufp
- )
-{
- register struct pkt *pkt;
- register struct mon_data *md;
- struct sockaddr_storage addr;
- register int hash;
- register int mode;
-
- if (mon_enabled == MON_OFF)
- return;
-
- pkt = &rbufp->recv_pkt;
- memset(&addr, 0, sizeof(addr));
- memcpy(&addr, &(rbufp->recv_srcadr), sizeof(addr));
- hash = MON_HASH(&addr);
- mode = PKT_MODE(pkt->li_vn_mode);
- md = mon_hash[hash];
- while (md != NULL) {
-
- /*
- * Match address only to conserve MRU size.
- */
- if (SOCKCMP(&md->rmtadr, &addr)) {
- md->drop_count = current_time - md->lasttime;
- md->lasttime = current_time;
- md->count++;
- md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
- md->mode = (u_char) mode;
- md->version = PKT_VERSION(pkt->li_vn_mode);
-
- /*
- * Shuffle to the head of the MRU list.
- */
- md->mru_next->mru_prev = md->mru_prev;
- md->mru_prev->mru_next = md->mru_next;
- md->mru_next = mon_mru_list.mru_next;
- md->mru_prev = &mon_mru_list;
- mon_mru_list.mru_next->mru_prev = md;
- mon_mru_list.mru_next = md;
- return;
- }
- md = md->hash_next;
- }
-
- /*
- * If we got here, this is the first we've heard of this
- * guy. Get him some memory, either from the free list
- * or from the tail of the MRU list.
- */
- if (mon_free == NULL && mon_total_mem >= MAXMONMEM) {
-
- /*
- * Preempt from the MRU list if old enough.
- */
- md = mon_mru_list.mru_prev;
- if (((u_long)RANDOM & 0xffffffff) / FRAC >
- (double)(current_time - md->lasttime) / mon_age)
- return;
-
- md->mru_prev->mru_next = &mon_mru_list;
- mon_mru_list.mru_prev = md->mru_prev;
- remove_from_hash(md);
- } else {
- if (mon_free == NULL)
- mon_getmoremem();
- md = mon_free;
- mon_free = md->hash_next;
- }
-
- /*
- * Got one, initialize it
- */
- md->avg_interval = 0;
- md->lasttime = current_time;
- md->count = 1;
- md->drop_count = 0;
- memset(&md->rmtadr, 0, sizeof(md->rmtadr));
- memcpy(&md->rmtadr, &addr, sizeof(addr));
- 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 = (u_char)(((rbufp->dstadr->flags & INT_MULTICAST) &&
- rbufp->fd == md->interface->fd) ? MDF_MCAST: rbufp->fd ==
- md->interface->bfd ? MDF_BCAST : MDF_UCAST);
-
- /*
- * Drop him into front of the hash table. Also put him on top of
- * the MRU list.
- */
- md->hash_next = mon_hash[hash];
- mon_hash[hash] = md;
- md->mru_next = mon_mru_list.mru_next;
- md->mru_prev = &mon_mru_list;
- mon_mru_list.mru_next->mru_prev = md;
- mon_mru_list.mru_next = md;
-}
-
-
-/*
- * mon_getmoremem - get more memory and put it on the free list
- */
-static void
-mon_getmoremem(void)
-{
- register struct mon_data *md;
- register int i;
- struct mon_data *freedata; /* 'old' free list (null) */
-
- md = (struct mon_data *)emalloc(MONMEMINC *
- sizeof(struct mon_data));
- freedata = mon_free;
- mon_free = md;
- for (i = 0; i < (MONMEMINC-1); i++) {
- md->hash_next = (md + 1);
- md++;
- }
-
- /*
- * md now points at the last. Link in the rest of the chain.
- */
- md->hash_next = freedata;
- mon_total_mem += MONMEMINC;
- mon_mem_increments++;
-}
-
-static void
-remove_from_hash(
- 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/contrib/ntp/ntpd/ntp_peer.c b/contrib/ntp/ntpd/ntp_peer.c
deleted file mode 100644
index cf8a600..0000000
--- a/contrib/ntp/ntpd/ntp_peer.c
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * ntp_peer.c - management of data maintained for peer associations
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "ntpd.h"
-#include "ntp_stdlib.h"
-#ifdef OPENSSL
-#include "openssl/rand.h"
-#endif /* OPENSSL */
-
-/*
- * Table of valid association combinations
- * ---------------------------------------
- *
- * packet->mode
- * peer->mode | UNSPEC ACTIVE PASSIVE CLIENT SERVER BCAST
- * ---------- | ---------------------------------------------
- * NO_PEER | e 1 e 1 1 1
- * ACTIVE | e 1 1 0 0 0
- * PASSIVE | e 1 e 0 0 0
- * CLIENT | e 0 0 0 1 1
- * SERVER | e 0 0 0 0 0
- * BCAST | e 0 0 0 0 0
- * CONTROL | e 0 0 0 0 0
- * PRIVATE | e 0 0 0 0 0
- * BCLIENT | e 0 0 0 e 1
- *
- * One point to note here: a packet in BCAST mode can potentially match
- * a peer in CLIENT mode, but we that is a special case and we check for
- * that early in the decision process. This avoids having to keep track
- * of what kind of associations are possible etc... We actually
- * circumvent that problem by requiring that the first b(m)roadcast
- * received after the change back to BCLIENT mode sets the clock.
- */
-
-int AM[AM_MODES][AM_MODES] = {
-/* { UNSPEC, ACTIVE, PASSIVE, CLIENT, SERVER, BCAST } */
-
-/*NONE*/{ AM_ERR, AM_NEWPASS, AM_ERR, AM_FXMIT, AM_MANYCAST, AM_NEWBCL},
-
-/*A*/ { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*P*/ { AM_ERR, AM_PROCPKT, AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*C*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT, AM_POSSBCL},
-
-/*S*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*CNTL*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*PRIV*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_ERR, AM_PROCPKT},
-};
-
-#define MATCH_ASSOC(x,y) AM[(x)][(y)]
-
-/*
- * These routines manage the allocation of memory to peer structures
- * and the maintenance of the peer hash table. The two main entry
- * points are findpeer(), which looks for matching peer sturctures in
- * the peer list, newpeer(), which allocates a new peer structure and
- * adds it to the list, and unpeer(), which demobilizes the association
- * and deallocates the structure.
- */
-/*
- * Peer hash tables
- */
-struct peer *peer_hash[HASH_SIZE]; /* peer hash table */
-int peer_hash_count[HASH_SIZE]; /* peers in each bucket */
-struct peer *assoc_hash[HASH_SIZE]; /* association ID hash table */
-int assoc_hash_count[HASH_SIZE]; /* peers in each bucket */
-static struct peer *peer_free; /* peer structures free list */
-int peer_free_count; /* count of free structures */
-
-/*
- * Association ID. We initialize this value randomly, then assign a new
- * value every time the peer structure is incremented.
- */
-static associd_t current_association_ID; /* association ID */
-
-/*
- * Memory allocation watermarks.
- */
-#define INIT_PEER_ALLOC 15 /* initialize for 15 peers */
-#define INC_PEER_ALLOC 5 /* when run out, add 5 more */
-
-/*
- * Miscellaneous statistic counters which may be queried.
- */
-u_long peer_timereset; /* time stat counters zeroed */
-u_long findpeer_calls; /* calls to findpeer */
-u_long assocpeer_calls; /* calls to findpeerbyassoc */
-u_long peer_allocations; /* allocations from free list */
-u_long peer_demobilizations; /* structs freed to free list */
-int total_peer_structs; /* peer structs */
-int peer_associations; /* active associations */
-static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
-
-static void getmorepeermem P((void));
-
-/*
- * init_peer - initialize peer data structures and counters
- *
- * N.B. We use the random number routine in here. It had better be
- * initialized prior to getting here.
- */
-void
-init_peer(void)
-{
- register int i;
-
- /*
- * Clear hash table and counters.
- */
- for (i = 0; i < HASH_SIZE; i++) {
- peer_hash[i] = 0;
- peer_hash_count[i] = 0;
- assoc_hash[i] = 0;
- assoc_hash_count[i] = 0;
- }
-
- /*
- * Clear stat counters
- */
- findpeer_calls = peer_allocations = 0;
- assocpeer_calls = peer_demobilizations = 0;
-
- /*
- * Initialize peer memory.
- */
- peer_free = 0;
- for (i = 0; i < INIT_PEER_ALLOC; i++) {
- init_peer_alloc[i].next = peer_free;
- peer_free = &init_peer_alloc[i];
- }
- total_peer_structs = INIT_PEER_ALLOC;
- peer_free_count = INIT_PEER_ALLOC;
-
- /*
- * Initialize our first association ID
- */
- current_association_ID = (associd_t)ranp2(16);
- if (current_association_ID == 0)
- current_association_ID = 1;
-}
-
-
-/*
- * getmorepeermem - add more peer structures to the free list
- */
-static void
-getmorepeermem(void)
-{
- register int i;
- register struct peer *peer;
-
- peer = (struct peer *)emalloc(INC_PEER_ALLOC *
- sizeof(struct peer));
- for (i = 0; i < INC_PEER_ALLOC; i++) {
- peer->next = peer_free;
- peer_free = peer;
- peer++;
- }
-
- total_peer_structs += INC_PEER_ALLOC;
- peer_free_count += INC_PEER_ALLOC;
-}
-
-
-/*
- * findexistingpeer - return a pointer to a peer in the hash table
- */
-struct peer *
-findexistingpeer(
- struct sockaddr_storage *addr,
- struct peer *start_peer,
- int mode
- )
-{
- register struct peer *peer;
-
- /*
- * start_peer is included so we can locate instances of the
- * same peer through different interfaces in the hash table.
- */
- if (start_peer == 0)
- peer = peer_hash[HASH_ADDR(addr)];
- else
- peer = start_peer->next;
-
- while (peer != 0) {
- if (SOCKCMP(addr, &peer->srcadr)
- && NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {
- if (mode == -1)
- return (peer);
- else if (peer->hmode == mode)
- break;
- }
- peer = peer->next;
- }
- return (peer);
-}
-
-
-/*
- * findpeer - find and return a peer in the hash table.
- */
-struct peer *
-findpeer(
- struct sockaddr_storage *srcadr,
- struct interface *dstadr,
- int fd,
- int pkt_mode,
- int *action
- )
-{
- register struct peer *peer;
- int hash;
-
- findpeer_calls++;
- hash = HASH_ADDR(srcadr);
- for (peer = peer_hash[hash]; peer != NULL; peer = peer->next) {
- if (SOCKCMP(srcadr, &peer->srcadr)
- && NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
-
- /*
- * if the association matching rules determine
- * that this is not a valid combination, then
- * look for the next valid peer association.
- */
- *action = MATCH_ASSOC(peer->hmode, pkt_mode);
-
- /*
- * Sigh! Check if BCLIENT peer in client
- * server mode, else return error.
- */
- if ((*action == AM_POSSBCL) && !(peer->flags &
- FLAG_MCAST))
- *action = AM_ERR;
-
- /*
- * if an error was returned, exit back right
- * here.
- */
- if (*action == AM_ERR)
- return ((struct peer *)0);
-
- /*
- * if a match is found, we stop our search.
- */
- if (*action != AM_NOMATCH)
- break;
- }
- }
-
- /*
- * If no matching association is found
- */
- if (peer == 0) {
- *action = MATCH_ASSOC(NO_PEER, pkt_mode);
- return ((struct peer *)0);
- }
- peer->dstadr = dstadr;
- return (peer);
-}
-
-/*
- * findpeerbyassocid - find and return a peer using his association ID
- */
-struct peer *
-findpeerbyassoc(
- u_int assoc
- )
-{
- register struct peer *peer;
- int hash;
-
- assocpeer_calls++;
-
- hash = assoc & HASH_MASK;
- for (peer = assoc_hash[hash]; peer != 0; peer =
- peer->ass_next) {
- if (assoc == peer->associd)
- return (peer);
- }
- return (NULL);
-}
-
-
-/*
- * clear_all - flush all time values for all associations
- */
-void
-clear_all(void)
-{
- struct peer *peer, *next_peer;
- int n;
-
- /*
- * This routine is called when the clock is stepped, and so all
- * previously saved time values are untrusted.
- */
- for (n = 0; n < HASH_SIZE; n++) {
- for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
- next_peer = peer->next;
- if (peer->flags & FLAG_CONFIG) {
- if (!(peer->cast_flags & (MDF_ACAST |
- MDF_MCAST | MDF_BCAST)))
- peer_clear(peer, "STEP");
- } else {
- unpeer(peer);
- }
- }
- }
-#ifdef DEBUG
- if (debug)
- printf("clear_all: at %lu\n", current_time);
-#endif
-}
-
-
-/*
- * unpeer - remove peer structure from hash table and free structure
- */
-void
-unpeer(
- struct peer *peer_to_remove
- )
-{
- int hash;
-#ifdef OPENSSL
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
-
- if (peer_to_remove->flags & FLAG_SKEY) {
- sprintf(statstr, "unpeer %d flash %x reach %03o flags %04x",
- peer_to_remove->associd, peer_to_remove->flash,
- peer_to_remove->reach, peer_to_remove->flags);
- record_crypto_stats(&peer_to_remove->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("peer: %s\n", statstr);
-#endif
- }
-#endif /* OPENSSL */
-#ifdef DEBUG
- if (debug)
- printf("demobilize %u %d\n", peer_to_remove->associd,
- peer_associations);
-#endif
- peer_clear(peer_to_remove, "NULL");
- hash = HASH_ADDR(&peer_to_remove->srcadr);
- peer_hash_count[hash]--;
- peer_demobilizations++;
-#ifdef REFCLOCK
- /*
- * If this peer is actually a clock, shut it down first
- */
- if (peer_to_remove->flags & FLAG_REFCLOCK)
- refclock_unpeer(peer_to_remove);
-#endif
- peer_to_remove->action = 0; /* disable timeout actions */
- if (peer_hash[hash] == peer_to_remove)
- peer_hash[hash] = peer_to_remove->next;
- else {
- register struct peer *peer;
-
- peer = peer_hash[hash];
- while (peer != 0 && peer->next != peer_to_remove)
- peer = peer->next;
-
- if (peer == 0) {
- peer_hash_count[hash]++;
- msyslog(LOG_ERR, "peer struct for %s not in table!",
- stoa(&peer->srcadr));
- } else {
- peer->next = peer_to_remove->next;
- }
- }
-
- /*
- * Remove him from the association hash as well.
- */
- hash = peer_to_remove->associd & HASH_MASK;
- assoc_hash_count[hash]--;
- if (assoc_hash[hash] == peer_to_remove)
- assoc_hash[hash] = peer_to_remove->ass_next;
- else {
- register struct peer *peer;
-
- peer = assoc_hash[hash];
- while (peer != 0 && peer->ass_next != peer_to_remove)
- peer = peer->ass_next;
-
- if (peer == 0) {
- assoc_hash_count[hash]++;
- msyslog(LOG_ERR,
- "peer struct for %s not in association table!",
- stoa(&peer->srcadr));
- } else {
- peer->ass_next = peer_to_remove->ass_next;
- }
- }
- peer_to_remove->next = peer_free;
- peer_free = peer_to_remove;
- peer_free_count++;
- peer_associations--;
-}
-
-
-/*
- * peer_config - configure a new association
- */
-struct peer *
-peer_config(
- struct sockaddr_storage *srcadr,
- struct interface *dstadr,
- int hmode,
- int version,
- int minpoll,
- int maxpoll,
- u_int flags,
- int ttl,
- keyid_t key,
- u_char *keystr
- )
-{
- register struct peer *peer;
- u_char cast_flags;
-
- /*
- * First search from the beginning for an association with given
- * remote address and mode. If an interface is given, search
- * from there to find the association which matches that
- * destination.
- */
- peer = findexistingpeer(srcadr, (struct peer *)0, hmode);
- if (dstadr != 0) {
- while (peer != 0) {
- if (peer->dstadr == dstadr)
- break;
- peer = findexistingpeer(srcadr, peer, hmode);
- }
- }
-
- /*
- * We do a dirty little jig to figure the cast flags. This is
- * probably not the best place to do this, at least until the
- * configure code is rebuilt. Note only one flag can be set.
- */
- switch (hmode) {
-
- case MODE_BROADCAST:
- if(srcadr->ss_family == AF_INET) {
- if (IN_CLASSD(ntohl(((struct sockaddr_in*)srcadr)->sin_addr.s_addr)))
- cast_flags = MDF_MCAST;
- else
- cast_flags = MDF_BCAST;
- break;
- }
- else {
- if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)srcadr)->sin6_addr))
- cast_flags = MDF_MCAST;
- else
- cast_flags = MDF_BCAST;
- break;
- }
-
- case MODE_CLIENT:
- if(srcadr->ss_family == AF_INET) {
- if (IN_CLASSD(ntohl(((struct sockaddr_in*)srcadr)->sin_addr.s_addr)))
- cast_flags = MDF_ACAST;
- else
- cast_flags = MDF_UCAST;
- break;
- }
- else {
- if (IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)srcadr)->sin6_addr))
- cast_flags = MDF_ACAST;
- else
- cast_flags = MDF_UCAST;
- break;
- }
-
- default:
- cast_flags = MDF_UCAST;
- }
-
- /*
- * If the peer is already configured, some dope has a duplicate
- * configureation entry or another dope is wiggling from afar.
- */
- if (peer != 0) {
- peer->hmode = (u_char)hmode;
- peer->version = (u_char) version;
- peer->minpoll = (u_char) minpoll;
- peer->maxpoll = (u_char) maxpoll;
- peer->flags = flags | FLAG_CONFIG |
- (peer->flags & FLAG_REFCLOCK);
- peer->cast_flags = cast_flags;
- peer->ttl = (u_char) ttl;
- peer->keyid = key;
- peer->precision = sys_precision;
- peer_clear(peer, "RMOT");
- return (peer);
- }
-
- /*
- * Here no match has been found, so presumably this is a new
- * persistent association. Mobilize the thing and initialize its
- * variables. If emulating ntpdate, force iburst.
- */
- if (mode_ntpdate)
- flags |= FLAG_IBURST;
- peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
- flags | FLAG_CONFIG, cast_flags, ttl, key);
- return (peer);
-}
-
-
-/*
- * newpeer - initialize a new peer association
- */
-struct peer *
-newpeer(
- struct sockaddr_storage *srcadr,
- struct interface *dstadr,
- int hmode,
- int version,
- int minpoll,
- int maxpoll,
- u_int flags,
- u_char cast_flags,
- int ttl,
- keyid_t key
- )
-{
- register struct peer *peer;
- register int i;
-#ifdef OPENSSL
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
-#endif /* OPENSSL */
-
- /*
- * Allocate a new peer structure. Some dirt here, since some of
- * the initialization requires knowlege of our system state.
- */
- if (peer_free_count == 0)
- getmorepeermem();
- peer = peer_free;
- peer_free = peer->next;
- peer_free_count--;
- peer_associations++;
- memset((char *)peer, 0, sizeof(struct peer));
-
- /*
- * Assign an association ID and increment the system variable.
- */
- peer->associd = current_association_ID;
- if (++current_association_ID == 0)
- ++current_association_ID;
-
- /*
- * Initialize the peer structure and dance the interface jig.
- * Reference clocks step the loopback waltz, the others
- * squaredance around the interface list looking for a buddy. If
- * the dance peters out, there is always the wildcard interface.
- * This might happen in some systems and would preclude proper
- * operation with public key cryptography.
- */
- if (ISREFCLOCKADR(srcadr))
- peer->dstadr = loopback_interface;
- else if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
- peer->dstadr = findbcastinter(srcadr);
- /*
- * If it was a multicast packet, findbcastinter() may not
- * find it, so try a little harder.
- */
- if (peer->dstadr == ANY_INTERFACE_CHOOSE(srcadr))
- peer->dstadr = findinterface(srcadr);
- } else if (dstadr != NULL && dstadr != ANY_INTERFACE_CHOOSE(srcadr))
- peer->dstadr = dstadr;
- else
- peer->dstadr = findinterface(srcadr);
- peer->srcadr = *srcadr;
- peer->hmode = (u_char)hmode;
- peer->version = (u_char)version;
- peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
- peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
- peer->flags = flags;
- if (key != 0)
- peer->flags |= FLAG_AUTHENABLE;
- if (key > NTP_MAXKEY)
- peer->flags |= FLAG_SKEY;
- peer->cast_flags = cast_flags;
- peer->ttl = (u_char)ttl;
- peer->keyid = key;
- peer->precision = sys_precision;
- if (cast_flags & MDF_ACAST)
- peer_clear(peer, "ACST");
- else if (cast_flags & MDF_MCAST)
- peer_clear(peer, "MCST");
- else if (cast_flags & MDF_BCAST)
- peer_clear(peer, "BCST");
- else
- peer_clear(peer, "INIT");
- if (mode_ntpdate)
- peer_ntpdate++;
-
- /*
- * Note time on statistics timers.
- */
- peer->timereset = current_time;
- peer->timereachable = current_time;
- peer->timereceived = current_time;
-#ifdef REFCLOCK
- if (ISREFCLOCKADR(&peer->srcadr)) {
- /*
- * We let the reference clock support do clock
- * dependent initialization. This includes setting
- * the peer timer, since the clock may have requirements
- * for this.
- */
- if (!refclock_newpeer(peer)) {
- /*
- * Dump it, something screwed up
- */
- peer->next = peer_free;
- peer_free = peer;
- peer_free_count++;
- return (NULL);
- }
- }
-#endif
-
- /*
- * Put the new peer in the hash tables.
- */
- i = HASH_ADDR(&peer->srcadr);
- peer->next = peer_hash[i];
- peer_hash[i] = peer;
- peer_hash_count[i]++;
- i = peer->associd & HASH_MASK;
- peer->ass_next = assoc_hash[i];
- assoc_hash[i] = peer;
- assoc_hash_count[i]++;
-#ifdef OPENSSL
- if (peer->flags & FLAG_SKEY) {
- sprintf(statstr, "newpeer %d", peer->associd);
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("peer: %s\n", statstr);
-#endif
- }
-#endif /* OPENSSL */
-#ifdef DEBUG
- if (debug)
- printf(
- "newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n",
- peer->dstadr == NULL ? "null" : stoa(&peer->dstadr->sin),
- stoa(&peer->srcadr),
- peer->hmode, peer->version, peer->minpoll,
- peer->maxpoll, peer->flags, peer->cast_flags,
- peer->ttl, peer->keyid);
-#endif
- return (peer);
-}
-
-
-/*
- * peer_unconfig - remove the configuration bit from a peer
- */
-int
-peer_unconfig(
- struct sockaddr_storage *srcadr,
- struct interface *dstadr,
- int mode
- )
-{
- register struct peer *peer;
- int num_found;
-
- num_found = 0;
- peer = findexistingpeer(srcadr, (struct peer *)0, mode);
- while (peer != 0) {
- if (peer->flags & FLAG_CONFIG
- && (dstadr == 0 || peer->dstadr == dstadr)) {
- num_found++;
-
- /*
- * Tricky stuff here. If the peer is polling us
- * in active mode, turn off the configuration
- * bit and make the mode passive. This allows us
- * to avoid dumping a lot of history for peers
- * we might choose to keep track of in passive
- * mode. The protocol will eventually terminate
- * undesirables on its own.
- */
- if (peer->hmode == MODE_ACTIVE
- && peer->pmode == MODE_ACTIVE) {
- peer->hmode = MODE_PASSIVE;
- peer->flags &= ~FLAG_CONFIG;
- } else {
- unpeer(peer);
- peer = 0;
- }
- }
- peer = findexistingpeer(srcadr, peer, mode);
- }
- return (num_found);
-}
-
-/*
- * peer_clr_stats - clear peer module stat counters
- */
-void
-peer_clr_stats(void)
-{
- findpeer_calls = 0;
- assocpeer_calls = 0;
- peer_allocations = 0;
- peer_demobilizations = 0;
- peer_timereset = current_time;
-}
-
-/*
- * peer_reset - reset stat counters in a peer structure
- */
-void
-peer_reset(
- struct peer *peer
- )
-{
- if (peer == 0)
- return;
- peer->sent = 0;
- peer->received = 0;
- peer->processed = 0;
- peer->badauth = 0;
- peer->bogusorg = 0;
- peer->oldpkt = 0;
- peer->seldisptoolarge = 0;
- peer->selbroken = 0;
- peer->rank = 0;
- peer->timereset = current_time;
-}
-
-
-/*
- * peer_all_reset - reset all peer stat counters
- */
-void
-peer_all_reset(void)
-{
- struct peer *peer;
- int hash;
-
- for (hash = 0; hash < HASH_SIZE; hash++)
- for (peer = peer_hash[hash]; peer != 0; peer = peer->next)
- peer_reset(peer);
-}
-
-
-#ifdef OPENSSL
-/*
- * expire_all - flush all crypto data and update timestamps.
- */
-void
-expire_all(void)
-{
- struct peer *peer, *next_peer;
- int n;
-
- /*
- * This routine is called about once per day from the timer
- * routine and when the client is first synchronized. Search the
- * peer list for all associations and flush only the key list
- * and cookie. If a manycast client association, flush
- * everything. Then, recompute and sign the agreement public
- * value, if present.
- */
- if (!crypto_flags)
- return;
- for (n = 0; n < HASH_SIZE; n++) {
- for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
- next_peer = peer->next;
- if (!(peer->flags & FLAG_SKEY)) {
- continue;
- } else if (peer->cast_flags & MDF_ACAST) {
- peer_clear(peer, "ACST");
- } else if (peer->hmode == MODE_ACTIVE ||
- peer->hmode == MODE_PASSIVE) {
- key_expire(peer);
- peer->crypto &= ~(CRYPTO_FLAG_AUTO |
- CRYPTO_FLAG_AGREE);
- }
-
- }
- }
- RAND_bytes((u_char *)&sys_private, 4);
- crypto_update();
- resetmanycast();
-}
-#endif /* OPENSSL */
-
-
-/*
- * findmanycastpeer - find and return a manycast peer
- */
-struct peer *
-findmanycastpeer(
- struct recvbuf *rbufp
- )
-{
- register struct peer *peer;
- struct pkt *pkt;
- l_fp p_org;
- int i;
-
- /*
- * This routine is called upon arrival of a client-mode message
- * from a manycast server. Search the peer list for a manycast
- * client association where the last transmit timestamp matches
- * the originate timestamp. This assumes the transmit timestamps
- * for possibly more than one manycast association are unique.
- */
- pkt = &rbufp->recv_pkt;
- for (i = 0; i < HASH_SIZE; i++) {
- if (peer_hash_count[i] == 0)
- continue;
-
- for (peer = peer_hash[i]; peer != 0; peer =
- peer->next) {
- if (peer->cast_flags & MDF_ACAST) {
- NTOHL_FP(&pkt->org, &p_org);
- if (L_ISEQU(&peer->xmt, &p_org))
- return (peer);
- }
- }
- }
- return (NULL);
-}
-
-
-/*
- * resetmanycast - reset all manycast clients
- */
-void
-resetmanycast(void)
-{
- register struct peer *peer;
- int i;
-
- /*
- * This routine is called when the number of client associations
- * falls below the minimum. Search the peer list for manycast
- * client associations and reset the ttl and poll interval.
- */
- for (i = 0; i < HASH_SIZE; i++) {
- if (peer_hash_count[i] == 0)
- continue;
-
- for (peer = peer_hash[i]; peer != 0; peer =
- peer->next) {
- if (peer->cast_flags & MDF_ACAST) {
- peer->ttl = 0;
- poll_update(peer, 0);
- }
- }
- }
-}
diff --git a/contrib/ntp/ntpd/ntp_proto.c b/contrib/ntp/ntpd/ntp_proto.c
deleted file mode 100644
index 451bc9a..0000000
--- a/contrib/ntp/ntpd/ntp_proto.c
+++ /dev/null
@@ -1,3208 +0,0 @@
-/*
- * ntp_proto.c - NTP version 4 protocol machinery
- *
- * ATTENTION: Get approval from Dave Mills on all changes to this file!
- *
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_stdlib.h"
-#include "ntp_unixtime.h"
-#include "ntp_control.h"
-#include "ntp_string.h"
-
-#include <stdio.h>
-
-#if defined(VMS) && defined(VMS_LOCALUNIT) /*wjm*/
-#include "ntp_refclock.h"
-#endif
-
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
-#include <sys/sysctl.h>
-#endif
-
-/*
- * 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 */
-double sys_rootdelay; /* roundtrip delay to primary source */
-double sys_rootdispersion; /* dispersion to primary source */
-u_int32 sys_refid; /* reference source for local clock */
-u_int32 sys_peer_refid; /* hashed refid of our current peer */
-static double sys_offset; /* current local clock offset */
-l_fp sys_reftime; /* time we were last updated */
-struct peer *sys_peer; /* our current peer */
-struct peer *sys_prefer; /* our cherished peer */
-int sys_kod; /* kod credit */
-int sys_kod_rate = 2; /* max kod packets per second */
-#ifdef OPENSSL
-u_long sys_automax; /* maximum session key lifetime */
-#endif /* OPENSSL */
-
-/*
- * Nonspecified system state variables.
- */
-int sys_bclient; /* broadcast client enable */
-double sys_bdelay; /* broadcast client default delay */
-int sys_calldelay; /* modem callup delay (s) */
-int sys_authenticate; /* requre authentication for config */
-l_fp sys_authdelay; /* authentication delay */
-static u_long sys_authdly[2]; /* authentication delay shift reg */
-static u_char leap_consensus; /* consensus of survivor leap bits */
-static double sys_selerr; /* select error (squares) */
-static double sys_syserr; /* system error (squares) */
-keyid_t sys_private; /* private value for session seed */
-int sys_manycastserver; /* respond to manycast client pkts */
-int peer_ntpdate; /* active peers in ntpdate mode */
-int sys_survivors; /* truest of the truechimers */
-#ifdef OPENSSL
-char *sys_hostname; /* gethostname() name */
-#endif /* OPENSSL */
-
-/*
- * TOS and multicast mapping stuff
- */
-int sys_floor = 1; /* cluster stratum floor */
-int sys_ceiling = STRATUM_UNSPEC; /* cluster stratum ceiling*/
-int sys_minsane = 1; /* minimum candidates */
-int sys_minclock = NTP_MINCLOCK; /* minimum survivors */
-int sys_cohort = 0; /* cohort switch */
-int sys_ttlmax; /* max ttl mapping vector index */
-u_char sys_ttl[MAX_TTL]; /* ttl mapping vector */
-
-/*
- * Statistics counters
- */
-u_long sys_stattime; /* time since reset */
-u_long sys_received; /* packets received */
-u_long sys_processed; /* packets processed */
-u_long sys_newversionpkt; /* current version */
-u_long sys_oldversionpkt; /* recent version */
-u_long sys_unknownversion; /* invalid version */
-u_long sys_restricted; /* access denied */
-u_long sys_badlength; /* bad length or format */
-u_long sys_badauth; /* bad authentication */
-u_long sys_limitrejected; /* rate exceeded */
-
-static double root_distance P((struct peer *));
-static double clock_combine P((struct peer **, int));
-static void peer_xmit P((struct peer *));
-static void fast_xmit P((struct recvbuf *, int, keyid_t, int));
-static void clock_update P((void));
-int default_get_precision P((void));
-static int peer_unfit P((struct peer *));
-
-/*
- * transmit - Transmit Procedure. See Section 3.4.2 of the
- * specification.
- */
-void
-transmit(
- struct peer *peer /* peer structure pointer */
- )
-{
- int hpoll;
-
-
- /*
- * The polling state machine. There are two kinds of machines,
- * those that never expect a reply (broadcast and manycast
- * server modes) and those that do (all other modes). The dance
- * is intricate...
- */
- hpoll = peer->hpoll;
- if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {
-
- /*
- * In broadcast mode the poll interval is fixed
- * at minpoll.
- */
- hpoll = peer->minpoll;
- } else if (peer->cast_flags & MDF_ACAST) {
-
- /*
- * In manycast mode we start with the minpoll interval
- * and ttl. However, the actual poll interval is eight
- * times the nominal poll interval shown here. If fewer
- * than sys_minclock servers are found, the ttl is
- * increased by one and we try again. If this continues
- * to the max ttl, the poll interval is bumped by one
- * and we try again. If at least sys_minclock servers
- * are found, the poll interval increases with the
- * system poll interval to the max and we continue
- * indefinately. However, about once per day when the
- * agreement parameters are refreshed, the manycast
- * clients are reset and we start from the beginning.
- * This is to catch and clamp the ttl to the lowest
- * practical value and avoid knocking on spurious doors.
- */
- if (sys_survivors < sys_minclock && peer->ttl <
- sys_ttlmax)
- peer->ttl++;
- hpoll = sys_poll;
- } else {
-
- /*
- * For associations expecting a reply, the watchdog
- * counter is bumped by one if the peer has not been
- * heard since the previous poll. If the counter reaches
- * the max, the poll interval is doubled and the peer is
- * demobilized if not configured.
- */
- peer->unreach++;
- if (peer->unreach >= NTP_UNREACH) {
- hpoll++;
- if (peer->flags & FLAG_CONFIG) {
-
- /*
- * If nothing is likely to change in
- * future, flash the access denied bit
- * so we won't bother the dude again.
- */
- if (memcmp((char *)&peer->refid,
- "DENY", 4) == 0 ||
- memcmp((char *)&peer->refid,
- "CRYP", 4) == 0)
- peer->flash |= TEST4;
- } else {
- unpeer(peer);
- return;
- }
- }
- if (peer->burst == 0) {
- u_char oreach;
-
- oreach = peer->reach;
- peer->reach <<= 1;
- peer->hyst *= HYST_TC;
- if (peer->reach == 0) {
-
- /*
- * If this association has become
- * unreachable, clear it and raise a
- * trap.
- */
- if (oreach != 0) {
- report_event(EVNT_UNREACH,
- peer);
- peer->timereachable =
- current_time;
- if (peer->flags & FLAG_CONFIG) {
- peer_clear(peer,
- "INIT");
- } else {
- unpeer(peer);
- return;
- }
- }
- if (peer->flags & FLAG_IBURST)
- peer->burst = NTP_BURST;
- } else {
- /*
- * Here the peer is reachable. If it has
- * not been heard for three consecutive
- * polls, stuff the clock filter. Next,
- * determine the poll interval. If the
- * peer is unfit for synchronization,
- * increase it by one; otherwise, use
- * the system poll interval.
- */
- if (!(peer->reach & 0x07)) {
- clock_filter(peer, 0., 0.,
- MAXDISPERSE);
- clock_select();
- }
- if (peer_unfit(peer))
- hpoll++;
- else
- hpoll = sys_poll;
- if (peer->flags & FLAG_BURST)
- peer->burst = NTP_BURST;
- }
- } else {
-
- /*
- * Source rate control. If we are restrained,
- * each burst consists of only one packet.
- */
- if (memcmp((char *)&peer->refid, "RSTR", 4) ==
- 0)
- peer->burst = 0;
- else
- peer->burst--;
- if (peer->burst == 0) {
- /*
- * If a broadcast client at this point,
- * the burst has concluded, so we switch
- * to client mode and purge the keylist,
- * since no further transmissions will
- * be made.
- */
- if (peer->cast_flags & MDF_BCLNT) {
- peer->hmode = MODE_BCLIENT;
-#ifdef OPENSSL
- key_expire(peer);
-#endif /* OPENSSL */
- }
- poll_update(peer, hpoll);
- clock_select();
-
- /*
- * If ntpdate mode and the clock has not
- * been set and all peers have completed
- * the burst, we declare a successful
- * failure.
- */
- if (mode_ntpdate) {
- peer_ntpdate--;
- if (peer_ntpdate > 0) {
- poll_update(
- peer, hpoll);
- return;
- }
- msyslog(LOG_NOTICE,
- "no reply; clock not set");
- exit (0);
- }
- poll_update(peer, hpoll);
- return;
- }
- }
- }
- peer->outdate = current_time;
-
- /*
- * Do not transmit if in broadcast cclient mode or access has
- * been denied.
- */
- if (peer->hmode == MODE_BCLIENT || peer->flash & TEST4) {
- poll_update(peer, hpoll);
- return;
-
- /*
- * Do not transmit in broadcast mode unless we are synchronized.
- */
- } else if (peer->hmode == MODE_BROADCAST && sys_peer == NULL) {
- poll_update(peer, hpoll);
- return;
- }
- peer_xmit(peer);
- poll_update(peer, hpoll);
-}
-
-/*
- * receive - Receive Procedure. See section 3.4.3 in the specification.
- */
-void
-receive(
- struct recvbuf *rbufp
- )
-{
- register struct peer *peer; /* peer structure pointer */
- register struct pkt *pkt; /* receive packet pointer */
- int hismode; /* packet mode */
- int restrict_mask; /* restrict bits */
- int has_mac; /* length of MAC field */
- int authlen; /* offset of MAC field */
- int is_authentic; /* cryptosum ok */
- keyid_t skeyid = 0; /* key ID */
- struct sockaddr_storage *dstadr_sin; /* active runway */
- struct peer *peer2; /* aux peer structure pointer */
- l_fp p_org; /* originate timestamp */
- l_fp p_xmt; /* transmit timestamp */
-#ifdef OPENSSL
- keyid_t tkeyid = 0; /* temporary key ID */
- keyid_t pkeyid = 0; /* previous key ID */
- struct autokey *ap; /* autokey structure pointer */
- int rval; /* cookie snatcher */
-#endif /* OPENSSL */
- int retcode = AM_NOMATCH;
-
- /*
- * Monitor the packet and get restrictions. Note that the packet
- * length for control and private mode packets must be checked
- * by the service routines. Note that no statistics counters are
- * recorded for restrict violations, since these counters are in
- * the restriction routine. Note the careful distinctions here
- * between a packet with a format error and a packet that is
- * simply discarded without prejudice. Some restrictions have to
- * be handled later in order to generate a kiss-of-death packet.
- */
- /*
- * Bogus port check is before anything, since it probably
- * reveals a clogging attack.
- */
- sys_received++;
- if (SRCPORT(&rbufp->recv_srcadr) == 0) {
- sys_badlength++;
- return; /* bogus port */
- }
- ntp_monitor(rbufp);
- restrict_mask = restrictions(&rbufp->recv_srcadr);
-#ifdef DEBUG
- if (debug > 1)
- printf("receive: at %ld %s<-%s restrict %03x\n",
- current_time, stoa(&rbufp->dstadr->sin),
- stoa(&rbufp->recv_srcadr), restrict_mask);
-#endif
- if (restrict_mask & RES_IGNORE) {
- sys_restricted++;
- return; /* no anything */
- }
- pkt = &rbufp->recv_pkt;
- hismode = (int)PKT_MODE(pkt->li_vn_mode);
- if (hismode == MODE_PRIVATE) {
- if (restrict_mask & RES_NOQUERY) {
- sys_restricted++;
- return; /* no query private */
- }
- process_private(rbufp, ((restrict_mask &
- RES_NOMODIFY) == 0));
- return;
- }
- if (hismode == MODE_CONTROL) {
- if (restrict_mask & RES_NOQUERY) {
- sys_restricted++;
- return; /* no query control */
- }
- process_control(rbufp, restrict_mask);
- return;
- }
- if (restrict_mask & RES_DONTSERVE) {
- sys_restricted++;
- return; /* no time */
- }
- if (rbufp->recv_length < LEN_PKT_NOMAC) {
- sys_badlength++;
- return; /* runt packet */
- }
-
- /*
- * Version check must be after the query packets, since they
- * intentionally use early version.
- */
- if (PKT_VERSION(pkt->li_vn_mode) == NTP_VERSION) {
- sys_newversionpkt++; /* new version */
- } else if (!(restrict_mask & RES_VERSION) &&
- PKT_VERSION(pkt->li_vn_mode) >= NTP_OLDVERSION) {
- sys_oldversionpkt++; /* previous version */
- } else {
- sys_unknownversion++;
- return; /* old version */
- }
-
- /*
- * Figure out his mode and validate the packet. This has some
- * legacy raunch that probably should be removed. In very early
- * NTP versions mode 0 was equivalent to what later versions
- * would interpret as client mode.
- */
- if (hismode == MODE_UNSPEC) {
- if (PKT_VERSION(pkt->li_vn_mode) == NTP_OLDVERSION) {
- hismode = MODE_CLIENT;
- } else {
- sys_badlength++;
- return; /* invalid mode */
- }
- }
-
- /*
- * Discard broadcast if not enabled as broadcast client. If
- * Autokey, the wildcard interface cannot be used, so dump
- * packets gettiing off the bus at that stop as well. This means
- * that some systems with broken interface code, specifically
- * Linux, will not work with Autokey.
- */
- if (hismode == MODE_BROADCAST) {
- if (!sys_bclient || restrict_mask & RES_NOPEER) {
- sys_restricted++;
- return; /* no client */
- }
-#ifdef OPENSSL
- if (crypto_flags && rbufp->dstadr == any_interface) {
- sys_restricted++;
- return; /* no client */
- }
-#endif /* OPENSSL */
- }
-
- /*
- * Parse the extension field if present. We figure out whether
- * an extension field is present by measuring the MAC size. If
- * the number of words following the packet header is 0 or 1, no
- * MAC is present and the packet is not authenticated. If 1, the
- * packet is a reply to a previous request that failed to
- * authenticate. If 3, the packet is authenticated with DES; if
- * 5, the packet is authenticated with MD5. If greater than 5,
- * an extension field is present. If 2 or 4, the packet is a
- * runt and goes poof! with a brilliant flash.
- */
- authlen = LEN_PKT_NOMAC;
- has_mac = rbufp->recv_length - authlen;
- while (has_mac > 0) {
- int temp;
-
- if (has_mac % 4 != 0 || has_mac < 0) {
- sys_badlength++;
- return; /* bad MAC length */
- }
- if (has_mac == 1 * 4 || has_mac == 3 * 4 || has_mac ==
- MAX_MAC_LEN) {
- skeyid = ntohl(((u_int32 *)pkt)[authlen / 4]);
- break;
-
- } else if (has_mac > MAX_MAC_LEN) {
- temp = ntohl(((u_int32 *)pkt)[authlen / 4]) &
- 0xffff;
- if (temp < 4 || temp > NTP_MAXEXTEN || temp % 4
- != 0) {
- sys_badlength++;
- return; /* bad MAC length */
- }
- authlen += temp;
- has_mac -= temp;
- } else {
- sys_badlength++;
- return; /* bad MAC length */
- }
- }
-#ifdef OPENSSL
- pkeyid = tkeyid = 0;
-#endif /* OPENSSL */
-
- /*
- * We have tossed out as many buggy packets as possible early in
- * the game to reduce the exposure to a clogging attack. Now we
- * have to burn some cycles to find the association and
- * authenticate the packet if required. Note that we burn only
- * MD5 cycles, again to reduce exposure. There may be no
- * matching association and that's okay.
- *
- * More on the autokey mambo. Normally the local interface is
- * found when the association was mobilized with respect to a
- * designated remote address. We assume packets arriving from
- * the remote address arrive via this interface and the local
- * address used to construct the autokey is the unicast address
- * of the interface. However, if the sender is a broadcaster,
- * the interface broadcast address is used instead.
- * Notwithstanding this technobabble, if the sender is a
- * multicaster, the broadcast address is null, so we use the
- * unicast address anyway. Don't ask.
- */
- peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, rbufp->fd,
- hismode, &retcode);
- is_authentic = 0;
- dstadr_sin = &rbufp->dstadr->sin;
- if (has_mac == 0) {
-#ifdef DEBUG
- if (debug)
- printf("receive: at %ld %s<-%s mode %d code %d\n",
- current_time, stoa(&rbufp->dstadr->sin),
- stoa(&rbufp->recv_srcadr), hismode,
- retcode);
-#endif
- } else {
-#ifdef OPENSSL
- /*
- * For autokey modes, generate the session key
- * and install in the key cache. Use the socket
- * broadcast or unicast address as appropriate.
- */
- if (skeyid > NTP_MAXKEY) {
-
- /*
- * More on the autokey dance (AKD). A cookie is
- * constructed from public and private values.
- * For broadcast packets, the cookie is public
- * (zero). For packets that match no
- * association, the cookie is hashed from the
- * addresses and private value. For server
- * packets, the cookie was previously obtained
- * from the server. For symmetric modes, the
- * cookie was previously constructed using an
- * agreement protocol; however, should PKI be
- * unavailable, we construct a fake agreement as
- * the EXOR of the peer and host cookies.
- *
- * hismode ephemeral persistent
- * =======================================
- * active 0 cookie#
- * passive 0% cookie#
- * client sys cookie 0%
- * server 0% sys cookie
- * broadcast 0 0
- *
- * # if unsync, 0
- * % can't happen
- */
- if (hismode == MODE_BROADCAST) {
-
- /*
- * For broadcaster, use the interface
- * broadcast address when available;
- * otherwise, use the unicast address
- * found when the association was
- * mobilized.
- */
- pkeyid = 0;
- if (!SOCKNUL(&rbufp->dstadr->bcast))
- dstadr_sin =
- &rbufp->dstadr->bcast;
- } else if (peer == NULL) {
- pkeyid = session_key(
- &rbufp->recv_srcadr, dstadr_sin, 0,
- sys_private, 0);
- } else {
- pkeyid = peer->pcookie;
- }
-
- /*
- * The session key includes both the public
- * values and cookie. In case of an extension
- * field, the cookie used for authentication
- * purposes is zero. Note the hash is saved for
- * use later in the autokey mambo.
- */
- if (authlen > LEN_PKT_NOMAC && pkeyid != 0) {
- session_key(&rbufp->recv_srcadr,
- dstadr_sin, skeyid, 0, 2);
- tkeyid = session_key(
- &rbufp->recv_srcadr, dstadr_sin,
- skeyid, pkeyid, 0);
- } else {
- tkeyid = session_key(
- &rbufp->recv_srcadr, dstadr_sin,
- skeyid, pkeyid, 2);
- }
-
- }
-#endif /* OPENSSL */
-
- /*
- * Compute the cryptosum. Note a clogging attack may
- * succeed in bloating the key cache. If an autokey,
- * purge it immediately, since we won't be needing it
- * again. If the packet is authentic, it may mobilize an
- * association.
- */
- if (authdecrypt(skeyid, (u_int32 *)pkt, authlen,
- has_mac)) {
- is_authentic = 1;
- restrict_mask &= ~RES_DONTTRUST;
- } else {
- sys_badauth++;
- }
-#ifdef OPENSSL
- if (skeyid > NTP_MAXKEY)
- authtrust(skeyid, 0);
-#endif /* OPENSSL */
-#ifdef DEBUG
- if (debug)
- printf(
- "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
- current_time, stoa(dstadr_sin),
- stoa(&rbufp->recv_srcadr), hismode, retcode,
- skeyid, authlen, has_mac,
- is_authentic);
-#endif
- }
-
- /*
- * The association matching rules are implemented by a set of
- * routines and a table in ntp_peer.c. A packet matching an
- * association is processed by that association. If not and
- * certain conditions prevail, then an ephemeral association is
- * mobilized: a broadcast packet mobilizes a broadcast client
- * aassociation; a manycast server packet mobilizes a manycast
- * client association; a symmetric active packet mobilizes a
- * symmetric passive association. And, the adventure
- * continues...
- */
- switch (retcode) {
- case AM_FXMIT:
-
- /*
- * This is a client mode packet not matching a known
- * association. If from a manycast client we run a few
- * sanity checks before deciding to send a unicast
- * server response. Otherwise, it must be a client
- * request, so send a server response and go home.
- */
- if (sys_manycastserver && (rbufp->dstadr->flags &
- INT_MULTICAST)) {
-
- /*
- * There is no reason to respond to a request if
- * our time is worse than the manycaster or it
- * has already synchronized to us.
- */
- if (sys_peer == NULL ||
- PKT_TO_STRATUM(pkt->stratum) <
- sys_stratum || (sys_cohort &&
- PKT_TO_STRATUM(pkt->stratum) ==
- sys_stratum) ||
- rbufp->dstadr->addr_refid == pkt->refid)
- return; /* manycast dropped */
- }
-
- /*
- * Note that we don't require an authentication check
- * here, since we can't set the system clock; but, we do
- * send a crypto-NAK to tell the caller about this.
- */
- if (has_mac && !is_authentic)
- fast_xmit(rbufp, MODE_SERVER, 0, restrict_mask);
- else
- fast_xmit(rbufp, MODE_SERVER, skeyid,
- restrict_mask);
- return;
-
- case AM_MANYCAST:
-
- /*
- * This is a server mode packet returned in response to
- * a client mode packet sent to a multicast group
- * address. The originate timestamp is a good nonce to
- * reliably associate the reply with what was sent. If
- * there is no match, that's curious and could be an
- * intruder attempting to clog, so we just ignore it.
- *
- * First, make sure the packet is authentic and not
- * restricted. If so and the manycast association is
- * found, we mobilize a client association and copy
- * pertinent variables from the manycast association to
- * the new client association.
- *
- * There is an implosion hazard at the manycast client,
- * since the manycast servers send the server packet
- * immediately. If the guy is already here, don't fire
- * up a duplicate.
- */
- if (restrict_mask & RES_DONTTRUST) {
- sys_restricted++;
- return; /* no trust */
- }
-
- if (sys_authenticate && !is_authentic)
- return; /* bad auth */
-
- if ((peer2 = findmanycastpeer(rbufp)) == NULL)
- return; /* no assoc match */
-
- if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
- MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, FLAG_IBURST, MDF_UCAST |
- MDF_ACLNT, 0, skeyid)) == NULL)
- return; /* system error */
-
- /*
- * We don't need these, but it warms the billboards.
- */
- peer->ttl = peer2->ttl;
- break;
-
- case AM_NEWPASS:
-
- /*
- * This is the first packet received from a symmetric
- * active peer. First, make sure it is authentic and not
- * restricted. If so, mobilize a passive association.
- * If authentication fails send a crypto-NAK; otherwise,
- * kiss the frog.
- */
- if (restrict_mask & RES_DONTTRUST) {
- sys_restricted++;
- return; /* no trust */
- }
- if (sys_authenticate && !is_authentic) {
- fast_xmit(rbufp, MODE_PASSIVE, 0,
- restrict_mask);
- return; /* bad auth */
- }
- if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
- MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_UCAST, 0,
- skeyid)) == NULL)
- return; /* system error */
-
- break;
-
- case AM_NEWBCL:
-
- /*
- * This is the first packet received from a broadcast
- * server. First, make sure it is authentic and not
- * restricted and that we are a broadcast client. If so,
- * mobilize a broadcast client association. We don't
- * kiss any frogs here.
- */
- if (restrict_mask & RES_DONTTRUST) {
- sys_restricted++;
- return; /* no trust */
- }
- if (sys_authenticate && !is_authentic)
- return; /* bad auth */
-
- if (!sys_bclient)
- return; /* not a client */
-
- if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
- MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, FLAG_MCAST |
- FLAG_IBURST, MDF_BCLNT, 0, skeyid)) == NULL)
- return; /* system error */
-#ifdef OPENSSL
- /*
- * Danger looms. If this is autokey, go process the
- * extension fields. If something goes wrong, abandon
- * ship and don't trust subsequent packets.
- */
- if (crypto_flags) {
- if ((rval = crypto_recv(peer, rbufp)) !=
- XEVNT_OK) {
- struct sockaddr_storage mskadr_sin;
-
- unpeer(peer);
- sys_restricted++;
- SET_HOSTMASK(&mskadr_sin,
- rbufp->recv_srcadr.ss_family);
- hack_restrict(RESTRICT_FLAGS,
- &rbufp->recv_srcadr, &mskadr_sin,
- 0, RES_DONTTRUST | RES_TIMEOUT);
-#ifdef DEBUG
- if (debug)
- printf(
- "packet: bad exten %x\n",
- rval);
-#endif
- }
- }
-#endif /* OPENSSL */
- return;
-
- case AM_POSSBCL:
-
- /*
- * This is a broadcast packet received in client mode.
- * It could happen if the initial client/server volley
- * is not complete before the next broadcast packet is
- * received. Be liberal in what we accept.
- */
- case AM_PROCPKT:
-
- /*
- * This is a symmetric mode packet received in symmetric
- * mode, a server packet received in client mode or a
- * broadcast packet received in broadcast client mode.
- * If it is restricted, this is very strange because it
- * is rude to send a packet to a restricted address. If
- * anyway, flash a restrain kiss and skedaddle to
- * Seattle. If not authentic, leave a light on and
- * continue.
- */
- peer->flash = 0;
- if (restrict_mask & RES_DONTTRUST) {
- sys_restricted++;
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "RSTR");
- else
- unpeer(peer);
- return; /* no trust */
- }
- if (has_mac && !is_authentic)
- peer->flash |= TEST5; /* bad auth */
- break;
-
- default:
-
- /*
- * Invalid mode combination. This happens when a passive
- * mode packet arrives and matches another passive
- * association or no association at all, or when a
- * server mode packet arrives and matches a broadcast
- * client association. This is usually the result of
- * reconfiguring a client on-fly. If authenticated
- * passive mode packet, send a crypto-NAK; otherwise,
- * ignore it.
- */
- if (has_mac && hismode == MODE_PASSIVE)
- fast_xmit(rbufp, MODE_ACTIVE, 0, restrict_mask);
-#ifdef DEBUG
- if (debug)
- printf("receive: bad protocol %d\n", retcode);
-#endif
- return;
- }
-
- /*
- * We do a little homework. Note we can get here with an
- * authentication error. We Need to do this in order to validate
- * a crypto-NAK later. Note the order of processing; it is very
- * important to avoid livelocks, deadlocks and lockpicks.
- */
- peer->timereceived = current_time;
- peer->received++;
- if (peer->flash & TEST5)
- peer->flags &= ~FLAG_AUTHENTIC;
- else
- peer->flags |= FLAG_AUTHENTIC;
- NTOHL_FP(&pkt->org, &p_org);
- NTOHL_FP(&pkt->xmt, &p_xmt);
-
- /*
- * If the packet is an old duplicate, we let it through so the
- * extension fields will be processed.
- */
- if (L_ISEQU(&peer->org, &p_xmt)) { /* test 1 */
- peer->flash |= TEST1; /* dupe */
- /* fall through */
-
- /*
- * For broadcast server mode, loopback checking is disabled. An
- * authentication error probably means the server restarted or
- * rolled a new private value. If so, dump the association
- * and wait for the next message.
- */
- } else if (hismode == MODE_BROADCAST) {
- if (peer->flash & TEST5) {
- unpeer(peer);
- return;
- }
- /* fall through */
-
- /*
- * For server and symmetric modes, if the association transmit
- * timestamp matches the packet originate timestamp, loopback is
- * confirmed. Note in symmetric modes this also happens when the
- * first packet from the active peer arrives at the newly
- * mobilized passive peer. An authentication error probably
- * means the server or peer restarted or rolled a new private
- * value, but could be an intruder trying to stir up trouble.
- * However, if this is a crypto-NAK, we know it is authentic, so
- * dump the association and wait for the next message.
- */
- } else if (L_ISEQU(&peer->xmt, &p_org)) {
- if (peer->flash & TEST5) {
- if (has_mac == 4 && pkt->exten[0] == 0) {
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "AUTH");
- else
- unpeer(peer);
- }
- return;
- }
- /* fall through */
-
- /*
- * If the client or passive peer has never transmitted anything,
- * this is either the first message from a symmetric peer or
- * possibly a duplicate received before the transmit timeout.
- * Pass it on.
- */
- } else if (L_ISZERO(&peer->xmt)) {
- /* fall through */
-
- /*
- * Now it gets interesting. We have transmitted at least one
- * packet. If the packet originate timestamp is nonzero, it
- * does not match the association transmit timestamp, which is a
- * loopback error. This error might mean a manycast server has
- * answered a manycast honk from us and we already have an
- * association for him, in which case quietly drop the packet
- * here. It might mean an old duplicate, dropped packet or
- * intruder replay, in which case we drop it later after
- * extension field processing, but never let it touch the time
- * values.
- */
- } else if (!L_ISZERO(&p_org)) {
- if (peer->cast_flags & MDF_ACLNT)
- return; /* not a client */
-
- peer->flash |= TEST2;
- /* fall through */
-
- /*
- * The packet originate timestamp is zero, meaning the other guy
- * either didn't receive the first packet or died and restarted.
- * If the association originate timestamp is zero, this is the
- * first packet received, so we pass it on.
- */
- } else if (L_ISZERO(&peer->org)) {
- /* fall through */
-
- /*
- * The other guy has restarted and we are still on the wire. We
- * should demobilize/clear and get out of Dodge. If this is
- * symmetric mode, we should also send a crypto-NAK.
- */
- } else {
- if (hismode == MODE_ACTIVE)
- fast_xmit(rbufp, MODE_PASSIVE, 0,
- restrict_mask);
- else if (hismode == MODE_PASSIVE)
- fast_xmit(rbufp, MODE_ACTIVE, 0, restrict_mask);
-#if DEBUG
- if (debug)
- printf("receive: dropped %03x\n", peer->flash);
-#endif
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "DROP");
- else
- unpeer(peer);
- return;
- }
- if (peer->flash & ~TEST2) {
- return;
- }
-
-#ifdef OPENSSL
- /*
- * More autokey dance. The rules of the cha-cha are as follows:
- *
- * 1. If there is no key or the key is not auto, do nothing.
- *
- * 2. If this packet is in response to the one just previously
- * sent or from a broadcast server, do the extension fields.
- * Otherwise, assume bogosity and bail out.
- *
- * 3. If an extension field contains a verified signature, it is
- * self-authenticated and we sit the dance.
- *
- * 4. If this is a server reply, check only to see that the
- * transmitted key ID matches the received key ID.
- *
- * 5. Check to see that one or more hashes of the current key ID
- * matches the previous key ID or ultimate original key ID
- * obtained from the broadcaster or symmetric peer. If no
- * match, sit the dance and wait for timeout.
- */
- if (crypto_flags && (peer->flags & FLAG_SKEY)) {
- peer->flash |= TEST10;
- rval = crypto_recv(peer, rbufp);
- if (rval != XEVNT_OK) {
- /* fall through */
-
- } else if (hismode == MODE_SERVER) {
- if (skeyid == peer->keyid)
- peer->flash &= ~TEST10;
- } else if (!peer->flash & TEST10) {
- peer->pkeyid = skeyid;
- } else if ((ap = (struct autokey *)peer->recval.ptr) !=
- NULL) {
- int i;
-
- for (i = 0; ; i++) {
- if (tkeyid == peer->pkeyid ||
- tkeyid == ap->key) {
- peer->flash &= ~TEST10;
- peer->pkeyid = skeyid;
- break;
- }
- if (i > ap->seq)
- break;
- tkeyid = session_key(
- &rbufp->recv_srcadr, dstadr_sin,
- tkeyid, pkeyid, 0);
- }
- }
- if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 11 */
- peer->flash |= TEST11; /* not proventic */
-
- /*
- * If the transmit queue is nonempty, clamp the host
- * poll interval to the packet poll interval.
- */
- if (peer->cmmd != 0) {
- peer->ppoll = pkt->ppoll;
- poll_update(peer, 0);
- }
-
- /*
- * If the return code from extension field processing is
- * not okay, we scrub the association and start over.
- */
- if (rval != XEVNT_OK) {
-
- /*
- * If the return code is bad, the crypto machine
- * may be jammed or an intruder may lurk. First,
- * we demobilize the association, then see if
- * the error is recoverable.
- */
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "CRYP");
- else
- unpeer(peer);
-#ifdef DEBUG
- if (debug)
- printf("packet: bad exten %x\n", rval);
-#endif
- return;
- }
-
- /*
- * If TEST10 is lit, the autokey sequence has broken,
- * which probably means the server has refreshed its
- * private value. We reset the poll interval to the
- & minimum and scrub the association clean.
- */
- if (peer->flash & TEST10 && peer->crypto &
- CRYPTO_FLAG_AUTO) {
- poll_update(peer, peer->minpoll);
-#ifdef DEBUG
- if (debug)
- printf(
- "packet: bad auto %03x\n",
- peer->flash);
-#endif
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "AUTO");
- else
- unpeer(peer);
- return;
- }
- }
-#endif /* OPENSSL */
-
- /*
- * We have survived the gaunt. Forward to the packet routine. If
- * a symmetric passive association has been mobilized and the
- * association doesn't deserve to live, it will die in the
- * transmit routine if not reachable after timeout. However, if
- * either symmetric mode and the crypto code has something
- * urgent to say, we expedite the response.
- */
- process_packet(peer, pkt, &rbufp->recv_time);
-}
-
-
-/*
- * process_packet - Packet Procedure, a la Section 3.4.4 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.
- */
-void
-process_packet(
- register struct peer *peer,
- register struct pkt *pkt,
- l_fp *recv_ts
- )
-{
- l_fp t34, t21;
- double p_offset, p_del, p_disp;
- double dtemp;
- l_fp p_rec, p_xmt, p_org, p_reftime;
- l_fp ci;
- u_char pmode, pleap, pstratum;
-
- /*
- * Swap header fields and keep the books. The books amount to
- * the receive timestamp and poll interval in the header. We
- * need these even if there are other problems in order to crank
- * up the state machine.
- */
- sys_processed++;
- peer->processed++;
- p_del = FPTOD(NTOHS_FP(pkt->rootdelay));
- p_disp = FPTOD(NTOHS_FP(pkt->rootdispersion));
- NTOHL_FP(&pkt->reftime, &p_reftime);
- NTOHL_FP(&pkt->rec, &p_rec);
- NTOHL_FP(&pkt->xmt, &p_xmt);
- pmode = PKT_MODE(pkt->li_vn_mode);
- pleap = PKT_LEAP(pkt->li_vn_mode);
- if (pmode != MODE_BROADCAST)
- NTOHL_FP(&pkt->org, &p_org);
- else
- p_org = peer->rec;
- pstratum = PKT_TO_STRATUM(pkt->stratum);
-
- /*
- * Test for unsynchronized server.
- */
- if (L_ISHIS(&peer->org, &p_xmt)) /* count old packets */
- peer->oldpkt++;
- if (pmode != MODE_BROADCAST && (L_ISZERO(&p_rec) ||
- L_ISZERO(&p_org))) /* test 3 */
- peer->flash |= TEST3; /* unsynch */
- if (L_ISZERO(&p_xmt)) /* test 3 */
- peer->flash |= TEST3; /* unsynch */
-
- /*
- * If any tests fail, the packet is discarded leaving only the
- * timestamps, which are enough to get the protocol started. The
- * originate timestamp is copied from the packet transmit
- * timestamp and the receive timestamp is copied from the
- * packet receive timestamp. If okay so far, we save the leap,
- * stratum and refid for billboards.
- */
- peer->org = p_xmt;
- peer->rec = *recv_ts;
- if (peer->flash) {
-#ifdef DEBUG
- if (debug)
- printf("packet: bad data %03x from address: %s\n",
- peer->flash, stoa(&peer->srcadr));
-#endif
- return;
- }
- peer->leap = pleap;
- peer->stratum = pstratum;
- peer->refid = pkt->refid;
-
- /*
- * Test for valid peer data (tests 6-8)
- */
- ci = p_xmt;
- L_SUB(&ci, &p_reftime);
- LFPTOD(&ci, dtemp);
- if (pleap == LEAP_NOTINSYNC || /* test 6 */
- pstratum >= STRATUM_UNSPEC || dtemp < 0)
- peer->flash |= TEST6; /* bad synch */
- if (!(peer->flags & FLAG_CONFIG) && sys_peer != NULL) { /* test 7 */
- if (pstratum > sys_stratum && pmode != MODE_ACTIVE)
- peer->flash |= TEST7; /* bad stratum */
- }
- if (p_del < 0 || p_disp < 0 || p_del / /* test 8 */
- 2 + p_disp >= MAXDISPERSE)
- peer->flash |= TEST8; /* bad peer values */
-
- /*
- * If any tests fail at this point, the packet is discarded.
- */
- if (peer->flash) {
-#ifdef DEBUG
- if (debug)
- printf("packet: bad header %03x\n",
- peer->flash);
-#endif
- return;
- }
-
- /*
- * The header is valid. Capture the remaining header values and
- * mark as reachable.
- */
- record_raw_stats(&peer->srcadr, &peer->dstadr->sin, &p_org,
- &p_rec, &p_xmt, &peer->rec);
- peer->pmode = pmode;
- peer->ppoll = pkt->ppoll;
- peer->precision = pkt->precision;
- peer->rootdelay = p_del;
- peer->rootdispersion = p_disp;
- peer->reftime = p_reftime;
- if (!(peer->reach)) {
- report_event(EVNT_REACH, peer);
- peer->timereachable = current_time;
- }
- peer->reach |= 1;
- peer->unreach = 0;
- poll_update(peer, 0);
-
- /*
- * 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.
- *
- * Let t1 = p_org, t2 = p_rec, t3 = p_xmt, t4 = peer->rec:
- */
- t34 = p_xmt; /* t3 - t4 */
- L_SUB(&t34, &peer->rec);
- t21 = p_rec; /* t2 - t1 */
- L_SUB(&t21, &p_org);
- ci = peer->rec; /* t4 - t1 */
- L_SUB(&ci, &p_org);
- LFPTOD(&ci, p_disp);
- p_disp = clock_phi * max(p_disp, LOGTOD(sys_precision));
-
- /*
- * If running in a broadcast 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 MODE_CLIENT
- * mode, set FLAG_MCAST and exchange eight messages to determine
- * the clock offset. When the last message is sent, we switch to
- * MODE_BCLIENT mode. The next broadcast message after that
- * computes the broadcast offset and clears FLAG_MCAST.
- */
- ci = t34;
- if (pmode == MODE_BROADCAST) {
- if (peer->flags & FLAG_MCAST) {
- LFPTOD(&ci, p_offset);
- peer->estbdelay = peer->offset - p_offset;
- if (peer->hmode == MODE_CLIENT)
- return;
-
- peer->flags &= ~FLAG_MCAST;
- }
- DTOLFP(peer->estbdelay, &t34);
- L_ADD(&ci, &t34);
- p_del = peer->delay;
- } else {
- L_ADD(&ci, &t21); /* (t2 - t1) + (t3 - t4) */
- L_RSHIFT(&ci);
- L_SUB(&t21, &t34); /* (t2 - t1) - (t3 - t4) */
- LFPTOD(&t21, p_del);
- }
- p_del = max(p_del, LOGTOD(sys_precision));
- LFPTOD(&ci, p_offset);
- if ((peer->rootdelay + p_del) / 2. + peer->rootdispersion +
- p_disp >= MAXDISPERSE) /* test 9 */
- peer->flash |= TEST9; /* bad root distance */
-
- /*
- * If any flasher bits remain set at this point, abandon ship.
- * Otherwise, forward to the clock filter.
- */
- if (peer->flash) {
-#ifdef DEBUG
- if (debug)
- printf("packet: bad packet data %03x\n",
- peer->flash);
-#endif
- return;
- }
- clock_filter(peer, p_offset, p_del, p_disp);
- clock_select();
- record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
- peer->offset, peer->delay, peer->disp,
- SQRT(peer->jitter));
-}
-
-
-/*
- * clock_update - Called at system process update intervals.
- */
-static void
-clock_update(void)
-{
- u_char oleap;
- u_char ostratum;
-
- /*
- * Reset/adjust the system clock. Do this only if there is a
- * system peer and the peer epoch is not older than the last
- * update.
- */
- if (sys_peer == NULL)
- return;
- if (sys_peer->epoch <= last_time)
- return;
-#ifdef DEBUG
- if (debug)
- printf("clock_update: at %ld assoc %d \n", current_time,
- peer_associations);
-#endif
- oleap = sys_leap;
- ostratum = sys_stratum;
- switch (local_clock(sys_peer, sys_offset, sys_syserr)) {
-
- /*
- * Clock is too screwed up. Just exit for now.
- */
- case -1:
- report_event(EVNT_SYSFAULT, NULL);
- exit (-1);
- /*NOTREACHED*/
-
- /*
- * Clock was stepped. Flush all time values of all peers.
- */
- case 1:
- clear_all();
- sys_peer = NULL;
- sys_stratum = STRATUM_UNSPEC;
- memcpy(&sys_refid, "STEP", 4);
- sys_poll = NTP_MINPOLL;
- report_event(EVNT_CLOCKRESET, NULL);
-#ifdef OPENSSL
- if (oleap != LEAP_NOTINSYNC)
- expire_all();
-#endif /* OPENSSL */
- break;
-
- /*
- * Update the system stratum, leap bits, root delay, root
- * dispersion, reference ID and reference time. We also update
- * select dispersion and max frequency error. If the leap
- * changes, we gotta reroll the keys.
- */
- default:
- sys_stratum = (u_char) (sys_peer->stratum + 1);
- if (sys_stratum == 1 || sys_stratum == STRATUM_UNSPEC)
- sys_refid = sys_peer->refid;
- else
- sys_refid = sys_peer_refid;
- sys_reftime = sys_peer->rec;
- sys_rootdelay = sys_peer->rootdelay + sys_peer->delay;
- sys_leap = leap_consensus;
- if (oleap == LEAP_NOTINSYNC) {
- report_event(EVNT_SYNCCHG, NULL);
-#ifdef OPENSSL
- expire_all();
-#endif /* OPENSSL */
- }
- }
- if (ostratum != sys_stratum)
- report_event(EVNT_PEERSTCHG, NULL);
-}
-
-
-/*
- * poll_update - update peer poll interval
- */
-void
-poll_update(
- struct peer *peer,
- int hpoll
- )
-{
-#ifdef OPENSSL
- int oldpoll;
-#endif /* OPENSSL */
-
- /*
- * A little foxtrot to determine what controls the poll
- * interval. If the peer is reachable, but the last four polls
- * have not been answered, use the minimum. If declared
- * truechimer, use the system poll interval. This allows each
- * association to ramp up the poll interval for useless sources
- * and to clamp it to the minimum when first starting up.
- */
-#ifdef OPENSSL
- oldpoll = peer->kpoll;
-#endif /* OPENSSL */
- if (hpoll > 0) {
- if (hpoll > peer->maxpoll)
- peer->hpoll = peer->maxpoll;
- else if (hpoll < peer->minpoll)
- peer->hpoll = peer->minpoll;
- else
- peer->hpoll = (u_char)hpoll;
- }
-
- /*
- * Bit of adventure here. If during a burst and not a poll, just
- * slink away. If a poll, figure what the next poll should be.
- * If a burst is pending and a reference clock or a pending
- * crypto response, delay for one second. If the first sent in a
- * burst, delay ten seconds for the modem to come up. For others
- * in the burst, delay two seconds.
- *
- * In case of manycast server, make the poll interval, which is
- * axtually the manycast beacon interval, eight times the system
- * poll interval. Normally when the host poll interval settles
- * up to 1024 s, the beacon interval settles up to 2.3 hours.
- */
-#ifdef OPENSSL
- if (peer->cmmd != NULL && (sys_leap != LEAP_NOTINSYNC ||
- peer->crypto)) {
- peer->nextdate = current_time + RESP_DELAY;
- } else if (peer->burst > 0) {
-#else /* OPENSSL */
- if (peer->burst > 0) {
-#endif /* OPENSSL */
- if (hpoll == 0 && peer->nextdate != current_time)
- return;
-#ifdef REFCLOCK
- else if (peer->flags & FLAG_REFCLOCK)
- peer->nextdate += RESP_DELAY;
-#endif
- else if (peer->flags & (FLAG_IBURST | FLAG_BURST) &&
- peer->burst == NTP_BURST)
- peer->nextdate += sys_calldelay;
- else
- peer->nextdate += BURST_DELAY;
- } else if (peer->cast_flags & MDF_ACAST) {
- if (sys_survivors >= sys_minclock || peer->ttl >=
- sys_ttlmax)
- peer->kpoll = (u_char) (peer->hpoll + 3);
- else
- peer->kpoll = peer->hpoll;
- peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
- } else {
- peer->kpoll = (u_char) max(min(peer->ppoll,
- peer->hpoll), peer->minpoll);
- peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
- }
- if (peer->nextdate < current_time)
- peer->nextdate = current_time;
-#ifdef OPENSSL
- /*
- * Bit of crass arrogance at this point. If the poll interval
- * has changed and we have a keylist, the lifetimes in the
- * keylist are probably bogus. In this case purge the keylist
- * and regenerate it later.
- */
- if (peer->kpoll != oldpoll)
- key_expire(peer);
-#endif /* OPENSSL */
-#ifdef DEBUG
- if (debug > 1)
- printf("poll_update: at %lu %s flags %04x poll %d burst %d last %lu next %lu\n",
- current_time, ntoa(&peer->srcadr), peer->flags,
- peer->kpoll, peer->burst, peer->outdate,
- peer->nextdate);
-#endif
-}
-
-
-/*
- * clear - clear peer filter registers. See Section 3.4.8 of the spec.
- */
-void
-peer_clear(
- struct peer *peer, /* peer structure */
- char *ident /* tally lights */
- )
-{
- u_char oreach, i;
-
- /*
- * If cryptographic credentials have been acquired, toss them to
- * Valhalla. Note that autokeys are ephemeral, in that they are
- * tossed immediately upon use. Therefore, the keylist can be
- * purged anytime without needing to preserve random keys. Note
- * that, if the peer is purged, the cryptographic variables are
- * purged, too. This makes it much harder to sneak in some
- * unauthenticated data in the clock filter.
- */
- oreach = peer->reach;
-#ifdef OPENSSL
- key_expire(peer);
- if (peer->pkey != NULL)
- EVP_PKEY_free(peer->pkey);
- if (peer->ident_pkey != NULL)
- EVP_PKEY_free(peer->ident_pkey);
- if (peer->subject != NULL)
- free(peer->subject);
- if (peer->issuer != NULL)
- free(peer->issuer);
- if (peer->iffval != NULL)
- BN_free(peer->iffval);
- if (peer->grpkey != NULL)
- BN_free(peer->grpkey);
- if (peer->cmmd != NULL)
- free(peer->cmmd);
- value_free(&peer->cookval);
- value_free(&peer->recval);
- value_free(&peer->tai_leap);
- value_free(&peer->encrypt);
- value_free(&peer->sndval);
-#endif /* OPENSSL */
-
- /*
- * Wipe the association clean and initialize the nonzero values.
- */
- memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
- if (peer == sys_peer)
- sys_peer = NULL;
- peer->estbdelay = sys_bdelay;
- peer->hpoll = peer->kpoll = peer->minpoll;
- peer->ppoll = peer->maxpoll;
- peer->jitter = MAXDISPERSE;
- peer->epoch = current_time;
-#ifdef REFCLOCK
- if (!(peer->flags & FLAG_REFCLOCK)) {
- peer->leap = LEAP_NOTINSYNC;
- peer->stratum = STRATUM_UNSPEC;
- memcpy(&peer->refid, ident, 4);
- }
-#else
- peer->leap = LEAP_NOTINSYNC;
- peer->stratum = STRATUM_UNSPEC;
- memcpy(&peer->refid, ident, 4);
-#endif
- for (i = 0; i < NTP_SHIFT; i++) {
- peer->filter_order[i] = i;
- peer->filter_disp[i] = MAXDISPERSE;
- peer->filter_epoch[i] = current_time;
- }
-
- /*
- * If he dies as a broadcast client, he comes back to life as
- * a broadcast client in client mode in order to recover the
- * initial autokey values.
- */
- if (peer->cast_flags & MDF_BCLNT) {
- peer->flags |= FLAG_MCAST;
- peer->hmode = MODE_CLIENT;
- }
-
- /*
- * Randomize the first poll to avoid bunching, but only if the
- * rascal has never been heard. During initialization use the
- * association count to spread out the polls at one-second
- * intervals.
- */
- peer->nextdate = peer->update = peer->outdate = current_time;
- peer->burst = 0;
- if (oreach)
- poll_update(peer, 0);
- else if (initializing)
- peer->nextdate = current_time + peer_associations;
- else
- peer->nextdate = current_time + (u_int)RANDOM %
- peer_associations;
-#ifdef DEBUG
- if (debug)
- printf("peer_clear: at %ld assoc ID %d refid %s\n",
- current_time, peer->associd, ident);
-#endif
-}
-
-
-/*
- * clock_filter - add incoming clock sample to filter register and run
- * the filter procedure to find the best sample.
- */
-void
-clock_filter(
- struct peer *peer, /* peer structure pointer */
- double sample_offset, /* clock offset */
- double sample_delay, /* roundtrip delay */
- double sample_disp /* dispersion */
- )
-{
- double dst[NTP_SHIFT]; /* distance vector */
- int ord[NTP_SHIFT]; /* index vector */
- int i, j, k, m;
- double dsp, jit, dtemp, etemp;
-
- /*
- * Shift the new sample into the register and discard the oldest
- * one. The new offset and delay come directly from the
- * timestamp calculations. The dispersion grows from the last
- * outbound packet or reference clock update to the present time
- * and increased by the sum of the peer precision and the system
- * precision. The delay can sometimes swing negative due to
- * frequency skew, so it is clamped non-negative.
- */
- dsp = min(LOGTOD(peer->precision) + LOGTOD(sys_precision) +
- sample_disp, MAXDISPERSE);
- j = peer->filter_nextpt;
- peer->filter_offset[j] = sample_offset;
- peer->filter_delay[j] = max(0, sample_delay);
- peer->filter_disp[j] = dsp;
- j++; j %= NTP_SHIFT;
- peer->filter_nextpt = (u_short) j;
-
- /*
- * Update dispersions since the last update and at the same
- * time initialize the distance and index lists. The distance
- * list uses a compound metric. If the sample is valid and
- * younger than the minimum Allan intercept, use delay;
- * otherwise, use biased dispersion.
- */
- dtemp = clock_phi * (current_time - peer->update);
- peer->update = current_time;
- for (i = NTP_SHIFT - 1; i >= 0; i--) {
- if (i != 0)
- peer->filter_disp[j] += dtemp;
- if (peer->filter_disp[j] >= MAXDISPERSE)
- peer->filter_disp[j] = MAXDISPERSE;
- if (peer->filter_disp[j] >= MAXDISPERSE)
- dst[i] = MAXDISPERSE;
- else if (peer->update - peer->filter_epoch[j] >
- allan_xpt)
- dst[i] = MAXDISTANCE + peer->filter_disp[j];
- else
- dst[i] = peer->filter_delay[j];
- ord[i] = j;
- j++; j %= NTP_SHIFT;
- }
- peer->filter_epoch[j] = current_time;
-
- /*
- * Sort the samples in both lists by distance.
- */
- for (i = 1; i < NTP_SHIFT; i++) {
- for (j = 0; j < i; j++) {
- if (dst[j] > dst[i]) {
- k = ord[j];
- ord[j] = ord[i];
- ord[i] = k;
- etemp = dst[j];
- dst[j] = dst[i];
- dst[i] = etemp;
- }
- }
- }
-
- /*
- * Copy the index list to the association structure so ntpq
- * can see it later. Prune the distance list to samples less
- * than MAXDISTANCE, but keep at least two valid samples for
- * jitter calculation.
- */
- m = 0;
- for (i = 0; i < NTP_SHIFT; i++) {
- peer->filter_order[i] = (u_char) ord[i];
- if (dst[i] >= MAXDISPERSE || (m >= 2 && dst[i] >=
- MAXDISTANCE))
- continue;
- m++;
- }
-
- /*
- * Compute the dispersion and jitter squares. The dispersion
- * is weighted exponentially by NTP_FWEIGHT (0.5) so it is
- * normalized close to 1.0. The jitter is the mean of the square
- * differences relative to the lowest delay sample. If no
- * acceptable samples remain in the shift register, quietly
- * tiptoe home leaving only the dispersion.
- */
- jit = 0;
- peer->disp = 0;
- k = ord[0];
- for (i = NTP_SHIFT - 1; i >= 0; i--) {
-
- j = ord[i];
- peer->disp = NTP_FWEIGHT * (peer->disp +
- peer->filter_disp[j]);
- if (i < m)
- jit += DIFF(peer->filter_offset[j],
- peer->filter_offset[k]);
- }
-
- /*
- * If no acceptable samples remain in the shift register,
- * quietly tiptoe home leaving only the dispersion. Otherwise,
- * save the offset, delay and jitter average. Note the jitter
- * must not be less than the system precision.
- */
- if (m == 0)
- return;
- etemp = fabs(peer->offset - peer->filter_offset[k]);
- dtemp = sqrt(peer->jitter);
- peer->offset = peer->filter_offset[k];
- peer->delay = peer->filter_delay[k];
- if (m > 1)
- jit /= m - 1;
- peer->jitter = max(jit, SQUARE(LOGTOD(sys_precision)));
-
- /*
- * A new sample is useful only if it is younger than the last
- * one used, but only if the sucker has been synchronized.
- */
- if (peer->filter_epoch[k] <= peer->epoch && sys_leap !=
- LEAP_NOTINSYNC) {
-#ifdef DEBUG
- if (debug)
- printf("clock_filter: discard %lu\n",
- peer->epoch - peer->filter_epoch[k]);
-#endif
- return;
- }
-
- /*
- * If the difference between the last offset and the current one
- * exceeds the jitter by CLOCK_SGATE and the interval since the
- * last update is less than twice the system poll interval,
- * consider the update a popcorn spike and ignore it.
- */
- if (m > 1 && etemp > CLOCK_SGATE * dtemp &&
- (long)(peer->filter_epoch[k] - peer->epoch) < (1 << (sys_poll +
- 1))) {
-#ifdef DEBUG
- if (debug)
- printf("clock_filter: popcorn %.6f %.6f\n",
- etemp, dtemp);
-#endif
- return;
- }
-
- /*
- * The mitigated sample statistics are saved for later
- * processing.
- */
- peer->epoch = peer->filter_epoch[k];
-#ifdef DEBUG
- if (debug)
- printf(
- "clock_filter: n %d off %.6f del %.6f dsp %.6f jit %.6f, age %lu\n",
- m, peer->offset, peer->delay, peer->disp,
- SQRT(peer->jitter), peer->update - peer->epoch);
-#endif
-}
-
-
-/*
- * clock_select - find the pick-of-the-litter clock
- *
- * LOCKCLOCK: If the local clock is the prefer peer, it will always be
- * enabled, even if declared falseticker, (2) only the prefer peer can
- * be selected as the system peer, (3) if the external source is down,
- * the system leap bits are set to 11 and the stratum set to infinity.
- */
-void
-clock_select(void)
-{
- struct peer *peer;
- int i, j, k, n;
- int nlist, nl3;
-
- double d, e, f;
- int allow, sw, osurv;
- double high, low;
- double synch[NTP_MAXCLOCK], error[NTP_MAXCLOCK];
- struct peer *osys_peer;
- struct peer *typeacts = NULL;
- struct peer *typelocal = NULL;
- struct peer *typepps = NULL;
- struct peer *typesystem = NULL;
-
- static int list_alloc = 0;
- static struct endpoint *endpoint = NULL;
- static int *indx = NULL;
- static struct peer **peer_list = NULL;
- static u_int endpoint_size = 0;
- static u_int indx_size = 0;
- static u_int peer_list_size = 0;
-
- /*
- * Initialize and create endpoint, index and peer lists big
- * enough to handle all associations.
- */
- osys_peer = sys_peer;
- sys_peer = NULL;
- osurv = sys_survivors;
- sys_survivors = 0;
- sys_prefer = NULL;
-#ifdef LOCKCLOCK
- sys_leap = LEAP_NOTINSYNC;
- sys_stratum = STRATUM_UNSPEC;
- memcpy(&sys_refid, "DOWN", 4);
-#endif /* LOCKCLOCK */
- nlist = 0;
- for (n = 0; n < HASH_SIZE; n++)
- nlist += peer_hash_count[n];
- if (nlist > list_alloc) {
- if (list_alloc > 0) {
- free(endpoint);
- free(indx);
- free(peer_list);
- }
- while (list_alloc < nlist) {
- list_alloc += 5;
- endpoint_size += 5 * 3 * sizeof(*endpoint);
- indx_size += 5 * 3 * sizeof(*indx);
- peer_list_size += 5 * sizeof(*peer_list);
- }
- endpoint = emalloc(endpoint_size);
- indx = emalloc(indx_size);
- peer_list = emalloc(peer_list_size);
- }
-
- /*
- * Initially, we populate the island with all the rifraff peers
- * that happen to be lying around. Those with seriously
- * defective clocks are immediately booted off the island. Then,
- * the falsetickers are culled and put to sea. The truechimers
- * remaining are subject to repeated rounds where the most
- * unpopular at each round is kicked off. When the population
- * has dwindled to sys_minclock, the survivors split a million
- * bucks and collectively crank the chimes.
- */
- nlist = nl3 = 0; /* none yet */
- for (n = 0; n < HASH_SIZE; n++) {
- for (peer = peer_hash[n]; peer != NULL; peer =
- peer->next) {
- peer->flags &= ~FLAG_SYSPEER;
- peer->status = CTL_PST_SEL_REJECT;
-
- /*
- * Leave the island immediately if the peer is
- * unfit to synchronize.
- */
- if (peer_unfit(peer))
- continue;
-
- /*
- * Don't allow the local clock or modem drivers
- * in the kitchen at this point, unless the
- * prefer peer. Do that later, but only if
- * nobody else is around. These guys are all
- * configured, so we never throw them away.
- */
- if (peer->refclktype == REFCLK_LOCALCLOCK
-#if defined(VMS) && defined(VMS_LOCALUNIT)
- /* wjm: VMS_LOCALUNIT taken seriously */
- && REFCLOCKUNIT(&peer->srcadr) !=
- VMS_LOCALUNIT
-#endif /* VMS && VMS_LOCALUNIT */
- ) {
- typelocal = peer;
- if (!(peer->flags & FLAG_PREFER))
- continue; /* no local clock */
-#ifdef LOCKCLOCK
- else
- sys_prefer = peer;
-#endif /* LOCKCLOCK */
- }
- if (peer->sstclktype == CTL_SST_TS_TELEPHONE) {
- typeacts = peer;
- if (!(peer->flags & FLAG_PREFER))
- continue; /* no acts */
- }
-
- /*
- * If we get this far, the peer can stay on the
- * island, but does not yet have the immunity
- * idol.
- */
- peer->status = CTL_PST_SEL_SANE;
- peer_list[nlist++] = peer;
-
- /*
- * Insert each interval endpoint on the sorted
- * list.
- */
- e = peer->offset; /* Upper end */
- f = root_distance(peer);
- e = e + f;
- for (i = nl3 - 1; i >= 0; i--) {
- if (e >= endpoint[indx[i]].val)
- break;
- indx[i + 3] = indx[i];
- }
- indx[i + 3] = nl3;
- endpoint[nl3].type = 1;
- endpoint[nl3++].val = e;
-
- e = e - f; /* Center point */
- for (; i >= 0; i--) {
- if (e >= endpoint[indx[i]].val)
- break;
- indx[i + 2] = indx[i];
- }
- indx[i + 2] = nl3;
- endpoint[nl3].type = 0;
- endpoint[nl3++].val = e;
-
- e = e - f; /* Lower end */
- for (; i >= 0; i--) {
- if (e >= endpoint[indx[i]].val)
- break;
- indx[i + 1] = indx[i];
- }
- indx[i + 1] = nl3;
- endpoint[nl3].type = -1;
- endpoint[nl3++].val = e;
- }
- }
-#ifdef DEBUG
- if (debug > 2)
- for (i = 0; i < nl3; i++)
- printf("select: endpoint %2d %.6f\n",
- endpoint[indx[i]].type,
- endpoint[indx[i]].val);
-#endif
- /*
- * This is the actual algorithm that cleaves the truechimers
- * from the falsetickers. The original algorithm was described
- * in Keith Marzullo's dissertation, but has been modified for
- * better accuracy.
- *
- * Briefly put, we first assume there are no falsetickers, then
- * scan the candidate list first from the low end upwards and
- * then from the high end downwards. The scans stop when the
- * number of intersections equals the number of candidates less
- * the number of falsetickers. If this doesn't happen for a
- * given number of falsetickers, we bump the number of
- * falsetickers and try again. If the number of falsetickers
- * becomes equal to or greater than half the number of
- * candidates, the Albanians have won the Byzantine wars and
- * correct synchronization is not possible.
- *
- * Here, nlist is the number of candidates and allow is the
- * number of falsetickers.
- */
- low = 1e9;
- high = -1e9;
- for (allow = 0; 2 * allow < nlist; allow++) {
- int found;
-
- /*
- * Bound the interval (low, high) as the largest
- * interval containing points from presumed truechimers.
- */
- found = 0;
- n = 0;
- for (i = 0; i < nl3; i++) {
- low = endpoint[indx[i]].val;
- n -= endpoint[indx[i]].type;
- if (n >= nlist - allow)
- break;
- if (endpoint[indx[i]].type == 0)
- found++;
- }
- n = 0;
- for (j = nl3 - 1; j >= 0; j--) {
- high = endpoint[indx[j]].val;
- n += endpoint[indx[j]].type;
- if (n >= nlist - allow)
- break;
- if (endpoint[indx[j]].type == 0)
- found++;
- }
-
- /*
- * If the number of candidates found outside the
- * interval is greater than the number of falsetickers,
- * then at least one truechimer is outside the interval,
- * so go around again. This is what makes this algorithm
- * different than Marzullo's.
- */
- if (found > allow)
- continue;
-
- /*
- * If an interval containing truechimers is found, stop.
- * If not, increase the number of falsetickers and go
- * around again.
- */
- if (high > low)
- break;
- }
-
- /*
- * If no survivors remain at this point, check if the local
- * clock or modem drivers have been found. If so, nominate one
- * of them as the only survivor. Otherwise, give up and leave
- * the island to the rats.
- */
- if (high <= low) {
- if (typeacts != 0) {
- typeacts->status = CTL_PST_SEL_SANE;
- peer_list[0] = typeacts;
- nlist = 1;
- } else if (typelocal != 0) {
- typelocal->status = CTL_PST_SEL_SANE;
- peer_list[0] = typelocal;
- nlist = 1;
- } else {
- if (osys_peer != NULL) {
- sys_poll = NTP_MINPOLL;
- NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO,
- "no servers reachable");
- report_event(EVNT_PEERSTCHG, NULL);
- }
- if (osurv > 0)
- resetmanycast();
- return;
- }
- }
-
- /*
- * We can only trust the survivors if the number of candidates
- * sys_minsane is at least the number required to detect and
- * cast out one falsticker. For the Byzantine agreement
- * algorithm used here, that number is 4; however, the default
- * sys_minsane is 1 to speed initial synchronization. Careful
- * operators will tinker the value to 4 and use at least that
- * number of synchronization sources.
- */
- if (nlist < sys_minsane)
- return;
-
- /*
- * Clustering algorithm. Construct candidate list in order first
- * by stratum then by root distance, but keep only the best
- * NTP_MAXCLOCK of them. Scan the list to find falsetickers, who
- * leave the island immediately. If a falseticker is not
- * configured, his association raft is drowned as well, but only
- * if at at least eight poll intervals have gone. We must leave
- * at least one peer to collect the million bucks.
- *
- * Note the hysteresis gimmick that increases the effective
- * distance for those rascals that have not made the final cut.
- * This is to discourage clockhopping. Note also the prejudice
- * against lower stratum peers if the floor is elevated.
- */
- j = 0;
- for (i = 0; i < nlist; i++) {
- peer = peer_list[i];
- if (nlist > 1 && (peer->offset <= low || peer->offset >=
- high)) {
- if (!(peer->flags & FLAG_CONFIG))
- unpeer(peer);
- continue;
- }
- peer->status = CTL_PST_SEL_DISTSYSPEER;
- d = peer->stratum;
- if (d < sys_floor)
- d += sys_floor;
- if (d > sys_ceiling)
- d = STRATUM_UNSPEC;
- d = root_distance(peer) + d * MAXDISTANCE;
- d *= 1. - peer->hyst;
- if (j >= NTP_MAXCLOCK) {
- if (d >= synch[j - 1])
- continue;
- else
- j--;
- }
- for (k = j; k > 0; k--) {
- if (d >= synch[k - 1])
- break;
- peer_list[k] = peer_list[k - 1];
- error[k] = error[k - 1];
- synch[k] = synch[k - 1];
- }
- peer_list[k] = peer;
- error[k] = peer->jitter;
- synch[k] = d;
- j++;
- }
- nlist = j;
- if (nlist == 0) {
-#ifdef DEBUG
- if (debug)
- printf("clock_select: empty intersection interval\n");
-#endif
- return;
- }
- for (i = 0; i < nlist; i++) {
- peer_list[i]->status = CTL_PST_SEL_SELCAND;
-
-#ifdef DEBUG
- if (debug > 2)
- printf("select: %s distance %.6f jitter %.6f\n",
- ntoa(&peer_list[i]->srcadr), synch[i],
- SQRT(error[i]));
-#endif
- }
-
- /*
- * Now, vote outlyers off the island by select jitter weighted
- * by root dispersion. Continue voting as long as there are more
- * than sys_minclock survivors and the minimum select jitter
- * squared is greater than the maximum peer jitter squared. Stop
- * if we are about to discard a prefer peer, who of course has
- * the immunity idol.
- */
- while (1) {
- d = 1e9;
- e = -1e9;
- k = 0;
- for (i = 0; i < nlist; i++) {
- if (error[i] < d)
- d = error[i];
- f = 0;
- if (nlist > 1) {
- for (j = 0; j < nlist; j++)
- f += DIFF(peer_list[j]->offset,
- peer_list[i]->offset);
- f /= nlist - 1;
- }
- if (f * synch[i] > e) {
- sys_selerr = f;
- e = f * synch[i];
- k = i;
- }
- }
- f = max(sys_selerr, SQUARE(LOGTOD(sys_precision)));
- if (nlist <= sys_minclock || f <= d ||
- peer_list[k]->flags & FLAG_PREFER)
- break;
-#ifdef DEBUG
- if (debug > 2)
- printf(
- "select: drop %s select %.6f jitter %.6f\n",
- ntoa(&peer_list[k]->srcadr),
- SQRT(sys_selerr), SQRT(d));
-#endif
- if (!(peer_list[k]->flags & FLAG_CONFIG) &&
- peer_list[k]->hmode == MODE_CLIENT)
- unpeer(peer_list[k]);
- for (j = k + 1; j < nlist; j++) {
- peer_list[j - 1] = peer_list[j];
- error[j - 1] = error[j];
- }
- nlist--;
- }
-
- /*
- * What remains is a list usually not greater than sys_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 each peer
- * in turn and OR the leap bits on the assumption that, if some
- * of them honk nonzero bits, they must know what they are
- * doing. Check for prefer and pps peers at any stratum. Check
- * if the old system peer is among the peers at the lowest
- * stratum. Note that the head of the list is at the lowest
- * stratum and that unsynchronized peers cannot survive this
- * far.
- *
- * Fiddle for hysteresis. Pump it up for a peer only if the peer
- * stratum is at least the floor and there are enough survivors.
- * This minimizes the pain when tossing out rascals beneath the
- * floorboard. Don't count peers with stratum above the ceiling.
- * Manycast is sooo complicated.
- */
- leap_consensus = 0;
- for (i = nlist - 1; i >= 0; i--) {
- peer = peer_list[i];
- leap_consensus |= peer->leap;
- peer->status = CTL_PST_SEL_SYNCCAND;
- peer->rank++;
- peer->flags |= FLAG_SYSPEER;
- if (peer->stratum >= sys_floor && osurv >= sys_minclock)
- peer->hyst = HYST;
- else
- peer->hyst = 0;
- if (peer->stratum <= sys_ceiling)
- sys_survivors++;
- if (peer->flags & FLAG_PREFER)
- sys_prefer = peer;
- if (peer->refclktype == REFCLK_ATOM_PPS &&
- peer->stratum < STRATUM_UNSPEC)
- typepps = peer;
- if (peer->stratum == peer_list[0]->stratum && peer ==
- osys_peer)
- typesystem = peer;
- }
-
- /*
- * In manycast client mode we may have spooked a sizeable number
- * of peers that we don't need. If there are at least
- * sys_minclock of them, the manycast message will be turned
- * off. By the time we get here we nay be ready to prune some of
- * them back, but we want to make sure all the candicates have
- * had a chance. If they didn't pass the sanity and intersection
- * tests, they have already been voted off the island.
- */
- if (sys_survivors < sys_minclock && osurv >= sys_minclock)
- resetmanycast();
-
- /*
- * 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 modem
- * peers (type REFCLK_NIST_ATOM etc 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 (sys_prefer)
- sw = sys_prefer->refclktype == REFCLK_LOCALCLOCK ||
- sys_prefer->sstclktype == CTL_SST_TS_TELEPHONE ||
- !typepps;
- else
- sw = 0;
- if (sw) {
- sys_peer = sys_prefer;
- sys_peer->status = CTL_PST_SEL_SYSPEER;
- sys_offset = sys_peer->offset;
- sys_syserr = sys_peer->jitter;
-#ifdef DEBUG
- if (debug > 1)
- printf("select: prefer offset %.6f\n",
- sys_offset);
-#endif
- }
-#ifndef LOCKCLOCK
- else if (typepps) {
- sys_peer = typepps;
- sys_peer->status = CTL_PST_SEL_PPS;
- sys_offset = sys_peer->offset;
- sys_syserr = sys_peer->jitter;
- if (!pps_control)
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "pps sync enabled");
- pps_control = current_time;
-#ifdef DEBUG
- if (debug > 1)
- printf("select: pps offset %.6f\n",
- sys_offset);
-#endif
- } else {
- if (typesystem)
- sys_peer = osys_peer;
- else
- sys_peer = peer_list[0];
- sys_peer->status = CTL_PST_SEL_SYSPEER;
- sys_peer->rank++;
- sys_offset = clock_combine(peer_list, nlist);
- sys_syserr = sys_peer->jitter + sys_selerr;
-#ifdef DEBUG
- if (debug > 1)
- printf("select: combine offset %.6f\n",
- sys_offset);
-#endif
- }
-#endif /* LOCKCLOCK */
- if (osys_peer != sys_peer) {
- char *src;
-
- if (sys_peer == NULL)
- sys_peer_refid = 0;
- else
- sys_peer_refid = addr2refid(&sys_peer->srcadr);
- report_event(EVNT_PEERSTCHG, NULL);
-
-#ifdef REFCLOCK
- if (ISREFCLOCKADR(&sys_peer->srcadr))
- src = refnumtoa(&sys_peer->srcadr);
- else
-#endif
- src = ntoa(&sys_peer->srcadr);
- NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO, "synchronized to %s, stratum=%d", src,
- sys_peer->stratum);
- }
- clock_update();
-}
-
-/*
- * clock_combine - combine offsets from selected peers
- */
-static double
-clock_combine(
- struct peer **peers,
- int npeers
- )
-{
- int i;
- double x, y, z;
-
- y = z = 0;
- for (i = 0; i < npeers; i++) {
- x = root_distance(peers[i]);
- y += 1. / x;
- z += peers[i]->offset / x;
- }
- return (z / y);
-}
-
-/*
- * root_distance - compute synchronization distance from peer to root
- */
-static double
-root_distance(
- struct peer *peer
- )
-{
- /*
- * Careful squeak here. The value returned must be greater than
- * zero blamed on the peer jitter, which must be at least the
- * square of sys_precision.
- */
- return ((peer->rootdelay + peer->delay) / 2 +
- peer->rootdispersion + peer->disp + clock_phi *
- (current_time - peer->update) + SQRT(peer->jitter));
-}
-
-/*
- * peer_xmit - send packet for persistent association.
- */
-static void
-peer_xmit(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct pkt xpkt; /* transmit packet */
- int sendlen, authlen;
- keyid_t xkeyid = 0; /* transmit key ID */
- l_fp xmt_tx;
-
- /*
- * Initialize transmit packet header fields.
- */
- 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(DTOFP(sys_rootdelay));
- xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion));
- xpkt.refid = sys_refid;
- HTONL_FP(&sys_reftime, &xpkt.reftime);
- HTONL_FP(&peer->org, &xpkt.org);
- HTONL_FP(&peer->rec, &xpkt.rec);
-
- /*
- * If the received packet contains a MAC, the transmitted packet
- * is authenticated and contains a MAC. If not, the transmitted
- * packet is not authenticated.
- *
- * In the current I/O semantics the default interface is set
- * until after receiving a packet and setting the right
- * interface. So, the first packet goes out unauthenticated.
- * That's why the really icky test next is here.
- */
- sendlen = LEN_PKT_NOMAC;
- if (!(peer->flags & FLAG_AUTHENABLE)) {
- get_systime(&peer->xmt);
- HTONL_FP(&peer->xmt, &xpkt.xmt);
- sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl],
- &xpkt, sendlen);
- peer->sent++;
-#ifdef DEBUG
- if (debug)
- printf("transmit: at %ld %s->%s mode %d\n",
- current_time, stoa(&peer->dstadr->sin),
- stoa(&peer->srcadr), peer->hmode);
-#endif
- return;
- }
-
- /*
- * The received packet contains a MAC, so the transmitted packet
- * must be authenticated. If autokey is enabled, fuss with the
- * various modes; otherwise, private key cryptography is used.
- */
-#ifdef OPENSSL
- if (crypto_flags && (peer->flags & FLAG_SKEY)) {
- struct exten *exten; /* extension field */
- u_int opcode;
-
- /*
- * The Public Key Dance (PKD): Cryptographic credentials
- * are contained in extension fields, each including a
- * 4-octet length/code word followed by a 4-octet
- * association ID and optional additional data. Optional
- * data includes a 4-octet data length field followed by
- * the data itself. Request messages are sent from a
- * configured association; response messages can be sent
- * from a configured association or can take the fast
- * path without ever matching an association. Response
- * messages have the same code as the request, but have
- * a response bit and possibly an error bit set. In this
- * implementation, a message may contain no more than
- * one command and no more than one response.
- *
- * Cryptographic session keys include both a public and
- * a private componet. Request and response messages
- * using extension fields are always sent with the
- * private component set to zero. Packets without
- * extension fields indlude the private component when
- * the session key is generated.
- */
- while (1) {
-
- /*
- * Allocate and initialize a keylist if not
- * already done. Then, use the list in inverse
- * order, discarding keys once used. Keep the
- * latest key around until the next one, so
- * clients can use client/server packets to
- * compute propagation delay.
- *
- * Note that once a key is used from the list,
- * it is retained in the key cache until the
- * next key is used. This is to allow a client
- * to retrieve the encrypted session key
- * identifier to verify authenticity.
- *
- * If for some reason a key is no longer in the
- * key cache, a birthday has happened and the
- * pseudo-random sequence is probably broken. In
- * that case, purge the keylist and regenerate
- * it.
- */
- if (peer->keynumber == 0)
- make_keylist(peer, peer->dstadr);
- else
- peer->keynumber--;
- xkeyid = peer->keylist[peer->keynumber];
- if (authistrusted(xkeyid))
- break;
- else
- key_expire(peer);
- }
- peer->keyid = xkeyid;
- switch (peer->hmode) {
-
- /*
- * In broadcast server mode the autokey values are
- * required by the broadcast clients. Push them when a
- * new keylist is generated; otherwise, push the
- * association message so the client can request them at
- * other times.
- */
- case MODE_BROADCAST:
- if (peer->flags & FLAG_ASSOC)
- exten = crypto_args(peer, CRYPTO_AUTO |
- CRYPTO_RESP, NULL);
- else
- exten = crypto_args(peer, CRYPTO_ASSOC |
- CRYPTO_RESP, NULL);
- sendlen += crypto_xmit(&xpkt, &peer->srcadr,
- sendlen, exten, 0);
- free(exten);
- break;
-
- /*
- * In symmetric modes the digest, certificate, agreement
- * parameters, cookie and autokey values are required.
- * The leapsecond table is optional. But, a passive peer
- * will not believe the active peer until the latter has
- * synchronized, so the agreement must be postponed
- * until then. In any case, if a new keylist is
- * generated, the autokey values are pushed.
- */
- case MODE_ACTIVE:
- case MODE_PASSIVE:
- if (peer->cmmd != NULL) {
- peer->cmmd->associd =
- htonl(peer->associd);
- sendlen += crypto_xmit(&xpkt,
- &peer->srcadr, sendlen, peer->cmmd,
- 0);
- free(peer->cmmd);
- peer->cmmd = NULL;
- }
- exten = NULL;
- if (!peer->crypto)
- exten = crypto_args(peer, CRYPTO_ASSOC,
- sys_hostname);
- else if (!(peer->crypto & CRYPTO_FLAG_VALID))
- exten = crypto_args(peer, CRYPTO_CERT,
- peer->issuer);
-
- /*
- * Identity. Note we have to sign the
- * certificate before the cookie to avoid a
- * deadlock when the passive peer is walking the
- * certificate trail. Awesome.
- */
- else if ((opcode = crypto_ident(peer)) != 0)
- exten = crypto_args(peer, opcode, NULL);
- else if (sys_leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_SIGN))
- exten = crypto_args(peer, CRYPTO_SIGN,
- sys_hostname);
-
- /*
- * Autokey. We request the cookie only when the
- * server and client are synchronized and
- * signatures work both ways. On the other hand,
- * the active peer needs the autokey values
- * before then and when the passive peer is
- * waiting for the active peer to synchronize.
- * Any time we regenerate the key list, we offer
- * the autokey values without being asked.
- */
- else if (sys_leap != LEAP_NOTINSYNC &&
- peer->leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_AGREE))
- exten = crypto_args(peer, CRYPTO_COOK,
- NULL);
- else if (peer->flags & FLAG_ASSOC)
- exten = crypto_args(peer, CRYPTO_AUTO |
- CRYPTO_RESP, NULL);
- else if (!(peer->crypto & CRYPTO_FLAG_AUTO))
- exten = crypto_args(peer, CRYPTO_AUTO,
- NULL);
-
- /*
- * Postamble. We trade leapseconds only when the
- * server and client are synchronized.
- */
- else if (sys_leap != LEAP_NOTINSYNC &&
- peer->leap != LEAP_NOTINSYNC &&
- peer->crypto & CRYPTO_FLAG_TAI &&
- !(peer->crypto & CRYPTO_FLAG_LEAP))
- exten = crypto_args(peer, CRYPTO_TAI,
- NULL);
- if (exten != NULL) {
- sendlen += crypto_xmit(&xpkt,
- &peer->srcadr, sendlen, exten, 0);
- free(exten);
- }
- break;
-
- /*
- * In client mode the digest, certificate, agreement
- * parameters and cookie are required. The leapsecond
- * table is optional. If broadcast client mode, the
- * autokey values are required as well. In broadcast
- * client mode, these values must be acquired during the
- * client/server exchange to avoid having to wait until
- * the next key list regeneration. Otherwise, the poor
- * dude may die a lingering death until becoming
- * unreachable and attempting rebirth.
- *
- * If neither the server or client have the agreement
- * parameters, the protocol transmits the cookie in the
- * clear. If the server has the parameters, the client
- * requests them and the protocol blinds it using the
- * agreed key. It is a protocol error if the client has
- * the parameters but the server does not.
- */
- case MODE_CLIENT:
- if (peer->cmmd != NULL) {
- peer->cmmd->associd =
- htonl(peer->associd);
- sendlen += crypto_xmit(&xpkt,
- &peer->srcadr, sendlen, peer->cmmd,
- 0);
- free(peer->cmmd);
- peer->cmmd = NULL;
- }
- exten = NULL;
- if (!peer->crypto)
- exten = crypto_args(peer, CRYPTO_ASSOC,
- sys_hostname);
- else if (!(peer->crypto & CRYPTO_FLAG_VALID))
- exten = crypto_args(peer, CRYPTO_CERT,
- peer->issuer);
-
- /*
- * Identity.
- */
- else if ((opcode = crypto_ident(peer)) != 0)
- exten = crypto_args(peer, opcode, NULL);
-
- /*
- * Autokey
- */
- else if (!(peer->crypto & CRYPTO_FLAG_AGREE))
- exten = crypto_args(peer, CRYPTO_COOK,
- NULL);
- else if (!(peer->crypto & CRYPTO_FLAG_AUTO) &&
- (peer->cast_flags & MDF_BCLNT))
- exten = crypto_args(peer, CRYPTO_AUTO,
- NULL);
-
- /*
- * Postamble. We can sign the certificate here,
- * since there is no chance of deadlock.
- */
- else if (sys_leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_SIGN))
- exten = crypto_args(peer, CRYPTO_SIGN,
- sys_hostname);
- else if (sys_leap != LEAP_NOTINSYNC &&
- peer->crypto & CRYPTO_FLAG_TAI &&
- !(peer->crypto & CRYPTO_FLAG_LEAP))
- exten = crypto_args(peer, CRYPTO_TAI,
- NULL);
- if (exten != NULL) {
- sendlen += crypto_xmit(&xpkt,
- &peer->srcadr, sendlen, exten, 0);
- free(exten);
- }
- break;
- }
-
- /*
- * If extension fields are present, we must use a
- * private value of zero and force min poll interval.
- * Most intricate.
- */
- if (sendlen > LEN_PKT_NOMAC)
- session_key(&peer->dstadr->sin, &peer->srcadr,
- xkeyid, 0, 2);
- }
-#endif /* OPENSSL */
- xkeyid = peer->keyid;
- get_systime(&peer->xmt);
- L_ADD(&peer->xmt, &sys_authdelay);
- HTONL_FP(&peer->xmt, &xpkt.xmt);
- authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
- if (authlen == 0) {
- msyslog(LOG_INFO,
- "transmit: encryption key %d not found", xkeyid);
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "NKEY");
- else
- unpeer(peer);
- return;
- }
- sendlen += authlen;
-#ifdef OPENSSL
- if (xkeyid > NTP_MAXKEY)
- authtrust(xkeyid, 0);
-#endif /* OPENSSL */
- get_systime(&xmt_tx);
- if (sendlen > sizeof(xpkt)) {
- msyslog(LOG_ERR, "buffer overflow %u", sendlen);
- exit (-1);
- }
- sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl], &xpkt,
- sendlen);
-
- /*
- * Calculate the encryption delay. Keep the minimum over
- * the latest two samples.
- */
- L_SUB(&xmt_tx, &peer->xmt);
- L_ADD(&xmt_tx, &sys_authdelay);
- sys_authdly[1] = sys_authdly[0];
- sys_authdly[0] = xmt_tx.l_uf;
- if (sys_authdly[0] < sys_authdly[1])
- sys_authdelay.l_uf = sys_authdly[0];
- else
- sys_authdelay.l_uf = sys_authdly[1];
- peer->sent++;
-#ifdef OPENSSL
-#ifdef DEBUG
- if (debug)
- printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d index %d\n",
- current_time, ntoa(&peer->dstadr->sin),
- ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
- authlen, authlen, peer->keynumber);
-#endif
-#else
-#ifdef DEBUG
- if (debug)
- printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
- current_time, ntoa(&peer->dstadr->sin),
- ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
- authlen, authlen);
-#endif
-#endif /* OPENSSL */
-}
-
-
-/*
- * fast_xmit - Send packet for nonpersistent association. Note that
- * neither the source or destination can be a broadcast address.
- */
-static void
-fast_xmit(
- struct recvbuf *rbufp, /* receive packet pointer */
- int xmode, /* transmit mode */
- keyid_t xkeyid, /* transmit key ID */
- int mask /* restrict mask */
- )
-{
- struct pkt xpkt; /* transmit packet structure */
- struct pkt *rpkt; /* receive packet structure */
- l_fp xmt_ts; /* timestamp */
- l_fp xmt_tx; /* timestamp after authent */
- int sendlen, authlen;
-#ifdef OPENSSL
- u_int32 temp32;
-#endif
-
- /*
- * Initialize transmit packet header fields from the receive
- * buffer provided. We leave some fields intact as received. If
- * the gazinta was from a multicast address, the gazouta must go
- * out another way.
- */
- rpkt = &rbufp->recv_pkt;
- if (rbufp->dstadr->flags & INT_MULTICAST)
- rbufp->dstadr = findinterface(&rbufp->recv_srcadr);
-
- /*
- * If the packet has picked up a restriction due to either
- * access denied or rate exceeded, decide what to do with it.
- */
- if (mask & (RES_DONTTRUST | RES_LIMITED)) {
- char *code = "????";
-
- if (mask & RES_LIMITED) {
- sys_limitrejected++;
- code = "RATE";
- } else if (mask & RES_DONTTRUST) {
- sys_restricted++;
- code = "DENY";
- }
-
- /*
- * Here we light up a kiss-of-death packet. Note the
- * rate limit on these packets. Once a second initialize
- * a bucket counter. Every packet sent decrements the
- * counter until reaching zero. If the counter is zero,
- * drop the kod.
- */
- if (sys_kod == 0 || !(mask & RES_DEMOBILIZE))
- return;
-
- sys_kod--;
- memcpy(&xpkt.refid, code, 4);
- xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOTINSYNC,
- PKT_VERSION(rpkt->li_vn_mode), xmode);
- xpkt.stratum = STRATUM_UNSPEC;
- } else {
- xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
- PKT_VERSION(rpkt->li_vn_mode), xmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
- xpkt.refid = sys_refid;
- }
- xpkt.ppoll = rpkt->ppoll;
- xpkt.precision = sys_precision;
- xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion =
- HTONS_FP(DTOUFP(sys_rootdispersion));
- HTONL_FP(&sys_reftime, &xpkt.reftime);
- xpkt.org = rpkt->xmt;
- HTONL_FP(&rbufp->recv_time, &xpkt.rec);
-
- /*
- * If the received packet contains a MAC, the transmitted packet
- * is authenticated and contains a MAC. If not, the transmitted
- * packet is not authenticated.
- */
- sendlen = LEN_PKT_NOMAC;
- if (rbufp->recv_length == sendlen) {
- get_systime(&xmt_ts);
- HTONL_FP(&xmt_ts, &xpkt.xmt);
- sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt,
- sendlen);
-#ifdef DEBUG
- if (debug)
- printf("transmit: at %ld %s->%s mode %d\n",
- current_time, stoa(&rbufp->dstadr->sin),
- stoa(&rbufp->recv_srcadr), xmode);
-#endif
- return;
- }
-
- /*
- * The received packet contains a MAC, so the transmitted packet
- * must be authenticated. For private-key cryptography, use the
- * predefined private keys to generate the cryptosum. For
- * autokey cryptography, use the server private value to
- * generate the cookie, which is unique for every source-
- * destination-key ID combination.
- */
-#ifdef OPENSSL
- if (xkeyid > NTP_MAXKEY) {
- keyid_t cookie;
-
- /*
- * The only way to get here is a reply to a legitimate
- * client request message, so the mode must be
- * MODE_SERVER. If an extension field is present, there
- * can be only one and that must be a command. Do what
- * needs, but with private value of zero so the poor
- * jerk can decode it. If no extension field is present,
- * use the cookie to generate the session key.
- */
- cookie = session_key(&rbufp->recv_srcadr,
- &rbufp->dstadr->sin, 0, sys_private, 0);
- if (rbufp->recv_length >= (int)(sendlen + MAX_MAC_LEN + 2 *
- sizeof(u_int32))) {
- session_key(&rbufp->dstadr->sin,
- &rbufp->recv_srcadr, xkeyid, 0, 2);
- temp32 = CRYPTO_RESP;
- rpkt->exten[0] |= htonl(temp32);
- sendlen += crypto_xmit(&xpkt,
- &rbufp->recv_srcadr, sendlen,
- (struct exten *)rpkt->exten, cookie);
- } else {
- session_key(&rbufp->dstadr->sin,
- &rbufp->recv_srcadr, xkeyid, cookie, 2);
- }
- }
-#endif /* OPENSSL */
- get_systime(&xmt_ts);
- L_ADD(&xmt_ts, &sys_authdelay);
- HTONL_FP(&xmt_ts, &xpkt.xmt);
- authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
- sendlen += authlen;
-#ifdef OPENSSL
- if (xkeyid > NTP_MAXKEY)
- authtrust(xkeyid, 0);
-#endif /* OPENSSL */
- get_systime(&xmt_tx);
- if (sendlen > sizeof(xpkt)) {
- msyslog(LOG_ERR, "buffer overflow %u", sendlen);
- exit (-1);
- }
- sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt, sendlen);
-
- /*
- * Calculate the encryption delay. Keep the minimum over the
- * latest two samples.
- */
- L_SUB(&xmt_tx, &xmt_ts);
- L_ADD(&xmt_tx, &sys_authdelay);
- sys_authdly[1] = sys_authdly[0];
- sys_authdly[0] = xmt_tx.l_uf;
- if (sys_authdly[0] < sys_authdly[1])
- sys_authdelay.l_uf = sys_authdly[0];
- else
- sys_authdelay.l_uf = sys_authdly[1];
-#ifdef DEBUG
- if (debug)
- printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
- current_time, ntoa(&rbufp->dstadr->sin),
- ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen -
- authlen, authlen);
-#endif
-}
-
-
-#ifdef OPENSSL
-/*
- * key_expire - purge the key list
- */
-void
-key_expire(
- struct peer *peer /* peer structure pointer */
- )
-{
- int i;
-
- if (peer->keylist != NULL) {
- for (i = 0; i <= peer->keynumber; i++)
- authtrust(peer->keylist[i], 0);
- free(peer->keylist);
- peer->keylist = NULL;
- }
- value_free(&peer->sndval);
- peer->keynumber = 0;
-#ifdef DEBUG
- if (debug)
- printf("key_expire: at %lu\n", current_time);
-#endif
-}
-#endif /* OPENSSL */
-
-
-/*
- * Determine if the peer is unfit for synchronization
- *
- * A peer is unfit for synchronization if
- * > not reachable
- * > a synchronization loop would form
- * > never been synchronized
- * > stratum undefined or too high
- * > too long without synchronization
- * > designated noselect
- */
-static int /* 0 if no, 1 if yes */
-peer_unfit(
- struct peer *peer /* peer structure pointer */
- )
-{
- return (!peer->reach || (peer->stratum > 1 && peer->refid ==
- peer->dstadr->addr_refid) || peer->leap == LEAP_NOTINSYNC ||
- peer->stratum >= STRATUM_UNSPEC || root_distance(peer) >=
- MAXDISTANCE + 2. * clock_phi * ULOGTOD(sys_poll) ||
- peer->flags & FLAG_NOSELECT );
-}
-
-
-/*
- * Find the precision of this particular machine
- */
-#define MINSTEP 100e-9 /* minimum clock increment (s) */
-#define MAXSTEP 20e-3 /* maximum clock increment (s) */
-#define MINLOOPS 5 /* minimum number of step samples */
-
-/*
- * This routine calculates the system precision, defined as the minimum
- * of a sequency of differences between successive readings of the
- * system clock. However, if the system clock can be read more than once
- * during a tick interval, the difference can be zero or one LSB unit,
- * where the LSB corresponds to one nanosecond or one microsecond.
- * Conceivably, if some other process preempts this one and reads the
- * clock, the difference can be more than one LSB unit.
- *
- * For hardware clock frequencies of 10 MHz or less, we assume the
- * logical clock advances only at the hardware clock tick. For higher
- * frequencies, we assume the logical clock can advance no more than 100
- * nanoseconds between ticks.
- */
-int
-default_get_precision(void)
-{
- l_fp val; /* current seconds fraction */
- l_fp last; /* last seconds fraction */
- l_fp diff; /* difference */
- double tick; /* computed tick value */
- double dtemp; /* scratch */
- int i; /* log2 precision */
-
- /*
- * Loop to find tick value in nanoseconds. Toss out outlyer
- * values less than the minimun tick value. In wacky cases, use
- * the default maximum value.
- */
- get_systime(&last);
- tick = MAXSTEP;
- for (i = 0; i < MINLOOPS;) {
- get_systime(&val);
- diff = val;
- L_SUB(&diff, &last);
- last = val;
- LFPTOD(&diff, dtemp);
- if (dtemp < MINSTEP)
- continue;
- i++;
- if (dtemp < tick)
- tick = dtemp;
- }
-
- /*
- * Find the nearest power of two.
- */
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "precision = %.3f usec", tick * 1e6);
- for (i = 0; tick <= 1; i++)
- tick *= 2;
- if (tick - 1. > 1. - tick / 2)
- i--;
- return (-i);
-}
-
-
-/*
- * kod_proto - called once per second to limit kiss-of-death packets
- */
-void
-kod_proto(void)
-{
- sys_kod = sys_kod_rate;
-}
-
-
-/*
- * init_proto - initialize the protocol module's data
- */
-void
-init_proto(void)
-{
- l_fp dummy;
- int i;
-
- /*
- * Fill in the sys_* stuff. Default is don't listen to
- * broadcasting, authenticate.
- */
- sys_leap = LEAP_NOTINSYNC;
- sys_stratum = STRATUM_UNSPEC;
- memcpy(&sys_refid, "INIT", 4);
- sys_precision = (s_char)default_get_precision();
- sys_jitter = LOGTOD(sys_precision);
- sys_rootdelay = 0;
- sys_rootdispersion = 0;
- L_CLR(&sys_reftime);
- sys_peer = NULL;
- sys_survivors = 0;
- get_systime(&dummy);
- sys_manycastserver = 0;
- sys_bclient = 0;
- sys_bdelay = DEFBROADDELAY;
- sys_calldelay = BURST_DELAY;
- sys_authenticate = 1;
- L_CLR(&sys_authdelay);
- sys_authdly[0] = sys_authdly[1] = 0;
- sys_stattime = 0;
- proto_clr_stats();
- for (i = 0; i < MAX_TTL; i++) {
- sys_ttl[i] = (u_char)((i * 256) / MAX_TTL);
- sys_ttlmax = i;
- }
-#ifdef OPENSSL
- sys_automax = 1 << NTP_AUTOMAX;
-#endif /* OPENSSL */
-
- /*
- * Default these to enable
- */
- ntp_enable = 1;
-#ifndef KERNEL_FLL_BUG
- kern_enable = 1;
-#endif
- pps_enable = 0;
- stats_control = 1;
-}
-
-
-/*
- * proto_config - configure the protocol module
- */
-void
-proto_config(
- int item,
- u_long value,
- double dvalue,
- struct sockaddr_storage* svalue
- )
-{
- /*
- * Figure out what he wants to change, then do it
- */
- switch (item) {
-
- /*
- * Turn on/off kernel discipline.
- */
- case PROTO_KERNEL:
- kern_enable = (int)value;
- break;
-
- /*
- * Turn on/off clock discipline.
- */
- case PROTO_NTP:
- ntp_enable = (int)value;
- break;
-
- /*
- * Turn on/off monitoring.
- */
- case PROTO_MONITOR:
- if (value)
- mon_start(MON_ON);
- else
- mon_stop(MON_ON);
- break;
-
- /*
- * Turn on/off statistics.
- */
- case PROTO_FILEGEN:
- stats_control = (int)value;
- break;
-
- /*
- * Turn on/off facility to listen to broadcasts.
- */
- case PROTO_BROADCLIENT:
- sys_bclient = (int)value;
- if (value)
- io_setbclient();
- else
- io_unsetbclient();
- break;
-
- /*
- * Add muliticast group address.
- */
- case PROTO_MULTICAST_ADD:
- if (svalue)
- io_multicast_add(*svalue);
- break;
-
- /*
- * Delete multicast group address.
- */
- case PROTO_MULTICAST_DEL:
- if (svalue)
- io_multicast_del(*svalue);
- break;
-
- /*
- * Set default broadcast delay.
- */
- case PROTO_BROADDELAY:
- sys_bdelay = dvalue;
- break;
-
- /*
- * Set modem call delay.
- */
- case PROTO_CALLDELAY:
- sys_calldelay = (int)value;
- break;
-
- /*
- * Require authentication to mobilize ephemeral associations.
- */
- case PROTO_AUTHENTICATE:
- sys_authenticate = (int)value;
- break;
-
- /*
- * Turn on/off PPS discipline.
- */
- case PROTO_PPS:
- pps_enable = (int)value;
- break;
-
- /*
- * Set the minimum number of survivors.
- */
- case PROTO_MINCLOCK:
- sys_minclock = (int)dvalue;
- break;
-
- /*
- * Set the minimum number of candidates.
- */
- case PROTO_MINSANE:
- sys_minsane = (int)dvalue;
- break;
-
- /*
- * Set the stratum floor.
- */
- case PROTO_FLOOR:
- sys_floor = (int)dvalue;
- break;
-
- /*
- * Set the stratum ceiling.
- */
- case PROTO_CEILING:
- sys_ceiling = (int)dvalue;
- break;
-
- /*
- * Set the cohort switch.
- */
- case PROTO_COHORT:
- sys_cohort= (int)dvalue;
- break;
- /*
- * Set the adjtime() resolution (s).
- */
- case PROTO_ADJ:
- sys_tick = dvalue;
- break;
-
-#ifdef REFCLOCK
- /*
- * Turn on/off refclock calibrate
- */
- case PROTO_CAL:
- cal_enable = (int)value;
- break;
-#endif
- default:
-
- /*
- * Log this error.
- */
- msyslog(LOG_INFO,
- "proto_config: illegal item %d, value %ld",
- item, value);
- }
-}
-
-
-/*
- * proto_clr_stats - clear protocol stat counters
- */
-void
-proto_clr_stats(void)
-{
- sys_stattime = current_time;
- sys_received = 0;
- sys_processed = 0;
- sys_newversionpkt = 0;
- sys_oldversionpkt = 0;
- sys_unknownversion = 0;
- sys_restricted = 0;
- sys_badlength = 0;
- sys_badauth = 0;
- sys_limitrejected = 0;
-}
diff --git a/contrib/ntp/ntpd/ntp_refclock.c b/contrib/ntp/ntpd/ntp_refclock.c
deleted file mode 100644
index 172fbda..0000000
--- a/contrib/ntp/ntpd/ntp_refclock.c
+++ /dev/null
@@ -1,1129 +0,0 @@
-/*
- * ntp_refclock - processing support for reference clocks
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_tty.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
-#ifdef REFCLOCK
-
-#ifdef TTYCLK
-# ifdef HAVE_SYS_CLKDEFS_H
-# include <sys/clkdefs.h>
-# include <stropts.h>
-# endif
-# ifdef HAVE_SYS_SIO_H
-# include <sys/sio.h>
-# endif
-#endif /* TTYCLK */
-
-#ifdef HAVE_PPSCLOCK_H
-#include <sys/ppsclock.h>
-#endif /* HAVE_PPSCLOCK_H */
-
-#ifdef KERNEL_PLL
-#include "ntp_syscall.h"
-#endif /* KERNEL_PLL */
-
-/*
- * 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. The peer structure is identified by an
- * interface address in the dotted quad form 127.127.t.u (for now only IPv4
- * addresses are used, so we need to be sure the address is it), where t is
- * the clock type and u the unit. Some legacy drivers derive the
- * refclockproc structure pointer from the table typeunit[type][unit].
- * This interface is strongly discouraged and may be abandoned in
- * future.
- */
-#define MAXUNIT 4 /* max units */
-#define FUDGEFAC .1 /* fudge correction factor */
-
-int fdpps; /* pps file descriptor */
-int cal_enable; /* enable refclock calibrate */
-
-/*
- * 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];
-
-/*
- * Forward declarations
- */
-#ifdef QSORT_USES_VOID_P
-static int refclock_cmpl_fp P((const void *, const void *));
-#else
-static int refclock_cmpl_fp P((const double *, const double *));
-#endif /* QSORT_USES_VOID_P */
-static int refclock_sample P((struct refclockproc *));
-
-/*
- * 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(
- struct peer *peer,
- int code
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
- if (pp == NULL)
- 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 = (u_char)code;
- pp->lastevent = (u_char)code;
- if (code == CEVNT_FAULT)
- msyslog(LOG_ERR,
- "clock %s event '%s' (0x%02x)",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
- else {
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_INFO,
- "clock %s event '%s' (0x%02x)",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
- }
- }
-#ifdef DEBUG
- if (debug)
- printf("clock %s event '%s' (0x%02x)\n",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
-#endif
-}
-
-
-/*
- * 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(void)
-{
- int i, j;
-
- for (i = 0; i < (int)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;
- }
-}
-
-
-/*
- * 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(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- u_char clktype;
- int unit;
-
- /*
- * Check for valid clock address. If already running, shut it
- * down first.
- */
- if (peer->srcadr.ss_family != AF_INET) {
- msyslog(LOG_ERR,
- "refclock_newpeer: clock address %s invalid, address family not implemented for refclock",
- stoa(&peer->srcadr));
- return (0);
- }
- if (!ISREFCLOCKADR(&peer->srcadr)) {
- msyslog(LOG_ERR,
- "refclock_newpeer: clock address %s invalid",
- stoa(&peer->srcadr));
- return (0);
- }
- clktype = (u_char)REFCLOCKTYPE(&peer->srcadr);
- unit = REFCLOCKUNIT(&peer->srcadr);
- if (clktype >= num_refclock_conf || unit >= MAXUNIT ||
- refclock_conf[clktype]->clock_start == noentry) {
- msyslog(LOG_ERR,
- "refclock_newpeer: clock type %d invalid\n",
- clktype);
- return (0);
- }
-
- /*
- * Allocate and initialize interface structure
- */
- pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc));
- if (pp == NULL)
- return (0);
- memset((char *)pp, 0, sizeof(struct refclockproc));
- typeunit[clktype][unit] = peer;
- peer->procptr = pp;
-
- /*
- * Initialize structures
- */
- peer->refclktype = clktype;
- peer->refclkunit = (u_char)unit;
- peer->flags |= FLAG_REFCLOCK;
- peer->maxpoll = peer->minpoll;
- peer->stratum = STRATUM_REFCLOCK;
- pp->type = clktype;
- pp->timestarted = current_time;
-
- /*
- * Set peer.pmode based on the hmode. For appearances only.
- */
- switch (peer->hmode) {
- case MODE_ACTIVE:
- peer->pmode = MODE_PASSIVE;
- break;
-
- default:
- peer->pmode = MODE_SERVER;
- break;
- }
-
- /*
- * Do driver dependent initialization. The above defaults
- * can be wiggled, then finish up for consistency.
- */
- if (!((refclock_conf[clktype]->clock_start)(unit, peer))) {
- refclock_unpeer(peer);
- return (0);
- }
- peer->hpoll = peer->minpoll;
- peer->ppoll = peer->maxpoll;
- peer->refid = pp->refid;
- return (1);
-}
-
-
-/*
- * refclock_unpeer - shut down a clock
- */
-void
-refclock_unpeer(
- struct peer *peer /* peer structure pointer */
- )
-{
- u_char clktype;
- int unit;
-
- /*
- * Wiggle the driver to release its resources, then give back
- * the interface structure.
- */
- 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 - 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.
- */
-void
-refclock_transmit(
- struct peer *peer /* peer structure pointer */
- )
-{
- u_char clktype;
- int unit;
- u_long next;
-
- clktype = peer->refclktype;
- unit = peer->refclkunit;
- peer->sent++;
-
- /*
- * This is a ripoff of the peer transmit routine, but
- * specialized for reference clocks. We do a little less
- * protocol here and call the driver-specific transmit routine.
- */
- next = peer->outdate;
- if (peer->burst == 0) {
- u_char oreach;
-#ifdef DEBUG
- if (debug)
- printf("refclock_transmit: at %ld %s\n",
- current_time, stoa(&(peer->srcadr)));
-#endif
-
- /*
- * Update reachability and poll variables like the
- * network code.
- */
- oreach = peer->reach;
- peer->reach <<= 1;
- if (!peer->reach) {
- if (oreach) {
- report_event(EVNT_UNREACH, peer);
- peer->timereachable = current_time;
- peer_clear(peer, "NONE");
- }
- } else {
- if (!(oreach & 0x03)) {
- clock_filter(peer, 0., 0., MAXDISPERSE);
- clock_select();
- }
- if (peer->flags & FLAG_BURST)
- peer->burst = NSTAGE;
- }
- next = current_time;
- }
- get_systime(&peer->xmt);
- if (refclock_conf[clktype]->clock_poll != noentry)
- (refclock_conf[clktype]->clock_poll)(unit, peer);
- peer->outdate = next;
- if (peer->burst > 0)
- peer->burst--;
- poll_update(peer, 0);
-}
-
-
-/*
- * Compare two doubles - used with qsort()
- */
-#ifdef QSORT_USES_VOID_P
-static int
-refclock_cmpl_fp(
- const void *p1,
- const void *p2
- )
-{
- const double *dp1 = (const double *)p1;
- const double *dp2 = (const double *)p2;
-
- if (*dp1 < *dp2)
- return (-1);
- if (*dp1 > *dp2)
- return (1);
- return (0);
-}
-#else
-static int
-refclock_cmpl_fp(
- const double *dp1,
- const double *dp2
- )
-{
- if (*dp1 < *dp2)
- return (-1);
- if (*dp1 > *dp2)
- return (1);
- return (0);
-}
-#endif /* QSORT_USES_VOID_P */
-
-
-/*
- * refclock_process_offset - update median filter
- *
- * This routine uses the given offset and timestamps to construct a new
- * entry in the median filter circular buffer. Samples that overflow the
- * filter are quietly discarded.
- */
-void
-refclock_process_offset(
- struct refclockproc *pp, /* refclock structure pointer */
- l_fp lasttim, /* last timecode timestamp */
- l_fp lastrec, /* last receive timestamp */
- double fudge
- )
-{
- l_fp lftemp;
- double doffset;
-
- pp->lastrec = lastrec;
- lftemp = lasttim;
- L_SUB(&lftemp, &lastrec);
- LFPTOD(&lftemp, doffset);
- SAMPLE(doffset + fudge);
-}
-
-/*
- * refclock_process - process a sample from the clock
- *
- * This routine converts the timecode in the form days, hours, minutes,
- * seconds and milliseconds/microseconds to internal timestamp format,
- * then constructs a new entry in the median filter circular buffer.
- * Return success (1) if the data are correct and consistent with the
- * converntional calendar.
-*/
-int
-refclock_process(
- struct refclockproc *pp /* refclock structure pointer */
- )
-{
- l_fp offset, ltemp;
-
- /*
- * 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.
- */
- if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
- pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui))
- return (0);
- offset.l_uf = 0;
- DTOLFP(pp->nsec / 1e9, &ltemp);
- L_ADD(&offset, &ltemp);
- refclock_process_offset(pp, offset, pp->lastrec,
- pp->fudgetime1);
- return (1);
-}
-
-/*
- * refclock_sample - process a pile of samples from the clock
- *
- * This routine implements a recursive median filter to suppress spikes
- * in the data, as well as determine a performance statistic. It
- * calculates the mean offset and jitter (squares). A time adjustment
- * fudgetime1 can be added to the final offset to compensate for various
- * systematic errors. The routine returns the number of samples
- * processed, which could be zero.
- */
-static int
-refclock_sample(
- struct refclockproc *pp /* refclock structure pointer */
- )
-{
- int i, j, k, m, n;
- double offset;
- double off[MAXSTAGE];
-
- /*
- * Copy the raw offsets and sort into ascending order. Don't do
- * anything if the buffer is empty.
- */
- n = 0;
- while (pp->codeproc != pp->coderecv) {
- pp->codeproc = (pp->codeproc + 1) % MAXSTAGE;
- off[n] = pp->filter[pp->codeproc];
- n++;
- }
- if (n == 0)
- return (0);
- if (n > 1)
- qsort((char *)off, (size_t)n, sizeof(double), refclock_cmpl_fp);
-
- /*
- * Reject the furthest from the median of the samples until
- * approximately 60 percent of the samples remain.
- */
- i = 0; j = n;
- m = n - (n * 2) / NSTAGE;
- while ((j - i) > m) {
- offset = off[(j + i) / 2];
- if (off[j - 1] - offset < offset - off[i])
- i++; /* reject low end */
- else
- j--; /* reject high end */
- }
-
- /*
- * Determine the offset and jitter.
- */
- offset = 0;
- for (k = i; k < j; k++)
- offset += off[k];
- pp->offset = offset / m;
- if (m > 1)
- pp->jitter = SQUARE(off[i] - off[j - 1]);
- else
- pp->jitter = 0;
-#ifdef DEBUG
- if (debug)
- printf(
- "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n",
- n, pp->offset, pp->disp, SQRT(pp->jitter));
-#endif
- return (n);
-}
-
-
-/*
- * 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(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-
-#ifdef DEBUG
- if (debug)
- printf("refclock_receive: at %lu %s\n",
- current_time, stoa(&peer->srcadr));
-#endif
-
- /*
- * Do a little sanity dance and update the peer structure. Groom
- * the median filter samples and give the data to the clock
- * filter.
- */
- peer->received++;
- pp = peer->procptr;
- peer->processed++;
- peer->timereceived = current_time;
- peer->leap = pp->leap;
- if (peer->leap == LEAP_NOTINSYNC) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- if (!peer->reach)
- report_event(EVNT_REACH, peer);
- peer->reach |= 1;
- peer->reftime = pp->lastref;
- peer->org = pp->lastrec;
- peer->rootdispersion = pp->disp;
- get_systime(&peer->rec);
- if (!refclock_sample(pp))
- return;
- clock_filter(peer, pp->offset, 0., pp->jitter);
- clock_select();
- record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
- peer->offset, peer->delay, clock_phi * (current_time -
- peer->epoch), SQRT(peer->jitter));
- if (cal_enable && last_offset < MINDISPERSE) {
-#ifdef KERNEL_PLL
- if (peer != sys_peer || pll_status & STA_PPSTIME)
-#else
- if (peer != sys_peer)
-#endif /* KERNEL_PLL */
- pp->fudgetime1 -= pp->offset * FUDGEFAC;
- else
- pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC;
- }
-}
-
-/*
- * 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 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.
- */
-int
-refclock_gtlin(
- struct recvbuf *rbufp, /* receive buffer pointer */
- char *lineptr, /* current line pointer */
- int bmax, /* remaining characters in line */
- l_fp *tsptr /* pointer to timestamp returned */
- )
-{
- char *dpt, *dpend, *dp;
- int i;
- l_fp trtmp, tstmp;
- char c;
-
- /*
- * Check for the presence of a timestamp left by the tty_clock
- * 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_buffer;
- 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 > 1) {
- printf(
- "refclock_gtlin: fd %d ldisc %s",
- rbufp->fd, lfptoa(&trtmp, 6));
- get_systime(&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 = (char) (*dpt & 0x7f);
- if (c >= ' ')
- *dp++ = c;
- }
- i = dp - lineptr;
- if (i > 0)
- *dp = '\0';
-#ifdef DEBUG
- if (debug > 1) {
- if (i > 0)
- printf("refclock_gtlin: fd %d time %s timecode %d %s\n",
- rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
- else
- printf("refclock_gtlin: fd %d time %s\n",
- rbufp->fd, ulfptoa(&trtmp, 6));
- }
-#endif
- *tsptr = trtmp;
- return (i);
-}
-
-/*
- * The following code does not apply to WINNT & VMS ...
- */
-#if !defined SYS_VXWORKS && !defined SYS_WINNT
-#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
-
-/*
- * 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(
- char *dev, /* device name pointer */
- int speed, /* serial port speed (code) */
- int lflags /* line discipline flags */
- )
-{
- int fd, i;
- int flags;
- TTY ttyb, *ttyp;
-#ifdef TIOCMGET
- u_long ltemp;
-#endif /* TIOCMGET */
- int omode;
-
- /*
- * Open serial port and set default options
- */
- flags = lflags;
-
- omode = O_RDWR;
-#ifdef O_NONBLOCK
- omode |= O_NONBLOCK;
-#endif
-#ifdef O_NOCTTY
- omode |= O_NOCTTY;
-#endif
-
- fd = open(dev, omode, 0777);
-
- if (fd < 0) {
- msyslog(LOG_ERR, "refclock_open: %s: %m", dev);
- return (0);
- }
-
- /*
- * This little jewel lights up the PPS file descriptor if the
- * device name matches the name in the pps line in the
- * configuration file. This is so the atom driver can glom onto
- * the right device. Very silly.
- */
- if (strcmp(dev, pps_device) == 0)
- fdpps = fd;
-
- /*
- * 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
- /*
- * POSIX serial line parameters (termios interface)
- */
- if (tcgetattr(fd, ttyp) < 0) {
- msyslog(LOG_ERR,
- "refclock_open: fd %d tcgetattr: %m", fd);
- return (0);
- }
-
- /*
- * 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, (u_int)speed);
- (void)cfsetospeed(&ttyb, (u_int)speed);
- ttyp->c_lflag = ICANON;
- for (i = 0; i < NCCS; ++i)
- {
- ttyp->c_cc[i] = '\0';
- }
-
- /*
- * Some special cases
- */
- if (flags & LDISC_RAW) {
- ttyp->c_iflag = 0;
- ttyp->c_lflag = 0;
- ttyp->c_cc[VMIN] = 1;
- }
-#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
- /*
- * 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)
- msyslog(LOG_ERR,
- "refclock_open: fd %d TIOCMGET failed: %m", fd);
-#ifdef DEBUG
- if (debug)
- printf("refclock_open: fd %d modem status 0x%lx\n",
- fd, ltemp);
-#endif
- if (ltemp & TIOCM_DSR)
- ttyp->c_cflag &= ~CLOCAL;
-#endif /* TIOCMGET */
- if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
- msyslog(LOG_ERR,
- "refclock_open: fd %d TCSANOW failed: %m", fd);
- return (0);
- }
- if (tcflush(fd, TCIOFLUSH) < 0) {
- msyslog(LOG_ERR,
- "refclock_open: fd %d TCIOFLUSH failed: %m", fd);
- return (0);
- }
-#endif /* HAVE_TERMIOS */
-
-#ifdef HAVE_SYSV_TTYS
-
- /*
- * System V serial line parameters (termio interface)
- *
- */
- if (ioctl(fd, TCGETA, ttyp) < 0) {
- msyslog(LOG_ERR,
- "refclock_open: fd %d TCGETA failed: %m", fd);
- return (0);
- }
-
- /*
- * 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';
-
- /*
- * Some special cases
- */
- if (flags & LDISC_RAW) {
- ttyp->c_iflag = 0;
- ttyp->c_lflag = 0;
- }
-#ifdef TIOCMGET
- /*
- * 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)
- msyslog(LOG_ERR,
- "refclock_open: fd %d TIOCMGET failed: %m", fd);
-#ifdef DEBUG
- if (debug)
- printf("refclock_open: fd %d modem status %lx\n",
- fd, ltemp);
-#endif
- if (ltemp & TIOCM_DSR)
- ttyp->c_cflag &= ~CLOCAL;
-#endif /* TIOCMGET */
- if (ioctl(fd, TCSETA, ttyp) < 0) {
- msyslog(LOG_ERR,
- "refclock_open: fd %d TCSETA failed: %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) {
- msyslog(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) {
- msyslog(LOG_ERR,
- "refclock_open: TIOCSETP failed: %m");
- return (0);
- }
-#endif /* HAVE_BSD_TTYS */
- if (!refclock_ioctl(fd, flags)) {
- (void)close(fd);
- msyslog(LOG_ERR,
- "refclock_open: fd %d ioctl failed: %m", fd);
- return (0);
- }
- return (fd);
-}
-#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
-#endif /* SYS_VXWORKS SYS_WINNT */
-
-/*
- * 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 optional features such as tty_clk. The routine returns 1 if
- * success and 0 if failure.
- */
-int
-refclock_ioctl(
- int fd, /* file descriptor */
- int flags /* line discipline flags */
- )
-{
- /* simply return 1 if no UNIX line discipline is supported */
-#if !defined SYS_VXWORKS && !defined SYS_WINNT
-#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
-
-#ifdef TTYCLK
- TTY ttyb, *ttyp;
-#endif /* TTYCLK */
-
-#ifdef DEBUG
- if (debug)
- printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags);
-#endif
- if (flags == 0)
- return (1);
-#if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS))
- if (flags & (LDISC_CLK | LDISC_PPS | LDISC_ACTS)) {
- msyslog(LOG_ERR,
- "refclock_ioctl: unsupported terminal interface");
- return (0);
- }
-#endif /* HAVE_TERMIOS HAVE_BSD_TTYS */
-#ifdef TTYCLK
- ttyp = &ttyb;
-#endif /* TTYCLK */
-
- /*
- * The following features may or may not require System V
- * STREAMS support, depending on the particular implementation.
- */
-#if defined(TTYCLK)
- /*
- * The TTYCLK option provides timestamping at the driver level.
- * It requires the tty_clk streams module and System V STREAMS
- * support. If not available, don't complain.
- */
- if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
- int rval = 0;
-
- if (ioctl(fd, I_PUSH, "clk") < 0) {
- msyslog(LOG_NOTICE,
- "refclock_ioctl: I_PUSH clk failed: %m");
- } else {
- char *str;
-
- if (flags & LDISC_CLKPPS)
- str = "\377";
- else if (flags & LDISC_ACTS)
- str = "*";
- else
- str = "\n";
-#ifdef CLK_SETSTR
- if ((rval = ioctl(fd, CLK_SETSTR, str)) < 0)
- msyslog(LOG_ERR,
- "refclock_ioctl: CLK_SETSTR failed: %m");
- if (debug)
- printf("refclock_ioctl: fd %d CLK_SETSTR %d str %s\n",
- fd, rval, str);
-#endif
- }
- }
-#endif /* TTYCLK */
-#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
-#endif /* SYS_VXWORKS SYS_WINNT */
- return (1);
-}
-
-/*
- * 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
- * ntpdc and the clockstat command. It can also be used to initialize
- * configuration variables, such as fudgetimes, fudgevalues, reference
- * ID and stratum.
- */
-void
-refclock_control(
- struct sockaddr_storage *srcadr,
- struct refclockstat *in,
- struct refclockstat *out
- )
-{
- struct peer *peer;
- struct refclockproc *pp;
- u_char clktype;
- int unit;
-
- /*
- * Check for valid address and running peer
- */
- if (srcadr->ss_family != AF_INET)
- return;
- if (!ISREFCLOCKADR(srcadr))
- return;
- clktype = (u_char)REFCLOCKTYPE(srcadr);
- unit = REFCLOCKUNIT(srcadr);
- if (clktype >= num_refclock_conf || unit >= MAXUNIT)
- return;
- peer = typeunit[clktype][unit];
- if (peer == NULL)
- return;
- if (peer->procptr == NULL)
- return;
- pp = peer->procptr;
-
- /*
- * Initialize requested data
- */
- 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)
- pp->stratum = (u_char) in->fudgeval1;
- if (in->haveflags & CLK_HAVEVAL2)
- pp->refid = in->fudgeval2;
- peer->stratum = pp->stratum;
- if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
- STRATUM_UNSPEC)
- peer->refid = pp->refid;
- else
- peer->refid = ((struct
- sockaddr_in*)&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;
- }
- }
-
- /*
- * 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 = pp->stratum;
- out->fudgeval2 = pp->refid;
- out->flags = (u_char) 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->p_lastcode = pp->a_lastcode;
- }
-
- /*
- * Give the stuff to the clock
- */
- if (refclock_conf[clktype]->clock_control != noentry)
- (refclock_conf[clktype]->clock_control)(unit, in, out, peer);
-}
-
-
-/*
- * 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
- * ntpdc and the clkbug command.
- */
-void
-refclock_buginfo(
- struct sockaddr_storage *srcadr, /* clock address */
- struct refclockbug *bug /* output structure */
- )
-{
- struct peer *peer;
- struct refclockproc *pp;
- u_char clktype;
- int unit;
- int i;
-
- /*
- * Check for valid address and peer structure
- */
- if (srcadr->ss_family != AF_INET)
- return;
- if (!ISREFCLOCKADR(srcadr))
- return;
- clktype = (u_char) REFCLOCKTYPE(srcadr);
- unit = REFCLOCKUNIT(srcadr);
- if (clktype >= num_refclock_conf || unit >= MAXUNIT)
- return;
- peer = typeunit[clktype][unit];
- if (peer == NULL)
- return;
- pp = peer->procptr;
-
- /*
- * Copy structure values
- */
- bug->nvalues = 8;
- bug->svalues = 0x0000003f;
- 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->nsec;
- bug->values[6] = pp->yearstart;
- bug->values[7] = pp->coderecv;
- bug->stimes = 0xfffffffc;
- bug->times[0] = pp->lastref;
- bug->times[1] = pp->lastrec;
- for (i = 2; i < (int)bug->ntimes; i++)
- DTOLFP(pp->filter[i - 2], &bug->times[i]);
-
- /*
- * Give the stuff to the clock
- */
- if (refclock_conf[clktype]->clock_buginfo != noentry)
- (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer);
-}
-
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/ntp_request.c b/contrib/ntp/ntpd/ntp_request.c
deleted file mode 100644
index eacba28..0000000
--- a/contrib/ntp/ntpd/ntp_request.c
+++ /dev/null
@@ -1,2756 +0,0 @@
-/*
- * ntp_request.c - respond to information requests
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_request.h"
-#include "ntp_control.h"
-#include "ntp_refclock.h"
-#include "ntp_if.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <stddef.h>
-#include <signal.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "recvbuff.h"
-
-#ifdef KERNEL_PLL
-#include "ntp_syscall.h"
-#endif /* KERNEL_PLL */
-
-/*
- * Structure to hold request procedure information
- */
-#define NOAUTH 0
-#define AUTH 1
-
-#define NO_REQUEST (-1)
-/*
- * Because we now have v6 addresses in the messages, we need to compensate
- * for the larger size. Therefore, we introduce the alternate size to
- * keep us friendly with older implementations. A little ugly.
- */
-static int client_v6_capable = 0; /* the client can handle longer messages */
-
-#define v6sizeof(type) (client_v6_capable ? sizeof(type) : v4sizeof(type))
-
-struct req_proc {
- short request_code; /* defined request code */
- short needs_auth; /* true when authentication needed */
- short sizeofitem; /* size of request data item (older size)*/
- short v6_sizeofitem; /* size of request data item (new size)*/
- void (*handler) P((struct sockaddr_storage *, struct interface *,
- struct req_pkt *)); /* routine to handle request */
-};
-
-/*
- * Universal request codes
- */
-static struct req_proc univ_codes[] = {
- { NO_REQUEST, NOAUTH, 0, 0 }
-};
-
-static void req_ack P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
-static char * prepare_pkt P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_int));
-static char * more_pkt P((void));
-static void flush_pkt P((void));
-static void peer_list P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void peer_list_sum P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void peer_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void peer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void sys_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void sys_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void mem_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void io_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void timer_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void loop_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_conf P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_unconf P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void set_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void clr_sys_flag P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void setclr_flags P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
-static void list_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_resaddflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_ressubflags P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_unrestrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_restrict P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
-static void mon_getlist_0 P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void mon_getlist_1 P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void reset_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void reset_peer P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_key_reread P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void trust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void untrust_key P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_trustkey P((struct sockaddr_storage *, struct interface *, struct req_pkt *, u_long));
-static void get_auth_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void reset_auth_stats P((void));
-static void req_get_traps P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void req_set_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void req_clr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void do_setclr_trap P((struct sockaddr_storage *, struct interface *, struct req_pkt *, int));
-static void set_request_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void set_control_keyid P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-#ifdef KERNEL_PLL
-static void get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-#endif /* KERNEL_PLL */
-#ifdef REFCLOCK
-static void get_clock_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-static void set_clock_fudge P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-#endif /* REFCLOCK */
-#ifdef REFCLOCK
-static void get_clkbug_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
-#endif /* REFCLOCK */
-
-/*
- * ntpd request codes
- */
-static struct req_proc ntp_codes[] = {
- { REQ_PEER_LIST, NOAUTH, 0, 0, peer_list },
- { REQ_PEER_LIST_SUM, NOAUTH, 0, 0, peer_list_sum },
- { REQ_PEER_INFO, NOAUTH, v4sizeof(struct info_peer_list),
- sizeof(struct info_peer_list), peer_info},
- { REQ_PEER_STATS, NOAUTH, v4sizeof(struct info_peer_list),
- sizeof(struct info_peer_list), peer_stats},
- { REQ_SYS_INFO, NOAUTH, 0, 0, sys_info },
- { REQ_SYS_STATS, NOAUTH, 0, 0, sys_stats },
- { REQ_IO_STATS, NOAUTH, 0, 0, io_stats },
- { REQ_MEM_STATS, NOAUTH, 0, 0, mem_stats },
- { REQ_LOOP_INFO, NOAUTH, 0, 0, loop_info },
- { REQ_TIMER_STATS, NOAUTH, 0, 0, timer_stats },
- { REQ_CONFIG, AUTH, v4sizeof(struct conf_peer),
- sizeof(struct conf_peer), do_conf },
- { REQ_UNCONFIG, AUTH, v4sizeof(struct conf_unpeer),
- sizeof(struct conf_unpeer), do_unconf },
- { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
- sizeof(struct conf_sys_flags), set_sys_flag },
- { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags),
- sizeof(struct conf_sys_flags), clr_sys_flag },
- { REQ_GET_RESTRICT, NOAUTH, 0, 0, list_restrict },
- { REQ_RESADDFLAGS, AUTH, v4sizeof(struct conf_restrict),
- sizeof(struct conf_restrict), do_resaddflags },
- { REQ_RESSUBFLAGS, AUTH, v4sizeof(struct conf_restrict),
- sizeof(struct conf_restrict), do_ressubflags },
- { REQ_UNRESTRICT, AUTH, v4sizeof(struct conf_restrict),
- sizeof(struct conf_restrict), do_unrestrict },
- { REQ_MON_GETLIST, NOAUTH, 0, 0, mon_getlist_0 },
- { REQ_MON_GETLIST_1, NOAUTH, 0, 0, mon_getlist_1 },
- { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), 0, reset_stats },
- { REQ_RESET_PEER, AUTH, v4sizeof(struct conf_unpeer),
- sizeof(struct conf_unpeer), reset_peer },
- { REQ_REREAD_KEYS, AUTH, 0, 0, do_key_reread },
- { REQ_TRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), trust_key },
- { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), sizeof(u_long), untrust_key },
- { REQ_AUTHINFO, NOAUTH, 0, 0, get_auth_info },
- { REQ_TRAPS, NOAUTH, 0, 0, req_get_traps },
- { REQ_ADD_TRAP, AUTH, v4sizeof(struct conf_trap),
- sizeof(struct conf_trap), req_set_trap },
- { REQ_CLR_TRAP, AUTH, v4sizeof(struct conf_trap),
- sizeof(struct conf_trap), req_clr_trap },
- { REQ_REQUEST_KEY, AUTH, sizeof(u_long), sizeof(u_long),
- set_request_keyid },
- { REQ_CONTROL_KEY, AUTH, sizeof(u_long), sizeof(u_long),
- set_control_keyid },
- { REQ_GET_CTLSTATS, NOAUTH, 0, 0, get_ctl_stats },
-#ifdef KERNEL_PLL
- { REQ_GET_KERNEL, NOAUTH, 0, 0, get_kernel_info },
-#endif
-#ifdef REFCLOCK
- { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
- get_clock_info },
- { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge),
- sizeof(struct conf_fudge), set_clock_fudge },
- { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
- get_clkbug_info },
-#endif
- { NO_REQUEST, NOAUTH, 0, 0, 0 }
-};
-
-
-/*
- * Authentication keyid used to authenticate requests. Zero means we
- * don't allow writing anything.
- */
-keyid_t 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 errorcounter[INFO_ERR_AUTH+1]; /* lazy way to count errors, indexed */
-/* by the error code */
-
-/*
- * A hack. To keep the authentication module clear of ntp-ism's, we
- * include a time reset variable for its stats here.
- */
-static u_long auth_timereset;
-
-/*
- * Response packet used by these routines. Also some state information
- * so that we can handle packet formatting within a common set of
- * subroutines. Note we try to enter data in place whenever possible,
- * but the need to set the more bit correctly means we occasionally
- * use the extra buffer and copy.
- */
-static struct resp_pkt rpkt;
-static int reqver;
-static int seqno;
-static int nitems;
-static int itemsize;
-static int databytes;
-static char exbuf[RESP_DATA_SIZE];
-static int usingexbuf;
-static struct sockaddr_storage *toaddr;
-static struct interface *frominter;
-
-/*
- * init_request - initialize request data
- */
-void
-init_request (void)
-{
- int i;
-
- numrequests = 0;
- numresppkts = 0;
- auth_timereset = 0;
- info_auth_keyid = 0; /* by default, can't do this */
-
- for (i = 0; i < sizeof(errorcounter)/sizeof(errorcounter[0]); i++)
- errorcounter[i] = 0;
-}
-
-
-/*
- * req_ack - acknowledge request with no data
- */
-static void
-req_ack(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt,
- int errcode
- )
-{
- /*
- * fill in the fields
- */
- rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
- rpkt.auth_seq = AUTH_SEQ(0, 0);
- rpkt.implementation = inpkt->implementation;
- rpkt.request = inpkt->request;
- rpkt.err_nitems = ERR_NITEMS(errcode, 0);
- rpkt.mbz_itemsize = MBZ_ITEMSIZE(0);
-
- /*
- * send packet and bump counters
- */
- sendpkt(srcadr, inter, -1, (struct pkt *)&rpkt, RESP_HEADER_SIZE);
- errorcounter[errcode]++;
-}
-
-
-/*
- * prepare_pkt - prepare response packet for transmission, return pointer
- * to storage for data item.
- */
-static char *
-prepare_pkt(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *pkt,
- u_int structsize
- )
-{
-#ifdef DEBUG
- if (debug > 3)
- printf("request: preparing pkt\n");
-#endif
-
- /*
- * Fill in the implementation, request and itemsize fields
- * since these won't change.
- */
- rpkt.implementation = pkt->implementation;
- rpkt.request = pkt->request;
- rpkt.mbz_itemsize = MBZ_ITEMSIZE(structsize);
-
- /*
- * Compute the static data needed to carry on.
- */
- toaddr = srcadr;
- frominter = inter;
- seqno = 0;
- nitems = 0;
- itemsize = structsize;
- databytes = 0;
- usingexbuf = 0;
-
- /*
- * return the beginning of the packet buffer.
- */
- return &rpkt.data[0];
-}
-
-
-/*
- * more_pkt - return a data pointer for a new item.
- */
-static char *
-more_pkt(void)
-{
- /*
- * If we were using the extra buffer, send the packet.
- */
- if (usingexbuf) {
-#ifdef DEBUG
- if (debug > 2)
- printf("request: sending pkt\n");
-#endif
- rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver);
- rpkt.auth_seq = AUTH_SEQ(0, seqno);
- rpkt.err_nitems = htons((u_short)nitems);
- sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
- RESP_HEADER_SIZE+databytes);
- numresppkts++;
-
- /*
- * Copy data out of exbuf into the packet.
- */
- memmove(&rpkt.data[0], exbuf, (unsigned)itemsize);
- seqno++;
- databytes = 0;
- nitems = 0;
- usingexbuf = 0;
- }
-
- databytes += itemsize;
- nitems++;
- if (databytes + itemsize <= RESP_DATA_SIZE) {
-#ifdef DEBUG
- if (debug > 3)
- printf("request: giving him more data\n");
-#endif
- /*
- * More room in packet. Give him the
- * next address.
- */
- return &rpkt.data[databytes];
- } else {
- /*
- * No room in packet. Give him the extra
- * buffer unless this was the last in the sequence.
- */
-#ifdef DEBUG
- if (debug > 3)
- printf("request: into extra buffer\n");
-#endif
- if (seqno == MAXSEQ)
- return (char *)0;
- else {
- usingexbuf = 1;
- return exbuf;
- }
- }
-}
-
-
-/*
- * flush_pkt - we're done, return remaining information.
- */
-static void
-flush_pkt(void)
-{
-#ifdef DEBUG
- if (debug > 2)
- printf("request: flushing packet, %d items\n", nitems);
-#endif
- /*
- * Must send the last packet. If nothing in here and nothing
- * has been sent, send an error saying no data to be found.
- */
- if (seqno == 0 && nitems == 0)
- req_ack(toaddr, frominter, (struct req_pkt *)&rpkt,
- INFO_ERR_NODATA);
- else {
- rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver);
- rpkt.auth_seq = AUTH_SEQ(0, seqno);
- rpkt.err_nitems = htons((u_short)nitems);
- sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt,
- RESP_HEADER_SIZE+databytes);
- numresppkts++;
- }
-}
-
-
-
-/*
- * process_private - process private mode (7) packets
- */
-void
-process_private(
- struct recvbuf *rbufp,
- int mod_okay
- )
-{
- struct req_pkt *inpkt;
- struct req_pkt_tail *tailinpkt;
- struct sockaddr_storage *srcadr;
- struct interface *inter;
- struct req_proc *proc;
- int ec;
- short temp_size;
-
- /*
- * Initialize pointers, for convenience
- */
- inpkt = (struct req_pkt *)&rbufp->recv_pkt;
- srcadr = &rbufp->recv_srcadr;
- inter = rbufp->dstadr;
-
-#ifdef DEBUG
- if (debug > 2)
- printf("process_private: impl %d req %d\n",
- inpkt->implementation, inpkt->request);
-#endif
-
- /*
- * Do some sanity checks on the packet. Return a format
- * error if it fails.
- */
- ec = 0;
- if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode))
- || (++ec, ISMORE(inpkt->rm_vn_mode))
- || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
- || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
- || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
- || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
- || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
- || (++ec, rbufp->recv_length < REQ_LEN_HDR)
- ) {
- msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d failed, pkt from %s", ec, stoa(srcadr));
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- reqver = INFO_VERSION(inpkt->rm_vn_mode);
-
- /*
- * Get the appropriate procedure list to search.
- */
- if (inpkt->implementation == IMPL_UNIV)
- proc = univ_codes;
- else if ((inpkt->implementation == IMPL_XNTPD) ||
- (inpkt->implementation == IMPL_XNTPD_OLD))
- proc = ntp_codes;
- else {
- req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
- return;
- }
-
- /*
- * Search the list for the request codes. If it isn't one
- * we know, return an error.
- */
- while (proc->request_code != NO_REQUEST) {
- if (proc->request_code == (short) inpkt->request)
- break;
- proc++;
- }
- if (proc->request_code == NO_REQUEST) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_REQ);
- return;
- }
-
-#ifdef DEBUG
- if (debug > 3)
- printf("found request in tables\n");
-#endif
-
- /*
- * If we need data, check to see if we have some. If we
- * don't, check to see that there is none (picky, picky).
- */
-
- /* This part is a bit tricky, we want to be sure that the size
- * returned is either the old or the new size. We also can find
- * out if the client can accept both types of messages this way.
- *
- * Handle the exception of REQ_CONFIG. It can have two data sizes.
- */
- temp_size = INFO_ITEMSIZE(inpkt->mbz_itemsize);
- if ((temp_size != proc->sizeofitem &&
- temp_size != proc->v6_sizeofitem) &&
- !(inpkt->implementation == IMPL_XNTPD &&
- inpkt->request == REQ_CONFIG &&
- temp_size == sizeof(struct old_conf_peer))) {
- if (debug > 2)
- printf("process_private: wrong item size, received %d, should be %d or %d\n",
- temp_size, proc->sizeofitem, proc->v6_sizeofitem);
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
- if ((proc->sizeofitem != 0) &&
- ((temp_size * INFO_NITEMS(inpkt->err_nitems)) >
- (rbufp->recv_length - REQ_LEN_HDR))) {
- if (debug > 2)
- printf("process_private: not enough data\n");
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- switch (inpkt->implementation) {
- case IMPL_XNTPD:
- client_v6_capable = 1;
- break;
- case IMPL_XNTPD_OLD:
- client_v6_capable = 0;
- break;
- default:
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- /*
- * If we need to authenticate, do so. Note that an
- * authenticatable packet must include a mac field, must
- * have used key info_auth_keyid and must have included
- * a time stamp in the appropriate field. The time stamp
- * must be within INFO_TS_MAXSKEW of the receive
- * time stamp.
- */
- if (proc->needs_auth && sys_authenticate) {
- l_fp ftmp;
- double dtemp;
-
- if (rbufp->recv_length < (int)((REQ_LEN_HDR +
- (INFO_ITEMSIZE(inpkt->mbz_itemsize) *
- INFO_NITEMS(inpkt->err_nitems))
- + sizeof(struct req_pkt_tail)))) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- }
- tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt +
- rbufp->recv_length - sizeof(struct req_pkt_tail));
-
- /*
- * 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
- || ntohl(tailinpkt->keyid) != info_auth_keyid) {
-#ifdef DEBUG
- if (debug > 4)
- printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
- INFO_IS_AUTH(inpkt->auth_seq),
- (u_long)info_auth_keyid,
- (u_long)ntohl(tailinpkt->keyid));
- msyslog(LOG_DEBUG,
- "process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n",
- INFO_IS_AUTH(inpkt->auth_seq),
- (u_long)info_auth_keyid,
- (u_long)ntohl(tailinpkt->keyid));
-#endif
- req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
- return;
- }
- if (rbufp->recv_length > REQ_LEN_MAC) {
-#ifdef DEBUG
- if (debug > 4)
- printf("bad pkt length %d\n",
- rbufp->recv_length);
-#endif
- msyslog(LOG_ERR, "process_private: bad pkt length %d",
- rbufp->recv_length);
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
- if (!mod_okay || !authhavekey(info_auth_keyid)) {
-#ifdef DEBUG
- if (debug > 4)
- printf("failed auth mod_okay %d\n", mod_okay);
- msyslog(LOG_DEBUG,
- "process_private: failed auth mod_okay %d\n",
- mod_okay);
-#endif
- req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
- return;
- }
-
- /*
- * calculate absolute time difference between xmit time stamp
- * and receive time stamp. If too large, too bad.
- */
- NTOHL_FP(&tailinpkt->tstamp, &ftmp);
- L_SUB(&ftmp, &rbufp->recv_time);
- LFPTOD(&ftmp, dtemp);
- if (fabs(dtemp) >= INFO_TS_MAXSKEW) {
- /*
- * He's a loser. Tell him.
- */
-#ifdef DEBUG
- if (debug > 4)
- printf("xmit/rcv timestamp delta > INFO_TS_MAXSKEW\n");
-#endif
- req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
- return;
- }
-
- /*
- * So far so good. See if decryption works out okay.
- */
- if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt,
- rbufp->recv_length - sizeof(struct req_pkt_tail) +
- REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) {
-#ifdef DEBUG
- if (debug > 4)
- printf("authdecrypt failed\n");
-#endif
- req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH);
- return;
- }
- }
-
-#ifdef DEBUG
- if (debug > 3)
- printf("process_private: all okay, into handler\n");
-#endif
-
- /*
- * Packet is okay. Call the handler to send him data.
- */
- (proc->handler)(srcadr, inter, inpkt);
-}
-
-
-/*
- * peer_list - send a list of the peers
- */
-static void
-peer_list(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_peer_list *ip;
- register struct peer *pp;
- register int i;
- register int skip = 0;
-
- ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_peer_list));
- for (i = 0; i < HASH_SIZE && ip != 0; i++) {
- pp = peer_hash[i];
- while (pp != 0 && ip != 0) {
- if (pp->srcadr.ss_family == AF_INET6) {
- if (client_v6_capable) {
- ip->addr6 = GET_INADDR6(pp->srcadr);
- ip->v6_flag = 1;
- skip = 0;
- } else {
- skip = 1;
- break;
- }
- } else {
- ip->addr = GET_INADDR(pp->srcadr);
- if (client_v6_capable)
- ip->v6_flag = 0;
- skip = 0;
- }
-
- if(!skip) {
- ip->port = NSRCPORT(&pp->srcadr);
- ip->hmode = pp->hmode;
- ip->flags = 0;
- if (pp->flags & FLAG_CONFIG)
- ip->flags |= INFO_FLAG_CONFIG;
- if (pp == sys_peer)
- ip->flags |= INFO_FLAG_SYSPEER;
- if (pp->status == CTL_PST_SEL_SYNCCAND)
- ip->flags |= INFO_FLAG_SEL_CANDIDATE;
- if (pp->status >= CTL_PST_SEL_SYSPEER)
- ip->flags |= INFO_FLAG_SHORTLIST;
- ip = (struct info_peer_list *)more_pkt();
- }
- pp = pp->next;
- }
- }
- flush_pkt();
-}
-
-
-/*
- * peer_list_sum - return extended peer list
- */
-static void
-peer_list_sum(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_peer_summary *ips;
- register struct peer *pp;
- register int i;
- l_fp ltmp;
- register int skip;
-
-#ifdef DEBUG
- if (debug > 2)
- printf("wants peer list summary\n");
-#endif
- ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_peer_summary));
- for (i = 0; i < HASH_SIZE && ips != 0; i++) {
- pp = peer_hash[i];
- while (pp != 0 && ips != 0) {
-#ifdef DEBUG
- if (debug > 3)
- printf("sum: got one\n");
-#endif
- /*
- * Be careful here not to return v6 peers when we
- * want only v4.
- */
- if (pp->srcadr.ss_family == AF_INET6) {
- if (client_v6_capable) {
- ips->srcadr6 = GET_INADDR6(pp->srcadr);
- ips->v6_flag = 1;
- ips->dstadr6 = GET_INADDR6(pp->dstadr->sin);
- skip = 0;
- } else {
- skip = 1;
- break;
- }
- } else {
- ips->srcadr = GET_INADDR(pp->srcadr);
- if (client_v6_capable)
- ips->v6_flag = 0;
-/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
- ips->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- GET_INADDR(pp->dstadr->bcast):
- pp->cast_flags ?
- GET_INADDR(pp->dstadr->sin) ?
- GET_INADDR(pp->dstadr->sin):
- GET_INADDR(pp->dstadr->bcast):
- 1 : GET_INADDR(pp->dstadr->sin);
-
- skip = 0;
- }
- if (!skip){
- ips->srcport = NSRCPORT(&pp->srcadr);
- ips->stratum = pp->stratum;
- ips->hpoll = pp->hpoll;
- ips->ppoll = pp->ppoll;
- ips->reach = pp->reach;
- ips->flags = 0;
- if (pp == sys_peer)
- ips->flags |= INFO_FLAG_SYSPEER;
- if (pp->flags & FLAG_CONFIG)
- ips->flags |= INFO_FLAG_CONFIG;
- if (pp->flags & FLAG_REFCLOCK)
- ips->flags |= INFO_FLAG_REFCLOCK;
- if (pp->flags & FLAG_AUTHENABLE)
- ips->flags |= INFO_FLAG_AUTHENABLE;
- if (pp->flags & FLAG_PREFER)
- ips->flags |= INFO_FLAG_PREFER;
- if (pp->flags & FLAG_BURST)
- ips->flags |= INFO_FLAG_BURST;
- if (pp->status == CTL_PST_SEL_SYNCCAND)
- ips->flags |= INFO_FLAG_SEL_CANDIDATE;
- if (pp->status >= CTL_PST_SEL_SYSPEER)
- ips->flags |= INFO_FLAG_SHORTLIST;
- ips->hmode = pp->hmode;
- ips->delay = HTONS_FP(DTOFP(pp->delay));
- DTOLFP(pp->offset, &ltmp);
- HTONL_FP(&ltmp, &ips->offset);
- ips->dispersion = HTONS_FP(DTOUFP(pp->disp));
- }
- pp = pp->next;
- ips = (struct info_peer_summary *)more_pkt();
- }
- }
- flush_pkt();
-}
-
-
-/*
- * peer_info - send information for one or more peers
- */
-static void
-peer_info (
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_peer_list *ipl;
- register struct peer *pp;
- register struct info_peer *ip;
- register int items;
- register int i, j;
- struct sockaddr_storage addr;
- extern struct peer *sys_peer;
- l_fp ltmp;
-
- memset((char *)&addr, 0, sizeof addr);
- items = INFO_NITEMS(inpkt->err_nitems);
- ipl = (struct info_peer_list *) inpkt->data;
-
- ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_peer));
- while (items-- > 0 && ip != 0) {
- memset((char *)&addr, 0, sizeof(addr));
- NSRCPORT(&addr) = ipl->port;
- if (client_v6_capable && ipl->v6_flag != 0) {
- addr.ss_family = AF_INET6;
- GET_INADDR6(addr) = ipl->addr6;
- } else {
- addr.ss_family = AF_INET;
- GET_INADDR(addr) = ipl->addr;
- }
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
-#endif
- ipl++;
- if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
- continue;
- if (pp->srcadr.ss_family == AF_INET6) {
- ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
- GET_INADDR6(pp->dstadr->bcast) :
- GET_INADDR6(pp->dstadr->sin);
- ip->srcadr6 = GET_INADDR6(pp->srcadr);
- ip->v6_flag = 1;
- } else {
-/* XXX PDM This code is buggy. Need to replace with a straightforward assignment */
- ip->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- GET_INADDR(pp->dstadr->bcast):
- pp->cast_flags ?
- GET_INADDR(pp->dstadr->sin) ?
- GET_INADDR(pp->dstadr->sin):
- GET_INADDR(pp->dstadr->bcast):
- 2 : GET_INADDR(pp->dstadr->sin);
-
- ip->srcadr = GET_INADDR(pp->srcadr);
- if (client_v6_capable)
- ip->v6_flag = 0;
- }
- ip->srcport = NSRCPORT(&pp->srcadr);
- ip->flags = 0;
- if (pp == sys_peer)
- ip->flags |= INFO_FLAG_SYSPEER;
- if (pp->flags & FLAG_CONFIG)
- ip->flags |= INFO_FLAG_CONFIG;
- if (pp->flags & FLAG_REFCLOCK)
- ip->flags |= INFO_FLAG_REFCLOCK;
- if (pp->flags & FLAG_AUTHENABLE)
- ip->flags |= INFO_FLAG_AUTHENABLE;
- if (pp->flags & FLAG_PREFER)
- ip->flags |= INFO_FLAG_PREFER;
- if (pp->flags & FLAG_BURST)
- ip->flags |= INFO_FLAG_BURST;
- if (pp->status == CTL_PST_SEL_SYNCCAND)
- ip->flags |= INFO_FLAG_SEL_CANDIDATE;
- if (pp->status >= CTL_PST_SEL_SYSPEER)
- ip->flags |= INFO_FLAG_SHORTLIST;
- ip->leap = pp->leap;
- ip->hmode = pp->hmode;
- ip->keyid = pp->keyid;
- ip->stratum = pp->stratum;
- ip->ppoll = pp->ppoll;
- ip->hpoll = pp->hpoll;
- ip->precision = pp->precision;
- ip->version = pp->version;
- ip->reach = pp->reach;
- ip->unreach = (u_char) pp->unreach;
- ip->flash = (u_char)pp->flash;
- ip->flash2 = (u_short) pp->flash;
- ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay));
- ip->ttl = pp->ttl;
- ip->associd = htons(pp->associd);
- ip->rootdelay = HTONS_FP(DTOUFP(pp->rootdelay));
- ip->rootdispersion = HTONS_FP(DTOUFP(pp->rootdispersion));
- ip->refid = pp->refid;
- HTONL_FP(&pp->reftime, &ip->reftime);
- HTONL_FP(&pp->org, &ip->org);
- HTONL_FP(&pp->rec, &ip->rec);
- HTONL_FP(&pp->xmt, &ip->xmt);
- j = pp->filter_nextpt - 1;
- for (i = 0; i < NTP_SHIFT; i++, j--) {
- if (j < 0)
- j = NTP_SHIFT-1;
- ip->filtdelay[i] = HTONS_FP(DTOFP(pp->filter_delay[j]));
- DTOLFP(pp->filter_offset[j], &ltmp);
- HTONL_FP(&ltmp, &ip->filtoffset[i]);
- ip->order[i] = (u_char)((pp->filter_nextpt+NTP_SHIFT-1)
- - pp->filter_order[i]);
- if (ip->order[i] >= NTP_SHIFT)
- ip->order[i] -= NTP_SHIFT;
- }
- DTOLFP(pp->offset, &ltmp);
- HTONL_FP(&ltmp, &ip->offset);
- ip->delay = HTONS_FP(DTOFP(pp->delay));
- ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
- ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter)));
- ip = (struct info_peer *)more_pkt();
- }
- flush_pkt();
-}
-
-
-/*
- * peer_stats - send statistics for one or more peers
- */
-static void
-peer_stats (
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_peer_list *ipl;
- register struct peer *pp;
- register struct info_peer_stats *ip;
- register int items;
- struct sockaddr_storage addr;
- extern struct peer *sys_peer;
-
- printf("peer_stats: called\n");
- items = INFO_NITEMS(inpkt->err_nitems);
- ipl = (struct info_peer_list *) inpkt->data;
- ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_peer_stats));
- while (items-- > 0 && ip != 0) {
- memset((char *)&addr, 0, sizeof(addr));
- NSRCPORT(&addr) = ipl->port;
- if (client_v6_capable && ipl->v6_flag) {
- addr.ss_family = AF_INET6;
- GET_INADDR6(addr) = ipl->addr6;
- } else {
- addr.ss_family = AF_INET;
- GET_INADDR(addr) = ipl->addr;
- }
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
-#endif
- printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr),
- ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port);
- ipl = (struct info_peer_list *)((char *)ipl +
- INFO_ITEMSIZE(inpkt->mbz_itemsize));
-
- if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
- continue;
- printf("peer_stats: found %s\n", stoa(&addr));
- if (pp->srcadr.ss_family == AF_INET) {
- ip->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- GET_INADDR(pp->dstadr->bcast):
- pp->cast_flags ?
- GET_INADDR(pp->dstadr->sin) ?
- GET_INADDR(pp->dstadr->sin):
- GET_INADDR(pp->dstadr->bcast):
- 3 : 7;
- ip->srcadr = GET_INADDR(pp->srcadr);
- if (client_v6_capable)
- ip->v6_flag = 0;
- } else {
- ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
- GET_INADDR6(pp->dstadr->bcast):
- GET_INADDR6(pp->dstadr->sin);
- ip->srcadr6 = GET_INADDR6(pp->srcadr);
- ip->v6_flag = 1;
- }
- ip->srcport = NSRCPORT(&pp->srcadr);
- ip->flags = 0;
- if (pp == sys_peer)
- ip->flags |= INFO_FLAG_SYSPEER;
- if (pp->flags & FLAG_CONFIG)
- ip->flags |= INFO_FLAG_CONFIG;
- if (pp->flags & FLAG_REFCLOCK)
- ip->flags |= INFO_FLAG_REFCLOCK;
- if (pp->flags & FLAG_AUTHENABLE)
- ip->flags |= INFO_FLAG_AUTHENABLE;
- if (pp->flags & FLAG_PREFER)
- ip->flags |= INFO_FLAG_PREFER;
- if (pp->flags & FLAG_BURST)
- ip->flags |= INFO_FLAG_BURST;
- if (pp->status == CTL_PST_SEL_SYNCCAND)
- ip->flags |= INFO_FLAG_SEL_CANDIDATE;
- if (pp->status >= CTL_PST_SEL_SYSPEER)
- ip->flags |= INFO_FLAG_SHORTLIST;
- ip->timereceived = htonl((u_int32)(current_time - pp->timereceived));
- ip->timetosend = htonl(pp->nextdate - current_time);
- ip->timereachable = htonl((u_int32)(current_time - pp->timereachable));
- ip->sent = htonl((u_int32)(pp->sent));
- ip->processed = htonl((u_int32)(pp->processed));
- ip->badauth = htonl((u_int32)(pp->badauth));
- ip->bogusorg = htonl((u_int32)(pp->bogusorg));
- ip->oldpkt = htonl((u_int32)(pp->oldpkt));
- ip->seldisp = htonl((u_int32)(pp->seldisptoolarge));
- ip->selbroken = htonl((u_int32)(pp->selbroken));
- ip->candidate = pp->status;
- ip = (struct info_peer_stats *)more_pkt();
- }
- flush_pkt();
-}
-
-
-/*
- * sys_info - return system info
- */
-static void
-sys_info(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_sys *is;
-
- /*
- * Importations from the protocol module
- */
- extern u_char sys_leap;
- extern u_char sys_stratum;
- extern s_char sys_precision;
- extern double sys_rootdelay;
- extern double sys_rootdispersion;
- extern u_int32 sys_refid;
- extern l_fp sys_reftime;
- extern u_char sys_poll;
- extern struct peer *sys_peer;
- extern int sys_bclient;
- extern double sys_bdelay;
- extern l_fp sys_authdelay;
- extern double clock_stability;
- extern double sys_jitter;
-
- is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_sys));
-
- if (sys_peer != 0) {
- if (sys_peer->srcadr.ss_family == AF_INET) {
- is->peer = GET_INADDR(sys_peer->srcadr);
- if (client_v6_capable)
- is->v6_flag = 0;
- } else if (client_v6_capable) {
- is->peer6 = GET_INADDR6(sys_peer->srcadr);
- is->v6_flag = 1;
- }
- is->peer_mode = sys_peer->hmode;
- } else {
- is->peer = 0;
- if (client_v6_capable) {
- is->v6_flag = 0;
- }
- is->peer_mode = 0;
- }
-
- is->leap = sys_leap;
- is->stratum = sys_stratum;
- is->precision = sys_precision;
- is->rootdelay = htonl(DTOFP(sys_rootdelay));
- is->rootdispersion = htonl(DTOUFP(sys_rootdispersion));
- is->frequency = htonl(DTOFP(sys_jitter));
- is->stability = htonl(DTOUFP(clock_stability * 1e6));
- is->refid = sys_refid;
- HTONL_FP(&sys_reftime, &is->reftime);
-
- is->poll = sys_poll;
-
- is->flags = 0;
- if (sys_authenticate)
- is->flags |= INFO_FLAG_AUTHENTICATE;
- if (sys_bclient)
- is->flags |= INFO_FLAG_BCLIENT;
-#ifdef REFCLOCK
- if (cal_enable)
- is->flags |= INFO_FLAG_CAL;
-#endif /* REFCLOCK */
- if (kern_enable)
- is->flags |= INFO_FLAG_KERNEL;
- if (mon_enabled != MON_OFF)
- is->flags |= INFO_FLAG_MONITOR;
- if (ntp_enable)
- is->flags |= INFO_FLAG_NTP;
- if (pps_enable)
- is->flags |= INFO_FLAG_PPS_SYNC;
- if (stats_control)
- is->flags |= INFO_FLAG_FILEGEN;
- is->bdelay = HTONS_FP(DTOFP(sys_bdelay));
- HTONL_UF(sys_authdelay.l_f, &is->authdelay);
-
- (void) more_pkt();
- flush_pkt();
-}
-
-
-/*
- * sys_stats - return system statistics
- */
-static void
-sys_stats(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_sys_stats *ss;
-
- /*
- * Importations from the protocol module
- */
- ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_sys_stats));
- ss->timeup = htonl((u_int32)current_time);
- ss->timereset = htonl((u_int32)(current_time - sys_stattime));
- ss->denied = htonl((u_int32)sys_restricted);
- ss->oldversionpkt = htonl((u_int32)sys_oldversionpkt);
- ss->newversionpkt = htonl((u_int32)sys_newversionpkt);
- ss->unknownversion = htonl((u_int32)sys_unknownversion);
- ss->badlength = htonl((u_int32)sys_badlength);
- ss->processed = htonl((u_int32)sys_processed);
- ss->badauth = htonl((u_int32)sys_badauth);
- ss->limitrejected = htonl((u_int32)sys_limitrejected);
- ss->received = htonl((u_int32)sys_received);
- (void) more_pkt();
- flush_pkt();
-}
-
-
-/*
- * mem_stats - return memory statistics
- */
-static void
-mem_stats(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_mem_stats *ms;
- register int i;
-
- /*
- * Importations from the peer module
- */
- 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 int total_peer_structs;
-
- ms = (struct info_mem_stats *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_mem_stats));
-
- ms->timereset = htonl((u_int32)(current_time - peer_timereset));
- ms->totalpeermem = htons((u_short)total_peer_structs);
- ms->freepeermem = htons((u_short)peer_free_count);
- ms->findpeer_calls = htonl((u_int32)findpeer_calls);
- ms->allocations = htonl((u_int32)peer_allocations);
- ms->demobilizations = htonl((u_int32)peer_demobilizations);
-
- for (i = 0; i < HASH_SIZE; i++) {
- if (peer_hash_count[i] > 255)
- ms->hashcount[i] = 255;
- else
- ms->hashcount[i] = (u_char)peer_hash_count[i];
- }
-
- (void) more_pkt();
- flush_pkt();
-}
-
-
-/*
- * io_stats - return io statistics
- */
-static void
-io_stats(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_io_stats *io;
-
- /*
- * Importations from the io module
- */
- extern u_long io_timereset;
-
- io = (struct info_io_stats *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_io_stats));
-
- io->timereset = htonl((u_int32)(current_time - io_timereset));
- io->totalrecvbufs = htons((u_short) total_recvbuffs());
- io->freerecvbufs = htons((u_short) free_recvbuffs());
- io->fullrecvbufs = htons((u_short) full_recvbuffs());
- io->lowwater = htons((u_short) lowater_additions());
- io->dropped = htonl((u_int32)packets_dropped);
- io->ignored = htonl((u_int32)packets_ignored);
- io->received = htonl((u_int32)packets_received);
- io->sent = htonl((u_int32)packets_sent);
- io->notsent = htonl((u_int32)packets_notsent);
- io->interrupts = htonl((u_int32)handler_calls);
- io->int_received = htonl((u_int32)handler_pkts);
-
- (void) more_pkt();
- flush_pkt();
-}
-
-
-/*
- * timer_stats - return timer statistics
- */
-static void
-timer_stats(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_timer_stats *ts;
-
- /*
- * Importations from the timer module
- */
- 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));
-
- ts->timereset = htonl((u_int32)(current_time - timer_timereset));
- ts->alarms = htonl((u_int32)alarm_overflow);
- ts->overflows = htonl((u_int32)timer_overflows);
- ts->xmtcalls = htonl((u_int32)timer_xmtcalls);
-
- (void) more_pkt();
- flush_pkt();
-}
-
-
-/*
- * loop_info - return the current state of the loop filter
- */
-static void
-loop_info(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_loop *li;
- l_fp ltmp;
-
- /*
- * Importations from the loop filter module
- */
- extern double last_offset;
- extern double drift_comp;
- extern int tc_counter;
- extern u_long last_time;
-
- li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_loop));
-
- DTOLFP(last_offset, &ltmp);
- HTONL_FP(&ltmp, &li->last_offset);
- DTOLFP(drift_comp * 1e6, &ltmp);
- HTONL_FP(&ltmp, &li->drift_comp);
- li->compliance = htonl((u_int32)(tc_counter));
- li->watchdog_timer = htonl((u_int32)(current_time - last_time));
-
- (void) more_pkt();
- flush_pkt();
-}
-
-
-/*
- * do_conf - add a peer to the configuration list
- */
-static void
-do_conf(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- int items;
- u_int fl;
- struct conf_peer *cp;
- struct conf_peer temp_cp;
- struct sockaddr_storage peeraddr;
- struct sockaddr_in tmp_clock;
-
- /*
- * Do a check of everything to see that it looks
- * okay. If not, complain about it. Note we are
- * very picky here.
- */
- items = INFO_NITEMS(inpkt->err_nitems);
- cp = (struct conf_peer *)inpkt->data;
- memset(&temp_cp, 0, sizeof(struct conf_peer));
- memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
- fl = 0;
- while (items-- > 0 && !fl) {
- if (((temp_cp.version) > NTP_VERSION)
- || ((temp_cp.version) < NTP_OLDVERSION))
- fl = 1;
- if (temp_cp.hmode != MODE_ACTIVE
- && temp_cp.hmode != MODE_CLIENT
- && temp_cp.hmode != MODE_BROADCAST)
- fl = 1;
- if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
- | CONF_FLAG_BURST | CONF_FLAG_SKEY))
- fl = 1;
- cp = (struct conf_peer *)
- ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
- }
-
- if (fl) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- /*
- * Looks okay, try it out
- */
- items = INFO_NITEMS(inpkt->err_nitems);
- cp = (struct conf_peer *)inpkt->data;
-
- while (items-- > 0) {
- memset(&temp_cp, 0, sizeof(struct conf_peer));
- memcpy(&temp_cp, (char *)cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
- memset((char *)&peeraddr, 0, sizeof(struct sockaddr_storage));
-
- fl = 0;
- if (temp_cp.flags & CONF_FLAG_AUTHENABLE)
- fl |= FLAG_AUTHENABLE;
- if (temp_cp.flags & CONF_FLAG_PREFER)
- fl |= FLAG_PREFER;
- if (temp_cp.flags & CONF_FLAG_BURST)
- fl |= FLAG_BURST;
- if (temp_cp.flags & CONF_FLAG_SKEY)
- fl |= FLAG_SKEY;
- if (client_v6_capable && temp_cp.v6_flag != 0) {
- peeraddr.ss_family = AF_INET6;
- GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
- } else {
- peeraddr.ss_family = AF_INET;
- GET_INADDR(peeraddr) = temp_cp.peeraddr;
- /*
- * Make sure the address is valid
- */
- tmp_clock = *CAST_V4(peeraddr);
- if (
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&tmp_clock) &&
-#endif
- ISBADADR(&tmp_clock)) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- }
- NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
-#endif
-
- /* XXX W2DO? minpoll/maxpoll arguments ??? */
- if (peer_config(&peeraddr, (struct interface *)0,
- temp_cp.hmode, temp_cp.version, temp_cp.minpoll,
- temp_cp.maxpoll, fl, temp_cp.ttl, temp_cp.keyid,
- NULL) == 0) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
- cp = (struct conf_peer *)
- ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
- }
-
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-#if 0
-/* XXX */
-/*
- * dns_a - Snarf DNS info for an association ID
- */
-static void
-dns_a(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_dns_assoc *dp;
- register int items;
- struct sockaddr_in peeraddr;
-
- /*
- * Do a check of everything to see that it looks
- * okay. If not, complain about it. Note we are
- * very picky here.
- */
- items = INFO_NITEMS(inpkt->err_nitems);
- dp = (struct info_dns_assoc *)inpkt->data;
-
- /*
- * Looks okay, try it out
- */
- items = INFO_NITEMS(inpkt->err_nitems);
- dp = (struct info_dns_assoc *)inpkt->data;
- memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
- peeraddr.sin_family = AF_INET;
- peeraddr.sin_port = htons(NTP_PORT);
-
- /*
- * Make sure the address is valid
- */
- if (
-#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
-#endif
- ISBADADR(&peeraddr)) {
-#ifdef REFCLOCK
- msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR");
-#else
- msyslog(LOG_ERR, "dns_a: ISBADADR");
-#endif
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- while (items-- > 0) {
- associd_t associd;
- size_t hnl;
- struct peer *peer;
- int bogon = 0;
-
- associd = dp->associd;
- peer = findpeerbyassoc(associd);
- if (peer == 0 || peer->flags & FLAG_REFCLOCK) {
- msyslog(LOG_ERR, "dns_a: %s",
- (peer == 0)
- ? "peer == 0"
- : "peer->flags & FLAG_REFCLOCK");
- ++bogon;
- }
- peeraddr.sin_addr.s_addr = dp->peeraddr;
- for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ;
- if (hnl >= sizeof dp->hostname) {
- msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld",
- (long)hnl, (long)sizeof dp->hostname);
- ++bogon;
- }
-
- msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
- dp->hostname,
- stoa((struct sockaddr_storage *)&peeraddr), associd,
- bogon);
-
- if (bogon) {
- /* If it didn't work */
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- } else {
-#if 0
-#ifdef PUBKEY
- crypto_public(peer, dp->hostname);
-#endif /* PUBKEY */
-#endif
- }
-
- dp++;
- }
-
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-#endif /* 0 */
-
-/*
- * do_unconf - remove a peer from the configuration list
- */
-static void
-do_unconf(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct conf_unpeer *cp;
- struct conf_unpeer temp_cp;
- register int items;
- register struct peer *peer;
- struct sockaddr_storage peeraddr;
- int bad, found;
-
- /*
- * This is a bit unstructured, but I like to be careful.
- * We check to see that every peer exists and is actually
- * configured. If so, we remove them. If not, we return
- * an error.
- */
- items = INFO_NITEMS(inpkt->err_nitems);
- cp = (struct conf_unpeer *)inpkt->data;
-
- bad = 0;
- while (items-- > 0 && !bad) {
- memset(&temp_cp, 0, sizeof(temp_cp));
- memset(&peeraddr, 0, sizeof(peeraddr));
- memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
- if (client_v6_capable && temp_cp.v6_flag != 0) {
- peeraddr.ss_family = AF_INET6;
- GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
- } else {
- peeraddr.ss_family = AF_INET;
- GET_INADDR(peeraddr) = temp_cp.peeraddr;
- }
- NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
-#endif
- found = 0;
- peer = (struct peer *)0;
- printf("searching for %s\n", stoa(&peeraddr));
- while (!found) {
- peer = findexistingpeer(&peeraddr, peer, -1);
- if (peer == (struct peer *)0)
- break;
- if (peer->flags & FLAG_CONFIG)
- found = 1;
- }
- if (!found)
- bad = 1;
- cp = (struct conf_unpeer *)
- ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
- }
-
- if (bad) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- /*
- * Now do it in earnest.
- */
-
- items = INFO_NITEMS(inpkt->err_nitems);
- cp = (struct conf_unpeer *)inpkt->data;
- while (items-- > 0) {
- memset(&temp_cp, 0, sizeof(temp_cp));
- memset(&peeraddr, 0, sizeof(peeraddr));
- memcpy(&temp_cp, cp, INFO_ITEMSIZE(inpkt->mbz_itemsize));
- if (client_v6_capable && temp_cp.v6_flag != 0) {
- peeraddr.ss_family = AF_INET6;
- GET_INADDR6(peeraddr) = temp_cp.peeraddr6;
- } else {
- peeraddr.ss_family = AF_INET;
- GET_INADDR(peeraddr) = temp_cp.peeraddr;
- }
- NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
-#endif
- peer_unconfig(&peeraddr, (struct interface *)0, -1);
- cp = (struct conf_unpeer *)
- ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
- }
-
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
- * set_sys_flag - set system flags
- */
-static void
-set_sys_flag(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- setclr_flags(srcadr, inter, inpkt, 1);
-}
-
-
-/*
- * clr_sys_flag - clear system flags
- */
-static void
-clr_sys_flag(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- setclr_flags(srcadr, inter, inpkt, 0);
-}
-
-
-/*
- * setclr_flags - do the grunge work of flag setting/clearing
- */
-static void
-setclr_flags(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt,
- u_long set
- )
-{
- register u_int flags;
-
- if (INFO_NITEMS(inpkt->err_nitems) > 1) {
- msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- flags = ((struct conf_sys_flags *)inpkt->data)->flags;
-
- if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
- SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
- SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) {
- msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
- flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
- SYS_FLAG_NTP | SYS_FLAG_KERNEL |
- SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN |
- SYS_FLAG_AUTH | SYS_FLAG_CAL));
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- if (flags & SYS_FLAG_BCLIENT)
- proto_config(PROTO_BROADCLIENT, set, 0., NULL);
- if (flags & SYS_FLAG_PPS)
- proto_config(PROTO_PPS, set, 0., NULL);
- if (flags & SYS_FLAG_NTP)
- proto_config(PROTO_NTP, set, 0., NULL);
- if (flags & SYS_FLAG_KERNEL)
- proto_config(PROTO_KERNEL, set, 0., NULL);
- if (flags & SYS_FLAG_MONITOR)
- proto_config(PROTO_MONITOR, set, 0., NULL);
- if (flags & SYS_FLAG_FILEGEN)
- proto_config(PROTO_FILEGEN, set, 0., NULL);
- if (flags & SYS_FLAG_AUTH)
- proto_config(PROTO_AUTHENTICATE, set, 0., NULL);
- if (flags & SYS_FLAG_CAL)
- proto_config(PROTO_CAL, set, 0., NULL);
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
- * list_restrict - return the restrict list
- */
-static void
-list_restrict(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_restrict *ir;
- register struct restrictlist *rl;
- register struct restrictlist6 *rl6;
-
-#ifdef DEBUG
- if (debug > 2)
- printf("wants restrict list summary\n");
-#endif
-
- ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_restrict));
-
- for (rl = restrictlist; rl != 0 && ir != 0; rl = rl->next) {
- ir->addr = htonl(rl->addr);
- if (client_v6_capable)
- ir->v6_flag = 0;
- ir->mask = htonl(rl->mask);
- ir->count = htonl((u_int32)rl->count);
- ir->flags = htons(rl->flags);
- ir->mflags = htons(rl->mflags);
- ir = (struct info_restrict *)more_pkt();
- }
- if (client_v6_capable)
- for (rl6 = restrictlist6; rl6 != 0 && ir != 0; rl6 = rl6->next) {
- ir->addr6 = rl6->addr6;
- ir->mask6 = rl6->mask6;
- ir->v6_flag = 1;
- ir->count = htonl((u_int32)rl6->count);
- ir->flags = htons(rl6->flags);
- ir->mflags = htons(rl6->mflags);
- ir = (struct info_restrict *)more_pkt();
- }
- flush_pkt();
-}
-
-
-
-/*
- * do_resaddflags - add flags to a restrict entry (or create one)
- */
-static void
-do_resaddflags(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- do_restrict(srcadr, inter, inpkt, RESTRICT_FLAGS);
-}
-
-
-
-/*
- * do_ressubflags - remove flags from a restrict entry
- */
-static void
-do_ressubflags(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- do_restrict(srcadr, inter, inpkt, RESTRICT_UNFLAG);
-}
-
-
-/*
- * do_unrestrict - remove a restrict entry from the list
- */
-static void
-do_unrestrict(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- do_restrict(srcadr, inter, inpkt, RESTRICT_REMOVE);
-}
-
-
-
-
-
-/*
- * do_restrict - do the dirty stuff of dealing with restrictions
- */
-static void
-do_restrict(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt,
- int op
- )
-{
- register struct conf_restrict *cr;
- register int items;
- struct sockaddr_storage matchaddr;
- struct sockaddr_storage matchmask;
- int bad;
-
- /*
- * Do a check of the flags to make sure that only
- * the NTPPORT flag is set, if any. If not, complain
- * about it. Note we are very picky here.
- */
- items = INFO_NITEMS(inpkt->err_nitems);
- cr = (struct conf_restrict *)inpkt->data;
-
- bad = 0;
- while (items-- > 0 && !bad) {
- if (cr->mflags & ~(RESM_NTPONLY))
- bad |= 1;
- if (cr->flags & ~(RES_ALLFLAGS))
- bad |= 2;
- if (cr->mask != htonl(INADDR_ANY)) {
- if (client_v6_capable && cr->v6_flag != 0) {
- if (IN6_IS_ADDR_UNSPECIFIED(&cr->addr6))
- bad |= 4;
- } else
- if (cr->addr == htonl(INADDR_ANY))
- bad |= 8;
- }
- cr = (struct conf_restrict *)((char *)cr +
- INFO_ITEMSIZE(inpkt->mbz_itemsize));
- }
-
- if (bad) {
- msyslog(LOG_ERR, "do_restrict: bad = %#x", bad);
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- /*
- * Looks okay, try it out
- */
- items = INFO_NITEMS(inpkt->err_nitems);
- cr = (struct conf_restrict *)inpkt->data;
- memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage));
- memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage));
-
- while (items-- > 0) {
- if (client_v6_capable && cr->v6_flag != 0) {
- GET_INADDR6(matchaddr) = cr->addr6;
- GET_INADDR6(matchmask) = cr->mask6;
- matchaddr.ss_family = AF_INET6;
- matchmask.ss_family = AF_INET6;
- } else {
- GET_INADDR(matchaddr) = cr->addr;
- GET_INADDR(matchmask) = cr->mask;
- matchaddr.ss_family = AF_INET;
- matchmask.ss_family = AF_INET;
- }
- hack_restrict(op, &matchaddr, &matchmask, cr->mflags,
- cr->flags);
- cr++;
- }
-
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
- * mon_getlist - return monitor data
- */
-static void
-mon_getlist_0(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_monitor *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 0 list\n");
-#endif
- if (!mon_enabled) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
- im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_monitor));
- for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
- md = md->mru_next) {
- im->lasttime = htonl((u_int32)md->avg_interval);
- im->firsttime = htonl((u_int32)(current_time - md->lasttime));
- im->lastdrop = htonl((u_int32)md->drop_count);
- im->count = htonl((u_int32)(md->count));
- if (md->rmtadr.ss_family == AF_INET6) {
- if (!client_v6_capable)
- continue;
- im->addr6 = GET_INADDR6(md->rmtadr);
- im->v6_flag = 1;
- } else {
- im->addr = GET_INADDR(md->rmtadr);
- if (client_v6_capable)
- im->v6_flag = 0;
- }
- im->port = md->rmtport;
- im->mode = md->mode;
- im->version = md->version;
- im = (struct info_monitor *)more_pkt();
- }
- flush_pkt();
-}
-
-/*
- * mon_getlist - return monitor data
- */
-static void
-mon_getlist_1(
- struct sockaddr_storage *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;
-
- if (!mon_enabled) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
- im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_monitor_1));
- for (md = mon_mru_list.mru_next; md != &mon_mru_list && im != 0;
- md = md->mru_next) {
- im->lasttime = htonl((u_int32)md->avg_interval);
- im->firsttime = htonl((u_int32)(current_time - md->lasttime));
- im->lastdrop = htonl((u_int32)md->drop_count);
- im->count = htonl((u_int32)md->count);
- if (md->rmtadr.ss_family == AF_INET6) {
- if (!client_v6_capable)
- continue;
- im->addr6 = GET_INADDR6(md->rmtadr);
- im->v6_flag = 1;
- im->daddr6 = GET_INADDR6(md->interface->sin);
- } else {
- im->addr = GET_INADDR(md->rmtadr);
- if (client_v6_capable)
- im->v6_flag = 0;
- im->daddr = (md->cast_flags == MDF_BCAST)
- ? GET_INADDR(md->interface->bcast)
- : (md->cast_flags
- ? (GET_INADDR(md->interface->sin)
- ? GET_INADDR(md->interface->sin)
- : GET_INADDR(md->interface->bcast))
- : 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 {
- int flag; /* flag this corresponds to */
- void (*handler) P((void)); /* routine to handle request */
-};
-
-struct reset_entry reset_entries[] = {
- { RESET_FLAG_ALLPEERS, peer_all_reset },
- { RESET_FLAG_IO, io_clr_stats },
- { RESET_FLAG_SYS, proto_clr_stats },
- { RESET_FLAG_MEM, peer_clr_stats },
- { RESET_FLAG_TIMER, timer_clr_stats },
- { RESET_FLAG_AUTH, reset_auth_stats },
- { RESET_FLAG_CTL, ctl_clr_stats },
- { 0, 0 }
-};
-
-/*
- * reset_stats - reset statistic counters here and there
- */
-static void
-reset_stats(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- u_long flags;
- struct reset_entry *rent;
-
- if (INFO_NITEMS(inpkt->err_nitems) > 1) {
- msyslog(LOG_ERR, "reset_stats: err_nitems > 1");
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- flags = ((struct reset_flags *)inpkt->data)->flags;
-
- if (flags & ~RESET_ALLFLAGS) {
- msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
- flags & ~RESET_ALLFLAGS);
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- for (rent = reset_entries; rent->flag != 0; rent++) {
- if (flags & rent->flag)
- (rent->handler)();
- }
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
- * reset_peer - clear a peer's statistics
- */
-static void
-reset_peer(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct conf_unpeer *cp;
- register int items;
- register struct peer *peer;
- struct sockaddr_storage peeraddr;
- int bad;
-
- /*
- * We check first to see that every peer exists. If not,
- * we return an error.
- */
-
- items = INFO_NITEMS(inpkt->err_nitems);
- cp = (struct conf_unpeer *)inpkt->data;
-
- bad = 0;
- while (items-- > 0 && !bad) {
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (client_v6_capable && cp->v6_flag != 0) {
- GET_INADDR6(peeraddr) = cp->peeraddr6;
- peeraddr.ss_family = AF_INET6;
- } else {
- GET_INADDR(peeraddr) = cp->peeraddr;
- peeraddr.ss_family = AF_INET;
- }
- NSRCPORT(&peeraddr) = htons(NTP_PORT);
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
-#endif
- peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
- if (peer == (struct peer *)0)
- bad++;
- cp = (struct conf_unpeer *)((char *)cp +
- INFO_ITEMSIZE(inpkt->mbz_itemsize));
- }
-
- if (bad) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- /*
- * Now do it in earnest.
- */
-
- items = INFO_NITEMS(inpkt->err_nitems);
- cp = (struct conf_unpeer *)inpkt->data;
- while (items-- > 0) {
- memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (client_v6_capable && cp->v6_flag != 0) {
- GET_INADDR6(peeraddr) = cp->peeraddr6;
- peeraddr.ss_family = AF_INET6;
- } else {
- GET_INADDR(peeraddr) = cp->peeraddr;
- peeraddr.ss_family = AF_INET;
- }
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- peeraddr.ss_len = SOCKLEN(&peeraddr);
-#endif
- peer = findexistingpeer(&peeraddr, (struct peer *)0, -1);
- while (peer != 0) {
- peer_reset(peer);
- peer = findexistingpeer(&peeraddr, (struct peer *)peer, -1);
- }
- cp = (struct conf_unpeer *)((char *)cp +
- INFO_ITEMSIZE(inpkt->mbz_itemsize));
- }
-
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
- * do_key_reread - reread the encryption key file
- */
-static void
-do_key_reread(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- rereadkeys();
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
- * trust_key - make one or more keys trusted
- */
-static void
-trust_key(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- do_trustkey(srcadr, inter, inpkt, 1);
-}
-
-
-/*
- * untrust_key - make one or more keys untrusted
- */
-static void
-untrust_key(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- do_trustkey(srcadr, inter, inpkt, 0);
-}
-
-
-/*
- * do_trustkey - make keys either trustable or untrustable
- */
-static void
-do_trustkey(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt,
- u_long trust
- )
-{
- register u_long *kp;
- register int items;
-
- items = INFO_NITEMS(inpkt->err_nitems);
- kp = (u_long *)inpkt->data;
- while (items-- > 0) {
- authtrust(*kp, trust);
- kp++;
- }
-
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-/*
- * get_auth_info - return some stats concerning the authentication module
- */
-static void
-get_auth_info(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_auth *ia;
-
- /*
- * Importations from the authentication module
- */
- extern u_long authnumkeys;
- extern int authnumfreekeys;
- extern u_long authkeylookups;
- extern u_long authkeynotfound;
- extern u_long authencryptions;
- extern u_long authdecryptions;
- extern u_long authkeyuncached;
- extern u_long authkeyexpired;
-
- ia = (struct info_auth *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_auth));
-
- ia->numkeys = htonl((u_int32)authnumkeys);
- ia->numfreekeys = htonl((u_int32)authnumfreekeys);
- ia->keylookups = htonl((u_int32)authkeylookups);
- ia->keynotfound = htonl((u_int32)authkeynotfound);
- ia->encryptions = htonl((u_int32)authencryptions);
- ia->decryptions = htonl((u_int32)authdecryptions);
- ia->keyuncached = htonl((u_int32)authkeyuncached);
- ia->expired = htonl((u_int32)authkeyexpired);
- ia->timereset = htonl((u_int32)(current_time - auth_timereset));
-
- (void) more_pkt();
- flush_pkt();
-}
-
-
-
-/*
- * reset_auth_stats - reset the authentication stat counters. Done here
- * to keep ntp-isms out of the authentication module
- */
-static void
-reset_auth_stats(void)
-{
- /*
- * Importations from the authentication module
- */
- 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;
- authkeyuncached = 0;
- auth_timereset = current_time;
-}
-
-
-/*
- * req_get_traps - return information about current trap holders
- */
-static void
-req_get_traps(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_trap *it;
- register struct ctl_trap *tr;
- register int i;
-
- /*
- * Imported from the control module
- */
- extern struct ctl_trap ctl_trap[];
- extern int num_ctl_traps;
-
- if (num_ctl_traps == 0) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt,
- v6sizeof(struct info_trap));
-
- for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) {
- if (tr->tr_flags & TRAP_INUSE) {
- if (tr->tr_addr.ss_family == AF_INET) {
- if (tr->tr_localaddr == any_interface)
- it->local_address = 0;
- else
- it->local_address
- = GET_INADDR(tr->tr_localaddr->sin);
- it->trap_address = GET_INADDR(tr->tr_addr);
- if (client_v6_capable)
- it->v6_flag = 0;
- } else {
- if (!client_v6_capable)
- continue;
- it->local_address6
- = GET_INADDR6(tr->tr_localaddr->sin);
- it->trap_address6 = GET_INADDR6(tr->tr_addr);
- it->v6_flag = 1;
- }
- it->trap_port = NSRCPORT(&tr->tr_addr);
- it->sequence = htons(tr->tr_sequence);
- it->settime = htonl((u_int32)(current_time - tr->tr_settime));
- it->origtime = htonl((u_int32)(current_time - tr->tr_origtime));
- it->resets = htonl((u_int32)tr->tr_resets);
- it->flags = htonl((u_int32)tr->tr_flags);
- it = (struct info_trap *)more_pkt();
- }
- }
- flush_pkt();
-}
-
-
-/*
- * req_set_trap - configure a trap
- */
-static void
-req_set_trap(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- do_setclr_trap(srcadr, inter, inpkt, 1);
-}
-
-
-
-/*
- * req_clr_trap - unconfigure a trap
- */
-static void
-req_clr_trap(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- do_setclr_trap(srcadr, inter, inpkt, 0);
-}
-
-
-
-/*
- * do_setclr_trap - do the grunge work of (un)configuring a trap
- */
-static void
-do_setclr_trap(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt,
- int set
- )
-{
- register struct conf_trap *ct;
- register struct interface *linter;
- int res;
- struct sockaddr_storage laddr;
-
- /*
- * Prepare sockaddr_storage structure
- */
- memset((char *)&laddr, 0, sizeof laddr);
- laddr.ss_family = srcadr->ss_family;
- NSRCPORT(&laddr) = ntohs(NTP_PORT);
-
- /*
- * Restrict ourselves to one item only. This eliminates
- * the error reporting problem.
- */
- if (INFO_NITEMS(inpkt->err_nitems) > 1) {
- msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1");
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
- ct = (struct conf_trap *)inpkt->data;
-
- /*
- * Look for the local interface. If none, use the default.
- */
- if (ct->local_address == 0) {
- linter = any_interface;
- } else {
- if (laddr.ss_family == AF_INET)
- GET_INADDR(laddr) = ct->local_address;
- else
- GET_INADDR6(laddr) = ct->local_address6;
- linter = findinterface(&laddr);
- if (linter == NULL) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
- }
-
- if (laddr.ss_family == AF_INET)
- GET_INADDR(laddr) = ct->trap_address;
- else
- GET_INADDR6(laddr) = ct->trap_address6;
- if (ct->trap_port != 0)
- NSRCPORT(&laddr) = ct->trap_port;
- else
- NSRCPORT(&laddr) = htons(TRAPPORT);
-
- if (set) {
- res = ctlsettrap(&laddr, linter, 0,
- INFO_VERSION(inpkt->rm_vn_mode));
- } else {
- res = ctlclrtrap(&laddr, linter, 0);
- }
-
- if (!res) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- } else {
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
- }
- return;
-}
-
-
-
-/*
- * set_request_keyid - set the keyid used to authenticate requests
- */
-static void
-set_request_keyid(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- keyid_t keyid;
-
- /*
- * Restrict ourselves to one item only.
- */
- if (INFO_NITEMS(inpkt->err_nitems) > 1) {
- msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- keyid = ntohl(*((u_int32 *)(inpkt->data)));
- info_auth_keyid = keyid;
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-
-/*
- * set_control_keyid - set the keyid used to authenticate requests
- */
-static void
-set_control_keyid(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- keyid_t keyid;
- extern keyid_t ctl_auth_keyid;
-
- /*
- * Restrict ourselves to one item only.
- */
- if (INFO_NITEMS(inpkt->err_nitems) > 1) {
- msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- keyid = ntohl(*((u_int32 *)(inpkt->data)));
- ctl_auth_keyid = keyid;
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-
-
-
-/*
- * get_ctl_stats - return some stats concerning the control message module
- */
-static void
-get_ctl_stats(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_control *ic;
-
- /*
- * 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;
-
- ic = (struct info_control *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_control));
-
- ic->ctltimereset = htonl((u_int32)(current_time - ctltimereset));
- ic->numctlreq = htonl((u_int32)numctlreq);
- ic->numctlbadpkts = htonl((u_int32)numctlbadpkts);
- ic->numctlresponses = htonl((u_int32)numctlresponses);
- ic->numctlfrags = htonl((u_int32)numctlfrags);
- ic->numctlerrors = htonl((u_int32)numctlerrors);
- ic->numctltooshort = htonl((u_int32)numctltooshort);
- ic->numctlinputresp = htonl((u_int32)numctlinputresp);
- ic->numctlinputfrag = htonl((u_int32)numctlinputfrag);
- ic->numctlinputerr = htonl((u_int32)numctlinputerr);
- ic->numctlbadoffset = htonl((u_int32)numctlbadoffset);
- ic->numctlbadversion = htonl((u_int32)numctlbadversion);
- ic->numctldatatooshort = htonl((u_int32)numctldatatooshort);
- ic->numctlbadop = htonl((u_int32)numctlbadop);
- ic->numasyncmsgs = htonl((u_int32)numasyncmsgs);
-
- (void) more_pkt();
- flush_pkt();
-}
-
-
-#ifdef KERNEL_PLL
-/*
- * get_kernel_info - get kernel pll/pps information
- */
-static void
-get_kernel_info(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_kernel *ik;
- struct timex ntx;
-
- if (!pll_control) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- memset((char *)&ntx, 0, sizeof(ntx));
- if (ntp_adjtime(&ntx) < 0)
- msyslog(LOG_ERR, "get_kernel_info: ntp_adjtime() failed: %m");
- ik = (struct info_kernel *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_kernel));
-
- /*
- * pll variables
- */
- ik->offset = htonl((u_int32)ntx.offset);
- ik->freq = htonl((u_int32)ntx.freq);
- ik->maxerror = htonl((u_int32)ntx.maxerror);
- ik->esterror = htonl((u_int32)ntx.esterror);
- ik->status = htons(ntx.status);
- ik->constant = htonl((u_int32)ntx.constant);
- ik->precision = htonl((u_int32)ntx.precision);
- ik->tolerance = htonl((u_int32)ntx.tolerance);
-
- /*
- * pps variables
- */
- ik->ppsfreq = htonl((u_int32)ntx.ppsfreq);
- ik->jitter = htonl((u_int32)ntx.jitter);
- ik->shift = htons(ntx.shift);
- ik->stabil = htonl((u_int32)ntx.stabil);
- ik->jitcnt = htonl((u_int32)ntx.jitcnt);
- ik->calcnt = htonl((u_int32)ntx.calcnt);
- ik->errcnt = htonl((u_int32)ntx.errcnt);
- ik->stbcnt = htonl((u_int32)ntx.stbcnt);
-
- (void) more_pkt();
- flush_pkt();
-}
-#endif /* KERNEL_PLL */
-
-
-#ifdef REFCLOCK
-/*
- * get_clock_info - get info about a clock
- */
-static void
-get_clock_info(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct info_clock *ic;
- register u_int32 *clkaddr;
- register int items;
- struct refclockstat clock_stat;
- struct sockaddr_storage addr;
- struct sockaddr_in tmp_clock;
- l_fp ltmp;
-
- memset((char *)&addr, 0, sizeof addr);
- addr.ss_family = AF_INET;
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
-#endif
- NSRCPORT(&addr) = htons(NTP_PORT);
- items = INFO_NITEMS(inpkt->err_nitems);
- clkaddr = (u_int32 *) inpkt->data;
-
- ic = (struct info_clock *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_clock));
-
- while (items-- > 0) {
- tmp_clock.sin_addr.s_addr = *clkaddr++;
- CAST_V4(addr)->sin_addr = tmp_clock.sin_addr;
- if (!ISREFCLOCKADR(&tmp_clock) ||
- findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- clock_stat.kv_list = (struct ctl_var *)0;
-
- refclock_control(&addr, (struct refclockstat *)0, &clock_stat);
-
- ic->clockadr = tmp_clock.sin_addr.s_addr;
- ic->type = clock_stat.type;
- ic->flags = clock_stat.flags;
- ic->lastevent = clock_stat.lastevent;
- ic->currentstatus = clock_stat.currentstatus;
- ic->polls = htonl((u_int32)clock_stat.polls);
- ic->noresponse = htonl((u_int32)clock_stat.noresponse);
- ic->badformat = htonl((u_int32)clock_stat.badformat);
- ic->baddata = htonl((u_int32)clock_stat.baddata);
- ic->timestarted = htonl((u_int32)clock_stat.timereset);
- DTOLFP(clock_stat.fudgetime1, &ltmp);
- HTONL_FP(&ltmp, &ic->fudgetime1);
- DTOLFP(clock_stat.fudgetime2, &ltmp);
- HTONL_FP(&ltmp, &ic->fudgetime2);
- ic->fudgeval1 = htonl((u_int32)clock_stat.fudgeval1);
- ic->fudgeval2 = htonl((u_int32)clock_stat.fudgeval2);
-
- free_varlist(clock_stat.kv_list);
-
- ic = (struct info_clock *)more_pkt();
- }
- flush_pkt();
-}
-
-
-
-/*
- * set_clock_fudge - get a clock's fudge factors
- */
-static void
-set_clock_fudge(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register struct conf_fudge *cf;
- register int items;
- struct refclockstat clock_stat;
- struct sockaddr_storage addr;
- struct sockaddr_in tmp_clock;
- l_fp ltmp;
-
- memset((char *)&addr, 0, sizeof addr);
- memset((char *)&clock_stat, 0, sizeof clock_stat);
- items = INFO_NITEMS(inpkt->err_nitems);
- cf = (struct conf_fudge *) inpkt->data;
-
- while (items-- > 0) {
- tmp_clock.sin_addr.s_addr = cf->clockadr;
- *CAST_V4(addr) = tmp_clock;
- addr.ss_family = AF_INET;
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
-#endif
- NSRCPORT(&addr) = htons(NTP_PORT);
- if (!ISREFCLOCKADR(&tmp_clock) ||
- findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- switch(ntohl(cf->which)) {
- case FUDGE_TIME1:
- NTOHL_FP(&cf->fudgetime, &ltmp);
- LFPTOD(&ltmp, clock_stat.fudgetime1);
- clock_stat.haveflags = CLK_HAVETIME1;
- break;
- case FUDGE_TIME2:
- NTOHL_FP(&cf->fudgetime, &ltmp);
- LFPTOD(&ltmp, clock_stat.fudgetime2);
- clock_stat.haveflags = CLK_HAVETIME2;
- break;
- case FUDGE_VAL1:
- clock_stat.fudgeval1 = ntohl(cf->fudgeval_flags);
- clock_stat.haveflags = CLK_HAVEVAL1;
- break;
- case FUDGE_VAL2:
- clock_stat.fudgeval2 = ntohl(cf->fudgeval_flags);
- clock_stat.haveflags = CLK_HAVEVAL2;
- break;
- case FUDGE_FLAGS:
- clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf);
- clock_stat.haveflags =
- (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
- break;
- default:
- msyslog(LOG_ERR, "set_clock_fudge: default!");
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
-
- refclock_control(&addr, &clock_stat, (struct refclockstat *)0);
- }
-
- req_ack(srcadr, inter, inpkt, INFO_OKAY);
-}
-#endif
-
-#ifdef REFCLOCK
-/*
- * get_clkbug_info - get debugging info about a clock
- */
-static void
-get_clkbug_info(
- struct sockaddr_storage *srcadr,
- struct interface *inter,
- struct req_pkt *inpkt
- )
-{
- register int i;
- register struct info_clkbug *ic;
- register u_int32 *clkaddr;
- register int items;
- struct refclockbug bug;
- struct sockaddr_storage addr;
- struct sockaddr_in tmp_clock;
-
- memset((char *)&addr, 0, sizeof addr);
- addr.ss_family = AF_INET;
-#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- addr.ss_len = SOCKLEN(&addr);
-#endif
- NSRCPORT(&addr) = htons(NTP_PORT);
- items = INFO_NITEMS(inpkt->err_nitems);
- clkaddr = (u_int32 *) inpkt->data;
-
- ic = (struct info_clkbug *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_clkbug));
-
- while (items-- > 0) {
- tmp_clock.sin_addr.s_addr = *clkaddr++;
- GET_INADDR(addr) = tmp_clock.sin_addr.s_addr;
- if (!ISREFCLOCKADR(&tmp_clock) ||
- findexistingpeer(&addr, (struct peer *)0, -1) == 0) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- memset((char *)&bug, 0, sizeof bug);
- refclock_buginfo(&addr, &bug);
- if (bug.nvalues == 0 && bug.ntimes == 0) {
- req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
- return;
- }
-
- ic->clockadr = tmp_clock.sin_addr.s_addr;
- i = bug.nvalues;
- if (i > NUMCBUGVALUES)
- i = NUMCBUGVALUES;
- ic->nvalues = (u_char)i;
- ic->svalues = htons((u_short) (bug.svalues & ((1<<i)-1)));
- while (--i >= 0)
- ic->values[i] = htonl(bug.values[i]);
-
- i = bug.ntimes;
- if (i > NUMCBUGTIMES)
- i = NUMCBUGTIMES;
- ic->ntimes = (u_char)i;
- ic->stimes = htonl(bug.stimes);
- while (--i >= 0) {
- HTONL_FP(&bug.times[i], &ic->times[i]);
- }
-
- ic = (struct info_clkbug *)more_pkt();
- }
- flush_pkt();
-}
-#endif
diff --git a/contrib/ntp/ntpd/ntp_restrict.c b/contrib/ntp/ntpd/ntp_restrict.c
deleted file mode 100644
index ede4225..0000000
--- a/contrib/ntp/ntpd/ntp_restrict.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * ntp_restrict.c - determine host restrictions
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "ntpd.h"
-#include "ntp_if.h"
-#include "ntp_stdlib.h"
-
-/*
- * This code keeps a simple address-and-mask list of hosts we want
- * to place restrictions on (or remove them from). The restrictions
- * are implemented as a set of flags which tell you what the host
- * can't do. There is a subroutine entry to return the flags. The
- * list is kept sorted to reduce the average number of comparisons
- * and make sure you get the set of restrictions most specific to
- * the address.
- *
- * The algorithm is that, when looking up a host, it is first assumed
- * that the default set of restrictions will apply. It then searches
- * down through the list. Whenever it finds a match it adopts the
- * match's flags instead. When you hit the point where the sorted
- * address is greater than the target, you return with the last set of
- * flags you found. Because of the ordering of the list, the most
- * specific match will provide the final set of flags.
- *
- * This was originally intended to restrict you from sync'ing to your
- * own broadcasts when you are doing that, by restricting yourself from
- * your own interfaces. It was also thought it would sometimes be useful
- * to keep a misbehaving host or two from abusing your primary clock. It
- * has been expanded, however, to suit the needs of those with more
- * restrictive access policies.
- */
-/*
- * We will use two lists, one for IPv4 addresses and one for IPv6
- * addresses. This is not protocol-independant but for now I can't
- * find a way to respect this. We'll check this later... JFB 07/2001
- */
-#define SET_IPV6_ADDR_MASK(dst, src, msk) \
- do { \
- int idx; \
- for (idx = 0; idx < 16; idx++) { \
- (dst)->s6_addr[idx] = \
- (u_char) ((src)->s6_addr[idx] & (msk)->s6_addr[idx]); \
- } \
- } while (0)
-
-/*
- * Memory allocation parameters. We allocate INITRESLIST entries
- * initially, and add INCRESLIST entries to the free list whenever
- * we run out.
- */
-#define INITRESLIST 10
-#define INCRESLIST 5
-
-#define RES_AVG 8. /* interpacket averaging factor */
-
-/*
- * The restriction list
- */
-struct restrictlist *restrictlist;
-struct restrictlist6 *restrictlist6;
-static int restrictcount; /* count of entries in the res list */
-static int restrictcount6; /* count of entries in the res list 2*/
-
-/*
- * The free list and associated counters. Also some uninteresting
- * stat counters.
- */
-static struct restrictlist *resfree;
-static struct restrictlist6 *resfree6;
-static int numresfree; /* number of structures on free list */
-static int numresfree6; /* number of structures on free list 2 */
-
-static u_long res_calls;
-static u_long res_found;
-static u_long res_not_found;
-
-/*
- * Parameters of the RES_LIMITED restriction option.
- */
-u_long res_avg_interval = 5; /* min average interpacket interval */
-u_long res_min_interval = 1; /* min interpacket interval */
-
-/*
- * Count number of restriction entries referring to RES_LIMITED controls
- * activation/deactivation of monitoring (with respect to RES_LIMITED
- * control)
- */
-static u_long res_limited_refcnt;
-static u_long res_limited_refcnt6;
-
-/*
- * Our initial allocation of lists entries.
- */
-static struct restrictlist resinit[INITRESLIST];
-static struct restrictlist6 resinit6[INITRESLIST];
-
-/*
- * init_restrict - initialize the restriction data structures
- */
-void
-init_restrict(void)
-{
- register int i;
-
- /*
- * Zero the list and put all but one on the free list
- */
- resfree = 0;
- memset((char *)resinit, 0, sizeof resinit);
- resfree6 = 0;
- memset((char *)resinit6, 0, sizeof resinit6);
- for (i = 1; i < INITRESLIST; i++) {
- resinit[i].next = resfree;
- resinit6[i].next = resfree6;
- resfree = &resinit[i];
- resfree6 = &resinit6[i];
- }
- numresfree = INITRESLIST-1;
- numresfree6 = INITRESLIST-1;
-
- /*
- * Put the remaining item at the head of the list as our default
- * entry. Everything in here should be zero for now.
- */
- resinit[0].addr = htonl(INADDR_ANY);
- resinit[0].mask = 0;
- memset(&resinit6[0].addr6, 0, sizeof(struct in6_addr));
- memset(&resinit6[0].mask6, 0, sizeof(struct in6_addr));
- restrictlist = &resinit[0];
- restrictlist6 = &resinit6[0];
- restrictcount = 1;
- restrictcount = 2;
-
- /*
- * fix up stat counters
- */
- res_calls = 0;
- res_found = 0;
- res_not_found = 0;
-
- /*
- * set default values for RES_LIMIT functionality
- */
- res_limited_refcnt = 0;
- res_limited_refcnt6 = 0;
-}
-
-
-/*
- * restrictions - return restrictions for this host
- */
-int
-restrictions(
- struct sockaddr_storage *srcadr
- )
-{
- struct restrictlist *rl;
- struct restrictlist *match = NULL;
- struct restrictlist6 *rl6;
- struct restrictlist6 *match6 = NULL;
- struct in6_addr hostaddr6;
- struct in6_addr hostservaddr6;
- u_int32 hostaddr;
- int flags = 0;
- int isntpport;
-
- res_calls++;
- if (srcadr->ss_family == AF_INET) {
- /*
- * We need the host address in host order. Also need to
- * know whether this is from the ntp port or not.
- */
- hostaddr = SRCADR(srcadr);
- isntpport = (SRCPORT(srcadr) == NTP_PORT);
-
- /*
- * Ignore any packets with a multicast source address
- * (this should be done early in the receive process,
- * later!)
- */
- if (IN_CLASSD(SRCADR(srcadr)))
- return (int)RES_IGNORE;
-
- /*
- * Set match to first entry, which is default entry.
- * Work our way down from there.
- */
- match = restrictlist;
- for (rl = match->next; rl != 0 && rl->addr <= hostaddr;
- rl = rl->next)
- if ((hostaddr & rl->mask) == rl->addr) {
- if ((rl->mflags & RESM_NTPONLY) &&
- !isntpport)
- continue;
- match = rl;
- }
- match->count++;
- if (match == restrictlist)
- res_not_found++;
- else
- res_found++;
- flags = match->flags;
- }
-
- /* IPv6 source address */
- if (srcadr->ss_family == AF_INET6) {
- /*
- * Need to know whether this is from the ntp port or
- * not.
- */
- hostaddr6 = GET_INADDR6(*srcadr);
- isntpport = (ntohs((
- (struct sockaddr_in6 *)srcadr)->sin6_port) ==
- NTP_PORT);
-
- /*
- * Ignore any packets with a multicast source address
- * (this should be done early in the receive process,
- * later!)
- */
- if (IN6_IS_ADDR_MULTICAST(&hostaddr6))
- return (int)RES_IGNORE;
-
- /*
- * Set match to first entry, which is default entry.
- * Work our way down from there.
- */
- match6 = restrictlist6;
- for (rl6 = match6->next; rl6 != 0 &&
- (memcmp(&(rl6->addr6), &hostaddr6,
- sizeof(hostaddr6)) <= 0); rl6 = rl6->next) {
- SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6,
- &rl6->mask6);
- if (memcmp(&hostservaddr6, &(rl6->addr6),
- sizeof(hostservaddr6)) == 0) {
- if ((rl6->mflags & RESM_NTPONLY) &&
- !isntpport)
- continue;
- match6 = rl6;
- }
- }
- match6->count++;
- if (match6 == restrictlist6)
- res_not_found++;
- else
- res_found++;
- flags = match6->flags;
- }
-
- /*
- * The following implements a generalized call gap facility.
- * Douse the RES_LIMITED bit only if the interval since the last
- * packet is greater than res_min_interval and the average is
- * greater thatn res_avg_interval.
- */
- if (mon_enabled == MON_OFF) {
- flags &= ~RES_LIMITED;
- } else {
- struct mon_data *md;
-
- /*
- * At this poin the most recent arrival is first in the
- * MRU list. Let the first 10 packets in for free until
- * the average stabilizes.
- */
- md = mon_mru_list.mru_next;
- if (md->avg_interval == 0)
- md->avg_interval = md->drop_count;
- else
- md->avg_interval += (md->drop_count -
- md->avg_interval) / RES_AVG;
- if (md->count < 10 || (md->drop_count >
- res_min_interval && md->avg_interval >
- res_avg_interval))
- flags &= ~RES_LIMITED;
- md->drop_count = flags;
- }
- return (flags);
-}
-
-
-/*
- * hack_restrict - add/subtract/manipulate entries on the restrict list
- */
-void
-hack_restrict(
- int op,
- struct sockaddr_storage *resaddr,
- struct sockaddr_storage *resmask,
- int mflags,
- int flags
- )
-{
- register u_int32 addr = 0;
- register u_int32 mask = 0;
- struct in6_addr addr6;
- struct in6_addr mask6;
- register struct restrictlist *rl = NULL;
- register struct restrictlist *rlprev = NULL;
- register struct restrictlist6 *rl6 = NULL;
- register struct restrictlist6 *rlprev6 = NULL;
- int i, addr_cmp, mask_cmp;
- memset(&addr6, 0, sizeof(struct in6_addr));
- memset(&mask6, 0, sizeof(struct in6_addr));
-
- if (resaddr->ss_family == AF_INET) {
- /*
- * Get address and mask in host byte order
- */
- addr = SRCADR(resaddr);
- mask = SRCADR(resmask);
- addr &= mask; /* make sure low bits zero */
-
- /*
- * If this is the default address, point at first on
- * list. Else go searching for it.
- */
- if (addr == 0) {
- rlprev = 0;
- rl = restrictlist;
- } else {
- rlprev = restrictlist;
- rl = rlprev->next;
- while (rl != 0) {
- if (rl->addr > addr) {
- rl = 0;
- break;
- } else if (rl->addr == addr) {
- if (rl->mask == mask) {
- if ((mflags &
- RESM_NTPONLY) ==
- (rl->mflags &
- RESM_NTPONLY))
- break;
-
- if (!(mflags &
- RESM_NTPONLY)) {
- rl = 0;
- break;
- }
- } else if (rl->mask > mask) {
- rl = 0;
- break;
- }
- }
- rlprev = rl;
- rl = rl->next;
- }
- }
- }
-
- if (resaddr->ss_family == AF_INET6) {
- mask6 = GET_INADDR6(*resmask);
- SET_IPV6_ADDR_MASK(&addr6,
- &GET_INADDR6(*resaddr), &mask6);
- if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
- rlprev6 = 0;
- rl6 = restrictlist6;
- } else {
- rlprev6 = restrictlist6;
- rl6 = rlprev6->next;
- while (rl6 != 0) {
- addr_cmp = memcmp(&rl6->addr6, &addr6,
- sizeof(addr6));
- if (addr_cmp > 0) {
- rl6 = 0;
- break;
- } else if (addr_cmp == 0) {
- mask_cmp = memcmp(&rl6->mask6,
- &mask6, sizeof(mask6));
- if (mask_cmp == 0) {
- if ((mflags &
- RESM_NTPONLY) ==
- (rl6->mflags &
- RESM_NTPONLY))
- break;
-
- if (!(mflags &
- RESM_NTPONLY)) {
- rl6 = 0;
- break;
- }
- } else if (mask_cmp > 0) {
- rl6 = 0;
- break;
- }
- }
- rlprev6 = rl6;
- rl6 = rl6->next;
- }
- }
- }
-
- /*
- * In case the above wasn't clear :-), either rl now points
- * at the entry this call refers to, or rl is zero and rlprev
- * points to the entry prior to where this one should go in
- * the sort.
- */
-
- /*
- * Switch based on operation
- */
- if (resaddr->ss_family == AF_INET) {
- switch (op) {
- case RESTRICT_FLAGS:
- /*
- * Here we add bits to the flags. If this is a
- * new restriction add it.
- */
- if (rl == 0) {
- if (numresfree == 0) {
- rl = (struct restrictlist *)
- emalloc(INCRESLIST *
- sizeof(struct
- restrictlist));
- memset((char *)rl, 0,
- INCRESLIST * sizeof(struct
- restrictlist));
- for (i = 0; i < INCRESLIST; i++) {
- rl->next = resfree;
- resfree = rl;
- rl++;
- }
- numresfree = INCRESLIST;
- }
-
- rl = resfree;
- resfree = rl->next;
- numresfree--;
-
- rl->addr = addr;
- rl->mask = mask;
- rl->mflags = (u_short)mflags;
-
- rl->next = rlprev->next;
- rlprev->next = rl;
- restrictcount++;
- }
- if ((rl->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt++;
- mon_start(MON_RES);
- }
- rl->flags |= (u_short)flags;
- break;
-
- case RESTRICT_UNFLAG:
- /*
- * Remove some bits from the flags. If we didn't
- * find this one, just return.
- */
- if (rl != 0) {
- if ((rl->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt--;
- if (res_limited_refcnt == 0)
- mon_stop(MON_RES);
- }
- rl->flags &= (u_short)~flags;
- }
- break;
-
- case RESTRICT_REMOVE:
- /*
- * Remove an entry from the table entirely if we
- * found one. Don't remove the default entry and
- * don't remove an interface entry.
- */
- if (rl != 0
- && rl->addr != htonl(INADDR_ANY)
- && !(rl->mflags & RESM_INTERFACE)) {
- rlprev->next = rl->next;
- restrictcount--;
- if (rl->flags & RES_LIMITED) {
- res_limited_refcnt--;
- if (res_limited_refcnt == 0)
- mon_stop(MON_RES);
- }
- memset((char *)rl, 0,
- sizeof(struct restrictlist));
-
- rl->next = resfree;
- resfree = rl;
- numresfree++;
- }
- break;
-
- default:
- break;
- }
- } else if (resaddr->ss_family == AF_INET6) {
- switch (op) {
- case RESTRICT_FLAGS:
- /*
- * Here we add bits to the flags. If this is a
- * new restriction add it.
- */
- if (rl6 == 0) {
- if (numresfree6 == 0) {
- rl6 = (struct
- restrictlist6 *)emalloc(
- INCRESLIST * sizeof(struct
- restrictlist6));
- memset((char *)rl6, 0,
- INCRESLIST * sizeof(struct
- restrictlist6));
-
- for (i = 0; i < INCRESLIST;
- i++) {
- rl6->next = resfree6;
- resfree6 = rl6;
- rl6++;
- }
- numresfree6 = INCRESLIST;
- }
- rl6 = resfree6;
- resfree6 = rl6->next;
- numresfree6--;
- rl6->addr6 = addr6;
- rl6->mask6 = mask6;
- rl6->mflags = (u_short)mflags;
- rl6->next = rlprev6->next;
- rlprev6->next = rl6;
- restrictcount6++;
- }
- if ((rl6->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt6++;
- mon_start(MON_RES);
- }
- rl6->flags |= (u_short)flags;
- break;
-
- case RESTRICT_UNFLAG:
- /*
- * Remove some bits from the flags. If we didn't
- * find this one, just return.
- */
- if (rl6 != 0) {
- if ((rl6->flags ^ (u_short)flags) &
- RES_LIMITED) {
- res_limited_refcnt6--;
- if (res_limited_refcnt6 == 0)
- mon_stop(MON_RES);
- }
- rl6->flags &= (u_short)~flags;
- }
- break;
-
- case RESTRICT_REMOVE:
- /*
- * Remove an entry from the table entirely if we
- * found one. Don't remove the default entry and
- * don't remove an interface entry.
- */
- if (rl6 != 0 &&
- !IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6)
- && !(rl6->mflags & RESM_INTERFACE)) {
- rlprev6->next = rl6->next;
- restrictcount6--;
- if (rl6->flags & RES_LIMITED) {
- res_limited_refcnt6--;
- if (res_limited_refcnt6 == 0)
- mon_stop(MON_RES);
- }
- memset((char *)rl6, 0,
- sizeof(struct restrictlist6));
- rl6->next = resfree6;
- resfree6 = rl6;
- numresfree6++;
- }
- break;
-
- default:
- break;
- }
- }
-}
diff --git a/contrib/ntp/ntpd/ntp_timer.c b/contrib/ntp/ntpd/ntp_timer.c
deleted file mode 100644
index 6f0f18b..0000000
--- a/contrib/ntp/ntpd/ntp_timer.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * ntp_timer.c - event timer support routines
- */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <signal.h>
-#ifdef HAVE_SYS_SIGNAL_H
-# include <sys/signal.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if defined(HAVE_IO_COMPLETION_PORT)
-# include "ntp_iocompletionport.h"
-# include "ntp_timer.h"
-#endif
-
-/*
- * These routines provide support for the event timer. The timer is
- * implemented by an interrupt routine which sets a flag once every
- * 2**EVENT_TIMEOUT seconds (currently 4), and a timer routine which
- * is called when the mainline code gets around to seeing the flag.
- * The timer routine dispatches the clock adjustment code if its time
- * has come, then searches the timer queue for expiries which are
- * dispatched to the transmit procedure. Finally, we call the hourly
- * procedure to do cleanup and print a message.
- */
-
-/*
- * Alarm flag. The mainline code imports this.
- */
-volatile int alarm_flag;
-
-/*
- * The counters
- */
-static u_long adjust_timer; /* second timer */
-static u_long keys_timer; /* minute timer */
-static u_long hourly_timer; /* hour timer */
-static u_long huffpuff_timer; /* huff-n'-puff timer */
-#ifdef OPENSSL
-static u_long revoke_timer; /* keys revoke timer */
-u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
-#endif /* OPENSSL */
-
-/*
- * Statistics counter for the interested.
- */
-volatile u_long alarm_overflow;
-
-#define MINUTE 60
-#define HOUR (60*60)
-
-u_long current_time;
-
-/*
- * Stats. Number of overflows and number of calls to transmit().
- */
-u_long timer_timereset;
-u_long timer_overflows;
-u_long timer_xmtcalls;
-
-#if defined(VMS)
-static int vmstimer[2]; /* time for next timer AST */
-static int vmsinc[2]; /* timer increment */
-#endif /* VMS */
-
-#if defined SYS_WINNT
-static HANDLE WaitableTimerHandle = NULL;
-#else
-static RETSIGTYPE alarming P((int));
-#endif /* SYS_WINNT */
-
-#if !defined(VMS)
-# if !defined SYS_WINNT || defined(SYS_CYGWIN32)
-# ifndef HAVE_TIMER_SETTIME
- struct itimerval itimer;
-# else
- static timer_t ntpd_timerid;
- struct itimerspec itimer;
-# endif /* HAVE_TIMER_SETTIME */
-# endif /* SYS_WINNT */
-#endif /* VMS */
-
-/*
- * reinit_timer - reinitialize interval timer.
- */
-void
-reinit_timer(void)
-{
-#if !defined(SYS_WINNT) && !defined(VMS)
-# if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
- timer_gettime(ntpd_timerid, &itimer);
- if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- }
- if (itimer.it_value.tv_nsec < 0 ) {
- itimer.it_value.tv_nsec = 0;
- }
- if (itimer.it_value.tv_sec == 0 && itimer.it_value.tv_nsec == 0) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_value.tv_nsec = 0;
- }
- itimer.it_interval.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_nsec = 0;
- timer_settime(ntpd_timerid, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
-# else
- getitimer(ITIMER_REAL, &itimer);
- if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- }
- if (itimer.it_value.tv_usec < 0 ) {
- itimer.it_value.tv_usec = 0;
- }
- if (itimer.it_value.tv_sec == 0 && itimer.it_value.tv_usec == 0) {
- itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_value.tv_usec = 0;
- }
- itimer.it_interval.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_usec = 0;
- setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
-# endif
-# endif /* VMS */
-}
-
-/*
- * init_timer - initialize the timer data structures
- */
-void
-init_timer(void)
-{
-# if defined SYS_WINNT & !defined(SYS_CYGWIN32)
- HANDLE hToken;
- TOKEN_PRIVILEGES tkp;
-# endif /* SYS_WINNT */
-
- /*
- * Initialize...
- */
- alarm_flag = 0;
- alarm_overflow = 0;
- adjust_timer = 1;
- hourly_timer = HOUR;
- huffpuff_timer = 0;
- current_time = 0;
- timer_overflows = 0;
- timer_xmtcalls = 0;
- timer_timereset = 0;
-
-#if !defined(SYS_WINNT)
- /*
- * Set up the alarm interrupt. The first comes 2**EVENT_TIMEOUT
- * seconds from now and they continue on every 2**EVENT_TIMEOUT
- * seconds.
- */
-# if !defined(VMS)
-# if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
- if (timer_create (CLOCK_REALTIME, NULL, &ntpd_timerid) ==
-# ifdef SYS_VXWORKS
- ERROR
-# else
- -1
-# endif
- )
- {
- fprintf (stderr, "timer create FAILED\n");
- exit (0);
- }
- (void) signal_no_reset(SIGALRM, alarming);
- itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_nsec = itimer.it_value.tv_nsec = 0;
- timer_settime(ntpd_timerid, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
-# else
- (void) signal_no_reset(SIGALRM, alarming);
- itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
- itimer.it_interval.tv_usec = itimer.it_value.tv_usec = 0;
- setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
-# endif
-# else /* VMS */
- vmsinc[0] = 10000000; /* 1 sec */
- vmsinc[1] = 0;
- lib$emul(&(1<<EVENT_TIMEOUT), &vmsinc, &0, &vmsinc);
-
- sys$gettim(&vmstimer); /* that's "now" as abstime */
-
- lib$addx(&vmsinc, &vmstimer, &vmstimer);
- sys$setimr(0, &vmstimer, alarming, alarming, 0);
-# endif /* VMS */
-#else /* SYS_WINNT */
- _tzset();
-
- /*
- * Get privileges needed for fiddling with the clock
- */
-
- /* get the current process token handle */
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
- msyslog(LOG_ERR, "OpenProcessToken failed: %m");
- exit(1);
- }
- /* get the LUID for system-time privilege. */
- LookupPrivilegeValue(NULL, SE_SYSTEMTIME_NAME, &tkp.Privileges[0].Luid);
- tkp.PrivilegeCount = 1; /* one privilege to set */
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- /* get set-time privilege for this process. */
- AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
- /* cannot test return value of AdjustTokenPrivileges. */
- if (GetLastError() != ERROR_SUCCESS) {
- msyslog(LOG_ERR, "AdjustTokenPrivileges failed: %m");
- }
-
- /*
- * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
- * Under Windows/NT,
- */
-
- WaitableTimerHandle = CreateWaitableTimer(NULL, FALSE, NULL);
- if (WaitableTimerHandle == NULL) {
- msyslog(LOG_ERR, "CreateWaitableTimer failed: %m");
- exit(1);
- }
- else {
- DWORD Period = (1<<EVENT_TIMEOUT) * 1000;
- LARGE_INTEGER DueTime;
- DueTime.QuadPart = Period * 10000i64;
- if (!SetWaitableTimer(WaitableTimerHandle, &DueTime, Period, NULL, NULL, FALSE) != NO_ERROR) {
- msyslog(LOG_ERR, "SetWaitableTimer failed: %m");
- exit(1);
- }
- }
-
-#endif /* SYS_WINNT */
-}
-
-#if defined(SYS_WINNT)
-extern HANDLE
-get_timer_handle(void)
-{
- return WaitableTimerHandle;
-}
-#endif
-
-/*
- * timer - dispatch anyone who needs to be
- */
-void
-timer(void)
-{
- register struct peer *peer, *next_peer;
-#ifdef OPENSSL
- char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
-#endif /* OPENSSL */
- u_int n;
-
- current_time += (1<<EVENT_TIMEOUT);
-
- /*
- * Adjustment timeout first.
- */
- if (adjust_timer <= current_time) {
- adjust_timer += 1;
- adj_host_clock();
- kod_proto();
- }
-
- /*
- * Now dispatch any peers whose event timer has expired. Be careful
- * here, since the peer structure might go away as the result of
- * the call.
- */
- for (n = 0; n < HASH_SIZE; n++) {
- for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
- next_peer = peer->next;
- if (peer->action && peer->nextaction <= current_time)
- peer->action(peer);
- if (peer->nextdate <= current_time) {
-#ifdef REFCLOCK
- if (peer->flags & FLAG_REFCLOCK)
- refclock_transmit(peer);
- else
- transmit(peer);
-#else /* REFCLOCK */
- transmit(peer);
-#endif /* REFCLOCK */
- }
- }
- }
-
- /*
- * Garbage collect expired keys.
- */
- if (keys_timer <= current_time) {
- keys_timer += MINUTE;
- auth_agekeys();
- }
-
- /*
- * Huff-n'-puff filter
- */
- if (huffpuff_timer <= current_time) {
- huffpuff_timer += HUFFPUFF;
- huffpuff();
- }
-
-#ifdef OPENSSL
- /*
- * Garbage collect old keys and generate new private value
- */
- if (revoke_timer <= current_time) {
- revoke_timer += RANDPOLL(sys_revoke);
- expire_all();
- sprintf(statstr, "refresh ts %u", ntohl(hostval.tstamp));
- record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
- if (debug)
- printf("timer: %s\n", statstr);
-#endif
- }
-#endif /* OPENSSL */
-
- /*
- * Finally, call the hourly routine.
- */
- if (hourly_timer <= current_time) {
- hourly_timer += HOUR;
- hourly_stats();
- }
-}
-
-
-#ifndef SYS_WINNT
-/*
- * alarming - tell the world we've been alarmed
- */
-static RETSIGTYPE
-alarming(
- int sig
- )
-{
-#if !defined(VMS)
- if (initializing)
- return;
- if (alarm_flag)
- alarm_overflow++;
- else
- alarm_flag++;
-#else /* VMS AST routine */
- if (!initializing) {
- if (alarm_flag) alarm_overflow++;
- else alarm_flag = 1; /* increment is no good */
- }
- lib$addx(&vmsinc,&vmstimer,&vmstimer);
- sys$setimr(0,&vmstimer,alarming,alarming,0);
-#endif /* VMS */
-}
-#endif /* SYS_WINNT */
-
-
-/*
- * timer_clr_stats - clear timer module stat counters
- */
-void
-timer_clr_stats(void)
-{
- timer_overflows = 0;
- timer_xmtcalls = 0;
- timer_timereset = current_time;
-}
-
diff --git a/contrib/ntp/ntpd/ntp_util.c b/contrib/ntp/ntpd/ntp_util.c
deleted file mode 100644
index 135f9b3..0000000
--- a/contrib/ntp/ntpd/ntp_util.c
+++ /dev/null
@@ -1,797 +0,0 @@
-/*
- * ntp_util.c - stuff I didn't have any other place for
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_filegen.h"
-#include "ntp_if.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_IEEEFP_H
-# include <ieeefp.h>
-#endif
-#ifdef HAVE_MATH_H
-# include <math.h>
-#endif
-
-#ifdef DOSYNCTODR
-#if !defined(VMS)
-#include <sys/resource.h>
-#endif /* VMS */
-#endif
-
-#if defined(VMS)
-#include <descrip.h>
-#endif /* VMS */
-
-/*
- * This contains odds and ends. Right now the only thing you'll find
- * in here is the hourly stats printer and some code to support
- * rereading the keys file, but I may eventually put other things in
- * here such as code to do something with the leap bits.
- */
-/*
- * Name of the keys file
- */
-static char *key_file_name;
-
-/*
- * The name of the drift_comp file and the temporary.
- */
-static char *stats_drift_file;
-static char *stats_temp_file;
-
-/*
- * Statistics file stuff
- */
-#ifndef NTP_VAR
-#ifndef SYS_WINNT
-#define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */
-#else
-#define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */
-#endif /* SYS_WINNT */
-#endif
-
-#ifndef MAXPATHLEN
-#define MAXPATHLEN 256
-#endif
-
-static char statsdir[MAXPATHLEN] = NTP_VAR;
-
-static FILEGEN peerstats;
-static FILEGEN loopstats;
-static FILEGEN clockstats;
-static FILEGEN rawstats;
-static FILEGEN sysstats;
-#ifdef OPENSSL
-static FILEGEN cryptostats;
-#endif /* OPENSSL */
-
-/*
- * This controls whether stats are written to the fileset. Provided
- * so that ntpdc can turn off stats when the file system fills up.
- */
-int stats_control;
-
-/*
- * init_util - initialize the utilities
- */
-void
-init_util(void)
-{
- stats_drift_file = 0;
- stats_temp_file = 0;
- key_file_name = 0;
-
-#define PEERNAME "peerstats"
-#define LOOPNAME "loopstats"
-#define CLOCKNAME "clockstats"
-#define RAWNAME "rawstats"
-#define STANAME "systats"
-#ifdef OPENSSL
-#define CRYPTONAME "cryptostats"
-#endif /* OPENSSL */
-
- peerstats.fp = NULL;
- peerstats.prefix = &statsdir[0];
- peerstats.basename = (char*)emalloc(strlen(PEERNAME)+1);
- strcpy(peerstats.basename, PEERNAME);
- peerstats.id = 0;
- peerstats.type = FILEGEN_DAY;
- peerstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("peerstats", &peerstats);
-
- loopstats.fp = NULL;
- loopstats.prefix = &statsdir[0];
- loopstats.basename = (char*)emalloc(strlen(LOOPNAME)+1);
- strcpy(loopstats.basename, LOOPNAME);
- loopstats.id = 0;
- loopstats.type = FILEGEN_DAY;
- loopstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("loopstats", &loopstats);
-
- clockstats.fp = NULL;
- clockstats.prefix = &statsdir[0];
- clockstats.basename = (char*)emalloc(strlen(CLOCKNAME)+1);
- strcpy(clockstats.basename, CLOCKNAME);
- clockstats.id = 0;
- clockstats.type = FILEGEN_DAY;
- clockstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("clockstats", &clockstats);
-
- rawstats.fp = NULL;
- rawstats.prefix = &statsdir[0];
- rawstats.basename = (char*)emalloc(strlen(RAWNAME)+1);
- strcpy(rawstats.basename, RAWNAME);
- rawstats.id = 0;
- rawstats.type = FILEGEN_DAY;
- rawstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("rawstats", &rawstats);
-
- sysstats.fp = NULL;
- sysstats.prefix = &statsdir[0];
- sysstats.basename = (char*)emalloc(strlen(STANAME)+1);
- strcpy(sysstats.basename, STANAME);
- sysstats.id = 0;
- sysstats.type = FILEGEN_DAY;
- sysstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("sysstats", &sysstats);
-
-#ifdef OPENSSL
- cryptostats.fp = NULL;
- cryptostats.prefix = &statsdir[0];
- cryptostats.basename = (char*)emalloc(strlen(CRYPTONAME)+1);
- strcpy(cryptostats.basename, CRYPTONAME);
- cryptostats.id = 0;
- cryptostats.type = FILEGEN_DAY;
- cryptostats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("cryptostats", &cryptostats);
-#endif /* OPENSSL */
-
-#undef PEERNAME
-#undef LOOPNAME
-#undef CLOCKNAME
-#undef RAWNAME
-#undef STANAME
-#ifdef OPENSSL
-#undef CRYPTONAME
-#endif /* OPENSSL */
-}
-
-
-/*
- * hourly_stats - print some interesting stats
- */
-void
-hourly_stats(void)
-{
- FILE *fp;
-
-#ifdef DOSYNCTODR
- struct timeval tv;
-#if !defined(VMS)
- int prio_set;
-#endif
-#ifdef HAVE_GETCLOCK
- struct timespec ts;
-#endif
- int o_prio;
-
- /*
- * Sometimes having a Sun can be a drag.
- *
- * The kernel variable dosynctodr controls whether the system's
- * soft clock is kept in sync with the battery clock. If it
- * is zero, then the soft clock is not synced, and the battery
- * clock is simply left to rot. That means that when the system
- * reboots, the battery clock (which has probably gone wacky)
- * sets the soft clock. That means ntpd starts off with a very
- * confused idea of what time it is. It then takes a large
- * amount of time to figure out just how wacky the battery clock
- * has made things drift, etc, etc. The solution is to make the
- * battery clock sync up to system time. The way to do THAT is
- * to simply set the time of day to the current time of day, but
- * as quickly as possible. This may, or may not be a sensible
- * thing to do.
- *
- * CAVEAT: settimeofday() steps the sun clock by about 800 us,
- * so setting DOSYNCTODR seems a bad idea in the
- * case of us resolution
- */
-
-#if !defined(VMS)
- /* (prr) getpriority returns -1 on error, but -1 is also a valid
- * return value (!), so instead we have to zero errno before the
- * call and check it for non-zero afterwards.
- */
- errno = 0;
- prio_set = 0;
- o_prio = getpriority(PRIO_PROCESS,0); /* Save setting */
-
- /*
- * (prr) if getpriority succeeded, call setpriority to raise
- * scheduling priority as high as possible. If that succeeds
- * as well, set the prio_set flag so we remember to reset
- * priority to its previous value below. Note that on Solaris
- * 2.6 (and beyond?), both getpriority and setpriority will fail
- * with ESRCH, because sched_setscheduler (called from main) put
- * us in the real-time scheduling class which setpriority
- * doesn't know about. Being in the real-time class is better
- * than anything setpriority can do, anyhow, so this error is
- * silently ignored.
- */
- if ((errno == 0) && (setpriority(PRIO_PROCESS,0,-20) == 0))
- prio_set = 1; /* overdrive */
-#endif /* VMS */
-#ifdef HAVE_GETCLOCK
- (void) getclock(TIMEOFDAY, &ts);
- tv.tv_sec = ts.tv_sec;
- tv.tv_usec = ts.tv_nsec / 1000;
-#else /* not HAVE_GETCLOCK */
- GETTIMEOFDAY(&tv,(struct timezone *)NULL);
-#endif /* not HAVE_GETCLOCK */
- if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0) {
- msyslog(LOG_ERR, "can't sync battery time: %m");
- }
-#if !defined(VMS)
- if (prio_set)
- setpriority(PRIO_PROCESS, 0, o_prio); /* downshift */
-#endif /* VMS */
-#endif /* DOSYNCTODR */
-
- NLOG(NLOG_SYSSTATIST)
- msyslog(LOG_INFO,
- "offset %.6f sec freq %.3f ppm error %.6f poll %d",
- last_offset, drift_comp * 1e6, sys_jitter,
- sys_poll);
-
-
- record_sys_stats();
- if (stats_drift_file != 0) {
- if ((fp = fopen(stats_temp_file, "w")) == NULL) {
- msyslog(LOG_ERR, "can't open %s: %m",
- stats_temp_file);
- return;
- }
- fprintf(fp, "%.3f\n", drift_comp * 1e6);
- (void)fclose(fp);
- /* atomic */
-#ifdef SYS_WINNT
- (void) _unlink(stats_drift_file); /* rename semantics differ under NT */
-#endif /* SYS_WINNT */
-
-#ifndef NO_RENAME
- (void) rename(stats_temp_file, stats_drift_file);
-#else
- /* we have no rename NFS of ftp in use*/
- if ((fp = fopen(stats_drift_file, "w")) == NULL) {
- msyslog(LOG_ERR, "can't open %s: %m",
- stats_drift_file);
- return;
- }
-
-#endif
-
-#if defined(VMS)
- /* PURGE */
- {
- $DESCRIPTOR(oldvers,";-1");
- struct dsc$descriptor driftdsc = {
- strlen(stats_drift_file),0,0,stats_drift_file };
-
- while(lib$delete_file(&oldvers,&driftdsc) & 1) ;
- }
-#endif
- }
-}
-
-
-/*
- * stats_config - configure the stats operation
- */
-void
-stats_config(
- int item,
- char *invalue /* only one type so far */
- )
-{
- FILE *fp;
- char *value;
- double old_drift;
- int len;
-
- /*
- * Expand environment strings under Windows NT, since the
- * command interpreter doesn't do this, the program must.
- */
-#ifdef SYS_WINNT
- char newvalue[MAX_PATH], parameter[MAX_PATH];
-
- if (!ExpandEnvironmentStrings(invalue, newvalue, MAX_PATH)) {
- switch(item) {
- case STATS_FREQ_FILE:
- strcpy(parameter,"STATS_FREQ_FILE");
- break;
- case STATS_STATSDIR:
- strcpy(parameter,"STATS_STATSDIR");
- break;
- case STATS_PID_FILE:
- strcpy(parameter,"STATS_PID_FILE");
- break;
- default:
- strcpy(parameter,"UNKNOWN");
- break;
- }
- value = invalue;
-
- msyslog(LOG_ERR,
- "ExpandEnvironmentStrings(%s) failed: %m\n", parameter);
- } else {
- value = newvalue;
- }
-#else
- value = invalue;
-#endif /* SYS_WINNT */
-
- switch(item) {
- case STATS_FREQ_FILE:
- if (stats_drift_file != 0) {
- (void) free(stats_drift_file);
- (void) free(stats_temp_file);
- stats_drift_file = 0;
- stats_temp_file = 0;
- }
-
- if (value == 0 || (len = strlen(value)) == 0)
- break;
-
- stats_drift_file = (char*)emalloc((u_int)(len + 1));
-#if !defined(VMS)
- stats_temp_file = (char*)emalloc((u_int)(len +
- sizeof(".TEMP")));
-#else
- stats_temp_file = (char*)emalloc((u_int)(len +
- sizeof("-TEMP")));
-#endif /* VMS */
- memmove(stats_drift_file, value, (unsigned)(len+1));
- memmove(stats_temp_file, value, (unsigned)len);
-#if !defined(VMS)
- memmove(stats_temp_file + len, ".TEMP",
- sizeof(".TEMP"));
-#else
- memmove(stats_temp_file + len, "-TEMP",
- sizeof("-TEMP"));
-#endif /* VMS */
-
- /*
- * Open drift file and read frequency. If the file is
- * missing or contains errors, tell the loop to reset.
- */
- if ((fp = fopen(stats_drift_file, "r")) == NULL) {
- loop_config(LOOP_DRIFTCOMP, 1e9);
- break;
- }
- if (fscanf(fp, "%lf", &old_drift) != 1) {
- msyslog(LOG_ERR, "Frequency format error in %s",
- stats_drift_file);
- loop_config(LOOP_DRIFTCOMP, 1e9);
- fclose(fp);
- break;
- }
- fclose(fp);
- msyslog(LOG_INFO,
- "frequency initialized %.3f PPM from %s",
- old_drift, stats_drift_file);
- loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
- break;
-
- case STATS_STATSDIR:
- if (strlen(value) >= sizeof(statsdir)) {
- msyslog(LOG_ERR,
- "value for statsdir too long (>%d, sigh)",
- (int)sizeof(statsdir)-1);
- } else {
- l_fp now;
-
- get_systime(&now);
- strcpy(statsdir,value);
- if(peerstats.prefix == &statsdir[0] &&
- peerstats.fp != NULL) {
- fclose(peerstats.fp);
- peerstats.fp = NULL;
- 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);
- }
- if(clockstats.prefix == &statsdir[0] &&
- clockstats.fp != NULL) {
- fclose(clockstats.fp);
- clockstats.fp = NULL;
- filegen_setup(&clockstats, now.l_ui);
- }
- if(rawstats.prefix == &statsdir[0] &&
- rawstats.fp != NULL) {
- fclose(rawstats.fp);
- rawstats.fp = NULL;
- filegen_setup(&rawstats, now.l_ui);
- }
- if(sysstats.prefix == &statsdir[0] &&
- sysstats.fp != NULL) {
- fclose(sysstats.fp);
- sysstats.fp = NULL;
- filegen_setup(&sysstats, now.l_ui);
- }
-#ifdef OPENSSL
- if(cryptostats.prefix == &statsdir[0] &&
- cryptostats.fp != NULL) {
- fclose(cryptostats.fp);
- cryptostats.fp = NULL;
- filegen_setup(&cryptostats, now.l_ui);
- }
-#endif /* OPENSSL */
- }
- break;
-
- case STATS_PID_FILE:
- if ((fp = fopen(value, "w")) == NULL) {
- msyslog(LOG_ERR, "Can't open %s: %m", value);
- break;
- }
- fprintf(fp, "%d", (int) getpid());
- fclose(fp);;
- break;
-
- default:
- /* oh well */
- break;
- }
-}
-
-/*
- * record_peer_stats - write peer statistics to file
- *
- * file format:
- * day (mjd)
- * time (s past UTC midnight)
- * peer (ip address)
- * peer status word (hex)
- * peer offset (s)
- * peer delay (s)
- * peer error bound (s)
- * peer error (s)
-*/
-void
-record_peer_stats(
- struct sockaddr_storage *addr,
- int status,
- double offset,
- double delay,
- double dispersion,
- double skew
- )
-{
- l_fp now;
- u_long day;
-
- if (!stats_control)
- return;
-
- get_systime(&now);
- filegen_setup(&peerstats, now.l_ui);
- day = now.l_ui / 86400 + MJD_1900;
- now.l_ui %= 86400;
- if (peerstats.fp != NULL) {
- fprintf(peerstats.fp,
- "%lu %s %s %x %.9f %.9f %.9f %.9f\n",
- day, ulfptoa(&now, 3), stoa(addr), status, offset,
- delay, dispersion, skew);
- fflush(peerstats.fp);
- }
-}
-/*
- * record_loop_stats - write loop filter statistics to file
- *
- * file format:
- * day (mjd)
- * time (s past midnight)
- * offset (s)
- * frequency (approx ppm)
- * time constant (log base 2)
- */
-void
-record_loop_stats(
- double offset,
- double freq,
- double jitter,
- double stability,
- int spoll
- )
-{
- l_fp now;
- u_long day;
-
- if (!stats_control)
- return;
-
- get_systime(&now);
- filegen_setup(&loopstats, now.l_ui);
- day = now.l_ui / 86400 + MJD_1900;
- now.l_ui %= 86400;
- if (loopstats.fp != NULL) {
- fprintf(loopstats.fp, "%lu %s %.9f %.6f %.9f %.6f %d\n",
- day, ulfptoa(&now, 3), offset, freq * 1e6, jitter,
- stability * 1e6, spoll);
- fflush(loopstats.fp);
- }
-}
-
-/*
- * record_clock_stats - write clock statistics to file
- *
- * file format:
- * day (mjd)
- * time (s past midnight)
- * peer (ip address)
- * text message
- */
-void
-record_clock_stats(
- struct sockaddr_storage *addr,
- const char *text
- )
-{
- l_fp now;
- u_long day;
-
- if (!stats_control)
- return;
-
- get_systime(&now);
- filegen_setup(&clockstats, now.l_ui);
- day = now.l_ui / 86400 + MJD_1900;
- now.l_ui %= 86400;
- if (clockstats.fp != NULL) {
- fprintf(clockstats.fp, "%lu %s %s %s\n",
- day, ulfptoa(&now, 3), stoa(addr), text);
- fflush(clockstats.fp);
- }
-}
-
-/*
- * record_raw_stats - write raw timestamps to file
- *
- *
- * file format
- * time (s past midnight)
- * peer ip address
- * local ip address
- * t1 t2 t3 t4 timestamps
- */
-void
-record_raw_stats(
- struct sockaddr_storage *srcadr,
- struct sockaddr_storage *dstadr,
- l_fp *t1,
- l_fp *t2,
- l_fp *t3,
- l_fp *t4
- )
-{
- l_fp now;
- u_long day;
-
- if (!stats_control)
- return;
-
- get_systime(&now);
- filegen_setup(&rawstats, now.l_ui);
- day = now.l_ui / 86400 + MJD_1900;
- now.l_ui %= 86400;
- if (rawstats.fp != NULL) {
- fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n",
- day, ulfptoa(&now, 3), stoa(srcadr), stoa(dstadr),
- ulfptoa(t1, 9), ulfptoa(t2, 9), ulfptoa(t3, 9),
- ulfptoa(t4, 9));
- fflush(rawstats.fp);
- }
-}
-
-
-/*
- * record_sys_stats - write system statistics to file
- *
- * file format
- * time (s past midnight)
- * time since startup (hr)
- * packets recieved
- * packets processed
- * current version
- * previous version
- * bad version
- * access denied
- * bad length or format
- * bad authentication
- * rate exceeded
- */
-void
-record_sys_stats(void)
-{
- l_fp now;
- u_long day;
-
- if (!stats_control)
- return;
-
- get_systime(&now);
- filegen_setup(&sysstats, now.l_ui);
- day = now.l_ui / 86400 + MJD_1900;
- now.l_ui %= 86400;
- if (sysstats.fp != NULL) {
- fprintf(sysstats.fp,
- "%lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
- day, ulfptoa(&now, 3), sys_stattime / 3600,
- sys_received, sys_processed, sys_newversionpkt,
- sys_oldversionpkt, sys_unknownversion,
- sys_restricted, sys_badlength, sys_badauth,
- sys_limitrejected);
- fflush(sysstats.fp);
- proto_clr_stats();
- }
-}
-
-
-#ifdef OPENSSL
-/*
- * record_crypto_stats - write crypto statistics to file
- *
- * file format:
- * day (mjd)
- * time (s past midnight)
- * peer (ip address)
- * text message
- */
-void
-record_crypto_stats(
- struct sockaddr_storage *addr,
- const char *text
- )
-{
- l_fp now;
- u_long day;
-
- if (!stats_control)
- return;
-
- get_systime(&now);
- filegen_setup(&cryptostats, now.l_ui);
- day = now.l_ui / 86400 + MJD_1900;
- now.l_ui %= 86400;
- if (cryptostats.fp != NULL) {
- if (addr == NULL)
- fprintf(cryptostats.fp, "%lu %s %s\n",
- day, ulfptoa(&now, 3), text);
- else
- fprintf(cryptostats.fp, "%lu %s %s %s\n",
- day, ulfptoa(&now, 3), stoa(addr), text);
- fflush(cryptostats.fp);
- }
-}
-#endif /* OPENSSL */
-
-
-/*
- * getauthkeys - read the authentication keys from the specified file
- */
-void
-getauthkeys(
- char *keyfile
- )
-{
- int len;
-
- len = strlen(keyfile);
- if (len == 0)
- return;
-
- if (key_file_name != 0) {
- if (len > (int)strlen(key_file_name)) {
- (void) free(key_file_name);
- key_file_name = 0;
- }
- }
-
- if (key_file_name == 0) {
-#ifndef SYS_WINNT
- key_file_name = (char*)emalloc((u_int) (len + 1));
-#else
- key_file_name = (char*)emalloc((u_int) (MAXPATHLEN));
-#endif
- }
-#ifndef SYS_WINNT
- memmove(key_file_name, keyfile, (unsigned)(len+1));
-#else
- if (!ExpandEnvironmentStrings(keyfile, key_file_name, MAXPATHLEN))
- {
- msyslog(LOG_ERR,
- "ExpandEnvironmentStrings(KEY_FILE) failed: %m\n");
- }
-#endif /* SYS_WINNT */
-
- authreadkeys(key_file_name);
-}
-
-
-/*
- * rereadkeys - read the authentication key file over again.
- */
-void
-rereadkeys(void)
-{
- if (key_file_name != 0)
- authreadkeys(key_file_name);
-}
-
-/*
- * sock_hash - hash an sockaddr_storage structure
- */
-int
-sock_hash(
- struct sockaddr_storage *addr
- )
-{
- int hashVal;
- int i;
- int len;
- char *ch;
-
- hashVal = 0;
- len = 0;
- /*
- * We can't just hash the whole thing because there are hidden
- * fields in sockaddr_in6 that might be filled in by recvfrom(),
- * so just use the family, port and address.
- */
- ch = (char *)&addr->ss_family;
- hashVal = 37 * hashVal + (int)*ch;
- if (sizeof(addr->ss_family) > 1) {
- ch++;
- hashVal = 37 * hashVal + (int)*ch;
- }
- switch(addr->ss_family) {
- case AF_INET:
- ch = (char *)&((struct sockaddr_in *)addr)->sin_addr;
- len = sizeof(struct in_addr);
- break;
- case AF_INET6:
- ch = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
- len = sizeof(struct in6_addr);
- break;
- }
-
- for (i = 0; i < len ; i++)
- hashVal = 37 * hashVal + (int)*(ch + i);
-
- hashVal = hashVal % 128; /* % MON_HASH_SIZE hardcoded */
-
- if (hashVal < 0)
- hashVal += 128;
-
- return hashVal;
-}
diff --git a/contrib/ntp/ntpd/ntpd.c b/contrib/ntp/ntpd/ntpd.c
deleted file mode 100644
index 0b05253..0000000
--- a/contrib/ntp/ntpd/ntpd.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*
- * ntpd.c - main program for the fixed point NTP daemon
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_stdlib.h"
-
-#ifdef SIM
-#include "ntpsim.h"
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#include <stdio.h>
-#ifndef SYS_WINNT
-# if !defined(VMS) /*wjm*/
-# ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# endif
-# endif /* VMS */
-# ifdef HAVE_SYS_SIGNAL_H
-# include <sys/signal.h>
-# else
-# include <signal.h>
-# endif
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-# endif /* HAVE_SYS_IOCTL_H */
-# ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-# endif /* HAVE_SYS_RESOURCE_H */
-#else
-# include <signal.h>
-# include <process.h>
-# include <io.h>
-# include "../libntp/log.h"
-# include <clockstuff.h>
-# include <crtdbg.h>
-#endif /* SYS_WINNT */
-#if defined(HAVE_RTPRIO)
-# ifdef HAVE_SYS_RESOURCE_H
-# include <sys/resource.h>
-# endif
-# ifdef HAVE_SYS_LOCK_H
-# include <sys/lock.h>
-# endif
-# include <sys/rtprio.h>
-#else
-# ifdef HAVE_PLOCK
-# ifdef HAVE_SYS_LOCK_H
-# include <sys/lock.h>
-# endif
-# endif
-#endif
-#if defined(HAVE_SCHED_SETSCHEDULER)
-# ifdef HAVE_SCHED_H
-# include <sched.h>
-# else
-# ifdef HAVE_SYS_SCHED_H
-# include <sys/sched.h>
-# endif
-# endif
-#endif
-#if defined(HAVE_SYS_MMAN_H)
-# include <sys/mman.h>
-#endif
-
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
-#endif
-
-#ifdef SYS_DOMAINOS
-# include <apollo/base.h>
-#endif /* SYS_DOMAINOS */
-
-#include "recvbuff.h"
-#include "ntp_cmdargs.h"
-
-#if 0 /* HMS: I don't think we need this. 961223 */
-#ifdef LOCK_PROCESS
-# ifdef SYS_SOLARIS
-# include <sys/mman.h>
-# else
-# include <sys/lock.h>
-# endif
-#endif
-#endif
-
-#ifdef _AIX
-# include <ulimit.h>
-#endif /* _AIX */
-
-#ifdef SCO5_CLOCK
-# include <sys/ci/ciioctl.h>
-#endif
-
-#ifdef HAVE_CLOCKCTL
-# include <ctype.h>
-# include <grp.h>
-# include <pwd.h>
-#endif
-
-/*
- * Signals we catch for debugging. If not debugging we ignore them.
- */
-#define MOREDEBUGSIG SIGUSR1
-#define LESSDEBUGSIG SIGUSR2
-
-/*
- * Signals which terminate us gracefully.
- */
-#ifndef SYS_WINNT
-# define SIGDIE1 SIGHUP
-# define SIGDIE3 SIGQUIT
-# define SIGDIE2 SIGINT
-# define SIGDIE4 SIGTERM
-#endif /* SYS_WINNT */
-
-#if defined SYS_WINNT
-/* handles for various threads, process, and objects */
-HANDLE ResolverThreadHandle = NULL;
-/* variables used to inform the Service Control Manager of our current state */
-BOOL NoWinService = FALSE;
-SERVICE_STATUS ssStatus;
-SERVICE_STATUS_HANDLE sshStatusHandle;
-HANDLE WaitHandles[3] = { NULL, NULL, NULL };
-char szMsgPath[255];
-static BOOL WINAPI OnConsoleEvent(DWORD dwCtrlType);
-BOOL init_randfile();
-#endif /* SYS_WINNT */
-
-/*
- * Scheduling priority we run at
- */
-#define NTPD_PRIO (-12)
-
-int priority_done = 2; /* 0 - Set priority */
- /* 1 - priority is OK where it is */
- /* 2 - Don't set priority */
- /* 1 and 2 are pretty much the same */
-
-/*
- * Debugging flag
- */
-volatile int debug;
-
-/*
- * Set the processing not to be in the forground
- */
-int forground_process = FALSE;
-
-/*
- * No-fork flag. If set, we do not become a background daemon.
- */
-int nofork;
-
-#ifdef HAVE_CLOCKCTL
-char *user = NULL; /* User to switch to */
-char *group = NULL; /* group to switch to */
-char *chrootdir = NULL; /* directory to chroot to */
-int sw_uid;
-int sw_gid;
-char *endp;
-struct group *gr;
-struct passwd *pw;
-#endif /* HAVE_CLOCKCTL */
-
-/*
- * Initializing flag. All async routines watch this and only do their
- * thing when it is clear.
- */
-int initializing;
-
-/*
- * Version declaration
- */
-extern const char *Version;
-
-int was_alarmed;
-
-#ifdef DECL_SYSCALL
-/*
- * We put this here, since the argument profile is syscall-specific
- */
-extern int syscall P((int, ...));
-#endif /* DECL_SYSCALL */
-
-
-#ifdef SIGDIE2
-static RETSIGTYPE finish P((int));
-#endif /* SIGDIE2 */
-
-#ifdef DEBUG
-#ifndef SYS_WINNT
-static RETSIGTYPE moredebug P((int));
-static RETSIGTYPE lessdebug P((int));
-#endif
-#else /* not DEBUG */
-static RETSIGTYPE no_debug P((int));
-#endif /* not DEBUG */
-
-int ntpdmain P((int, char **));
-static void set_process_priority P((void));
-
-#ifdef SIM
-int
-main(
- int argc,
- char *argv[]
- )
-{
- return ntpsim(argc, argv);
-}
-#else /* SIM */
-#ifdef NO_MAIN_ALLOWED
-CALL(ntpd,"ntpd",ntpdmain);
-#else
-int
-main(
- int argc,
- char *argv[]
- )
-{
- return ntpdmain(argc, argv);
-}
-#endif
-#endif /* SIM */
-
-#ifdef _AIX
-/*
- * OK. AIX is different than solaris in how it implements plock().
- * If you do NOT adjust the stack limit, you will get the MAXIMUM
- * stack size allocated and PINNED with you program. To check the
- * value, use ulimit -a.
- *
- * To fix this, we create an automatic variable and set our stack limit
- * to that PLUS 32KB of extra space (we need some headroom).
- *
- * This subroutine gets the stack address.
- *
- * Grover Davidson and Matt Ladendorf
- *
- */
-static char *
-get_aix_stack(void)
-{
- char ch;
- return (&ch);
-}
-
-/*
- * Signal handler for SIGDANGER.
- */
-static void
-catch_danger(int signo)
-{
- msyslog(LOG_INFO, "ntpd: setpgid(): %m");
- /* Make the system believe we'll free something, but don't do it! */
- return;
-}
-#endif /* _AIX */
-
-/*
- * Set the process priority
- */
-static void
-set_process_priority(void)
-{
-
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>",
- ((priority_done)
- ? "Leave priority alone"
- : "Attempt to set priority"
- ),
- priority_done);
-#endif /* DEBUG */
-
-#ifdef SYS_WINNT
- priority_done += NT_set_process_priority();
-#endif
-
-#if defined(HAVE_SCHED_SETSCHEDULER)
- if (!priority_done) {
- extern int config_priority_override, config_priority;
- int pmax, pmin;
- struct sched_param sched;
-
- pmax = sched_get_priority_max(SCHED_FIFO);
- sched.sched_priority = pmax;
- if ( config_priority_override ) {
- pmin = sched_get_priority_min(SCHED_FIFO);
- if ( config_priority > pmax )
- sched.sched_priority = pmax;
- else if ( config_priority < pmin )
- sched.sched_priority = pmin;
- else
- sched.sched_priority = config_priority;
- }
- if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 )
- msyslog(LOG_ERR, "sched_setscheduler(): %m");
- else
- ++priority_done;
- }
-#endif /* HAVE_SCHED_SETSCHEDULER */
-#if defined(HAVE_RTPRIO)
-# ifdef RTP_SET
- if (!priority_done) {
- struct rtprio srtp;
-
- srtp.type = RTP_PRIO_REALTIME; /* was: RTP_PRIO_NORMAL */
- srtp.prio = 0; /* 0 (hi) -> RTP_PRIO_MAX (31,lo) */
-
- if (rtprio(RTP_SET, getpid(), &srtp) < 0)
- msyslog(LOG_ERR, "rtprio() error: %m");
- else
- ++priority_done;
- }
-# else /* not RTP_SET */
- if (!priority_done) {
- if (rtprio(0, 120) < 0)
- msyslog(LOG_ERR, "rtprio() error: %m");
- else
- ++priority_done;
- }
-# endif /* not RTP_SET */
-#endif /* HAVE_RTPRIO */
-#if defined(NTPD_PRIO) && NTPD_PRIO != 0
-# ifdef HAVE_ATT_NICE
- if (!priority_done) {
- errno = 0;
- if (-1 == nice (NTPD_PRIO) && errno != 0)
- msyslog(LOG_ERR, "nice() error: %m");
- else
- ++priority_done;
- }
-# endif /* HAVE_ATT_NICE */
-# ifdef HAVE_BSD_NICE
- if (!priority_done) {
- if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO))
- msyslog(LOG_ERR, "setpriority() error: %m");
- else
- ++priority_done;
- }
-# endif /* HAVE_BSD_NICE */
-#endif /* NTPD_PRIO && NTPD_PRIO != 0 */
- if (!priority_done)
- msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority");
-}
-
-
-/*
- * Main program. Initialize us, disconnect us from the tty if necessary,
- * and loop waiting for I/O and/or timer expiries.
- */
-int
-ntpdmain(
- int argc,
- char *argv[]
- )
-{
- l_fp now;
- char *cp;
- struct recvbuf *rbuflist;
- struct recvbuf *rbuf;
-#ifdef _AIX /* HMS: ifdef SIGDANGER? */
- struct sigaction sa;
-#endif
-
- initializing = 1; /* mark that we are initializing */
- debug = 0; /* no debugging by default */
- nofork = 0; /* will fork by default */
-
-#ifdef HAVE_UMASK
- {
- mode_t uv;
-
- uv = umask(0);
- if(uv)
- (void) umask(uv);
- else
- (void) umask(022);
- }
-#endif
-
-#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
- {
- uid_t uid;
-
- uid = getuid();
- if (uid)
- {
- msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
- exit(1);
- }
- }
-#endif
-
-#ifdef SYS_WINNT
- /* Set the Event-ID message-file name. */
- if (!GetModuleFileName(NULL, szMsgPath, sizeof(szMsgPath))) {
- msyslog(LOG_ERR, "GetModuleFileName(PGM_EXE_FILE) failed: %m\n");
- exit(1);
- }
- addSourceToRegistry("NTP", szMsgPath);
-#endif
- getstartup(argc, argv); /* startup configuration, may set debug */
-
- if (debug)
- printf("%s\n", Version);
-
- /*
- * Initialize random generator and public key pair
- */
-#ifdef SYS_WINNT
- /* Initialize random file before OpenSSL checks */
- if(!init_randfile())
- msyslog(LOG_ERR, "Unable to initialize .rnd file\n");
-#endif
- get_systime(&now);
- SRANDOM((int)(now.l_i * now.l_uf));
-
-#if !defined(VMS)
-# ifndef NODETACH
- /*
- * Detach us from the terminal. May need an #ifndef GIZMO.
- */
-# ifdef DEBUG
- if (!debug && !nofork)
-# else /* DEBUG */
- if (!nofork)
-# endif /* DEBUG */
- {
-# ifndef SYS_WINNT
-# ifdef HAVE_DAEMON
- daemon(0, 0);
-# else /* not HAVE_DAEMON */
- if (fork()) /* HMS: What about a -1? */
- exit(0);
-
- {
-#if !defined(F_CLOSEM)
- u_long s;
- int max_fd;
-#endif /* not F_CLOSEM */
-
-#if defined(F_CLOSEM)
- /*
- * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
- * by Eric Agar (saves us from doing 32767 system
- * calls)
- */
- if (fcntl(0, F_CLOSEM, 0) == -1)
- msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
-#else /* not F_CLOSEM */
-
-# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
- max_fd = sysconf(_SC_OPEN_MAX);
-# else /* HAVE_SYSCONF && _SC_OPEN_MAX */
- max_fd = getdtablesize();
-# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
- for (s = 0; s < max_fd; s++)
- (void) close((int)s);
-#endif /* not F_CLOSEM */
- (void) open("/", 0);
- (void) dup2(0, 1);
- (void) dup2(0, 2);
-#ifdef SYS_DOMAINOS
- {
- uid_$t puid;
- status_$t st;
-
- proc2_$who_am_i(&puid);
- proc2_$make_server(&puid, &st);
- }
-#endif /* SYS_DOMAINOS */
-#if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
-# ifdef HAVE_SETSID
- if (setsid() == (pid_t)-1)
- msyslog(LOG_ERR, "ntpd: setsid(): %m");
-# else
- if (setpgid(0, 0) == -1)
- msyslog(LOG_ERR, "ntpd: setpgid(): %m");
-# endif
-#else /* HAVE_SETPGID || HAVE_SETSID */
- {
-# if defined(TIOCNOTTY)
- int fid;
-
- fid = open("/dev/tty", 2);
- if (fid >= 0)
- {
- (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
- (void) close(fid);
- }
-# endif /* defined(TIOCNOTTY) */
-# ifdef HAVE_SETPGRP_0
- (void) setpgrp();
-# else /* HAVE_SETPGRP_0 */
- (void) setpgrp(0, getpid());
-# endif /* HAVE_SETPGRP_0 */
- }
-#endif /* HAVE_SETPGID || HAVE_SETSID */
-#ifdef _AIX
- /* Don't get killed by low-on-memory signal. */
- sa.sa_handler = catch_danger;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
-
- (void) sigaction(SIGDANGER, &sa, NULL);
-#endif /* _AIX */
- }
-# endif /* not HAVE_DAEMON */
-# else /* SYS_WINNT */
-
- {
- if (NoWinService == FALSE) {
- SERVICE_TABLE_ENTRY dispatchTable[] = {
- { TEXT("NetworkTimeProtocol"), (LPSERVICE_MAIN_FUNCTION)service_main },
- { NULL, NULL }
- };
-
- /* daemonize */
- if (!StartServiceCtrlDispatcher(dispatchTable))
- {
- msyslog(LOG_ERR, "StartServiceCtrlDispatcher: %m");
- ExitProcess(2);
- }
- }
- else {
- service_main(argc, argv);
- return 0;
- }
- }
-# endif /* SYS_WINNT */
- }
-# endif /* NODETACH */
-# if defined(SYS_WINNT) && !defined(NODETACH)
- else
- service_main(argc, argv);
- return 0; /* must return a value */
-} /* end main */
-
-/*
- * If this runs as a service under NT, the main thread will block at
- * StartServiceCtrlDispatcher() and another thread will be started by the
- * Service Control Dispatcher which will begin execution at the routine
- * specified in that call (viz. service_main)
- */
-void
-service_main(
- DWORD argc,
- LPTSTR *argv
- )
-{
- char *cp;
- struct recvbuf *rbuflist;
- struct recvbuf *rbuf;
-
- if(!debug && NoWinService == FALSE)
- {
- /* register our service control handler */
- sshStatusHandle = RegisterServiceCtrlHandler( TEXT("NetworkTimeProtocol"),
- (LPHANDLER_FUNCTION)service_ctrl);
- if(sshStatusHandle == 0)
- {
- msyslog(LOG_ERR, "RegisterServiceCtrlHandler failed: %m");
- return;
- }
-
- /* report pending status to Service Control Manager */
- ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- ssStatus.dwCurrentState = SERVICE_START_PENDING;
- ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- ssStatus.dwServiceSpecificExitCode = 0;
- ssStatus.dwCheckPoint = 1;
- ssStatus.dwWaitHint = 5000;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- ssStatus.dwCurrentState = SERVICE_STOPPED;
- SetServiceStatus(sshStatusHandle, &ssStatus);
- return;
- }
-
- } /* debug */
-# endif /* defined(SYS_WINNT) && !defined(NODETACH) */
-#endif /* VMS */
-
- /*
- * Logging. This may actually work on the gizmo board. Find a name
- * to log with by using the basename of argv[0]
- */
- cp = strrchr(argv[0], '/');
- if (cp == 0)
- cp = argv[0];
- else
- cp++;
-
- debug = 0; /* will be immediately re-initialized 8-( */
- getstartup(argc, argv); /* startup configuration, catch logfile this time */
-
-#if !defined(VMS)
-
-# ifndef LOG_DAEMON
- openlog(cp, LOG_PID);
-# else /* LOG_DAEMON */
-
-# ifndef LOG_NTP
-# define LOG_NTP LOG_DAEMON
-# endif
- openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
-# ifdef DEBUG
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
- else
-# endif /* DEBUG */
- setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
-# endif /* LOG_DAEMON */
-#endif /* !SYS_WINNT && !VMS */
-
- NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "%s", Version);
-
-#ifdef SYS_WINNT
- /* GMS 1/18/1997
- * TODO: lock the process in memory using SetProcessWorkingSetSize() and VirtualLock() functions
- *
- process_handle = GetCurrentProcess();
- if (SetProcessWorkingSetSize(process_handle, 2097152 , 4194304 ) == TRUE) {
- if (VirtualLock(0 , 4194304) == FALSE)
- msyslog(LOG_ERR, "VirtualLock() failed: %m");
- } else {
- msyslog(LOG_ERR, "SetProcessWorkingSetSize() failed: %m");
- }
- */
-#endif /* SYS_WINNT */
-
-#ifdef SCO5_CLOCK
- /*
- * SCO OpenServer's system clock offers much more precise timekeeping
- * on the base CPU than the other CPUs (for multiprocessor systems),
- * so we must lock to the base CPU.
- */
- {
- int fd = open("/dev/at1", O_RDONLY);
- if (fd >= 0) {
- int zero = 0;
- if (ioctl(fd, ACPU_LOCK, &zero) < 0)
- msyslog(LOG_ERR, "cannot lock to base CPU: %m\n");
- close( fd );
- } /* else ...
- * If we can't open the device, this probably just isn't
- * a multiprocessor system, so we're A-OK.
- */
- }
-#endif
-
-#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
-# ifdef HAVE_SETRLIMIT
- /*
- * Set the stack limit to something smaller, so that we don't lock a lot
- * of unused stack memory.
- */
- {
- struct rlimit rl;
-
- if (getrlimit(RLIMIT_STACK, &rl) != -1
- && (rl.rlim_cur = 20 * 4096) < rl.rlim_max)
- {
- if (setrlimit(RLIMIT_STACK, &rl) == -1)
- {
- msyslog(LOG_ERR,
- "Cannot adjust stack limit for mlockall: %m");
- }
- }
- }
-# endif /* HAVE_SETRLIMIT */
- /*
- * lock the process into memory
- */
- if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
- msyslog(LOG_ERR, "mlockall(): %m");
-#else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
-# ifdef HAVE_PLOCK
-# ifdef PROCLOCK
-# ifdef _AIX
- /*
- * set the stack limit for AIX for plock().
- * see get_aix_stack for more info.
- */
- if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
- {
- msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m");
- }
-# endif /* _AIX */
- /*
- * lock the process into memory
- */
- if (plock(PROCLOCK) < 0)
- msyslog(LOG_ERR, "plock(PROCLOCK): %m");
-# else /* not PROCLOCK */
-# ifdef TXTLOCK
- /*
- * Lock text into ram
- */
- if (plock(TXTLOCK) < 0)
- msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
-# else /* not TXTLOCK */
- msyslog(LOG_ERR, "plock() - don't know what to lock!");
-# endif /* not TXTLOCK */
-# endif /* not PROCLOCK */
-# endif /* HAVE_PLOCK */
-#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
-
- /*
- * Set up signals we pay attention to locally.
- */
-#ifdef SIGDIE1
- (void) signal_no_reset(SIGDIE1, finish);
-#endif /* SIGDIE1 */
-#ifdef SIGDIE2
- (void) signal_no_reset(SIGDIE2, finish);
-#endif /* SIGDIE2 */
-#ifdef SIGDIE3
- (void) signal_no_reset(SIGDIE3, finish);
-#endif /* SIGDIE3 */
-#ifdef SIGDIE4
- (void) signal_no_reset(SIGDIE4, finish);
-#endif /* SIGDIE4 */
-
-#ifdef SIGBUS
- (void) signal_no_reset(SIGBUS, finish);
-#endif /* SIGBUS */
-
-#if !defined(SYS_WINNT) && !defined(VMS)
-# ifdef DEBUG
- (void) signal_no_reset(MOREDEBUGSIG, moredebug);
- (void) signal_no_reset(LESSDEBUGSIG, lessdebug);
-# else
- (void) signal_no_reset(MOREDEBUGSIG, no_debug);
- (void) signal_no_reset(LESSDEBUGSIG, no_debug);
-# endif /* DEBUG */
-#endif /* !SYS_WINNT && !VMS */
-
- /*
- * Set up signals we should never pay attention to.
- */
-#if defined SIGPIPE
- (void) signal_no_reset(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
-
-#if defined SYS_WINNT
- if (!SetConsoleCtrlHandler(OnConsoleEvent, TRUE)) {
- msyslog(LOG_ERR, "Can't set console control handler: %m");
- }
-#endif
-
- /*
- * Call the init_ routines to initialize the data structures.
- */
-#if defined (HAVE_IO_COMPLETION_PORT)
- init_io_completion_port();
- init_winnt_time();
-#endif
- init_auth();
- init_util();
- init_restrict();
- init_mon();
- init_timer();
- init_lib();
- init_random();
- init_request();
- init_control();
- init_peer();
-#ifdef REFCLOCK
- init_refclock();
-#endif
- set_process_priority();
- init_proto(); /* Call at high priority */
- 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
- * for the gizmo board. While at it, save the host name for later
- * along with the length. The crypto needs this.
- */
-#ifdef DEBUG
- debug = 0;
-#endif
- getconfig(argc, argv);
-#ifdef OPENSSL
- crypto_setup();
-#endif /* OPENSSL */
- initializing = 0;
-
-#if defined(SYS_WINNT) && !defined(NODETACH)
-# if defined(DEBUG)
- if(!debug)
- {
-# endif
- if (NoWinService == FALSE) {
- /* report to the service control manager that the service is running */
- ssStatus.dwCurrentState = SERVICE_RUNNING;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- if (ResolverThreadHandle != NULL)
- CloseHandle(ResolverThreadHandle);
- ssStatus.dwCurrentState = SERVICE_STOPPED;
- SetServiceStatus(sshStatusHandle, &ssStatus);
- return;
- }
- }
-# if defined(DEBUG)
- }
-# endif
-#endif
-
-#ifdef HAVE_CLOCKCTL
- /*
- * Drop super-user privileges and chroot now if the OS supports
- * non root clock control (only NetBSD for now).
- */
- if (user != NULL) {
- if (isdigit((unsigned char)*user)) {
- sw_uid = (uid_t)strtoul(user, &endp, 0);
- if (*endp != '\0')
- goto getuser;
- } else {
-getuser:
- if ((pw = getpwnam(user)) != NULL) {
- sw_uid = pw->pw_uid;
- } else {
- errno = 0;
- msyslog(LOG_ERR, "Cannot find user `%s'", user);
- exit (-1);
- }
- }
- }
- if (group != NULL) {
- if (isdigit((unsigned char)*group)) {
- sw_gid = (gid_t)strtoul(group, &endp, 0);
- if (*endp != '\0')
- goto getgroup;
- } else {
-getgroup:
- if ((gr = getgrnam(group)) != NULL) {
- sw_gid = pw->pw_gid;
- } else {
- errno = 0;
- msyslog(LOG_ERR, "Cannot find group `%s'", group);
- exit (-1);
- }
- }
- }
- if (chrootdir && chroot(chrootdir)) {
- msyslog(LOG_ERR, "Cannot chroot to `%s': %m", chrootdir);
- exit (-1);
- }
- if (group && setgid(sw_gid)) {
- msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
- exit (-1);
- }
- if (group && setegid(sw_gid)) {
- msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
- exit (-1);
- }
- if (user && setuid(sw_uid)) {
- msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
- exit (-1);
- }
- if (user && seteuid(sw_uid)) {
- msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
- exit (-1);
- }
-#endif
- /*
- * Report that we're up to any trappers
- */
- report_event(EVNT_SYSRESTART, (struct peer *)0);
-
- /*
- * Use select() on all on all input fd's for unlimited
- * time. select() will terminate on SIGALARM or on the
- * reception of input. Using select() means we can't do
- * robust signal handling and we get a potential race
- * between checking for alarms and doing the select().
- * Mostly harmless, I think.
- */
- /* On VMS, I suspect that select() can't be interrupted
- * by a "signal" either, so I take the easy way out and
- * have select() time out after one second.
- * System clock updates really aren't time-critical,
- * and - lacking a hardware reference clock - I have
- * yet to learn about anything else that is.
- */
-#if defined(HAVE_IO_COMPLETION_PORT)
- WaitHandles[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* exit reques */
- WaitHandles[1] = get_timer_handle();
- WaitHandles[2] = get_io_event();
-
- for (;;) {
- DWORD Index = WaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, FALSE, 1000, TRUE);
- switch (Index) {
- case WAIT_OBJECT_0 + 0 : /* exit request */
- exit(0);
- break;
-
- case WAIT_OBJECT_0 + 1 : /* timer */
- timer();
- break;
-
- case WAIT_OBJECT_0 + 2 : /* Io event */
-# ifdef DEBUG
- if ( debug > 3 )
- {
- printf( "IoEvent occurred\n" );
- }
-# endif
- break;
-
- case WAIT_IO_COMPLETION : /* loop */
- case WAIT_TIMEOUT :
- break;
- case WAIT_FAILED:
- msyslog(LOG_ERR, "ntpdc: WaitForMultipleObjectsEx Failed: Error: %m");
- break;
-
- /* For now do nothing if not expected */
- default:
- break;
-
- } /* switch */
- rbuflist = getrecvbufs(); /* get received buffers */
-
-#else /* normal I/O */
-
- was_alarmed = 0;
- rbuflist = (struct recvbuf *)0;
- for (;;)
- {
-# if !defined(HAVE_SIGNALED_IO)
- extern fd_set activefds;
- extern int maxactivefd;
-
- fd_set rdfdes;
- int nfound;
-# elif defined(HAVE_SIGNALED_IO)
- block_io_and_alarm();
-# endif
-
- rbuflist = getrecvbufs(); /* get received buffers */
- if (alarm_flag) /* alarmed? */
- {
- was_alarmed = 1;
- alarm_flag = 0;
- }
-
- if (!was_alarmed && rbuflist == (struct recvbuf *)0)
- {
- /*
- * Nothing to do. Wait for something.
- */
-# ifndef HAVE_SIGNALED_IO
- rdfdes = activefds;
-# if defined(VMS) || defined(SYS_VXWORKS)
- /* make select() wake up after one second */
- {
- struct timeval t1;
-
- t1.tv_sec = 1; t1.tv_usec = 0;
- nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
- (fd_set *)0, &t1);
- }
-# else
- nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
- (fd_set *)0, (struct timeval *)0);
-# endif /* VMS */
- if (nfound > 0)
- {
- l_fp ts;
-
- get_systime(&ts);
-
- (void)input_handler(&ts);
- }
- else if (nfound == -1 && errno != EINTR)
- msyslog(LOG_ERR, "select() error: %m");
-# ifdef DEBUG
- else if (debug > 2)
- msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
-# endif /* DEBUG */
-# else /* HAVE_SIGNALED_IO */
-
- wait_for_signal();
-# endif /* HAVE_SIGNALED_IO */
- if (alarm_flag) /* alarmed? */
- {
- was_alarmed = 1;
- alarm_flag = 0;
- }
- rbuflist = getrecvbufs(); /* get received buffers */
- }
-# ifdef HAVE_SIGNALED_IO
- unblock_io_and_alarm();
-# endif /* HAVE_SIGNALED_IO */
-
- /*
- * Out here, signals are unblocked. Call timer routine
- * to process expiry.
- */
- if (was_alarmed)
- {
- timer();
- was_alarmed = 0;
- }
-
-#endif /* HAVE_IO_COMPLETION_PORT */
- /*
- * Call the data procedure to handle each received
- * packet.
- */
- while (rbuflist != (struct recvbuf *)0)
- {
- rbuf = rbuflist;
- rbuflist = rbuf->next;
- (rbuf->receiver)(rbuf);
- freerecvbuf(rbuf);
- }
-#if defined DEBUG && defined SYS_WINNT
- if (debug > 4)
- printf("getrecvbufs: %ld handler interrupts, %ld frames\n",
- handler_calls, handler_pkts);
-#endif
-
- /*
- * Go around again
- */
- }
-#ifndef SYS_WINNT
- exit(1); /* unreachable */
-#endif
-#ifndef SYS_WINNT
- return 1; /* DEC OSF cc braindamage */
-#endif
-}
-
-
-#ifdef SIGDIE2
-/*
- * finish - exit gracefully
- */
-static RETSIGTYPE
-finish(
- int sig
- )
-{
-
- msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
-
- switch (sig)
- {
-# ifdef SIGBUS
- case SIGBUS:
- printf("\nfinish(SIGBUS)\n");
- exit(0);
-# endif
- case 0: /* Should never happen... */
- return;
- default:
- exit(0);
- }
-}
-#endif /* SIGDIE2 */
-
-
-#ifdef DEBUG
-#ifndef SYS_WINNT
-/*
- * moredebug - increase debugging verbosity
- */
-static RETSIGTYPE
-moredebug(
- int sig
- )
-{
- int saved_errno = errno;
-
- if (debug < 255)
- {
- debug++;
- msyslog(LOG_DEBUG, "debug raised to %d", debug);
- }
- errno = saved_errno;
-}
-
-/*
- * lessdebug - decrease debugging verbosity
- */
-static RETSIGTYPE
-lessdebug(
- int sig
- )
-{
- int saved_errno = errno;
-
- if (debug > 0)
- {
- debug--;
- msyslog(LOG_DEBUG, "debug lowered to %d", debug);
- }
- errno = saved_errno;
-}
-#endif
-#else /* not DEBUG */
-#ifndef SYS_WINNT/*
- * no_debug - We don't do the debug here.
- */
-static RETSIGTYPE
-no_debug(
- int sig
- )
-{
- int saved_errno = errno;
-
- msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig);
- errno = saved_errno;
-}
-#endif /* not SYS_WINNT */
-#endif /* not DEBUG */
-
-#ifdef SYS_WINNT
-/* service_ctrl - control handler for NTP service
- * signals the service_main routine of start/stop requests
- * from the control panel or other applications making
- * win32API calls
- */
-void
-service_ctrl(
- DWORD dwCtrlCode
- )
-{
- DWORD dwState = SERVICE_RUNNING;
-
- /* Handle the requested control code */
- switch(dwCtrlCode)
- {
- case SERVICE_CONTROL_PAUSE:
- /* see no reason to support this */
- break;
-
- case SERVICE_CONTROL_CONTINUE:
- /* see no reason to support this */
- break;
-
- case SERVICE_CONTROL_STOP:
- dwState = SERVICE_STOP_PENDING;
- /*
- * Report the status, specifying the checkpoint and waithint,
- * before setting the termination event.
- */
- ssStatus.dwCurrentState = dwState;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- ssStatus.dwWaitHint = 3000;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- }
- if (WaitHandles[0] != NULL) {
- SetEvent(WaitHandles[0]);
- }
- return;
-
- case SERVICE_CONTROL_INTERROGATE:
- /* Update the service status */
- break;
-
- default:
- /* invalid control code */
- break;
-
- }
-
- ssStatus.dwCurrentState = dwState;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- }
-}
-
-static BOOL WINAPI
-OnConsoleEvent(
- DWORD dwCtrlType
- )
-{
- switch (dwCtrlType) {
- case CTRL_BREAK_EVENT :
- if (debug > 0) {
- debug <<= 1;
- }
- else {
- debug = 1;
- }
- if (debug > 8) {
- debug = 0;
- }
- printf("debug level %d\n", debug);
- break ;
-
- case CTRL_C_EVENT :
- case CTRL_CLOSE_EVENT :
- case CTRL_SHUTDOWN_EVENT :
- if (WaitHandles[0] != NULL) {
- SetEvent(WaitHandles[0]);
- }
- break;
-
- default :
- return FALSE;
-
-
- }
- return TRUE;;
-}
-
-
-/*
- * NT version of exit() - all calls to exit() should be routed to
- * this function.
- */
-void
-service_exit(
- int status
- )
-{
- if (!debug) { /* did not become a service, simply exit */
- /* service mode, need to have the service_main routine
- * register with the service control manager that the
- * service has stopped running, before exiting
- */
- ssStatus.dwCurrentState = SERVICE_STOPPED;
- SetServiceStatus(sshStatusHandle, &ssStatus);
-
- }
- uninit_io_completion_port();
- reset_winnt_time();
-
-# if defined _MSC_VER
- _CrtDumpMemoryLeaks();
-# endif
-#undef exit
- exit(status);
-}
-
-#endif /* SYS_WINNT */
diff --git a/contrib/ntp/ntpd/ntpsim.c b/contrib/ntp/ntpd/ntpsim.c
deleted file mode 100644
index 3fbae17..0000000
--- a/contrib/ntp/ntpd/ntpsim.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * NTP simulator engine - Harish Nair
- * University of Delaware, 2001
- */
-#include "ntpd.h"
-#include "ntpsim.h"
-
-/*
- * Defines...
- */
-#define SIM_TIME 86400 /* end simulation time */
-#define NET_DLY .001 /* network delay */
-#define PROC_DLY .001 /* processing delay */
-#define BEEP_DLY 3600 /* beep interval (s) */
-#define SLEW 500e-6 /* correction rate (PPM) */
-
-/*
- * Function pointers
- */
-void (*funcPtr[]) (Node *, Event) = {
- &ndbeep, &ndeclk, &ntptmr, &netpkt
-};
-
-
-/*
- * ntpsim - initialize global variables and event queue and start
- */
-int
-ntpsim(
- int argc,
- char *argv[]
- )
-{
- Event e;
- double maxtime;
- struct timeval seed;
-
- /*
- * Initialize the global node
- */
- ntp_node.time = 0; /* simulation time */
- ntp_node.sim_time = SIM_TIME; /* end simulation time (-S) */
- ntp_node.ntp_time = 0; /* client disciplined time */
- ntp_node.adj = 0; /* remaining time correction */
- ntp_node.slew = SLEW; /* correction rate (-H) */
-
- ntp_node.clk_time = 0; /* server time (-O) */
- ntp_node.ferr = 0; /* frequency error (-T) */
- ntp_node.fnse = 0; /* random walk noise (-W) */
- ntp_node.ndly = NET_DLY; /* network delay (-Y) */
- ntp_node.snse = 0; /* phase noise (-C) */
- ntp_node.pdly = PROC_DLY; /* processing delay (-Z) */
- ntp_node.bdly = BEEP_DLY; /* beep interval (-B) */
-
- ntp_node.events = NULL;
- ntp_node.rbuflist = NULL;
-
- /*
- * Initialize ntp variables
- */
- initializing = 1;
- init_auth();
- init_util();
- init_restrict();
- init_mon();
- init_timer();
- init_lib();
- init_random();
- init_request();
- init_control();
- init_peer();
- init_proto();
- init_io();
- init_loopfilter();
- mon_start(MON_OFF);
- getconfig(argc, argv);
- initializing = 0;
-
- /*
- * Watch out here, we want the real time, not the silly stuff.
- */
- gettimeofday(&seed, NULL);
- srand48(seed.tv_usec);
-
- /*
- * Push a beep and timer interrupt on the queue
- */
- push(event(0, BEEP), &ntp_node.events);
- push(event(ntp_node.time + 1.0, TIMER), &ntp_node.events);
-
- /*
- * Pop the queue until nothing is left or time is exceeded
- */
- maxtime = ntp_node.time + ntp_node.sim_time;
- while (ntp_node.time <= maxtime && ntp_node.events != NULL ) {
- e = pop(&ntp_node.events);
- ndeclk(&ntp_node, e);
- funcPtr[e.function](&ntp_node, e);
- }
- return (0);
-}
-
-
-/*
- * Return an event
- */
-Event
-event(
- double t,
- funcTkn f
- )
-{
- Event e;
-
- e.time = t;
- e.function = f;
- return (e);
-}
-
-/*
- * Create an event queue
- */
-Queue
-queue(
- Event e,
- Queue q
- )
-{
- Queue ret;
-
- if ((ret = (Queue)malloc(sizeof(struct List))) == NULL)
- abortsim("queue-malloc");
- ret->event = e;
- ret->next = q;
- return (ret);
-}
-
-
-/*
- * Push an event into the event queue
- */
-void push(
- Event e,
- Queue *qp
- )
-{
- Queue *tmp = qp;
-
- while (*tmp != NULL && ((*tmp)->event.time < e.time))
- tmp = &((*tmp)->next);
- *tmp = queue(e, (*tmp));
-}
-
-
-/*
- * Pop the first event from the event queue
- */
-Event
-pop(
- Queue *qp
- )
-{
- Event ret;
- Queue tmp;
-
- tmp = *qp;
- if (tmp == NULL)
- abortsim("pop - empty queue");
- ret = tmp->event;
- *qp = tmp->next;
- free(tmp);
- return (ret);
-}
-
-
-/*
- * Update clocks
- */
-void
-ndeclk(
- Node *n,
- Event e
- )
-{
- node_clock(n, e.time);
-}
-
-
-/*
- * Timer interrupt. Eventually, this results in calling the
- * srvr_rplyi() routine below.
- */
-void
-ntptmr(
- Node *n,
- Event e
- )
-{
- struct recvbuf *rbuf;
-
- timer();
-
- /*
- * Process buffers received. They had better be in order by
- * receive timestamp.
- */
- while (n->rbuflist != NULL) {
- rbuf = n->rbuflist;
- n->rbuflist = rbuf->next;
- (rbuf->receiver)(rbuf);
- free(rbuf);
- }
-
- /*
- * Arm the next timer interrupt.
- */
- push(event(e.time + (1 << EVENT_TIMEOUT), TIMER), &n->events);
-}
-
-
-/*
- * srvr_rply() - send packet
- */
-int srvr_rply(
- Node *n,
- struct sockaddr_storage *dest,
- struct interface *inter, struct pkt *rpkt
- )
-{
- struct pkt xpkt;
- struct recvbuf rbuf;
- Event xvnt;
- double dtemp, etemp;
-
- /*
- * Insert packet header values. We make this look like a
- * stratum-1 server with a GPS clock, but nobody will ever
- * notice that.
- */
- xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING, NTP_VERSION,
- MODE_SERVER);
- xpkt.stratum = STRATUM_TO_PKT(((u_char)1));
- memcpy(&xpkt.refid, "GPS", 4);
- xpkt.ppoll = rpkt->ppoll;
- xpkt.precision = rpkt->precision;
- xpkt.rootdelay = 0;
- xpkt.rootdispersion = 0;
-
- /*
- * Insert the timestamps.
- */
- xpkt.org = rpkt->xmt;
- dtemp = poisson(n->ndly, n->snse); /* client->server delay */
- DTOLFP(dtemp + n->clk_time, &xpkt.rec);
- dtemp += poisson(n->pdly, 0); /* server delay */
- DTOLFP(dtemp + n->clk_time, &xpkt.xmt);
- xpkt.reftime = xpkt.xmt;
- dtemp += poisson(n->ndly, n->snse); /* server->client delay */
-
- /*
- * Insert the I/O stuff.
- */
- rbuf.receiver = receive;
- get_systime(&rbuf.recv_time);
- rbuf.recv_length = LEN_PKT_NOMAC;
- rbuf.recv_pkt = xpkt;
- memcpy(&rbuf.srcadr, dest, sizeof(struct sockaddr_storage));
- memcpy(&rbuf.recv_srcadr, dest,
- sizeof(struct sockaddr_storage));
- if ((rbuf.dstadr = malloc(sizeof(struct interface))) == NULL)
- abortsim("server-malloc");
- memcpy(rbuf.dstadr, inter, sizeof(struct interface));
- rbuf.next = NULL;
-
- /*
- * Very carefully predict the time of arrival for the received
- * packet.
- */
- LFPTOD(&xpkt.org, etemp);
- etemp += dtemp;
- xvnt = event(etemp, PACKET);
- xvnt.rcv_buf = rbuf;
- push(xvnt, &n->events);
- return (0);
-}
-
-
-/*
- * netpkt() - receive packet
- */
-void
-netpkt(
- Node *n,
- Event e
- )
-{
- struct recvbuf *rbuf;
- struct recvbuf *obuf;
-
- /*
- * Insert the packet on the receive queue and record the arrival
- * time.
- */
- if ((rbuf = malloc(sizeof(struct recvbuf))) == NULL)
- abortsim("ntprcv-malloc");
- memcpy(rbuf, &e.rcv_buf, sizeof(struct recvbuf));
- rbuf->receiver = receive;
- DTOLFP(n->ntp_time, &rbuf->recv_time);
- rbuf->next = NULL;
- obuf = n->rbuflist;
-
- /*
- * In the present incarnation, no more than one buffer can be on
- * the queue; however, we sniff the queue anyway as a hint for
- * further development.
- */
- if (obuf == NULL) {
- n->rbuflist = rbuf;
- } else {
- while (obuf->next != NULL)
- obuf = obuf->next;
- obuf->next = rbuf;
- }
-}
-
-
-/*
- * ndbeep() - progress indicator
- */
-void
-ndbeep(
- Node *n,
- Event e
- )
-{
- static int first_time = 1;
- char *dash = "-----------------";
-
- if(n->bdly > 0) {
- if (first_time) {
- printf(
- "\t%4c T %4c\t%4c T+ERR %3c\t%5cT+ERR+NTP\n", ' ', ' ', ' ', ' ',' ');
- printf("\t%s\t%s\t%s\n", dash, dash, dash);
- first_time = 0;
- push(event(n->bdly, BEEP), &n->events);
- push(event(n->sim_time, BEEP), &n->events);
- printf("\t%16.6f\t%16.6f\t%16.6f\n",
- n->time, n->clk_time, n->ntp_time);
- return;
- }
- printf("\t%16.6f\t%16.6f\t%16.6f\n",
- n->time, n->clk_time, n->ntp_time);
- push(event(e.time + n->bdly, BEEP), &n->events);
- }
-}
-
-
-/*
- * Abort simulation
- */
-void
-abortsim(
- char *errmsg
- )
-{
- perror(errmsg);
- exit(1);
-}
diff --git a/contrib/ntp/ntpd/refclock_acts.c b/contrib/ntp/ntpd/refclock_acts.c
deleted file mode 100644
index d26ceed..0000000
--- a/contrib/ntp/ntpd/refclock_acts.c
+++ /dev/null
@@ -1,984 +0,0 @@
-/*
- * refclock_acts - clock driver for the NIST/PTB Automated Computer Time
- * Service aka Amalgamated Containerized Trash Service (ACTS)
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && (defined(CLOCK_ACTS) || defined(CLOCK_PTBACTS))
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-#include "ntp_control.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
-/* MUST BE AFTER LAST #include <config.h> !!! */
-
-#if defined(CLOCK_ACTS) && defined(CLOCK_PTBACTS)
-# if defined(KEEPPTBACTS)
-# undef CLOCK_ACTS
-# else /* not KEEPPTBACTS */
-# undef CLOCK_PTBACTS
-# endif /* not KEEPPTBACTS */
-#endif /* CLOCK_ACTS && CLOCK_PTBACTS */
-
-/*
- * 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
- * ntp - Version 3 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 ntpdc, 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
- * ntpdc.
- *
- * 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
- *
- * PTB timecode service (+49 531 512038)
- * The Physikalisch-Technische Bundesanstalt (Germany)
- * also supports a modem time service
- * as the data formats are very similar this driver can also be compiled for
- * utilizing the PTB time code service.
- *
- * Data format
- * 0000000000111111111122222222223333333333444444444455555555556666666666777777777 7
- * 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9
- * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500 *
- * A B C D EF G H IJ K L M N O P Q R S T U V W XY Z<CR><LF>
- *
- * A year
- * B month
- * C day
- * D hour
- * E : normally
- * A for DST to ST switch first hour
- * B for DST to ST switch second hour if not marked in H
- * F minute
- * G second
- * H timezone
- * I day of week
- * J week of year
- * K day of year
- * L month for next ST/DST changes
- * M day
- * N hour
- * O UTC year
- * P UTC month
- * Q UTC day
- * R UTC hour
- * S UTC minute
- * T modified julian day (MJD)
- * U DUT1
- * V direction and month if leap second
- * W signal delay (assumed/measured)
- * X sequence number for additional text line in Y
- * Y additional text
- * Z on time marker (* - assumed delay / # measured delay)
- * <CR>!<LF> ! is second change !
- *
- * This format is also used by the National Physical Laboratory (NPL)'s
- * TRUETIME service in the UK. In this case the timezone field is
- * UTC+0 or UTC+1 for standard and daylight saving time. The phone
- * number for this service (a premium rate number) is 0891 516 333.
- * It is not clear whether the echo check is implemented.
- *
- * For more detail, see http://www.npl.co.uk/npl/cetm/taf/truetime.html.
- */
-
-/*
- * Interface definitions
- */
-#define SPEED232 B1200 /* uart speed (1200 cowardly baud) */
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#ifdef CLOCK_ACTS
-# define REFID "ACTS" /* reference ID */
-# define DESCRIPTION "NIST Automated Computer Time Service" /* WRU */
-# define LENCODE 50 /* length of valid timecode string */
-# define DEVICE "/dev/acts%d" /* device name and unit */
-# define REF_ENTRY refclock_acts
-#else /* not CLOCK_ACTS */
-# define REFID "TPTB" /* reference ID */
-# define DESCRIPTION "PTB Automated Computer Time Service"
-# define LENCODE 78 /* length of valid timecode string */
-# define DEVICE "/dev/ptb%d" /* device name and unit */
-# define REF_ENTRY refclock_ptb
-#endif /* not CLOCK_ACTS */
-#define MODE_AUTO 0 /* automatic mode */
-#define MODE_BACKUP 1 /* backup mode */
-#define MODE_MANUAL 2 /* manual mode */
-
-#define MSGCNT 10 /* we need this many ACTS messages */
-#define SMAX 80 /* max token string length */
-#define ACTS_MINPOLL 10 /* log2 min poll interval (1024 s) */
-#define ACTS_MAXPOLL 18 /* 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) */
-
-/*
- * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
- * leap.
- */
-static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/*
- * Unit control structure
- */
-struct actsunit {
- 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 *, const char *));
-
-/*
- * Transfer vector (conditional structure name)
- */
-struct refclock REF_ENTRY = {
- 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 (
- 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, TIOCMBIS, (char *)&dtr) < 0) {
- msyslog(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;
- peer->sstclktype = CTL_SST_TS_TELEPHONE;
-
- /*
- * 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
- */
- peer->nextdate = current_time + WAIT;
- return (1);
-}
-
-
-/*
- * acts_shutdown - shut down the clock
- */
-static void
-acts_shutdown (
- int unit,
- struct peer *peer
- )
-{
- register struct actsunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct actsunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * acts_receive - receive data from the serial interface
- */
-static void
-acts_receive (
- struct recvbuf *rbufp
- )
-{
- register struct actsunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- char str[SMAX];
- int i;
- char hangup = '%'; /* ACTS hangup */
- int day; /* day of the month */
- int month; /* month of the year */
- u_long mjd; /* Modified Julian Day */
- double dut1; /* DUT adjustment */
- double msADV; /* ACTS transmit advance (ms) */
- char flag; /* calibration flag */
-#ifndef CLOCK_PTBACTS
- char utc[10]; /* this is NIST and you're not */
- u_int dst; /* daylight/standard time indicator */
- u_int leap; /* leap-second indicator */
-#else
- char leapdir; /* leap direction */
- u_int leapmonth; /* month of leap */
-#endif
- /*
- * 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->a_lastcode, BMAX,
- &pp->lastrec);
- if (pp->lencode == 0) {
- if (strcmp(pp->a_lastcode, "OK") == 0)
- pp->lencode = 2;
- return;
- }
-#ifdef DEBUG
- if (debug)
- printf("acts: state %d timecode %d %*s\n", up->state,
- pp->lencode, pp->lencode, pp->a_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.
- */
- if( strcmp(pp->a_lastcode, " ") == 0) {
- acts_disc(peer);
- return;
- }
- if( strcmp(sys_phone[0],"DIRECT") != 0 ) {
- (void)strncpy(str, strtok(pp->a_lastcode, " "), SMAX);
- if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") ==
- 0 || strcmp(str, "NO") == 0) {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s ACTS modem status %s",
- ntoa(&peer->srcadr), pp->a_lastcode);
- acts_disc(peer);
- } else if (strcmp(str, "CONNECT") == 0) {
- peer->nextdate = current_time + CONNECT;
- up->msgcnt = 0;
- up->state++;
- }
- } else {
- (void) strncpy(str,"CONNECT",7);
- peer->nextdate = current_time + CONNECT;
- 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.
- */
- peer->nextdate = current_time + TIMECODE;
- 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;
-
-#ifndef CLOCK_PTBACTS
- /*
- * 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->a_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;
- }
-#else
- /*
- * Data format
- * 0000000000111111111122222222223333333333444444444455555555556666666666777777777 7
- * 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9
- * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500 *
- */
- if (sscanf(pp->a_lastcode,
- "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c",
- &pp->second, &pp->year, &month, &day, &pp->hour, &pp->minute, &mjd, &dut1, &leapdir, &leapmonth, &msADV, &flag) != 12) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-#endif
- /*
- * 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);
-
- /*
- * The ACTS timecode format croaks in 2000. 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;
- }
-
- /*
- * Depending on the driver, at this point we have a two-digit year
- * or a four-digit year. Make sure we have a four-digit year.
- */
- if ( pp->year < YEAR_PIVOT ) pp->year += 100; /* Y2KFixes */
- if ( pp->year < YEAR_BREAK ) pp->year += 1900; /* Y2KFixes */
- if ( !isleap_4(pp->year) ) { /* Y2KFixes */
- 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;
-
-#ifndef CLOCK_PTBACTS
- if (leap == 1)
- pp->leap = LEAP_ADDSECOND;
- else if (pp->leap == 2)
- pp->leap = LEAP_DELSECOND;
-#else
- if (leapmonth == month) {
- if (leapdir == '+')
- pp->leap = LEAP_ADDSECOND;
- else if (leapdir == '-')
- pp->leap = LEAP_DELSECOND;
- }
-#endif
-
- /*
- * 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 == '#') {
- pp->offset += (msADV - up->msADV) * 1000 * 1e-6;
- } else {
- up->msADV = msADV;
- if (!refclock_process(pp)) {
- 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.
- */
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- pp->sloppyclockflag &= ~CLK_FLAG1;
- up->pollcnt = 0;
- (void)write(pp->io.fd, &hangup, 1);
- up->state = 0;
- acts_disc(peer);
-}
-
-
-/*
- * acts_poll - called by the transmit routine
- */
-static void
-acts_poll (
- 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
- * ntpdc. 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 (peer);
- return;
-}
-
-
-/*
- * acts_timeout - called by the timer interrupt
- */
-static void
-acts_timeout (
- 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 ntpdc 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;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s ACTS backup started ",
- ntoa(&peer->srcadr));
- }
- } else if (up->run && sys_peer->sstclktype != CTL_SST_TS_TELEPHONE) {
- peer->hpoll = peer->minpoll;
- up->run = 0;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s ACTS backup stopped",
- ntoa(&peer->srcadr));
- }
- break;
-
- default:
- msyslog(LOG_ERR,
- "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 ntpdc, the ACTS calling program is
- * started; if reset, the phones stop ringing.
- */
- if (!(pp->sloppyclockflag & CLK_FLAG1)) {
- up->pollcnt = 0;
- peer->nextdate = current_time + IDLE;
- 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);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(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;
- peer->nextdate = current_time + IDLE;
- 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->a_lastcode, "OK") != 0)
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(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]);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s ACTS calling %s\n",
- ntoa(&peer->srcadr), sys_phone[up->pollcnt]);
- up->state = 1;
- up->pollcnt++;
- pp->polls++;
- peer->nextdate = current_time + ANSWER;
- return;
-}
-
-
-/*
- * acts_disc - disconnect the call and wait for the ruckus to cool
- */
-static void
-acts_disc (
- 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) {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(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->state = 0;
- }
- peer->nextdate = current_time + WAIT;
-}
-
-
-/*
- * acts_write - write a message to the serial port
- */
-static int
-acts_write (
- struct peer *peer,
- const 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, (unsigned)len) == len;
- code &= write(pp->io.fd, &cr, 1) == 1;
- if (!code)
- refclock_report(peer, CEVNT_FAULT);
- return (code);
-}
-
-#else
-int refclock_acts_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_arbiter.c b/contrib/ntp/ntpd/refclock_arbiter.c
deleted file mode 100644
index cf5f92f..0000000
--- a/contrib/ntp/ntpd/refclock_arbiter.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * refclock_arbiter - clock driver for Arbiter 1088A/B Satellite
- * Controlled Clock
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_ARBITER)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * This driver supports the Arbiter 1088A/B Satellite Controlled Clock.
- * The claimed accuracy of this clock is 100 ns relative to the PPS
- * output when receiving four or more satellites.
- *
- * The receiver should be configured before starting the NTP daemon, in
- * order to establish reliable position and operating conditions. It
- * does not initiate surveying or hold mode. For use with NTP, the
- * daylight savings time feature should be disables (D0 command) and the
- * broadcast mode set to operate in UTC (BU command).
- *
- * The timecode format supported by this driver is selected by the poll
- * sequence "B5", which initiates a line in the following format to be
- * repeated once per second until turned off by the "B0" poll sequence.
- *
- * Format B5 (24 ASCII printing characters):
- *
- * <cr><lf>i yy ddd hh:mm:ss.000bbb
- *
- * on-time = <cr>
- * i = synchronization flag (' ' = locked, '?' = unlocked)
- * yy = year of century
- * ddd = day of year
- * hh:mm:ss = hours, minutes, seconds
- * .000 = fraction of second (not used)
- * bbb = tailing spaces for fill
- *
- * The alarm condition is indicated by a '?' at i, which indicates the
- * receiver is not synchronized. In normal operation, a line consisting
- * of the timecode followed by the time quality character (TQ) followed
- * by the receiver status string (SR) is written to the clockstats file.
- * The time quality character is encoded in IEEE P1344 standard:
- *
- * Format TQ (IEEE P1344 estimated worst-case time quality)
- *
- * 0 clock locked, maximum accuracy
- * F clock failure, time not reliable
- * 4 clock unlocked, accuracy < 1 us
- * 5 clock unlocked, accuracy < 10 us
- * 6 clock unlocked, accuracy < 100 us
- * 7 clock unlocked, accuracy < 1 ms
- * 8 clock unlocked, accuracy < 10 ms
- * 9 clock unlocked, accuracy < 100 ms
- * A clock unlocked, accuracy < 1 s
- * B clock unlocked, accuracy < 10 s
- *
- * The status string is encoded as follows:
- *
- * Format SR (25 ASCII printing characters)
- *
- * V=vv S=ss T=t P=pdop E=ee
- *
- * vv = satellites visible
- * ss = relative signal strength
- * t = satellites tracked
- * pdop = position dilution of precision (meters)
- * ee = hardware errors
- *
- * If flag4 is set, an additional line consisting of the receiver
- * latitude (LA), longitude (LO) and elevation (LH) (meters) is written
- * to this file. If channel B is enabled for deviation mode and connected
- * to a 1-PPS signal, the last two numbers on the line are the deviation
- * and standard deviation averaged over the last 15 seconds.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/gps%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS " /* reference ID */
-#define DESCRIPTION "Arbiter 1088A/B GPS Receiver" /* WRU */
-
-#define LENARB 24 /* format B5 timecode length */
-#define MAXSTA 30 /* max length of status string */
-#define MAXPOS 70 /* max length of position string */
-
-/*
- * ARB unit control structure
- */
-struct arbunit {
- l_fp laststamp; /* last receive timestamp */
- int tcswitch; /* timecode switch/counter */
- char qualchar; /* IEEE P1344 quality (TQ command) */
- char status[MAXSTA]; /* receiver status (SR command) */
- char latlon[MAXPOS]; /* receiver position (lat/lon/alt) */
-};
-
-/*
- * Function prototypes
- */
-static int arb_start P((int, struct peer *));
-static void arb_shutdown P((int, struct peer *));
-static void arb_receive P((struct recvbuf *));
-static void arb_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_arbiter = {
- arb_start, /* start up driver */
- arb_shutdown, /* shut down driver */
- arb_poll, /* transmit poll message */
- noentry, /* not used (old arb_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old arb_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-/*
- * arb_start - open the devices and initialize data for processing
- */
-static int
-arb_start(
- int unit,
- struct peer *peer
- )
-{
- register struct arbunit *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 arbunit *)emalloc(sizeof(struct arbunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct arbunit));
- pp = peer->procptr;
- pp->io.clock_recv = arb_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);
- write(pp->io.fd, "B0", 2);
- return (1);
-}
-
-
-/*
- * arb_shutdown - shut down the clock
- */
-static void
-arb_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct arbunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct arbunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * arb_receive - receive data from the serial interface
- */
-static void
-arb_receive(
- struct recvbuf *rbufp
- )
-{
- register struct arbunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- l_fp trtmp;
- int temp;
- u_char syncchar; /* synchronization indicator */
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct arbunit *)pp->unitptr;
- temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
-
- /*
- * Note we get a buffer and timestamp for both a <cr> and <lf>,
- * but only the <cr> timestamp is retained. The program first
- * sends a TQ and expects the echo followed by the time quality
- * character. It then sends a B5 starting the timecode broadcast
- * and expects the echo followed some time later by the on-time
- * character <cr> and then the <lf> beginning the timecode
- * itself. Finally, at the <cr> beginning the next timecode at
- * the next second, the program sends a B0 shutting down the
- * timecode broadcast.
- *
- * If flag4 is set, the program snatches the latitude, longitude
- * and elevation and writes it to the clockstats file.
- */
- if (temp == 0)
- return;
- pp->lastrec = up->laststamp;
- up->laststamp = trtmp;
- if (temp < 3)
- return;
- if (up->tcswitch == 0) {
-
- /*
- * Collect statistics. If nothing is recogized, just
- * ignore; sometimes the clock doesn't stop spewing
- * timecodes for awhile after the B0 commant.
- */
- if (!strncmp(pp->a_lastcode, "TQ", 2)) {
- up->qualchar = pp->a_lastcode[2];
- write(pp->io.fd, "SR", 2);
- } else if (!strncmp(pp->a_lastcode, "SR", 2)) {
- strcpy(up->status, pp->a_lastcode + 2);
- if (pp->sloppyclockflag & CLK_FLAG4)
- write(pp->io.fd, "LA", 2);
- else {
- write(pp->io.fd, "B5", 2);
- up->tcswitch++;
- }
- } else if (!strncmp(pp->a_lastcode, "LA", 2)) {
- strcpy(up->latlon, pp->a_lastcode + 2);
- write(pp->io.fd, "LO", 2);
- } else if (!strncmp(pp->a_lastcode, "LO", 2)) {
- strcat(up->latlon, " ");
- strcat(up->latlon, pp->a_lastcode + 2);
- write(pp->io.fd, "LH", 2);
- } else if (!strncmp(pp->a_lastcode, "LH", 2)) {
- strcat(up->latlon, " ");
- strcat(up->latlon, pp->a_lastcode + 2);
- write(pp->io.fd, "DB", 2);
- } else if (!strncmp(pp->a_lastcode, "DB", 2)) {
- strcat(up->latlon, " ");
- strcat(up->latlon, pp->a_lastcode + 2);
- record_clock_stats(&peer->srcadr, up->latlon);
- write(pp->io.fd, "B5", 2);
- up->tcswitch++;
- }
- return;
- }
- pp->lencode = temp;
-
- /*
- * We get down to business, check the timecode format and decode
- * its contents. If the timecode has valid length, but not in
- * proper format, we declare bad format and exit. If the
- * timecode has invalid length, which sometimes occurs when the
- * B0 amputates the broadcast, we just quietly steal away. Note
- * that the time quality character and receiver status string is
- * tacked on the end for clockstats display.
- */
- if (pp->lencode == LENARB) {
- /*
- * Timecode format B5: "i yy ddd hh:mm:ss.000 "
- */
- pp->a_lastcode[LENARB - 2] = up->qualchar;
- strcat(pp->a_lastcode, up->status);
- syncchar = ' ';
- if (sscanf(pp->a_lastcode, "%c%2d %3d %2d:%2d:%2d",
- &syncchar, &pp->year, &pp->day, &pp->hour,
- &pp->minute, &pp->second) != 6) {
- refclock_report(peer, CEVNT_BADREPLY);
- write(pp->io.fd, "B0", 2);
- return;
- }
- } else {
- write(pp->io.fd, "B0", 2);
- return;
- }
- up->tcswitch++;
-
- /*
- * We decode the clock dispersion from the time quality
- * character.
- */
- switch (up->qualchar) {
-
- case '0': /* locked, max accuracy */
- pp->disp = 1e-7;
- break;
-
- case '4': /* unlock accuracy < 1 us */
- pp->disp = 1e-6;
- break;
-
- case '5': /* unlock accuracy < 10 us */
- pp->disp = 1e-5;
- break;
-
- case '6': /* unlock accuracy < 100 us */
- pp->disp = 1e-4;
- break;
-
- case '7': /* unlock accuracy < 1 ms */
- pp->disp = .001;
- break;
-
- case '8': /* unlock accuracy < 10 ms */
- pp->disp = .01;
- break;
-
- case '9': /* unlock accuracy < 100 ms */
- pp->disp = .1;
- break;
-
- case 'A': /* unlock accuracy < 1 s */
- pp->disp = 1;
- break;
-
- case 'B': /* unlock accuracy < 10 s */
- pp->disp = 10;
- break;
-
- case 'F': /* clock failure */
- pp->disp = MAXDISPERSE;
- refclock_report(peer, CEVNT_FAULT);
- write(pp->io.fd, "B0", 2);
- return;
-
- default:
- pp->disp = MAXDISPERSE;
- refclock_report(peer, CEVNT_BADREPLY);
- write(pp->io.fd, "B0", 2);
- return;
- }
- if (syncchar != ' ')
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
-#ifdef DEBUG
- if (debug)
- printf("arbiter: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
- if (up->tcswitch >= NSTAGE)
- write(pp->io.fd, "B0", 2);
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if (!refclock_process(pp))
- refclock_report(peer, CEVNT_BADTIME);
-}
-
-
-/*
- * arb_poll - called by the transmit procedure
- */
-static void
-arb_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct arbunit *up;
- struct refclockproc *pp;
-
- /*
- * Time to poll the clock. The Arbiter clock responds to a "B5"
- * by returning a timecode in the format specified above.
- * Transmission occurs once per second, unless turned off by a
- * "B0". 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.
- */
- pp = peer->procptr;
- up = (struct arbunit *)pp->unitptr;
- up->tcswitch = 0;
- if (write(pp->io.fd, "TQ", 2) != 2) {
- refclock_report(peer, CEVNT_FAULT);
- } else
- pp->polls++;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-}
-
-#else
-int refclock_arbiter_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_arc.c b/contrib/ntp/ntpd/refclock_arc.c
deleted file mode 100644
index f556da6..0000000
--- a/contrib/ntp/ntpd/refclock_arc.c
+++ /dev/null
@@ -1,1529 +0,0 @@
-/*
- * refclock_arc - clock driver for ARCRON MSF/DCF/WWVB receivers
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_ARCRON_MSF)
-static const char arc_version[] = { "V1.3 2003/02/21" };
-
-/* define PRE_NTP420 for compatibility to previous versions of NTP (at least
- to 4.1.0 */
-#undef PRE_NTP420
-
-#ifndef ARCRON_NOT_KEEN
-#define ARCRON_KEEN 1 /* Be keen, and trusting of the clock, if defined. */
-#endif
-
-#ifndef ARCRON_NOT_MULTIPLE_SAMPLES
-#define ARCRON_MULTIPLE_SAMPLES 1 /* Use all timestamp bytes as samples. */
-#endif
-
-#ifndef ARCRON_NOT_LEAPSECOND_KEEN
-#ifndef ARCRON_LEAPSECOND_KEEN
-#undef ARCRON_LEAPSECOND_KEEN /* Respond quickly to leap seconds: doesn't work yet. */
-#endif
-#endif
-
-/*
-Code by Derek Mulcahy, <derek@toybox.demon.co.uk>, 1997.
-Modifications by Damon Hart-Davis, <d@hd.org>, 1997.
-Modifications by Paul Alfille, <palfille@partners.org>, 2003.
-Modifications by Christopher Price, <cprice@cs-home.com>, 2003.
-
-
-THIS CODE IS SUPPLIED AS IS, WITH NO WARRANTY OF ANY KIND. USE AT
-YOUR OWN RISK.
-
-Orginally developed and used with ntp3-5.85 by Derek Mulcahy.
-
-Built against ntp3-5.90 on Solaris 2.5 using gcc 2.7.2.
-
-This code may be freely copied and used and incorporated in other
-systems providing the disclaimer and notice of authorship are
-reproduced.
-
--------------------------------------------------------------------------------
-
-Christopher's notes:
-
-MAJOR CHANGES SINCE V1.2
-========================
- 1) Applied patch by Andrey Bray <abuse@madhouse.demon.co.uk>
- 2001-02-17 comp.protocols.time.ntp
-
- 2) Added WWVB support via clock mode command, localtime/UTC time configured
- via flag1=(0=UTC, 1=localtime)
-
- 3) Added ignore resync request via flag2=(0=resync, 1=ignore resync)
-
- 4) Added simplified conversion from localtime to UTC with dst/bst translation
-
- 5) Added average signal quality poll
-
- 6) Fixed a badformat error when no code is available due to stripping
- \n & \r's
-
- 7) Fixed a badformat error when clearing lencode & memset a_lastcode in poll
- routine
-
- 8) Lots of code cleanup, including standardized DEBUG macros and removal
- of unused code
-
--------------------------------------------------------------------------------
-
-Author's original note:
-
-I enclose my ntp driver for the Galleon Systems Arc MSF receiver.
-
-It works (after a fashion) on both Solaris-1 and Solaris-2.
-
-I am currently using ntp3-5.85. I have been running the code for
-about 7 months without any problems. Even coped with the change to BST!
-
-I had to do some funky things to read from the clock because it uses the
-power from the receive lines to drive the transmit lines. This makes the
-code look a bit stupid but it works. I also had to put in some delays to
-allow for the turnaround time from receive to transmit. These delays
-are between characters when requesting a time stamp so that shouldn't affect
-the results too drastically.
-
-...
-
-The bottom line is that it works but could easily be improved. You are
-free to do what you will with the code. I haven't been able to determine
-how good the clock is. I think that this requires a known good clock
-to compare it against.
-
--------------------------------------------------------------------------------
-
-Damon's notes for adjustments:
-
-MAJOR CHANGES SINCE V1.0
-========================
- 1) Removal of pollcnt variable that made the clock go permanently
- off-line once two time polls failed to gain responses.
-
- 2) Avoiding (at least on Solaris-2) terminal becoming the controlling
- terminal of the process when we do a low-level open().
-
- 3) Additional logic (conditional on ARCRON_LEAPSECOND_KEEN being
- defined) to try to resync quickly after a potential leap-second
- insertion or deletion.
-
- 4) Code significantly slimmer at run-time than V1.0.
-
-
-GENERAL
-=======
-
- 1) The C preprocessor symbol to have the clock built has been changed
- from ARC to ARCRON_MSF to CLOCK_ARCRON_MSF to minimise the
- possiblity of clashes with other symbols in the future.
-
- 2) PRECISION should be -4/-5 (63ms/31ms) for the following reasons:
-
- a) The ARC documentation claims the internal clock is (only)
- accurate to about 20ms relative to Rugby (plus there must be
- noticable drift and delay in the ms range due to transmission
- delays and changing atmospheric effects). This clock is not
- designed for ms accuracy as NTP has spoilt us all to expect.
-
- b) The clock oscillator looks like a simple uncompensated quartz
- crystal of the sort used in digital watches (ie 32768Hz) which
- can have large temperature coefficients and drifts; it is not
- clear if this oscillator is properly disciplined to the MSF
- transmission, but as the default is to resync only once per
- *day*, we can imagine that it is not, and is free-running. We
- can minimise drift by resyncing more often (at the cost of
- reduced battery life), but drift/wander may still be
- significant.
-
- c) Note that the bit time of 3.3ms adds to the potential error in
- the the clock timestamp, since the bit clock of the serial link
- may effectively be free-running with respect to the host clock
- and the MSF clock. Actually, the error is probably 1/16th of
- the above, since the input data is probably sampled at at least
- 16x the bit rate.
-
- By keeping the clock marked as not very precise, it will have a
- fairly large dispersion, and thus will tend to be used as a
- `backup' time source and sanity checker, which this clock is
- probably ideal for. For an isolated network without other time
- sources, this clock can probably be expected to provide *much*
- better than 1s accuracy, which will be fine.
-
- By default, PRECISION is set to -4, but experience, especially at a
- particular geographic location with a particular clock, may allow
- this to be altered to -5. (Note that skews of +/- 10ms are to be
- expected from the clock from time-to-time.) This improvement of
- reported precision can be instigated by setting flag3 to 1, though
- the PRECISION will revert to the normal value while the clock
- signal quality is unknown whatever the flag3 setting.
-
- IN ANY CASE, BE SURE TO SET AN APPROPRIATE FUDGE FACTOR TO REMOVE
- ANY RESIDUAL SKEW, eg:
-
- server 127.127.27.0 # ARCRON MSF radio clock unit 0.
- # Fudge timestamps by about 20ms.
- fudge 127.127.27.0 time1 0.020
-
- You will need to observe your system's behaviour, assuming you have
- some other NTP source to compare it with, to work out what the
- fudge factor should be. For my Sun SS1 running SunOS 4.1.3_U1 with
- my MSF clock with my distance from the MSF transmitter, +20ms
- seemed about right, after some observation.
-
- 3) REFID has been made "MSFa" to reflect the MSF time source and the
- ARCRON receiver.
-
- 4) DEFAULT_RESYNC_TIME is the time in seconds (by default) before
- forcing a resync since the last attempt. This is picked to give a
- little less than an hour between resyncs and to try to avoid
- clashing with any regular event at a regular time-past-the-hour
- which might cause systematic errors.
-
- The INITIAL_RESYNC_DELAY is to avoid bothering the clock and
- running down its batteries unnecesarily if ntpd is going to crash
- or be killed or reconfigured quickly. If ARCRON_KEEN is defined
- then this period is long enough for (with normal polling rates)
- enough time samples to have been taken to allow ntpd to sync to
- the clock before the interruption for the clock to resync to MSF.
- This avoids ntpd syncing to another peer first and then
- almost immediately hopping to the MSF clock.
-
- The RETRY_RESYNC_TIME is used before rescheduling a resync after a
- resync failed to reveal a statisfatory signal quality (too low or
- unknown).
-
- 5) The clock seems quite jittery, so I have increased the
- median-filter size from the typical (previous) value of 3. I
- discard up to half the results in the filter. It looks like maybe
- 1 sample in 10 or so (maybe less) is a spike, so allow the median
- filter to discard at least 10% of its entries or 1 entry, whichever
- is greater.
-
- 6) Sleeping *before* each character sent to the unit to allow required
- inter-character time but without introducting jitter and delay in
- handling the response if possible.
-
- 7) If the flag ARCRON_KEEN is defined, take time samples whenever
- possible, even while resyncing, etc. We rely, in this case, on the
- clock always giving us a reasonable time or else telling us in the
- status byte at the end of the timestamp that it failed to sync to
- MSF---thus we should never end up syncing to completely the wrong
- time.
-
- 8) If the flag ARCRON_OWN_FILTER is defined, use own versions of
- refclock median-filter routines to get round small bug in 3-5.90
- code which does not return the median offset. XXX Removed this
- bit due NTP Version 4 upgrade - dlm.
-
- 9) We would appear to have a year-2000 problem with this clock since
- it returns only the two least-significant digits of the year. But
- ntpd ignores the year and uses the local-system year instead, so
- this is in fact not a problem. Nevertheless, we attempt to do a
- sensible thing with the dates, wrapping them into a 100-year
- window.
-
- 10)Logs stats information that can be used by Derek's Tcl/Tk utility
- to show the status of the clock.
-
- 11)The clock documentation insists that the number of bits per
- character to be sent to the clock, and sent by it, is 11, including
- one start bit and two stop bits. The data format is either 7+even
- or 8+none.
-
-
-TO-DO LIST
-==========
-
- * Eliminate use of scanf(), and maybe sprintf().
-
- * Allow user setting of resync interval to trade battery life for
- accuracy; maybe could be done via fudge factor or unit number.
-
- * Possibly note the time since the last resync of the MSF clock to
- MSF as the age of the last reference timestamp, ie trust the
- clock's oscillator not very much...
-
- * Add very slow auto-adjustment up to a value of +/- time2 to correct
- for long-term errors in the clock value (time2 defaults to 0 so the
- correction would be disabled by default).
-
- * Consider trying to use the tty_clk/ppsclock support.
-
- * Possibly use average or maximum signal quality reported during
- resync, rather than just the last one, which may be atypical.
-
-*/
-
-
-/* Notes for HKW Elektronik GmBH Radio clock driver */
-/* Author Lyndon David, Sentinet Ltd, Feb 1997 */
-/* These notes seem also to apply usefully to the ARCRON clock. */
-
-/* The HKW clock module is a radio receiver tuned into the Rugby */
-/* MSF time signal tranmitted on 60 kHz. The clock module connects */
-/* to the computer via a serial line and transmits the time encoded */
-/* in 15 bytes at 300 baud 7 bits two stop bits even parity */
-
-/* Clock communications, from the datasheet */
-/* All characters sent to the clock are echoed back to the controlling */
-/* device. */
-/* Transmit time/date information */
-/* syntax ASCII o<cr> */
-/* Character o may be replaced if neccesary by a character whose code */
-/* contains the lowest four bits f(hex) eg */
-/* syntax binary: xxxx1111 00001101 */
-
-/* DHD note:
-You have to wait for character echo + 10ms before sending next character.
-*/
-
-/* The clock replies to this command with a sequence of 15 characters */
-/* which contain the complete time and a final <cr> making 16 characters */
-/* in total. */
-/* The RC computer clock will not reply immediately to this command because */
-/* the start bit edge of the first reply character marks the beginning of */
-/* the second. So the RC Computer Clock will reply to this command at the */
-/* start of the next second */
-/* The characters have the following meaning */
-/* 1. hours tens */
-/* 2. hours units */
-/* 3. minutes tens */
-/* 4. minutes units */
-/* 5. seconds tens */
-/* 6. seconds units */
-/* 7. day of week 1-monday 7-sunday */
-/* 8. day of month tens */
-/* 9. day of month units */
-/* 10. month tens */
-/* 11. month units */
-/* 12. year tens */
-/* 13. year units */
-/* 14. BST/UTC status */
-/* bit 7 parity */
-/* bit 6 always 0 */
-/* bit 5 always 1 */
-/* bit 4 always 1 */
-/* bit 3 always 0 */
-/* bit 2 =1 if UTC is in effect, complementary to the BST bit */
-/* bit 1 =1 if BST is in effect, according to the BST bit */
-/* bit 0 BST/UTC change impending bit=1 in case of change impending */
-/* 15. status */
-/* bit 7 parity */
-/* bit 6 always 0 */
-/* bit 5 always 1 */
-/* bit 4 always 1 */
-/* bit 3 =1 if low battery is detected */
-/* bit 2 =1 if the very last reception attempt failed and a valid */
-/* time information already exists (bit0=1) */
-/* =0 if the last reception attempt was successful */
-/* bit 1 =1 if at least one reception since 2:30 am was successful */
-/* =0 if no reception attempt since 2:30 am was successful */
-/* bit 0 =1 if the RC Computer Clock contains valid time information */
-/* This bit is zero after reset and one after the first */
-/* successful reception attempt */
-
-/* DHD note:
-Also note g<cr> command which confirms that a resync is in progress, and
-if so what signal quality (0--5) is available.
-Also note h<cr> command which starts a resync to MSF signal.
-*/
-
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.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
-
-/*
- * This driver supports the ARCRON MSF/DCF/WWVB Radio Controlled Clock
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/arc%d" /* Device name and unit. */
-#define SPEED B300 /* UART speed (300 baud) */
-#define PRECISION (-4) /* Precision (~63 ms). */
-#define HIGHPRECISION (-5) /* If things are going well... */
-#define REFID "MSFa" /* Reference ID. */
-#define REFID_MSF "MSF" /* Reference ID. */
-#define REFID_DCF77 "DCF" /* Reference ID. */
-#define REFID_WWVB "WWVB" /* Reference ID. */
-#define DESCRIPTION "ARCRON MSF/DCF/WWVB Receiver"
-
-#ifdef PRE_NTP420
-#define MODE ttlmax
-#else
-#define MODE ttl
-#endif
-
-#define LENARC 16 /* Format `o' timecode length. */
-
-#define BITSPERCHAR 11 /* Bits per character. */
-#define BITTIME 0x0DA740E /* Time for 1 bit at 300bps. */
-#define CHARTIME10 0x8888888 /* Time for 10-bit char at 300bps. */
-#define CHARTIME11 0x962FC96 /* Time for 11-bit char at 300bps. */
-#define CHARTIME /* Time for char at 300bps. */ \
-( (BITSPERCHAR == 11) ? CHARTIME11 : ( (BITSPERCHAR == 10) ? CHARTIME10 : \
- (BITSPERCHAR * BITTIME) ) )
-
- /* Allow for UART to accept char half-way through final stop bit. */
-#define INITIALOFFSET (u_int32)(-BITTIME/2)
-
- /*
- charoffsets[x] is the time after the start of the second that byte
- x (with the first byte being byte 1) is received by the UART,
- assuming that the initial edge of the start bit of the first byte
- is on-time. The values are represented as the fractional part of
- an l_fp.
-
- We store enough values to have the offset of each byte including
- the trailing \r, on the assumption that the bytes follow one
- another without gaps.
- */
- static const u_int32 charoffsets[LENARC+1] = {
-#if BITSPERCHAR == 11 /* Usual case. */
- /* Offsets computed as accurately as possible... */
- 0,
- INITIALOFFSET + 0x0962fc96, /* 1 chars, 11 bits */
- INITIALOFFSET + 0x12c5f92c, /* 2 chars, 22 bits */
- INITIALOFFSET + 0x1c28f5c3, /* 3 chars, 33 bits */
- INITIALOFFSET + 0x258bf259, /* 4 chars, 44 bits */
- INITIALOFFSET + 0x2eeeeeef, /* 5 chars, 55 bits */
- INITIALOFFSET + 0x3851eb85, /* 6 chars, 66 bits */
- INITIALOFFSET + 0x41b4e81b, /* 7 chars, 77 bits */
- INITIALOFFSET + 0x4b17e4b1, /* 8 chars, 88 bits */
- INITIALOFFSET + 0x547ae148, /* 9 chars, 99 bits */
- INITIALOFFSET + 0x5dddddde, /* 10 chars, 110 bits */
- INITIALOFFSET + 0x6740da74, /* 11 chars, 121 bits */
- INITIALOFFSET + 0x70a3d70a, /* 12 chars, 132 bits */
- INITIALOFFSET + 0x7a06d3a0, /* 13 chars, 143 bits */
- INITIALOFFSET + 0x8369d037, /* 14 chars, 154 bits */
- INITIALOFFSET + 0x8ccccccd, /* 15 chars, 165 bits */
- INITIALOFFSET + 0x962fc963 /* 16 chars, 176 bits */
-#else
- /* Offsets computed with a small rounding error... */
- 0,
- INITIALOFFSET + 1 * CHARTIME,
- INITIALOFFSET + 2 * CHARTIME,
- INITIALOFFSET + 3 * CHARTIME,
- INITIALOFFSET + 4 * CHARTIME,
- INITIALOFFSET + 5 * CHARTIME,
- INITIALOFFSET + 6 * CHARTIME,
- INITIALOFFSET + 7 * CHARTIME,
- INITIALOFFSET + 8 * CHARTIME,
- INITIALOFFSET + 9 * CHARTIME,
- INITIALOFFSET + 10 * CHARTIME,
- INITIALOFFSET + 11 * CHARTIME,
- INITIALOFFSET + 12 * CHARTIME,
- INITIALOFFSET + 13 * CHARTIME,
- INITIALOFFSET + 14 * CHARTIME,
- INITIALOFFSET + 15 * CHARTIME,
- INITIALOFFSET + 16 * CHARTIME
-#endif
- };
-
-#define DEFAULT_RESYNC_TIME (57*60) /* Gap between resync attempts (s). */
-#define RETRY_RESYNC_TIME (27*60) /* Gap to emergency resync attempt. */
-#ifdef ARCRON_KEEN
-#define INITIAL_RESYNC_DELAY 500 /* Delay before first resync. */
-#else
-#define INITIAL_RESYNC_DELAY 50 /* Delay before first resync. */
-#endif
-
- static const int moff[12] =
-{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-/* Flags for a raw open() of the clock serial device. */
-#ifdef O_NOCTTY /* Good, we can avoid tty becoming controlling tty. */
-#define OPEN_FLAGS (O_RDWR | O_NOCTTY)
-#else /* Oh well, it may not matter... */
-#define OPEN_FLAGS (O_RDWR)
-#endif
-
-
-/* Length of queue of command bytes to be sent. */
-#define CMDQUEUELEN 4 /* Enough for two cmds + each \r. */
-/* Queue tick time; interval in seconds between chars taken off queue. */
-/* Must be >= 2 to allow o\r response to come back uninterrupted. */
-#define QUEUETICK 2 /* Allow o\r reply to finish. */
-
-/*
- * ARC unit control structure
- */
-struct arcunit {
- l_fp lastrec; /* Time tag for the receive time (system). */
- int status; /* Clock status. */
-
- int quality; /* Quality of reception 0--5 for unit. */
- /* We may also use the values -1 or 6 internally. */
- u_long quality_stamp; /* Next time to reset quality average. */
-
- u_long next_resync; /* Next resync time (s) compared to current_time. */
- int resyncing; /* Resync in progress if true. */
-
- /* In the outgoing queue, cmdqueue[0] is next to be sent. */
- char cmdqueue[CMDQUEUELEN+1]; /* Queue of outgoing commands + \0. */
-
- u_long saved_flags; /* Saved fudge flags. */
-};
-
-#ifdef ARCRON_LEAPSECOND_KEEN
-/* The flag `possible_leap' is set non-zero when any MSF unit
- thinks a leap-second may have happened.
-
- Set whenever we receive a valid time sample in the first hour of
- the first day of the first/seventh months.
-
- Outside the special hour this value is unconditionally set
- to zero by the receive routine.
-
- On finding itself in this timeslot, as long as the value is
- non-negative, the receive routine sets it to a positive value to
- indicate a resync to MSF should be performed.
-
- In the poll routine, if this value is positive and we are not
- already resyncing (eg from a sync that started just before
- midnight), start resyncing and set this value negative to
- indicate that a leap-triggered resync has been started. Having
- set this negative prevents the receive routine setting it
- positive and thus prevents multiple resyncs during the witching
- hour.
- */
-static int possible_leap = 0; /* No resync required by default. */
-#endif
-
-#if 0
-static void dummy_event_handler P((struct peer *));
-static void arc_event_handler P((struct peer *));
-#endif /* 0 */
-
-#define QUALITY_UNKNOWN -1 /* Indicates unknown clock quality. */
-#define MIN_CLOCK_QUALITY 0 /* Min quality clock will return. */
-#define MIN_CLOCK_QUALITY_OK 3 /* Min quality for OK reception. */
-#define MAX_CLOCK_QUALITY 5 /* Max quality clock will return. */
-
-/*
- * Function prototypes
- */
-static int arc_start P((int, struct peer *));
-static void arc_shutdown P((int, struct peer *));
-static void arc_receive P((struct recvbuf *));
-static void arc_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_arc = {
- arc_start, /* start up driver */
- arc_shutdown, /* shut down driver */
- arc_poll, /* transmit poll message */
- noentry, /* not used (old arc_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old arc_buginfo) */
- NOFLAGS /* not used */
-};
-
-/* Queue us up for the next tick. */
-#define ENQUEUE(up) \
- do { \
- peer->nextaction = current_time + QUEUETICK; \
- } while(0)
-
-/* Placeholder event handler---does nothing safely---soaks up loose tick. */
-static void
-dummy_event_handler(
- struct peer *peer
- )
-{
-#ifdef DEBUG
- if(debug) { printf("arc: dummy_event_handler() called.\n"); }
-#endif
-}
-
-/*
-Normal event handler.
-
-Take first character off queue and send to clock if not a null.
-
-Shift characters down and put a null on the end.
-
-We assume that there is no parallelism so no race condition, but even
-if there is nothing bad will happen except that we might send some bad
-data to the clock once in a while.
-*/
-static void
-arc_event_handler(
- struct peer *peer
- )
-{
- struct refclockproc *pp = peer->procptr;
- register struct arcunit *up = (struct arcunit *)pp->unitptr;
- int i;
- char c;
-#ifdef DEBUG
- if(debug > 2) { printf("arc: arc_event_handler() called.\n"); }
-#endif
-
- c = up->cmdqueue[0]; /* Next char to be sent. */
- /* Shift down characters, shifting trailing \0 in at end. */
- for(i = 0; i < CMDQUEUELEN; ++i)
- { up->cmdqueue[i] = up->cmdqueue[i+1]; }
-
- /* Don't send '\0' characters. */
- if(c != '\0') {
- if(write(pp->io.fd, &c, 1) != 1) {
- msyslog(LOG_NOTICE, "ARCRON: write to fd %d failed", pp->io.fd);
- }
-#ifdef DEBUG
- else if(debug) { printf("arc: sent `%2.2x', fd %d.\n", c, pp->io.fd); }
-#endif
- }
-
- ENQUEUE(up);
-}
-
-/*
- * arc_start - open the devices and initialize data for processing
- */
-static int
-arc_start(
- int unit,
- struct peer *peer
- )
-{
- register struct arcunit *up;
- struct refclockproc *pp;
- int fd;
- char device[20];
-#ifdef HAVE_TERMIOS
- struct termios arg;
-#endif
-
- msyslog(LOG_NOTICE, "ARCRON: %s: opening unit %d", arc_version, unit);
-#ifdef DEBUG
- if(debug) {
- printf("arc: %s: attempt to open unit %d.\n", arc_version, unit);
- }
-#endif
-
- /* Prevent a ridiculous device number causing overflow of device[]. */
- if((unit < 0) || (unit > 255)) { return(0); }
-
- /*
- * Open serial port. Use CLK line discipline, if available.
- */
- (void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED, LDISC_CLK)))
- return(0);
-#ifdef DEBUG
- if(debug) { printf("arc: unit %d using open().\n", unit); }
-#endif
- fd = open(device, OPEN_FLAGS);
- if(fd < 0) {
-#ifdef DEBUG
- if(debug) { printf("arc: failed [open()] to open %s.\n", device); }
-#endif
- return(0);
- }
-
- fcntl(fd, F_SETFL, 0); /* clear the descriptor flags */
-#ifdef DEBUG
- if(debug)
- { printf("arc: opened RS232 port with file descriptor %d.\n", fd); }
-#endif
-
-#ifdef HAVE_TERMIOS
-
- arg.c_iflag = IGNBRK | ISTRIP;
- arg.c_oflag = 0;
- arg.c_cflag = B300 | CS8 | CREAD | CLOCAL | CSTOPB;
- arg.c_lflag = 0;
- arg.c_cc[VMIN] = 1;
- arg.c_cc[VTIME] = 0;
-
- tcsetattr(fd, TCSANOW, &arg);
-
-#else
-
- msyslog(LOG_ERR, "ARCRON: termios not supported in this driver");
- (void)close(fd);
-
- return 0;
-
-#endif
-
- up = (struct arcunit *) emalloc(sizeof(struct arcunit));
- if(!up) { (void) close(fd); return(0); }
- /* Set structure to all zeros... */
- memset((char *)up, 0, sizeof(struct arcunit));
- pp = peer->procptr;
- pp->io.clock_recv = arc_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;
- peer->stratum = 2; /* Default to stratum 2 not 0. */
- pp->clockdesc = DESCRIPTION;
- if (peer->MODE > 3) {
- msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d", peer->MODE);
- return 0;
- }
-#ifdef DEBUG
- if(debug) { printf("arc: mode = %d.\n", peer->MODE); }
-#endif
- switch (peer->MODE) {
- case 1:
- memcpy((char *)&pp->refid, REFID_MSF, 4);
- break;
- case 2:
- memcpy((char *)&pp->refid, REFID_DCF77, 4);
- break;
- case 3:
- memcpy((char *)&pp->refid, REFID_WWVB, 4);
- break;
- default:
- memcpy((char *)&pp->refid, REFID, 4);
- break;
- }
- /* Spread out resyncs so that they should remain separated. */
- up->next_resync = current_time + INITIAL_RESYNC_DELAY + (67*unit)%1009;
-
-#if 0 /* Not needed because of zeroing of arcunit structure... */
- up->resyncing = 0; /* Not resyncing yet. */
- up->saved_flags = 0; /* Default is all flags off. */
- /* Clear send buffer out... */
- {
- int i;
- for(i = CMDQUEUELEN; i >= 0; --i) { up->cmdqueue[i] = '\0'; }
- }
-#endif
-
-#ifdef ARCRON_KEEN
- up->quality = QUALITY_UNKNOWN; /* Trust the clock immediately. */
-#else
- up->quality = MIN_CLOCK_QUALITY;/* Don't trust the clock yet. */
-#endif
-
- peer->action = arc_event_handler;
-
- ENQUEUE(up);
-
- return(1);
-}
-
-
-/*
- * arc_shutdown - shut down the clock
- */
-static void
-arc_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct arcunit *up;
- struct refclockproc *pp;
-
- peer->action = dummy_event_handler;
-
- pp = peer->procptr;
- up = (struct arcunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-/*
-Compute space left in output buffer.
-*/
-static int
-space_left(
- register struct arcunit *up
- )
-{
- int spaceleft;
-
- /* Compute space left in buffer after any pending output. */
- for(spaceleft = 0; spaceleft < CMDQUEUELEN; ++spaceleft)
- { if(up->cmdqueue[CMDQUEUELEN - 1 - spaceleft] != '\0') { break; } }
- return(spaceleft);
-}
-
-/*
-Send command by copying into command buffer as far forward as possible,
-after any pending output.
-
-Indicate an error by returning 0 if there is not space for the command.
-*/
-static int
-send_slow(
- register struct arcunit *up,
- int fd,
- const char *s
- )
-{
- int sl = strlen(s);
- int spaceleft = space_left(up);
-
-#ifdef DEBUG
- if(debug > 1) { printf("arc: spaceleft = %d.\n", spaceleft); }
-#endif
- if(spaceleft < sl) { /* Should not normally happen... */
-#ifdef DEBUG
- msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)",
- sl, spaceleft);
-#endif
- return(0); /* FAILED! */
- }
-
- /* Copy in the command to be sent. */
- while(*s) { up->cmdqueue[CMDQUEUELEN - spaceleft--] = *s++; }
-
- return(1);
-}
-
-
-/* Macro indicating action we will take for different quality values. */
-#define quality_action(q) \
-(((q) == QUALITY_UNKNOWN) ? "UNKNOWN, will use clock anyway" : \
- (((q) < MIN_CLOCK_QUALITY_OK) ? "TOO POOR, will not use clock" : \
- "OK, will use clock"))
-
- /*
- * arc_receive - receive data from the serial interface
- */
- static void
-arc_receive(
- struct recvbuf *rbufp
- )
-{
- register struct arcunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- char c;
- int i, n, wday, month, flags, status;
- int arc_last_offset;
- static int quality_average = 0;
- static int quality_sum = 0;
- static int quality_polls = 0;
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct arcunit *)pp->unitptr;
-
-
- /*
- If the command buffer is empty, and we are resyncing, insert a
- g\r quality request into it to poll for signal quality again.
- */
- if((up->resyncing) && (space_left(up) == CMDQUEUELEN)) {
-#ifdef DEBUG
- if(debug > 1) { printf("arc: inserting signal-quality poll.\n"); }
-#endif
- send_slow(up, pp->io.fd, "g\r");
- }
-
- /*
- The `arc_last_offset' is the offset in lastcode[] of the last byte
- received, and which we assume actually received the input
- timestamp.
-
- (When we get round to using tty_clk and it is available, we
- assume that we will receive the whole timecode with the
- trailing \r, and that that \r will be timestamped. But this
- assumption also works if receive the characters one-by-one.)
- */
- arc_last_offset = pp->lencode+rbufp->recv_length - 1;
-
- /*
- We catch a timestamp iff:
-
- * The command code is `o' for a timestamp.
-
- * If ARCRON_MULTIPLE_SAMPLES is undefined then we must have
- exactly char in the buffer (the command code) so that we
- only sample the first character of the timecode as our
- `on-time' character.
-
- * The first character in the buffer is not the echoed `\r'
- from the `o` command (so if we are to timestamp an `\r' it
- must not be first in the receive buffer with lencode==1.
- (Even if we had other characters following it, we probably
- would have a premature timestamp on the '\r'.)
-
- * We have received at least one character (I cannot imagine
- how it could be otherwise, but anyway...).
- */
- c = rbufp->recv_buffer[0];
- if((pp->a_lastcode[0] == 'o') &&
-#ifndef ARCRON_MULTIPLE_SAMPLES
- (pp->lencode == 1) &&
-#endif
- ((pp->lencode != 1) || (c != '\r')) &&
- (arc_last_offset >= 1)) {
- /* Note that the timestamp should be corrected if >1 char rcvd. */
- l_fp timestamp;
- timestamp = rbufp->recv_time;
-#ifdef DEBUG
- if(debug) { /* Show \r as `R', other non-printing char as `?'. */
- printf("arc: stamp -->%c<-- (%d chars rcvd)\n",
- ((c == '\r') ? 'R' : (isgraph((int)c) ? c : '?')),
- rbufp->recv_length);
- }
-#endif
-
- /*
- Now correct timestamp by offset of last byte received---we
- subtract from the receive time the delay implied by the
- extra characters received.
-
- Reject the input if the resulting code is too long, but
- allow for the trailing \r, normally not used but a good
- handle for tty_clk or somesuch kernel timestamper.
- */
- if(arc_last_offset > LENARC) {
-#ifdef DEBUG
- if(debug) {
- printf("arc: input code too long (%d cf %d); rejected.\n",
- arc_last_offset, LENARC);
- }
-#endif
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- L_SUBUF(&timestamp, charoffsets[arc_last_offset]);
-#ifdef DEBUG
- if(debug > 1) {
- printf(
- "arc: %s%d char(s) rcvd, the last for lastcode[%d]; -%sms offset applied.\n",
- ((rbufp->recv_length > 1) ? "*** " : ""),
- rbufp->recv_length,
- arc_last_offset,
- mfptoms((unsigned long)0,
- charoffsets[arc_last_offset],
- 1));
- }
-#endif
-
-#ifdef ARCRON_MULTIPLE_SAMPLES
- /*
- If taking multiple samples, capture the current adjusted
- sample iff:
-
- * No timestamp has yet been captured (it is zero), OR
-
- * This adjusted timestamp is earlier than the one already
- captured, on the grounds that this one suffered less
- delay in being delivered to us and is more accurate.
-
- */
- if(L_ISZERO(&(up->lastrec)) ||
- L_ISGEQ(&(up->lastrec), &timestamp))
-#endif
- {
-#ifdef DEBUG
- if(debug > 1) {
- printf("arc: system timestamp captured.\n");
-#ifdef ARCRON_MULTIPLE_SAMPLES
- if(!L_ISZERO(&(up->lastrec))) {
- l_fp diff;
- diff = up->lastrec;
- L_SUB(&diff, &timestamp);
- printf("arc: adjusted timestamp by -%sms.\n",
- mfptoms(diff.l_i, diff.l_f, 3));
- }
-#endif
- }
-#endif
- up->lastrec = timestamp;
- }
-
- }
-
- /* Just in case we still have lots of rubbish in the buffer... */
- /* ...and to avoid the same timestamp being reused by mistake, */
- /* eg on receipt of the \r coming in on its own after the */
- /* timecode. */
- if(pp->lencode >= LENARC) {
-#ifdef DEBUG
- if(debug && (rbufp->recv_buffer[0] != '\r'))
- { printf("arc: rubbish in pp->a_lastcode[].\n"); }
-#endif
- pp->lencode = 0;
- return;
- }
-
- /* Append input to code buffer, avoiding overflow. */
- for(i = 0; i < rbufp->recv_length; i++) {
- if(pp->lencode >= LENARC) { break; } /* Avoid overflow... */
- c = rbufp->recv_buffer[i];
-
- /* Drop trailing '\r's and drop `h' command echo totally. */
- if(c != '\r' && c != 'h') { pp->a_lastcode[pp->lencode++] = c; }
-
- /*
- If we've just put an `o' in the lastcode[0], clear the
- timestamp in anticipation of a timecode arriving soon.
-
- We would expect to get to process this before any of the
- timecode arrives.
- */
- if((c == 'o') && (pp->lencode == 1)) {
- L_CLR(&(up->lastrec));
-#ifdef DEBUG
- if(debug > 1) { printf("arc: clearing timestamp.\n"); }
-#endif
- }
- }
- if (pp->lencode == 0) return;
-
- /* Handle a quality message. */
- if(pp->a_lastcode[0] == 'g') {
- int r, q;
-
- if(pp->lencode < 3) { return; } /* Need more data... */
- r = (pp->a_lastcode[1] & 0x7f); /* Strip parity. */
- q = (pp->a_lastcode[2] & 0x7f); /* Strip parity. */
- if(((q & 0x70) != 0x30) || ((q & 0xf) > MAX_CLOCK_QUALITY) ||
- ((r & 0x70) != 0x30)) {
- /* Badly formatted response. */
-#ifdef DEBUG
- if(debug) { printf("arc: bad `g' response %2x %2x.\n", r, q); }
-#endif
- return;
- }
- if(r == '3') { /* Only use quality value whilst sync in progress. */
- if (up->quality_stamp < current_time) {
- struct calendar cal;
- l_fp new_stamp;
-
- get_systime (&new_stamp);
- caljulian (new_stamp.l_ui, &cal);
- up->quality_stamp =
- current_time + 60 - cal.second + 5;
- quality_sum = 0;
- quality_polls = 0;
- }
- quality_sum += (q & 0xf);
- quality_polls++;
- quality_average = (quality_sum / quality_polls);
-#ifdef DEBUG
- if(debug) { printf("arc: signal quality %d (%d).\n", quality_average, (q & 0xf)); }
-#endif
- } else if( /* (r == '2') && */ up->resyncing) {
- up->quality = quality_average;
-#ifdef DEBUG
- if(debug)
- {
- printf("arc: sync finished, signal quality %d: %s\n",
- up->quality,
- quality_action(up->quality));
- }
-#endif
- msyslog(LOG_NOTICE,
- "ARCRON: sync finished, signal quality %d: %s",
- up->quality,
- quality_action(up->quality));
- up->resyncing = 0; /* Resync is over. */
- quality_average = 0;
- quality_sum = 0;
- quality_polls = 0;
-
-#ifdef ARCRON_KEEN
- /* Clock quality dubious; resync earlier than usual. */
- if((up->quality == QUALITY_UNKNOWN) ||
- (up->quality < MIN_CLOCK_QUALITY_OK))
- { up->next_resync = current_time + RETRY_RESYNC_TIME; }
-#endif
- }
- pp->lencode = 0;
- return;
- }
-
- /* Stop now if this is not a timecode message. */
- if(pp->a_lastcode[0] != 'o') {
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /* If we don't have enough data, wait for more... */
- if(pp->lencode < LENARC) { return; }
-
-
- /* WE HAVE NOW COLLECTED ONE TIMESTAMP (phew)... */
-#ifdef DEBUG
- if(debug > 1) { printf("arc: NOW HAVE TIMESTAMP...\n"); }
-#endif
-
- /* But check that we actually captured a system timestamp on it. */
- if(L_ISZERO(&(up->lastrec))) {
-#ifdef DEBUG
- if(debug) { printf("arc: FAILED TO GET SYSTEM TIMESTAMP\n"); }
-#endif
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- /*
- Append a mark of the clock's received signal quality for the
- benefit of Derek Mulcahy's Tcl/Tk utility (we map the `unknown'
- quality value to `6' for his s/w) and terminate the string for
- sure. This should not go off the buffer end.
- */
- pp->a_lastcode[pp->lencode] = ((up->quality == QUALITY_UNKNOWN) ?
- '6' : ('0' + up->quality));
- pp->a_lastcode[pp->lencode + 1] = '\0'; /* Terminate for printf(). */
-
-#ifdef PRE_NTP420
- /* We don't use the micro-/milli- second part... */
- pp->usec = 0;
- pp->msec = 0;
-#else
- /* We don't use the nano-second part... */
- pp->nsec = 0;
-#endif
- n = sscanf(pp->a_lastcode, "o%2d%2d%2d%1d%2d%2d%2d%1d%1d",
- &pp->hour, &pp->minute, &pp->second,
- &wday, &pp->day, &month, &pp->year, &flags, &status);
-
- /* Validate format and numbers. */
- if(n != 9) {
-#ifdef DEBUG
- /* Would expect to have caught major problems already... */
- if(debug) { printf("arc: badly formatted data.\n"); }
-#endif
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- /*
- Validate received values at least enough to prevent internal
- array-bounds problems, etc.
- */
- if((pp->hour < 0) || (pp->hour > 23) ||
- (pp->minute < 0) || (pp->minute > 59) ||
- (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
- (wday < 1) || (wday > 7) ||
- (pp->day < 1) || (pp->day > 31) ||
- (month < 1) || (month > 12) ||
- (pp->year < 0) || (pp->year > 99)) {
- /* Data out of range. */
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
-
- if(peer->MODE == 0) { /* compatiblity to original version */
- int bst = flags;
- /* Check that BST/UTC bits are the complement of one another. */
- if(!(bst & 2) == !(bst & 4)) {
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- }
- if(status & 0x8) { msyslog(LOG_NOTICE, "ARCRON: battery low"); }
-
- /* Year-2000 alert! */
- /* Attempt to wrap 2-digit date into sensible window. */
- if(pp->year < YEAR_PIVOT) { pp->year += 100; } /* Y2KFixes */
- pp->year += 1900; /* use full four-digit year */ /* Y2KFixes */
- /*
- Attempt to do the right thing by screaming that the code will
- soon break when we get to the end of its useful life. What a
- hero I am... PLEASE FIX LEAP-YEAR AND WRAP CODE IN 209X!
- */
- if(pp->year >= YEAR_PIVOT+2000-2 ) { /* Y2KFixes */
- /*This should get attention B^> */
- msyslog(LOG_NOTICE,
- "ARCRON: fix me! EITHER YOUR DATE IS BADLY WRONG or else I will break soon!");
- }
-#ifdef DEBUG
- if(debug) {
- printf("arc: n=%d %02d:%02d:%02d %02d/%02d/%04d %1d %1d\n",
- n,
- pp->hour, pp->minute, pp->second,
- pp->day, month, pp->year, flags, status);
- }
-#endif
-
- /*
- The status value tested for is not strictly supported by the
- clock spec since the value of bit 2 (0x4) is claimed to be
- undefined for MSF, yet does seem to indicate if the last resync
- was successful or not.
- */
- pp->leap = LEAP_NOWARNING;
- status &= 0x7;
- if(status == 0x3) {
- if(status != up->status)
- { msyslog(LOG_NOTICE, "ARCRON: signal acquired"); }
- } else {
- if(status != up->status) {
- msyslog(LOG_NOTICE, "ARCRON: signal lost");
- pp->leap = LEAP_NOTINSYNC; /* MSF clock is free-running. */
- up->status = status;
- pp->lencode = 0;
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- }
- up->status = status;
-
- if (peer->MODE == 0) { /* compatiblity to original version */
- int bst = flags;
-
- pp->day += moff[month - 1];
-
- if(isleap_4(pp->year) && month > 2) { pp->day++; }/* Y2KFixes */
-
- /* Convert to UTC if required */
- if(bst & 2) {
- pp->hour--;
- if (pp->hour < 0) {
- pp->hour = 23;
- pp->day--;
- /* If we try to wrap round the year
- * (BST on 1st Jan), reject.*/
- if(pp->day < 0) {
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- }
- }
- }
-
- if(peer->MODE > 0) {
- if(pp->sloppyclockflag & CLK_FLAG1) {
- struct tm local;
- struct tm *gmtp;
- time_t unixtime;
-
- /*
- * Convert to GMT for sites that distribute localtime.
- * This means we have to do Y2K conversion on the
- * 2-digit year; otherwise, we get the time wrong.
- */
-
- local.tm_year = pp->year-1900;
- local.tm_mon = month-1;
- local.tm_mday = pp->day;
- local.tm_hour = pp->hour;
- local.tm_min = pp->minute;
- local.tm_sec = pp->second;
- switch (peer->MODE) {
- case 1:
- local.tm_isdst = (flags & 2);
- break;
- case 2:
- local.tm_isdst = (flags & 2);
- break;
- case 3:
- switch (flags & 3) {
- case 0: /* It is unclear exactly when the
- Arcron changes from DST->ST and
- ST->DST. Testing has shown this
- to be irregular. For the time
- being, let the OS decide. */
- local.tm_isdst = 0;
-#ifdef DEBUG
- if (debug)
- printf ("arc: DST = 00 (0)\n");
-#endif
- break;
- case 1: /* dst->st time */
- local.tm_isdst = -1;
-#ifdef DEBUG
- if (debug)
- printf ("arc: DST = 01 (1)\n");
-#endif
- break;
- case 2: /* st->dst time */
- local.tm_isdst = -1;
-#ifdef DEBUG
- if (debug)
- printf ("arc: DST = 10 (2)\n");
-#endif
- break;
- case 3: /* dst time */
- local.tm_isdst = 1;
-#ifdef DEBUG
- if (debug)
- printf ("arc: DST = 11 (3)\n");
-#endif
- break;
- }
- break;
- default:
- msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d",
- peer->MODE);
- return;
- break;
- }
- unixtime = mktime (&local);
- if ((gmtp = gmtime (&unixtime)) == NULL)
- {
- pp->lencode = 0;
- refclock_report (peer, CEVNT_FAULT);
- return;
- }
- pp->year = gmtp->tm_year+1900;
- month = gmtp->tm_mon+1;
- pp->day = ymd2yd(pp->year,month,gmtp->tm_mday);
- /* pp->day = gmtp->tm_yday; */
- pp->hour = gmtp->tm_hour;
- pp->minute = gmtp->tm_min;
- pp->second = gmtp->tm_sec;
-#ifdef DEBUG
- if (debug)
- {
- printf ("arc: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
- pp->year,month,gmtp->tm_mday,pp->hour,pp->minute,
- pp->second);
- }
-#endif
- } else
- {
- /*
- * For more rational sites distributing UTC
- */
- pp->day = ymd2yd(pp->year,month,pp->day);
- }
- }
-
- if (peer->MODE == 0) { /* compatiblity to original version */
- /* If clock signal quality is
- * unknown, revert to default PRECISION...*/
- if(up->quality == QUALITY_UNKNOWN) {
- peer->precision = PRECISION;
- } else { /* ...else improve precision if flag3 is set... */
- peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ?
- HIGHPRECISION : PRECISION);
- }
- } else {
- if ((status == 0x3) && (pp->sloppyclockflag & CLK_FLAG2)) {
- peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ?
- HIGHPRECISION : PRECISION);
- } else if (up->quality == QUALITY_UNKNOWN) {
- peer->precision = PRECISION;
- } else {
- peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ?
- HIGHPRECISION : PRECISION);
- }
- }
-
- /* Notice and log any change (eg from initial defaults) for flags. */
- if(up->saved_flags != pp->sloppyclockflag) {
-#ifdef DEBUG
- msyslog(LOG_NOTICE, "ARCRON: flags enabled: %s%s%s%s",
- ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."),
- ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."),
- ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."),
- ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : "."));
- /* Note effects of flags changing... */
- if(debug) {
- printf("arc: PRECISION = %d.\n", peer->precision);
- }
-#endif
- up->saved_flags = pp->sloppyclockflag;
- }
-
- /* Note time of last believable timestamp. */
- pp->lastrec = up->lastrec;
-
-#ifdef ARCRON_LEAPSECOND_KEEN
- /* Find out if a leap-second might just have happened...
- (ie is this the first hour of the first day of Jan or Jul?)
- */
- if((pp->hour == 0) &&
- (pp->day == 1) &&
- ((month == 1) || (month == 7))) {
- if(possible_leap >= 0) {
- /* A leap may have happened, and no resync has started yet...*/
- possible_leap = 1;
- }
- } else {
- /* Definitely not leap-second territory... */
- possible_leap = 0;
- }
-#endif
-
- if (!refclock_process(pp)) {
- pp->lencode = 0;
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- refclock_receive(peer);
-}
-
-
-/* request_time() sends a time request to the clock with given peer. */
-/* This automatically reports a fault if necessary. */
-/* No data should be sent after this until arc_poll() returns. */
-static void request_time P((int, struct peer *));
-static void
-request_time(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp = peer->procptr;
- register struct arcunit *up = (struct arcunit *)pp->unitptr;
-#ifdef DEBUG
- if(debug) { printf("arc: unit %d: requesting time.\n", unit); }
-#endif
- if (!send_slow(up, pp->io.fd, "o\r")) {
-#ifdef DEBUG
- if (debug) {
- printf("arc: unit %d: problem sending", unit);
- }
-#endif
- pp->lencode = 0;
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- pp->polls++;
-}
-
-/*
- * arc_poll - called by the transmit procedure
- */
-static void
-arc_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct arcunit *up;
- struct refclockproc *pp;
- int resync_needed; /* Should we start a resync? */
-
- pp = peer->procptr;
- up = (struct arcunit *)pp->unitptr;
-#if 0
- pp->lencode = 0;
- memset(pp->a_lastcode, 0, sizeof(pp->a_lastcode));
-#endif
-
-#if 0
- /* Flush input. */
- tcflush(pp->io.fd, TCIFLUSH);
-#endif
-
- /* Resync if our next scheduled resync time is here or has passed. */
- resync_needed = ( !(pp->sloppyclockflag & CLK_FLAG2) &&
- (up->next_resync <= current_time) );
-
-#ifdef ARCRON_LEAPSECOND_KEEN
- /*
- Try to catch a potential leap-second insertion or deletion quickly.
-
- In addition to the normal NTP fun of clocks that don't report
- leap-seconds spooking their hosts, this clock does not even
- sample the radio sugnal the whole time, so may miss a
- leap-second insertion or deletion for up to a whole sample
- time.
-
- To try to minimise this effect, if in the first few minutes of
- the day immediately following a leap-second-insertion point
- (ie in the first hour of the first day of the first and sixth
- months), and if the last resync was in the previous day, and a
- resync is not already in progress, resync the clock
- immediately.
-
- */
- if((possible_leap > 0) && /* Must be 00:XX 01/0{1,7}/XXXX. */
- (!up->resyncing)) { /* No resync in progress yet. */
- resync_needed = 1;
- possible_leap = -1; /* Prevent multiple resyncs. */
- msyslog(LOG_NOTICE,"ARCRON: unit %d: checking for leap second",unit);
- }
-#endif
-
- /* Do a resync if required... */
- if(resync_needed) {
- /* First, reset quality value to `unknown' so we can detect */
- /* when a quality message has been responded to by this */
- /* being set to some other value. */
- up->quality = QUALITY_UNKNOWN;
-
- /* Note that we are resyncing... */
- up->resyncing = 1;
-
- /* Now actually send the resync command and an immediate poll. */
-#ifdef DEBUG
- if(debug) { printf("arc: sending resync command (h\\r).\n"); }
-#endif
- msyslog(LOG_NOTICE, "ARCRON: unit %d: sending resync command", unit);
- send_slow(up, pp->io.fd, "h\r");
-
- /* Schedule our next resync... */
- up->next_resync = current_time + DEFAULT_RESYNC_TIME;
-
- /* Drop through to request time if appropriate. */
- }
-
- /* If clock quality is too poor to trust, indicate a fault. */
- /* If quality is QUALITY_UNKNOWN and ARCRON_KEEN is defined,*/
- /* we'll cross our fingers and just hope that the thing */
- /* synced so quickly we did not catch it---we'll */
- /* double-check the clock is OK elsewhere. */
- if(
-#ifdef ARCRON_KEEN
- (up->quality != QUALITY_UNKNOWN) &&
-#else
- (up->quality == QUALITY_UNKNOWN) ||
-#endif
- (up->quality < MIN_CLOCK_QUALITY_OK)) {
-#ifdef DEBUG
- if(debug) {
- printf("arc: clock quality %d too poor.\n", up->quality);
- }
-#endif
- pp->lencode = 0;
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- /* This is the normal case: request a timestamp. */
- request_time(unit, peer);
-}
-
-#else
-int refclock_arc_bs;
-#endif
diff --git a/contrib/ntp/ntpd/refclock_as2201.c b/contrib/ntp/ntpd/refclock_as2201.c
deleted file mode 100644
index f04d417b..0000000
--- a/contrib/ntp/ntpd/refclock_as2201.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * refclock_as2201 - clock driver for the Austron 2201A GPS
- * Timing Receiver
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_AS2201)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * This driver supports the Austron 2200A/2201A GPS Receiver with
- * Buffered RS-232-C Interface Module. Note that the original 2200/2201
- * receivers will not work reliably with this driver, since the older
- * design cannot accept input commands at any reasonable data rate.
- *
- * The program sends a "*toc\r" to the radio and expects a response of
- * the form "yy:ddd:hh:mm:ss.mmm\r" where yy = year of century, ddd =
- * day of year, hh:mm:ss = second of day and mmm = millisecond of
- * second. Then, it sends statistics commands to the radio and expects
- * 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. 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>
- * response using the "term cr" command. The setting of the "echo"
- * and "df" commands does not matter. The radio should select UTC
- * timescale using the "ts utc" command.
- *
- * There are two modes of operation for this driver. The first with
- * 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 more
- * than one hosts, but only one of them should be connected to the
- * radio input data line.
- */
-
-/*
- * GPS Definitions
- */
-#define SMAX 200 /* statistics buffer length */
-#define DEVICE "/dev/gps%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS\0" /* reference ID */
-#define DESCRIPTION "Austron 2201A GPS Receiver" /* WRU */
-
-#define LENTOC 19 /* yy:ddd:hh:mm:ss.mmm timecode lngth */
-
-/*
- * AS2201 unit control structure.
- */
-struct as2201unit {
- char *lastptr; /* statistics buffer pointer */
- char stats[SMAX]; /* statistics buffer */
- int linect; /* count of lines remaining */
- int index; /* current statistics command */
-};
-
-/*
- * Radio commands to extract statitistics
- *
- * A command consists of an ASCII string terminated by a <cr> (\r). The
- * command list consist of a sequence of commands terminated by a null
- * string ("\0"). One command from the list is sent immediately
- * following each received timecode (*toc\r command) and the ASCII
- * strings received from the radio are saved along with the timecode in
- * the clockstats file. Subsequent commands are sent at each timecode,
- * with the last one in the list followed by the first one. The data
- * received from the radio consist of ASCII strings, each terminated by
- * a <cr> (\r) character. The number of strings for each command is
- * specified as the first line of output as an ASCII-encode number. Note
- * that the ETF command requires the Input Buffer Module and the LORAN
- * commands require the LORAN Assist Module. However, if these modules
- * are not installed, the radio and this driver will continue to operate
- * successfuly, but no data will be captured for these commands.
- */
-static char stat_command[][30] = {
- "ITF\r", /* internal time/frequency */
- "ETF\r", /* external time/frequency */
- "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */
- "LORAN TDATA\r", /* LORAN signal data */
- "ID;OPT;VER\r", /* model; options; software version */
-
- "ITF\r", /* internal time/frequency */
- "ETF\r", /* external time/frequency */
- "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */
- "TRSTAT\r", /* satellite tracking status */
- "POS;PPS;PPSOFF\r", /* position, pps source, offsets */
-
- "ITF\r", /* internal time/frequency */
- "ETF\r", /* external time/frequency */
- "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */
- "LORAN TDATA\r", /* LORAN signal data */
- "UTC\r", /* UTC leap info */
-
- "ITF\r", /* internal time/frequency */
- "ETF\r", /* external time/frequency */
- "LORAN ENSEMBLE\r", /* GPS/LORAN ensemble statistics */
- "TRSTAT\r", /* satellite tracking status */
- "OSC;ET;TEMP\r", /* osc type; tune volts; oven temp */
- "\0" /* end of table */
-};
-
-/*
- * Function prototypes
- */
-static int as2201_start P((int, struct peer *));
-static void as2201_shutdown P((int, struct peer *));
-static void as2201_receive P((struct recvbuf *));
-static void as2201_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-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_start - open the devices and initialize data for processing
- */
-static int
-as2201_start(
- int unit,
- struct peer *peer
- )
-{
- register struct as2201unit *up;
- struct refclockproc *pp;
- int fd;
- char gpsdev[20];
-
- /*
- * Open serial port. Use CLK line discipline, if available.
- */
- (void)sprintf(gpsdev, DEVICE, unit);
- if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_CLK)))
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct as2201unit *)
- emalloc(sizeof(struct as2201unit)))) {
- (void) close(fd);
- return (0);
- }
- 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);
- }
- pp->unitptr = (caddr_t)up;
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- peer->burst = NSTAGE;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- up->lastptr = up->stats;
- up->index = 0;
- return (1);
-}
-
-
-/*
- * as2201_shutdown - shut down the clock
- */
-static void
-as2201_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct as2201unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct as2201unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * as2201__receive - receive data from the serial interface
- */
-static void
-as2201_receive(
- struct recvbuf *rbufp
- )
-{
- register struct as2201unit *up;
- struct refclockproc *pp;
- struct peer *peer;
- l_fp trtmp;
-
- /*
- * Initialize pointers and read the timecode and timestamp.
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct as2201unit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
-#ifdef DEBUG
- if (debug)
- printf("gps: timecode %d %d %s\n",
- up->linect, pp->lencode, pp->a_lastcode);
-#endif
- if (pp->lencode == 0)
- return;
-
- /*
- * If linect is greater than zero, we must be in the middle of a
- * statistics operation, so simply tack the received data at the
- * end of the statistics string. If not, we could either have
- * just received the timecode itself or a decimal number
- * indicating the number of following lines of the statistics
- * reply. In the former case, write the accumulated statistics
- * data to the clockstats file and continue onward to process
- * the timecode; in the later case, save the number of lines and
- * quietly return.
- */
- if (pp->sloppyclockflag & CLK_FLAG2)
- pp->lastrec = trtmp;
- if (up->linect > 0) {
- up->linect--;
- if ((int)(up->lastptr - up->stats + pp->lencode) > SMAX - 2)
- return;
- *up->lastptr++ = ' ';
- (void)strcpy(up->lastptr, pp->a_lastcode);
- up->lastptr += pp->lencode;
- return;
- } else {
- if (pp->lencode == 1) {
- up->linect = atoi(pp->a_lastcode);
- return;
- } else {
- record_clock_stats(&peer->srcadr, up->stats);
-#ifdef DEBUG
- if (debug)
- printf("gps: stat %s\n", up->stats);
-#endif
- }
- }
- up->lastptr = up->stats;
- *up->lastptr = '\0';
-
- /*
- * 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 < LENTOC) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Timecode format: "yy:ddd:hh:mm:ss.mmm"
- */
- if (sscanf(pp->a_lastcode, "%2d:%3d:%2d:%2d:%2d.%3ld", &pp->year,
- &pp->day, &pp->hour, &pp->minute, &pp->second, &pp->nsec)
- != 6) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- pp->nsec *= 1000000;
-
- /*
- * Test for synchronization (this is a temporary crock).
- */
- if (pp->a_lastcode[2] != ':')
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
- /*
- * If 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(up->lastptr, pp->a_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;
- }
-}
-
-
-/*
- * as2201_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
-as2201_poll(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
-
- /*
- * 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;
- if (write(pp->io.fd, "\r*toc\r", 6) != 6) {
- refclock_report(peer, CEVNT_FAULT);
- } else {
- pp->polls++;
- if (!(pp->sloppyclockflag & CLK_FLAG2))
- get_systime(&pp->lastrec);
- }
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- refclock_receive(peer);
- peer->burst = NSTAGE;
-}
-
-#else
-int refclock_as2201_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_atom.c b/contrib/ntp/ntpd/refclock_atom.c
deleted file mode 100644
index 51153ae..0000000
--- a/contrib/ntp/ntpd/refclock_atom.c
+++ /dev/null
@@ -1,504 +0,0 @@
-
-/*
- * refclock_atom - clock driver for 1-pps signals
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#if defined(REFCLOCK) && defined(CLOCK_ATOM)
-
-#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
-#endif /* HAVE_PPSAPI */
-
-/*
- * 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.
- *
- * Before this driver becomes active, the local clock must be set to
- * within +-500 ms by another means, such as a radio clock or NTP
- * itself. There are two ways to connect the PPS signal, normally at TTL
- * levels, to the computer. One is to shift to EIA levels and connect to
- * pin 8 (DCD) of a serial port. This requires a level converter and
- * may require a one-shot flipflop to lengthen the pulse. The other is
- * to connect the PPS signal directly to pin 10 (ACK) of a PC paralell
- * port. These methods are architecture dependent.
- *
- * Both methods require a modified device driver and kernel interface
- * compatible with the Pulse-per-Second API for Unix-like Operating
- * Systems, Version 1.0, RFC-2783 (PPSAPI). Implementations are
- * available for FreeBSD, Linux, SunOS, Solaris and Alpha. However, at
- * present only the Alpha implementation provides the full generality of
- * the API with multiple PPS drivers and multiple handles per driver.
- *
- * In many configurations a single port is used for the radio timecode
- * and PPS signal. In order to provide for this configuration and others
- * involving dedicated multiple serial/parallel ports, the driver first
- * attempts to open the device /dev/pps%d, where %d is the unit number.
- * If this fails, the driver attempts to open the device specified by
- * the pps configuration command. If a port is to be shared, the pps
- * command must be placed before the radio device(s) and the radio
- * device(s) must be placed before the PPS driver(s) in the
- * configuration file.
- *
- * This driver normally uses the PLL/FLL clock discipline implemented in
- * the ntpd code. If kernel support is available, the kernel PLL/FLL
- * clock discipline is used instead. The default configuration is not to
- * use the kernel PPS discipline, if present. The kernel PPS discipline
- * can be enabled using the pps command.
- *
- * Fudge Factors
- *
- * There are no special fudge factors other than the generic. The fudge
- * time1 parameter can be used to compensate for miscellaneous device
- * driver and OS delays.
- */
-/*
- * Interface definitions
- */
-#ifdef HAVE_PPSAPI
-#define DEVICE "/dev/pps%d" /* device name and unit */
-#endif /* HAVE_PPSAPI */
-
-#define PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "PPS\0" /* reference ID */
-#define DESCRIPTION "PPS Clock Discipline" /* WRU */
-#define NANOSECOND 1000000000 /* one second (ns) */
-#define RANGEGATE 500000 /* range gate (ns) */
-#define ASTAGE 8 /* filter stages */
-
-static struct peer *pps_peer; /* atom driver for PPS sources */
-
-#ifdef HAVE_PPSAPI
-/*
- * PPS unit control structure
- */
-struct ppsunit {
- struct timespec ts; /* last timestamp */
- int fddev; /* pps device descriptor */
- pps_params_t pps_params; /* pps parameters */
- pps_info_t pps_info; /* last pps data */
- pps_handle_t handle; /* pps handlebars */
-};
-#endif /* HAVE_PPSAPI */
-
-/*
- * Function prototypes
- */
-static int atom_start P((int, struct peer *));
-static void atom_poll P((int, struct peer *));
-#ifdef HAVE_PPSAPI
-static void atom_shutdown P((int, struct peer *));
-static void atom_control P((int, struct refclockstat *, struct
- refclockstat *, struct peer *));
-static int atom_pps P((struct peer *));
-static int atom_ppsapi P((struct peer *, int, int));
-#endif /* HAVE_PPSAPI */
-
-/*
- * Transfer vector
- */
-struct refclock refclock_atom = {
- atom_start, /* start up driver */
-#ifdef HAVE_PPSAPI
- atom_shutdown, /* shut down driver */
-#else
- noentry, /* shut down driver */
-#endif /* HAVE_PPSAPI */
- atom_poll, /* transmit poll message */
-#ifdef HAVE_PPSAPI
- atom_control, /* fudge control */
-#else
- noentry, /* fudge control */
-#endif /* HAVE_PPSAPI */
- noentry, /* initialize driver */
- noentry, /* not used (old atom_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-/*
- * atom_start - initialize data for processing
- */
-static int
-atom_start(
- int unit, /* unit number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
- register struct ppsunit *up;
- char device[80];
-#endif /* HAVE_PPSAPI */
-
- /*
- * Allocate and initialize unit structure
- */
- pps_peer = peer;
- pp = peer->procptr;
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- pp->stratum = STRATUM_UNSPEC;
- memcpy((char *)&pp->refid, REFID, 4);
- peer->burst = ASTAGE;
-#ifdef HAVE_PPSAPI
- up = emalloc(sizeof(struct ppsunit));
- memset(up, 0, sizeof(struct ppsunit));
- pp->unitptr = (caddr_t)up;
-
- /*
- * Open PPS device. If this fails and some driver has already
- * opened the associated radio device, fdpps has the file
- * descriptor for it.
- */
- sprintf(device, DEVICE, unit);
- up->fddev = open(device, O_RDWR, 0777);
- if (up->fddev <= 0 && fdpps > 0) {
- strcpy(device, pps_device);
- up->fddev = fdpps;
- }
- if (up->fddev <= 0) {
- msyslog(LOG_ERR,
- "refclock_atom: %s: %m", device);
- return (0);
- }
-
- /*
- * Light off the PPSAPI interface. If this PPS device is shared
- * with the radio device, take the default options from the pps
- * command. This is for legacy purposes.
- */
- if (time_pps_create(up->fddev, &up->handle) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_create failed: %m");
- return (0);
- }
- return (atom_ppsapi(peer, 0, 0));
-#else /* HAVE_PPSAPI */
- return (1);
-#endif /* HAVE_PPSAPI */
-}
-
-
-#ifdef HAVE_PPSAPI
-/*
- * atom_control - fudge control
- */
-static void
-atom_control(
- int unit, /* unit (not used */
- struct refclockstat *in, /* input parameters (not uded) */
- struct refclockstat *out, /* output parameters (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
- atom_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
- pp->sloppyclockflag & CLK_FLAG3);
-}
-
-
-/*
- * Initialize PPSAPI
- */
-int
-atom_ppsapi(
- struct peer *peer, /* peer structure pointer */
- int enb_clear, /* clear enable */
- int enb_hardpps /* hardpps enable */
- )
-{
- struct refclockproc *pp;
- register struct ppsunit *up;
- int capability;
-
- pp = peer->procptr;
- up = (struct ppsunit *)pp->unitptr;
- if (time_pps_getcap(up->handle, &capability) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_getcap failed: %m");
- return (0);
- }
- memset(&up->pps_params, 0, sizeof(pps_params_t));
- if (enb_clear)
- up->pps_params.mode = capability & PPS_CAPTURECLEAR;
- else
- up->pps_params.mode = capability & PPS_CAPTUREASSERT;
- if (!up->pps_params.mode) {
- msyslog(LOG_ERR,
- "refclock_atom: invalid capture edge %d",
- enb_clear);
- return (0);
- }
- up->pps_params.mode |= PPS_TSFMT_TSPEC;
- if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_setparams failed: %m");
- return (0);
- }
- if (enb_hardpps) {
- if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
- up->pps_params.mode & ~PPS_TSFMT_TSPEC,
- PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_kcbind failed: %m");
- return (0);
- }
- pps_enable = 1;
- }
-#if DEBUG
- if (debug) {
- time_pps_getparams(up->handle, &up->pps_params);
- printf(
- "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x kern %d\n",
- up->fddev, capability, up->pps_params.api_version,
- up->pps_params.mode, enb_hardpps);
- }
-#endif
- return (1);
-}
-
-
-/*
- * atom_shutdown - shut down the clock
- */
-static void
-atom_shutdown(
- int unit, /* unit number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- register struct ppsunit *up;
-
- pp = peer->procptr;
- up = (struct ppsunit *)pp->unitptr;
- if (up->fddev > 0)
- close(up->fddev);
- if (up->handle != 0)
- time_pps_destroy(up->handle);
- if (pps_peer == peer)
- pps_peer = 0;
- free(up);
-}
-
-
-/*
- * atom_pps - receive data from the PPSAPI interface
- *
- * This routine is called once per second when the PPSAPI interface 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.
- */
-static int
-atom_pps(
- struct peer *peer /* peer structure pointer */
- )
-{
- register struct ppsunit *up;
- struct refclockproc *pp;
- pps_info_t pps_info;
- struct timespec timeout, ts;
- double dtemp;
-
- /*
- * Convert the timespec nanoseconds field to signed double and
- * save in the median filter. for billboards. No harm is done if
- * previous data are overwritten. If the discipline comes bum or
- * the data grow stale, just forget it. A range gate rejects new
- * samples if less than a jiggle time from the next second.
- */
- pp = peer->procptr;
- up = (struct ppsunit *)pp->unitptr;
- if (up->handle == 0)
- return (-1);
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
- if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
- &timeout) < 0)
- return (-1);
- if (up->pps_params.mode & PPS_CAPTUREASSERT) {
- if (pps_info.assert_sequence ==
- up->pps_info.assert_sequence)
- return (1);
- ts = up->pps_info.assert_timestamp;
- } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
- if (pps_info.clear_sequence ==
- up->pps_info.clear_sequence)
- return (1);
- ts = up->pps_info.clear_timestamp;
- } else {
- return (-1);
- }
- if (!((ts.tv_sec == up->ts.tv_sec && ts.tv_nsec -
- up->ts.tv_nsec > NANOSECOND - RANGEGATE) ||
- (ts.tv_sec - up->ts.tv_sec == 1 && ts.tv_nsec -
- up->ts.tv_nsec < RANGEGATE))) {
- up->ts = ts;
- return (1);
- }
- up->ts = ts;
- pp->lastrec.l_ui = ts.tv_sec + JAN_1970;
- dtemp = ts.tv_nsec * FRAC / 1e9;
- if (dtemp >= FRAC)
- pp->lastrec.l_ui++;
- pp->lastrec.l_uf = (u_int32)dtemp;
- if (ts.tv_nsec > NANOSECOND / 2)
- ts.tv_nsec -= NANOSECOND;
- dtemp = -(double)ts.tv_nsec / NANOSECOND;
- SAMPLE(dtemp + pp->fudgetime1);
-#ifdef DEBUG
- if (debug > 1)
- printf("atom_pps %f %f\n", dtemp, pp->fudgetime1);
-#endif
- return (0);
-}
-#endif /* HAVE_PPSAPI */
-
-
-/*
- * pps_sample - receive PPS data from some other clock driver
- *
- * This routine is called once per second when the external clock driver
- * processes PPS information. It processes the PPS timestamp and saves
- * the sign-extended fraction in a circular buffer for processing at the
- * next poll event. This works only for a single PPS device.
- */
-int
-pps_sample(
- l_fp *offset /* PPS offset */
- )
-{
- register struct peer *peer;
- struct refclockproc *pp;
- l_fp lftmp;
- double doffset;
-
- peer = pps_peer;
- if (peer == 0) /* nobody home */
- return (1);
- pp = peer->procptr;
-
- /*
- * 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.
- */
- pp->lastrec = *offset;
- L_CLR(&lftmp);
- L_ADDF(&lftmp, pp->lastrec.l_f);
- LFPTOD(&lftmp, doffset);
- SAMPLE(-doffset + pp->fudgetime1);
- return (0);
-}
-
-/*
- * atom_poll - called by the transmit procedure
- *
- * This routine is called once per second when in burst mode to save PPS
- * sample offsets in the median filter. At the end of the burst period
- * the samples are processed as a heap and the clock filter updated.
- */
-static void
-atom_poll(
- int unit, /* unit number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
- int err;
-#endif /* HAVE_PPSAPI */
-
- /*
- * Accumulate samples in the median filter. If a noise sample,
- * return with no prejudice; if a protocol error, get mean;
- * otherwise, cool. At the end of each poll interval, do a
- * little bookeeping and process the surviving samples.
- */
- pp = peer->procptr;
- pp->polls++;
-#ifdef HAVE_PPSAPI
- err = atom_pps(peer);
- if (err < 0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
-#endif /* HAVE_PPSAPI */
-
- /*
- * Valid time 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 ensures the PPS time is within
- * +-0.5 s of the local time and the seconds numbering is
- * unambiguous. Note that the leap bits are set no-warning on
- * the first valid update and the stratum is set at the prefer
- * peer, unless overriden by a fudge command.
- */
- if (peer->burst > 0)
- return;
- peer->leap = LEAP_NOTINSYNC;
- if (pp->codeproc == pp->coderecv) {
- refclock_report(peer, CEVNT_TIMEOUT);
- peer->burst = ASTAGE;
- return;
-
- } else if (sys_prefer == NULL) {
- pp->codeproc = pp->coderecv;
- peer->burst = ASTAGE;
- return;
-
- } else if (fabs(sys_prefer->offset) > clock_max) {
- pp->codeproc = pp->coderecv;
- peer->burst = ASTAGE;
- return;
- }
- pp->leap = LEAP_NOWARNING;
- if (pp->stratum >= STRATUM_UNSPEC)
- peer->stratum = sys_prefer->stratum;
- else
- peer->stratum = pp->stratum;
- if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
- STRATUM_UNSPEC)
- peer->refid = pp->refid;
- else
- peer->refid = addr2refid(&sys_prefer->srcadr);
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- peer->burst = ASTAGE;
-}
-#else
-int refclock_atom_bs;
-int
-pps_sample(
- l_fp *offset /* PPS offset */
- )
-{
- return 1;
-}
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_bancomm.c b/contrib/ntp/ntpd/refclock_bancomm.c
deleted file mode 100644
index a63be44..0000000
--- a/contrib/ntp/ntpd/refclock_bancomm.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/* refclock_bancomm.c - clock driver for the Datum/Bancomm bc635VME
- * Time and Frequency Processor. It requires the BANCOMM bc635VME/
- * bc350VXI Time and Frequency Processor Module Driver for SunOS4.x
- * and SunOS5.x UNIX Systems. It has been tested on a UltraSparc
- * IIi-cEngine running Solaris 2.6.
- *
- * Author(s): Ganesh Ramasivan & Gary Cliff, Computing Devices Canada,
- * Ottawa, Canada
- *
- * Date: July 1999
- *
- * Note(s): The refclock type has been defined as 16.
- *
- * This program has been modelled after the Bancomm driver
- * originally written by R. Schmidt of Time Service, U.S.
- * Naval Observatory for a HP-UX machine. Since the original
- * authors no longer plan to maintain this code, all
- * references to the HP-UX vme2 driver subsystem bave been
- * removed. Functions vme_report_event(), vme_receive(),
- * vme_control() and vme_buginfo() have been deleted because
- * they are no longer being used.
- *
- * The time on the bc635 TFP must be set to GMT due to the
- * fact that NTP makes use of GMT for all its calculations.
- *
- * Installation of the Datum/Bancomm driver creates the
- * device file /dev/btfp0
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_BANC)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <syslog.h>
-#include <ctype.h>
-
-/* STUFF BY RES */
-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)*/
-};
-
-/* SunOS5 ioctl commands definitions.*/
-#define BTFPIOC ( 'b'<< 8 )
-#define IOCIO( l, n ) ( BTFPIOC | n )
-#define IOCIOR( l, n, s ) ( BTFPIOC | n )
-#define IOCIORN( l, n, s ) ( BTFPIOC | n )
-#define IOCIOWN( l, n, s ) ( BTFPIOC | n )
-
-/***** Simple ioctl commands *****/
-#define RUNLOCK IOCIOR(b, 19, int ) /* Release Capture Lockout */
-#define RCR0 IOCIOR(b, 22, int ) /* Read control register zero.*/
-#define WCR0 IOCIOWN(b, 23, int) /* Write control register zero*/
-
-/***** Compound ioctl commands *****/
-
-/* Read all 5 time words in one call. */
-#define READTIME IOCIORN(b, 32, sizeof( struct btfp_time ))
-#define VMEFD "/dev/btfp0"
-
-struct vmedate { /* structure returned by get_vmetime.c */
- unsigned short year;
- unsigned short day;
- unsigned short hr;
- unsigned short mn;
- unsigned short sec;
- unsigned long frac;
- unsigned short status;
-};
-
-/* END OF STUFF FROM RES */
-
-/*
- * VME interface parameters.
- */
-#define VMEPRECISION (-21) /* precision assumed (1 us) */
-#define USNOREFID "BTFP" /* or whatever */
-#define VMEREFID "BTFP" /* reference id */
-#define VMEDESCRIPTION "Bancomm bc635 TFP" /* who we are */
-#define VMEHSREFID 0x7f7f1000 /* 127.127.16.00 refid hi strata */
-/* clock type 16 is used here */
-#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.
- * Changes made to vmeunit structure. Most members are now available in the
- * new refclockproc structure in ntp_refclock.h - 07/99 - Ganesh Ramasivan
- */
-struct vmeunit {
- struct vmedate vmedata; /* data returned from vme read */
- u_long lasttime; /* last time clock heard from */
-};
-
-/*
- * Function prototypes
- */
-static void vme_init (void);
-static int vme_start (int, struct peer *);
-static void vme_shutdown (int, struct peer *);
-static void vme_receive (struct recvbuf *);
-static void vme_poll (int unit, struct peer *);
-struct vmedate *get_datumtime(struct vmedate *);
-
-/*
- * Transfer vector
- */
-struct refclock refclock_bancomm = {
- vme_start, /* start up driver */
- vme_shutdown, /* shut down driver */
- vme_poll, /* transmit poll message */
- noentry, /* not used (old vme_control) */
- noentry, /* initialize driver */
- noentry, /* not used (old vme_buginfo) */
- NOFLAGS /* not used */
-};
-
-int fd_vme; /* file descriptor for ioctls */
-int regvalue;
-
-
-/*
- * vme_start - open the VME device and initialize data for processing
- */
-static int
-vme_start(
- int unit,
- struct peer *peer
- )
-{
- register struct vmeunit *vme;
- struct refclockproc *pp;
- int dummy;
- char vmedev[20];
-
- /*
- * Open VME device
- */
-#ifdef DEBUG
-
- printf("Opening DATUM VME DEVICE \n");
-#endif
- if ( (fd_vme = open(VMEFD, O_RDWR)) < 0) {
- msyslog(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 ) )
- msyslog(LOG_ERR, "vme_start: RUNLOCK failed %m");
-
- regvalue = 0; /* More esoteric stuff to do... */
- if( ioctl( fd_vme, WCR0, &regvalue ) )
- msyslog(LOG_ERR, "vme_start: WCR0 failed %m");
- }
-
- /*
- * Allocate unit structure
- */
- vme = (struct vmeunit *)emalloc(sizeof(struct vmeunit));
- bzero((char *)vme, sizeof(struct vmeunit));
-
-
- /*
- * Set up the structures
- */
- pp = peer->procptr;
- pp->unitptr = (caddr_t) vme;
- pp->timestarted = current_time;
-
- pp->io.clock_recv = vme_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->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;
- memcpy(&pp->refid, USNOREFID,4);
- return (1);
-}
-
-
-/*
- * vme_shutdown - shut down a VME clock
- */
-static void
-vme_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct vmeunit *vme;
- struct refclockproc *pp;
-
- /*
- * Tell the I/O module to turn us off. We're history.
- */
- pp = peer->procptr;
- vme = (struct vmeunit *)pp->unitptr;
- io_closeclock(&pp->io);
- pp->unitptr = NULL;
- free(vme);
-}
-
-
-/*
- * 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(
- struct recvbuf *rbufp
- )
-{
-}
-
-
-/*
- * vme_poll - called by the transmit procedure
- */
-static void
-vme_poll(
- int unit,
- struct peer *peer
- )
-{
- struct vmedate *tptr;
- struct vmeunit *vme;
- struct refclockproc *pp;
- time_t tloc;
- struct tm *tadr;
-
- pp = peer->procptr;
- vme = (struct vmeunit *)pp->unitptr; /* Here is the structure */
-
- tptr = &vme->vmedata;
- if ((tptr = get_datumtime(tptr)) == NULL ) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- get_systime(&pp->lastrec);
- pp->polls++;
- 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(pp->a_lastcode,
- "%3.3d %2.2d:%2.2d:%2.2d.%.6ld %1d",
- tptr->day,
- tptr->hr,
- tptr->mn,
- tptr->sec,
- tptr->frac,
- tptr->status);
-
- pp->lencode = (u_short) strlen(pp->a_lastcode);
-
- pp->day = tptr->day;
- pp->hour = tptr->hr;
- pp->minute = tptr->mn;
- pp->second = tptr->sec;
- pp->usec = tptr->frac;
-
-#ifdef DEBUG
- if (debug)
- printf("pp: %3d %02d:%02d:%02d.%06ld %1x\n",
- pp->day, pp->hour, pp->minute, pp->second,
- pp->usec, tptr->status);
-#endif
- if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */
- refclock_report(peer, 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 (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-}
-
-struct vmedate *
-get_datumtime(struct vmedate *time_vme)
-{
- unsigned short status;
- char cbuf[7];
- struct btfp_time vts;
-
- if ( time_vme == (struct vmedate *)NULL) {
- time_vme = (struct vmedate *)malloc(sizeof(struct vmedate ));
- }
-
- if( ioctl(fd_vme, READTIME, &vts))
- msyslog(LOG_ERR, "get_datumtime error: %m");
-
- /* if you want to actually check the validity of these registers, do a
- define of CHECK above this. I didn't find it necessary. - RES
- */
-
-#ifdef CHECK
-
- /* Get day */
- sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
- ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
-
- if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2]) )
- time_vme->day = (unsigned short)atoi(cbuf);
- else
- time_vme->day = (unsigned short) 0;
-
- /* Get hour */
- sprintf(cbuf,"%2.2x", 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", (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", 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", 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;
-#else
-
- /* DONT CHECK just trust the card */
-
- /* Get day */
- sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
- ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
- time_vme->day = (unsigned short)atoi(cbuf);
-
- /* Get hour */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff);
-
- time_vme->hr = (unsigned short)atoi(cbuf);
-
- /* Get minutes */
- sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8);
- time_vme->mn = (unsigned short)atoi(cbuf);
-
- /* Get seconds */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff);
- time_vme->sec = (unsigned short)atoi(cbuf);
-
- /* 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", vts.btfp_time[ 3 ],
- vts.btfp_time[ 4 ]>>8);
-
- time_vme->frac = (u_long) atoi(cbuf);
-
-#endif /* CHECK */
-
- /* 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);
-}
-
-#else
-int refclock_bancomm_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_chronolog.c b/contrib/ntp/ntpd/refclock_chronolog.c
deleted file mode 100644
index a1d131e..0000000
--- a/contrib/ntp/ntpd/refclock_chronolog.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * refclock_chronolog - clock driver for Chronolog K-series WWVB receiver.
- */
-
-/*
- * Must interpolate back to local time. Very annoying.
- */
-#define GET_LOCALTIME
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_CHRONOLOG)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * This driver supports the Chronolog K-series WWVB receiver.
- *
- * Input format:
- *
- * Y YY/MM/DD<cr><lf>
- * Z hh:mm:ss<cr><lf>
- *
- * YY/MM/DD -- what you'd expect. This arrives a few seconds before the
- * timestamp.
- * hh:mm:ss -- what you'd expect. We take time on the <cr>.
- *
- * Our Chronolog writes time out at 2400 bps 8/N/1, but it can be configured
- * otherwise. The clock seems to appear every 60 seconds, which doesn't make
- * for good statistics collection.
- *
- * The original source of this module was the WWVB module.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/chronolog%d" /* device name and unit */
-#define SPEED232 B2400 /* uart speed (2400 baud) */
-#define PRECISION (-13) /* precision assumed (about 100 us) */
-#define REFID "chronolog" /* reference ID */
-#define DESCRIPTION "Chrono-log K" /* WRU */
-
-#define MONLIN 15 /* number of monitoring lines */
-
-/*
- * Chrono-log unit control structure
- */
-struct chronolog_unit {
- u_char tcswitch; /* timecode switch */
- l_fp laststamp; /* last receive timestamp */
- u_char lasthour; /* last hour (for monitor) */
- int year; /* Y2K-adjusted year */
- int day; /* day-of-month */
- int month; /* month-of-year */
-};
-
-/*
- * Function prototypes
- */
-static int chronolog_start P((int, struct peer *));
-static void chronolog_shutdown P((int, struct peer *));
-static void chronolog_receive P((struct recvbuf *));
-static void chronolog_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_chronolog = {
- chronolog_start, /* start up driver */
- chronolog_shutdown, /* shut down driver */
- chronolog_poll, /* poll the driver -- a nice fabrication */
- noentry, /* not used */
- noentry, /* not used */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-
-/*
- * chronolog_start - open the devices and initialize data for processing
- */
-static int
-chronolog_start(
- int unit,
- struct peer *peer
- )
-{
- register struct chronolog_unit *up;
- struct refclockproc *pp;
- int fd;
- char device[20];
-
- /*
- * Open serial port. Don't bother with CLK line discipline, since
- * it's not available.
- */
- (void)sprintf(device, DEVICE, unit);
-#ifdef DEBUG
- if (debug)
- printf ("starting Chronolog with device %s\n",device);
-#endif
- if (!(fd = refclock_open(device, SPEED232, 0)))
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct chronolog_unit *)
- emalloc(sizeof(struct chronolog_unit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct chronolog_unit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = chronolog_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);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- return (1);
-}
-
-
-/*
- * chronolog_shutdown - shut down the clock
- */
-static void
-chronolog_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct chronolog_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct chronolog_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * chronolog_receive - receive data from the serial interface
- */
-static void
-chronolog_receive(
- struct recvbuf *rbufp
- )
-{
- struct chronolog_unit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- l_fp trtmp; /* arrival timestamp */
- int hours; /* hour-of-day */
- int minutes; /* minutes-past-the-hour */
- int seconds; /* seconds */
- int temp; /* int temp */
- int got_good; /* got a good time flag */
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct chronolog_unit *)pp->unitptr;
- temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
-
- if (temp == 0) {
- if (up->tcswitch == 0) {
- up->tcswitch = 1;
- up->laststamp = trtmp;
- } else
- up->tcswitch = 0;
- return;
- }
- pp->lencode = temp;
- pp->lastrec = up->laststamp;
- up->laststamp = trtmp;
- up->tcswitch = 1;
-
-#ifdef DEBUG
- if (debug)
- printf("chronolog: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
-
- /*
- * We get down to business. Check the timecode format and decode
- * its contents. This code uses the first character to see whether
- * we're looking at a date or a time. We store data data across
- * calls since it is transmitted a few seconds ahead of the
- * timestamp.
- */
- got_good=0;
- if (sscanf(pp->a_lastcode, "Y %d/%d/%d", &up->year,&up->month,&up->day))
- {
- /*
- * Y2K convert the 2-digit year
- */
- up->year = up->year >= 69 ? up->year : up->year + 100;
- return;
- }
- if (sscanf(pp->a_lastcode,"Z %02d:%02d:%02d",
- &hours,&minutes,&seconds) == 3)
- {
-#ifdef GET_LOCALTIME
- struct tm local;
- struct tm *gmtp;
- time_t unixtime;
- int adjyear;
- int adjmon;
-
- /*
- * Convert to GMT for sites that distribute localtime. This
- * means we have to do Y2K conversion on the 2-digit year;
- * otherwise, we get the time wrong.
- */
-
- local.tm_year = up->year;
- local.tm_mon = up->month-1;
- local.tm_mday = up->day;
- local.tm_hour = hours;
- local.tm_min = minutes;
- local.tm_sec = seconds;
- local.tm_isdst = -1;
-
- unixtime = mktime (&local);
- if ((gmtp = gmtime (&unixtime)) == NULL)
- {
- refclock_report (peer, CEVNT_FAULT);
- return;
- }
- adjyear = gmtp->tm_year+1900;
- adjmon = gmtp->tm_mon+1;
- pp->day = ymd2yd (adjyear, adjmon, gmtp->tm_mday);
- pp->hour = gmtp->tm_hour;
- pp->minute = gmtp->tm_min;
- pp->second = gmtp->tm_sec;
-#ifdef DEBUG
- if (debug)
- printf ("time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
- adjyear,adjmon,gmtp->tm_mday,pp->hour,pp->minute,
- pp->second);
-#endif
-
-#else
- /*
- * For more rational sites distributing UTC
- */
- pp->day = ymd2yd(year+1900,month,day);
- pp->hour = hours;
- pp->minute = minutes;
- pp->second = seconds;
-
-#endif
- got_good=1;
- }
-
- if (!got_good)
- return;
-
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- up->lasthour = pp->hour;
-}
-
-
-/*
- * chronolog_poll - called by the transmit procedure
- */
-static void
-chronolog_poll(
- int unit,
- struct peer *peer
- )
-{
- /*
- * Time to poll the clock. The Chrono-log clock is supposed to
- * respond to a 'T' by returning a timecode in the format(s)
- * specified above. Ours does (can?) not, but this seems to be
- * an installation-specific problem. This code is dyked out,
- * but may be re-enabled if anyone ever finds a Chrono-log that
- * actually listens to this command.
- */
-#if 0
- register struct chronolog_unit *up;
- struct refclockproc *pp;
- char pollchar;
-
- pp = peer->procptr;
- up = (struct chronolog_unit *)pp->unitptr;
- if (peer->burst == 0 && peer->reach == 0)
- refclock_report(peer, CEVNT_TIMEOUT);
- if (up->linect > 0)
- pollchar = 'R';
- else
- pollchar = 'T';
- if (write(pp->io.fd, &pollchar, 1) != 1)
- refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
-#endif
-}
-
-#else
-int refclock_chronolog_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_chu.c b/contrib/ntp/ntpd/refclock_chu.c
deleted file mode 100644
index e0c79e2..0000000
--- a/contrib/ntp/ntpd/refclock_chu.c
+++ /dev/null
@@ -1,1687 +0,0 @@
-/*
- * refclock_chu - clock driver for Canadian CHU time/frequency station
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_CHU)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <math.h>
-
-#ifdef HAVE_AUDIO
-#include "audio.h"
-#endif /* HAVE_AUDIO */
-
-#define ICOM 1 /* undefine to suppress ICOM code */
-
-#ifdef ICOM
-#include "icom.h"
-#endif /* ICOM */
-
-/*
- * Audio CHU demodulator/decoder
- *
- * This driver synchronizes the computer time using data encoded in
- * radio transmissions from Canadian time/frequency station CHU in
- * Ottawa, Ontario. Transmissions are made continuously on 3330 kHz,
- * 7335 kHz and 14670 kHz in upper sideband, compatible AM mode. An
- * ordinary shortwave receiver can be tuned manually to one of these
- * frequencies or, in the case of ICOM receivers, the receiver can be
- * tuned automatically using this program as propagation conditions
- * change throughout the day and night.
- *
- * The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a suported workstation hardware and
- * operating system. These include Solaris, SunOS, FreeBSD, NetBSD and
- * Linux. In this implementation, only one audio driver and codec can be
- * supported on a single machine.
- *
- * The driver can be compiled to use a Bell 103 compatible modem or
- * modem chip to receive the radio signal and demodulate the data.
- * Alternatively, the driver can be compiled to use the audio codec of
- * the Sun workstation or another with compatible audio drivers. In the
- * latter case, the driver implements the modem using DSP routines, so
- * the radio can be connected directly to either the microphone on line
- * input port. In either case, the driver decodes the data using a
- * maximum likelihood technique which exploits the considerable degree
- * of redundancy available to maximize accuracy and minimize errors.
- *
- * The CHU time broadcast includes an audio signal compatible with the
- * Bell 103 modem standard (mark = 2225 Hz, space = 2025 Hz). It consist
- * of nine, ten-character bursts transmitted at 300 bps and beginning
- * each second from second 31 to second 39 of the minute. Each character
- * consists of eight data bits plus one start bit and two stop bits to
- * encode two hex digits. The burst data consist of five characters (ten
- * hex digits) followed by a repeat of these characters. In format A,
- * the characters are repeated in the same polarity; in format B, the
- * characters are repeated in the opposite polarity.
- *
- * Format A bursts are sent at seconds 32 through 39 of the minute in
- * hex digits
- *
- * 6dddhhmmss6dddhhmmss
- *
- * The first ten digits encode a frame marker (6) followed by the day
- * (ddd), hour (hh in UTC), minute (mm) and the second (ss). Since
- * format A bursts are sent during the third decade of seconds the tens
- * digit of ss is always 3. The driver uses this to determine correct
- * burst synchronization. These digits are then repeated with the same
- * polarity.
- *
- * Format B bursts are sent at second 31 of the minute in hex digits
- *
- * xdyyyyttaaxdyyyyttaa
- *
- * The first ten digits encode a code (x described below) followed by
- * the DUT1 (d in deciseconds), Gregorian year (yyyy), difference TAI -
- * UTC (tt) and daylight time indicator (aa) peculiar to Canada. These
- * digits are then repeated with inverted polarity.
- *
- * The x is coded
- *
- * 1 Sign of DUT (0 = +)
- * 2 Leap second warning. One second will be added.
- * 4 Leap second warning. One second will be subtracted.
- * 8 Even parity bit for this nibble.
- *
- * By design, the last stop bit of the last character in the burst
- * coincides with 0.5 second. Since characters have 11 bits and are
- * transmitted at 300 bps, the last stop bit of the first character
- * coincides with 0.5 - 10 * 11/300 = 0.133 second. Depending on the
- * UART, character interrupts can vary somewhere between the beginning
- * of bit 9 and end of bit 11. These eccentricities can be corrected
- * along with the radio propagation delay using fudge time 1.
- *
- * Debugging aids
- *
- * The timecode format used for debugging and data recording includes
- * data helpful in diagnosing problems with the radio signal and serial
- * connections. With debugging enabled (-d on the ntpd command line),
- * the driver produces one line for each burst in two formats
- * corresponding to format A and B. Following is format A:
- *
- * n b f s m code
- *
- * where n is the number of characters in the burst (0-11), b the burst
- * distance (0-40), f the field alignment (-1, 0, 1), s the
- * synchronization distance (0-16), m the burst number (2-9) and code
- * the burst characters as received. Note that the hex digits in each
- * character are reversed, so the burst
- *
- * 10 38 0 16 9 06851292930685129293
- *
- * is interpreted as containing 11 characters with burst distance 38,
- * field alignment 0, synchronization distance 16 and burst number 9.
- * The nibble-swapped timecode shows day 58, hour 21, minute 29 and
- * second 39.
- *
- * When the audio driver is compiled, format A is preceded by
- * the current gain (0-255) and relative signal level (0-9999). The
- * receiver folume control should be set so that the gain is somewhere
- * near the middle of the range 0-255, which results in a signal level
- * near 1000.
- *
- * Following is format B:
- *
- * n b s code
- *
- * where n is the number of characters in the burst (0-11), b the burst
- * distance (0-40), s the synchronization distance (0-40) and code the
- * burst characters as received. Note that the hex digits in each
- * character are reversed and the last ten digits inverted, so the burst
- *
- * 11 40 1091891300ef6e76ecff
- *
- * is interpreted as containing 11 characters with burst distance 40.
- * The nibble-swapped timecode shows DUT1 +0.1 second, year 1998 and TAI
- * - UTC 31 seconds.
- *
- * In addition to the above, the reference timecode is updated and
- * written to the clockstats file and debug score after the last burst
- * received in the minute. The format is
- *
- * qq yyyy ddd hh:mm:ss nn dd tt
- *
- * where qq are the error flags, as described below, yyyy is the year,
- * ddd the day, hh:mm:ss the time of day, nn the number of format A
- * bursts received during the previous minute, dd the decoding distance
- * and tt the number of timestamps. The error flags are cleared after
- * every update.
- *
- * Fudge factors
- *
- * For accuracies better than the low millisceconds, fudge time1 can be
- * set to the radio propagation delay from CHU to the receiver. This can
- * be done conviently using the minimuf program.
- *
- * Fudge flag4 causes the dubugging output described above to be
- * recorded in the clockstats file. When the audio driver is compiled,
- * fudge flag2 selects the audio input port, where 0 is the mike port
- * (default) and 1 is the line-in port. It does not seem useful to
- * select the compact disc player port. Fudge flag3 enables audio
- * monitoring of the input signal. For this purpose, the monitor gain is
- * set to a default value.
- *
- * The audio codec code is normally compiled in the driver if the
- * architecture supports it (HAVE_AUDIO defined), but is used only if
- * the link /dev/chu_audio is defined and valid. The serial port code is
- * always compiled in the driver, but is used only if the autdio codec
- * is not available and the link /dev/chu%d is defined and valid.
- *
- * The ICOM code is normally compiled in the driver if selected (ICOM
- * defined), but is used only if the link /dev/icom%d is defined and
- * valid and the mode keyword on the server configuration command
- * specifies a nonzero mode (ICOM ID select code). The C-IV speed is
- * 9600 bps if the high order 0x80 bit of the mode is zero and 1200 bps
- * if one. The C-IV trace is turned on if the debug level is greater
- * than one.
- */
-/*
- * Interface definitions
- */
-#define SPEED232 B300 /* uart speed (300 baud) */
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#define REFID "CHU" /* reference ID */
-#define DEVICE "/dev/chu%d" /* device name and unit */
-#define SPEED232 B300 /* UART speed (300 baud) */
-#ifdef ICOM
-#define TUNE .001 /* offset for narrow filter (kHz) */
-#define DWELL 5 /* minutes in a probe cycle */
-#define NCHAN 3 /* number of channels */
-#define ISTAGE 3 /* number of integrator stages */
-#endif /* ICOM */
-
-#ifdef HAVE_AUDIO
-/*
- * Audio demodulator definitions
- */
-#define SECOND 8000 /* nominal sample rate (Hz) */
-#define BAUD 300 /* modulation rate (bps) */
-#define OFFSET 128 /* companded sample offset */
-#define SIZE 256 /* decompanding table size */
-#define MAXSIG 6000. /* maximum signal level */
-#define MAXCLP 100 /* max clips above reference per s */
-#define LIMIT 1000. /* soft limiter threshold */
-#define AGAIN 6. /* baseband gain */
-#define LAG 10 /* discriminator lag */
-#define DEVICE_AUDIO "/dev/chu_audio" /* device name */
-#define DESCRIPTION "CHU Audio/Modem Receiver" /* WRU */
-#define AUDIO_BUFSIZ 240 /* audio buffer size (30 ms) */
-#else
-#define DESCRIPTION "CHU Modem Receiver" /* WRU */
-#endif /* HAVE_AUDIO */
-
-/*
- * Decoder definitions
- */
-#define CHAR (11. / 300.) /* character time (s) */
-#define FUDGE .185 /* offset to first stop bit (s) */
-#define BURST 11 /* max characters per burst */
-#define MINCHAR 9 /* min characters per burst */
-#define MINDIST 28 /* min burst distance (of 40) */
-#define MINBURST 4 /* min bursts in minute */
-#define MINSYNC 8 /* min sync distance (of 16) */
-#define MINSTAMP 20 /* min timestamps (of 60) */
-#define METRIC 50. /* min channel metric */
-#define PANIC 1440 /* panic timeout (m) */
-#define HOLD 30 /* reach hold (m) */
-
-/*
- * Hex extension codes (>= 16)
- */
-#define HEX_MISS 16 /* miss _ */
-#define HEX_SOFT 17 /* soft error * */
-#define HEX_HARD 18 /* hard error = */
-
-/*
- * Status bits (status)
- */
-#define RUNT 0x0001 /* runt burst */
-#define NOISE 0x0002 /* noise burst */
-#define BFRAME 0x0004 /* invalid format B frame sync */
-#define BFORMAT 0x0008 /* invalid format B data */
-#define AFRAME 0x0010 /* invalid format A frame sync */
-#define AFORMAT 0x0020 /* invalid format A data */
-#define DECODE 0x0040 /* invalid data decode */
-#define STAMP 0x0080 /* too few timestamps */
-#define AVALID 0x0100 /* valid A frame */
-#define BVALID 0x0200 /* valid B frame */
-#define INSYNC 0x0400 /* clock synchronized */
-
-/*
- * Alarm status bits (alarm)
- *
- * These alarms are set at the end of a minute in which at least one
- * burst was received. SYNERR is raised if the AFRAME or BFRAME status
- * bits are set during the minute, FMTERR is raised if the AFORMAT or
- * BFORMAT status bits are set, DECERR is raised if the DECODE status
- * bit is set and TSPERR is raised if the STAMP status bit is set.
- */
-#define SYNERR 0x01 /* frame sync error */
-#define FMTERR 0x02 /* data format error */
-#define DECERR 0x04 /* data decoding error */
-#define TSPERR 0x08 /* insufficient data */
-
-#ifdef HAVE_AUDIO
-/*
- * Maximum likelihood UART structure. There are eight of these
- * corresponding to the number of phases.
- */
-struct surv {
- double shift[12]; /* mark register */
- double es_max, es_min; /* max/min envelope signals */
- double dist; /* sample distance */
- int uart; /* decoded character */
-};
-#endif /* HAVE_AUDIO */
-
-#ifdef ICOM
-/*
- * CHU station structure. There are three of these corresponding to the
- * three frequencies.
- */
-struct xmtr {
- double integ[ISTAGE]; /* circular integrator */
- double metric; /* integrator sum */
- int iptr; /* integrator pointer */
- int probe; /* dwells since last probe */
-};
-#endif /* ICOM */
-
-/*
- * CHU unit control structure
- */
-struct chuunit {
- u_char decode[20][16]; /* maximum likelihood decoding matrix */
- l_fp cstamp[BURST]; /* character timestamps */
- l_fp tstamp[MAXSTAGE]; /* timestamp samples */
- l_fp timestamp; /* current buffer timestamp */
- l_fp laststamp; /* last buffer timestamp */
- l_fp charstamp; /* character time as a l_fp */
- int errflg; /* error flags */
- int status; /* status bits */
- char ident[5]; /* station ID and channel */
-#ifdef ICOM
- int fd_icom; /* ICOM file descriptor */
- int chan; /* data channel */
- int achan; /* active channel */
- int dwell; /* dwell cycle */
- struct xmtr xmtr[NCHAN]; /* station metric */
-#endif /* ICOM */
-
- /*
- * Character burst variables
- */
- int cbuf[BURST]; /* character buffer */
- int ntstamp; /* number of timestamp samples */
- int ndx; /* buffer start index */
- int prevsec; /* previous burst second */
- int burdist; /* burst distance */
- int syndist; /* sync distance */
- int burstcnt; /* format A bursts this minute */
-
- /*
- * Format particulars
- */
- int leap; /* leap/dut code */
- int dut; /* UTC1 correction */
- int tai; /* TAI - UTC correction */
- int dst; /* Canadian DST code */
-
-#ifdef HAVE_AUDIO
- /*
- * Audio codec variables
- */
- int fd_audio; /* audio port file descriptor */
- double comp[SIZE]; /* decompanding table */
- int port; /* codec port */
- int gain; /* codec gain */
- int mongain; /* codec monitor gain */
- int clipcnt; /* sample clip count */
- int seccnt; /* second interval counter */
-
- /*
- * Modem variables
- */
- l_fp tick; /* audio sample increment */
- double bpf[9]; /* IIR bandpass filter */
- double disc[LAG]; /* discriminator shift register */
- double lpf[27]; /* FIR lowpass filter */
- double monitor; /* audio monitor */
- double maxsignal; /* signal level */
- int discptr; /* discriminator pointer */
-
- /*
- * Maximum likelihood UART variables
- */
- double baud; /* baud interval */
- struct surv surv[8]; /* UART survivor structures */
- int decptr; /* decode pointer */
- int dbrk; /* holdoff counter */
-#endif /* HAVE_AUDIO */
-};
-
-/*
- * Function prototypes
- */
-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_poll P((int, struct peer *));
-
-/*
- * More function prototypes
- */
-static void chu_decode P((struct peer *, int));
-static void chu_burst P((struct peer *));
-static void chu_clear P((struct peer *));
-static void chu_a P((struct peer *, int));
-static void chu_b P((struct peer *, int));
-static int chu_dist P((int, int));
-static double chu_major P((struct peer *));
-#ifdef HAVE_AUDIO
-static void chu_uart P((struct surv *, double));
-static void chu_rf P((struct peer *, double));
-static void chu_gain P((struct peer *));
-static void chu_audio_receive P((struct recvbuf *rbufp));
-#endif /* HAVE_AUDIO */
-#ifdef ICOM
-static int chu_newchan P((struct peer *, double));
-#endif /* ICOM */
-static void chu_serial_receive P((struct recvbuf *rbufp));
-
-/*
- * Global variables
- */
-static char hexchar[] = "0123456789abcdef_*=";
-
-#ifdef ICOM
-/*
- * Note the tuned frequencies are 1 kHz higher than the carrier. CHU
- * transmits on USB with carrier so we can use AM and the narrow SSB
- * filter.
- */
-static double qsy[NCHAN] = {3.330, 7.335, 14.670}; /* freq (MHz) */
-#endif /* ICOM */
-
-/*
- * Transfer vector
- */
-struct refclock refclock_chu = {
- 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_start - open the devices and initialize data for processing
- */
-static int
-chu_start(
- int unit, /* instance number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct chuunit *up;
- struct refclockproc *pp;
- char device[20]; /* device name */
- int fd; /* file descriptor */
-#ifdef ICOM
- int temp;
-#endif /* ICOM */
-#ifdef HAVE_AUDIO
- int fd_audio; /* audio port file descriptor */
- int i; /* index */
- double step; /* codec adjustment */
-
- /*
- * Open audio device.
- */
- fd_audio = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
-#ifdef DEBUG
- if (fd_audio > 0 && debug)
- audio_show();
-#endif
-
- /*
- * Open serial port in raw mode.
- */
- if (fd_audio > 0) {
- fd = fd_audio;
- } else {
- sprintf(device, DEVICE, unit);
- fd = refclock_open(device, SPEED232, LDISC_RAW);
- }
-#else /* HAVE_AUDIO */
-
- /*
- * Open serial port in raw mode.
- */
- sprintf(device, DEVICE, unit);
- fd = refclock_open(device, SPEED232, LDISC_RAW);
-#endif /* HAVE_AUDIO */
- if (fd <= 0)
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct chuunit *)
- emalloc(sizeof(struct chuunit)))) {
- close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct chuunit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- 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)) {
- close(fd);
- free(up);
- return (0);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- strcpy(up->ident, "CHU");
- memcpy(&peer->refid, up->ident, 4);
- DTOLFP(CHAR, &up->charstamp);
-#ifdef HAVE_AUDIO
-
- /*
- * The companded samples are encoded sign-magnitude. The table
- * contains all the 256 values in the interest of speed. We do
- * this even if the audio codec is not available. C'est la lazy.
- */
- up->fd_audio = fd_audio;
- up->gain = 127;
- up->comp[0] = up->comp[OFFSET] = 0.;
- up->comp[1] = 1; up->comp[OFFSET + 1] = -1.;
- up->comp[2] = 3; up->comp[OFFSET + 2] = -3.;
- step = 2.;
- for (i = 3; i < OFFSET; i++) {
- up->comp[i] = up->comp[i - 1] + step;
- up->comp[OFFSET + i] = -up->comp[i];
- if (i % 16 == 0)
- step *= 2.;
- }
- DTOLFP(1. / SECOND, &up->tick);
-#endif /* HAVE_AUDIO */
-#ifdef ICOM
- temp = 0;
-#ifdef DEBUG
- if (debug > 1)
- temp = P_TRACE;
-#endif
- if (peer->ttl > 0) {
- if (peer->ttl & 0x80)
- up->fd_icom = icom_init("/dev/icom", B1200,
- temp);
- else
- up->fd_icom = icom_init("/dev/icom", B9600,
- temp);
- }
- if (up->fd_icom > 0) {
- if (chu_newchan(peer, 0) != 0) {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: radio not found");
- up->errflg = CEVNT_FAULT;
- close(up->fd_icom);
- up->fd_icom = 0;
- } else {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: autotune enabled");
- }
- }
-#endif /* ICOM */
- return (1);
-}
-
-
-/*
- * chu_shutdown - shut down the clock
- */
-static void
-chu_shutdown(
- int unit, /* instance number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct chuunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
- if (up == NULL)
- return;
-
- io_closeclock(&pp->io);
-#ifdef ICOM
- if (up->fd_icom > 0)
- close(up->fd_icom);
-#endif /* ICOM */
- free(up);
-}
-
-
-/*
- * chu_receive - receive data from the audio or serial device
- */
-static void
-chu_receive(
- struct recvbuf *rbufp /* receive buffer structure pointer */
- )
-{
-#ifdef HAVE_AUDIO
- struct chuunit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * If the audio codec is warmed up, the buffer contains codec
- * samples which need to be demodulated and decoded into CHU
- * characters using the software UART. Otherwise, the buffer
- * contains CHU characters from the serial port, so the software
- * UART is bypassed. In this case the CPU will probably run a
- * few degrees cooler.
- */
- if (up->fd_audio > 0)
- chu_audio_receive(rbufp);
- else
- chu_serial_receive(rbufp);
-#else
- chu_serial_receive(rbufp);
-#endif /* HAVE_AUDIO */
-}
-
-
-#ifdef HAVE_AUDIO
-/*
- * chu_audio_receive - receive data from the audio device
- */
-static void
-chu_audio_receive(
- struct recvbuf *rbufp /* receive buffer structure pointer */
- )
-{
- struct chuunit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- double sample; /* codec sample */
- u_char *dpt; /* buffer pointer */
- int bufcnt; /* buffer counter */
- l_fp ltemp; /* l_fp temp */
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Main loop - read until there ain't no more. Note codec
- * samples are bit-inverted.
- */
- DTOLFP((double)rbufp->recv_length / SECOND, &ltemp);
- L_SUB(&rbufp->recv_time, &ltemp);
- up->timestamp = rbufp->recv_time;
- dpt = rbufp->recv_buffer;
- for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
- sample = up->comp[~*dpt++ & 0xff];
-
- /*
- * Clip noise spikes greater than MAXSIG. If no clips,
- * increase the gain a tad; if the clips are too high,
- * decrease a tad.
- */
- if (sample > MAXSIG) {
- sample = MAXSIG;
- up->clipcnt++;
- } else if (sample < -MAXSIG) {
- sample = -MAXSIG;
- up->clipcnt++;
- }
- chu_rf(peer, sample);
- L_ADD(&up->timestamp, &up->tick);
-
- /*
- * Once each second ride gain.
- */
- up->seccnt = (up->seccnt + 1) % SECOND;
- if (up->seccnt == 0) {
- pp->second = (pp->second + 1) % 60;
- chu_gain(peer);
- }
- }
-
- /*
- * Set the input port and monitor gain for the next buffer.
- */
- if (pp->sloppyclockflag & CLK_FLAG2)
- up->port = 2;
- else
- up->port = 1;
- if (pp->sloppyclockflag & CLK_FLAG3)
- up->mongain = MONGAIN;
- else
- up->mongain = 0;
-}
-
-
-/*
- * chu_rf - filter and demodulate the FSK signal
- *
- * This routine implements a 300-baud Bell 103 modem with mark 2225 Hz
- * and space 2025 Hz. It uses a bandpass filter followed by a soft
- * limiter, FM discriminator and lowpass filter. A maximum likelihood
- * decoder samples the baseband signal at eight times the baud rate and
- * detects the start bit of each character.
- *
- * The filters are built for speed, which explains the rather clumsy
- * code. Hopefully, the compiler will efficiently implement the move-
- * and-muiltiply-and-add operations.
- */
-static void
-chu_rf(
- struct peer *peer, /* peer structure pointer */
- double sample /* analog sample */
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
- struct surv *sp;
-
- /*
- * Local variables
- */
- double signal; /* bandpass signal */
- double limit; /* limiter signal */
- double disc; /* discriminator signal */
- double lpf; /* lowpass signal */
- double span; /* UART signal span */
- double dist; /* UART signal distance */
- int i, j;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Bandpass filter. 4th-order elliptic, 500-Hz bandpass centered
- * at 2125 Hz. Passband ripple 0.3 dB, stopband ripple 50 dB.
- */
- signal = (up->bpf[8] = up->bpf[7]) * 5.844676e-01;
- signal += (up->bpf[7] = up->bpf[6]) * 4.884860e-01;
- signal += (up->bpf[6] = up->bpf[5]) * 2.704384e+00;
- signal += (up->bpf[5] = up->bpf[4]) * 1.645032e+00;
- signal += (up->bpf[4] = up->bpf[3]) * 4.644557e+00;
- signal += (up->bpf[3] = up->bpf[2]) * 1.879165e+00;
- signal += (up->bpf[2] = up->bpf[1]) * 3.522634e+00;
- signal += (up->bpf[1] = up->bpf[0]) * 7.315738e-01;
- up->bpf[0] = sample - signal;
- signal = up->bpf[0] * 6.176213e-03
- + up->bpf[1] * 3.156599e-03
- + up->bpf[2] * 7.567487e-03
- + up->bpf[3] * 4.344580e-03
- + up->bpf[4] * 1.190128e-02
- + up->bpf[5] * 4.344580e-03
- + up->bpf[6] * 7.567487e-03
- + up->bpf[7] * 3.156599e-03
- + up->bpf[8] * 6.176213e-03;
-
- up->monitor = signal / 4.; /* note monitor after filter */
-
- /*
- * Soft limiter/discriminator. The 11-sample discriminator lag
- * interval corresponds to three cycles of 2125 Hz, which
- * requires the sample frequency to be 2125 * 11 / 3 = 7791.7
- * Hz. The discriminator output varies +-0.5 interval for input
- * frequency 2025-2225 Hz. However, we don't get to sample at
- * this frequency, so the discriminator output is biased. Life
- * at 8000 Hz sucks.
- */
- limit = signal;
- if (limit > LIMIT)
- limit = LIMIT;
- else if (limit < -LIMIT)
- limit = -LIMIT;
- disc = up->disc[up->discptr] * -limit;
- up->disc[up->discptr] = limit;
- up->discptr = (up->discptr + 1 ) % LAG;
- if (disc >= 0)
- disc = SQRT(disc);
- else
- disc = -SQRT(-disc);
-
- /*
- * Lowpass filter. Raised cosine, Ts = 1 / 300, beta = 0.1.
- */
- lpf = (up->lpf[26] = up->lpf[25]) * 2.538771e-02;
- lpf += (up->lpf[25] = up->lpf[24]) * 1.084671e-01;
- lpf += (up->lpf[24] = up->lpf[23]) * 2.003159e-01;
- lpf += (up->lpf[23] = up->lpf[22]) * 2.985303e-01;
- lpf += (up->lpf[22] = up->lpf[21]) * 4.003697e-01;
- lpf += (up->lpf[21] = up->lpf[20]) * 5.028552e-01;
- lpf += (up->lpf[20] = up->lpf[19]) * 6.028795e-01;
- lpf += (up->lpf[19] = up->lpf[18]) * 6.973249e-01;
- lpf += (up->lpf[18] = up->lpf[17]) * 7.831828e-01;
- lpf += (up->lpf[17] = up->lpf[16]) * 8.576717e-01;
- lpf += (up->lpf[16] = up->lpf[15]) * 9.183463e-01;
- lpf += (up->lpf[15] = up->lpf[14]) * 9.631951e-01;
- lpf += (up->lpf[14] = up->lpf[13]) * 9.907208e-01;
- lpf += (up->lpf[13] = up->lpf[12]) * 1.000000e+00;
- lpf += (up->lpf[12] = up->lpf[11]) * 9.907208e-01;
- lpf += (up->lpf[11] = up->lpf[10]) * 9.631951e-01;
- lpf += (up->lpf[10] = up->lpf[9]) * 9.183463e-01;
- lpf += (up->lpf[9] = up->lpf[8]) * 8.576717e-01;
- lpf += (up->lpf[8] = up->lpf[7]) * 7.831828e-01;
- lpf += (up->lpf[7] = up->lpf[6]) * 6.973249e-01;
- lpf += (up->lpf[6] = up->lpf[5]) * 6.028795e-01;
- lpf += (up->lpf[5] = up->lpf[4]) * 5.028552e-01;
- lpf += (up->lpf[4] = up->lpf[3]) * 4.003697e-01;
- lpf += (up->lpf[3] = up->lpf[2]) * 2.985303e-01;
- lpf += (up->lpf[2] = up->lpf[1]) * 2.003159e-01;
- lpf += (up->lpf[1] = up->lpf[0]) * 1.084671e-01;
- lpf += up->lpf[0] = disc * 2.538771e-02;
-
- /*
- * Maximum likelihood decoder. The UART updates each of the
- * eight survivors and determines the span, slice level and
- * tentative decoded character. Valid 11-bit characters are
- * framed so that bit 1 and bit 11 (stop bits) are mark and bit
- * 2 (start bit) is space. When a valid character is found, the
- * survivor with maximum distance determines the final decoded
- * character.
- */
- up->baud += 1. / SECOND;
- if (up->baud > 1. / (BAUD * 8.)) {
- up->baud -= 1. / (BAUD * 8.);
- sp = &up->surv[up->decptr];
- span = sp->es_max - sp->es_min;
- up->maxsignal += (span - up->maxsignal) / 80.;
- if (up->dbrk > 0) {
- up->dbrk--;
- } else if ((sp->uart & 0x403) == 0x401 && span > 1000.)
- {
- dist = 0;
- j = 0;
- for (i = 0; i < 8; i++) {
- if (up->surv[i].dist > dist) {
- dist = up->surv[i].dist;
- j = i;
- }
- }
- chu_decode(peer, (up->surv[j].uart >> 2) &
- 0xff);
- up->dbrk = 80;
- }
- up->decptr = (up->decptr + 1) % 8;
- chu_uart(sp, -lpf * AGAIN);
- }
-}
-
-
-/*
- * chu_uart - maximum likelihood UART
- *
- * This routine updates a shift register holding the last 11 envelope
- * samples. It then computes the slice level and span over these samples
- * and determines the tentative data bits and distance. The calling
- * program selects over the last eight survivors the one with maximum
- * distance to determine the decoded character.
- */
-static void
-chu_uart(
- struct surv *sp, /* survivor structure pointer */
- double sample /* baseband signal */
- )
-{
- double es_max, es_min; /* max/min envelope */
- double slice; /* slice level */
- double dist; /* distance */
- double dtemp;
- int i;
-
- /*
- * Save the sample and shift right. At the same time, measure
- * the maximum and minimum over all eleven samples.
- */
- es_max = -1e6;
- es_min = 1e6;
- sp->shift[0] = sample;
- for (i = 11; i > 0; i--) {
- sp->shift[i] = sp->shift[i - 1];
- if (sp->shift[i] > es_max)
- es_max = sp->shift[i];
- if (sp->shift[i] < es_min)
- es_min = sp->shift[i];
- }
-
- /*
- * Determine the slice level midway beteen the maximum and
- * minimum and the span as the maximum less the minimum. Compute
- * the distance on the assumption the first and last bits must
- * be mark, the second space and the rest either mark or space.
- */
- slice = (es_max + es_min) / 2.;
- dist = 0;
- sp->uart = 0;
- for (i = 1; i < 12; i++) {
- sp->uart <<= 1;
- dtemp = sp->shift[i];
- if (dtemp > slice)
- sp->uart |= 0x1;
- if (i == 1 || i == 11) {
- dist += dtemp - es_min;
- } else if (i == 10) {
- dist += es_max - dtemp;
- } else {
- if (dtemp > slice)
- dist += dtemp - es_min;
- else
- dist += es_max - dtemp;
- }
- }
- sp->es_max = es_max;
- sp->es_min = es_min;
- sp->dist = dist / (11 * (es_max - es_min));
-}
-#endif /* HAVE_AUDIO */
-
-
-/*
- * chu_serial_receive - receive data from the serial device
- */
-static void
-chu_serial_receive(
- struct recvbuf *rbufp /* receive buffer structure pointer */
- )
-{
- struct chuunit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- u_char *dpt; /* receive buffer pointer */
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Initialize pointers and read the timecode and timestamp.
- */
- up->timestamp = rbufp->recv_time;
- dpt = (u_char *)&rbufp->recv_space;
- chu_decode(peer, *dpt);
-}
-
-
-/*
- * chu_decode - decode the character data
- */
-static void
-chu_decode(
- struct peer *peer, /* peer structure pointer */
- int hexhex /* data character */
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
-
- l_fp tstmp; /* timestamp temp */
- double dtemp;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * If the interval since the last character is greater than the
- * longest burst, process the last burst and start a new one. If
- * the interval is less than this but greater than two
- * characters, consider this a noise burst and reject it.
- */
- tstmp = up->timestamp;
- if (L_ISZERO(&up->laststamp))
- up->laststamp = up->timestamp;
- L_SUB(&tstmp, &up->laststamp);
- up->laststamp = up->timestamp;
- LFPTOD(&tstmp, dtemp);
- if (dtemp > BURST * CHAR) {
- chu_burst(peer);
- up->ndx = 0;
- } else if (dtemp > 2.5 * CHAR) {
- up->ndx = 0;
- }
-
- /*
- * Append the character to the current burst and append the
- * timestamp to the timestamp list.
- */
- if (up->ndx < BURST) {
- up->cbuf[up->ndx] = hexhex & 0xff;
- up->cstamp[up->ndx] = up->timestamp;
- up->ndx++;
-
- }
-}
-
-
-/*
- * chu_burst - search for valid burst format
- */
-static void
-chu_burst(
- struct peer *peer
- )
-{
- struct chuunit *up;
- struct refclockproc *pp;
-
- int i;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Correlate a block of five characters with the next block of
- * five characters. The burst distance is defined as the number
- * of bits that match in the two blocks for format A and that
- * match the inverse for format B.
- */
- if (up->ndx < MINCHAR) {
- up->status |= RUNT;
- return;
- }
- up->burdist = 0;
- for (i = 0; i < 5 && i < up->ndx - 5; i++)
- up->burdist += chu_dist(up->cbuf[i], up->cbuf[i + 5]);
-
- /*
- * If the burst distance is at least MINDIST, this must be a
- * format A burst; if the value is not greater than -MINDIST, it
- * must be a format B burst. If the B burst is perfect, we
- * believe it; otherwise, it is a noise burst and of no use to
- * anybody.
- */
- if (up->burdist >= MINDIST) {
- chu_a(peer, up->ndx);
- } else if (up->burdist <= -MINDIST) {
- chu_b(peer, up->ndx);
- } else {
- up->status |= NOISE;
- return;
- }
-
- /*
- * If this is a valid burst, wait a guard time of ten seconds to
- * allow for more bursts, then arm the poll update routine to
- * process the minute. Don't do this if this is called from the
- * timer interrupt routine.
- */
- if (peer->outdate != current_time)
- peer->nextdate = current_time + 10;
-}
-
-
-/*
- * chu_b - decode format B burst
- */
-static void
-chu_b(
- struct peer *peer,
- int nchar
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
-
- u_char code[11]; /* decoded timecode */
- char tbuf[80]; /* trace buffer */
- l_fp offset; /* timestamp offset */
- int i;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * In a format B burst, a character is considered valid only if
- * the first occurrence matches the last occurrence. The burst
- * is considered valid only if all characters are valid; that
- * is, only if the distance is 40. Note that once a valid frame
- * has been found errors are ignored.
- */
- sprintf(tbuf, "chuB %04x %2d %2d ", up->status, nchar,
- -up->burdist);
- for (i = 0; i < nchar; i++)
- sprintf(&tbuf[strlen(tbuf)], "%02x", up->cbuf[i]);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif
- if (up->burdist > -40) {
- up->status |= BFRAME;
- return;
- }
- up->status |= BVALID;
-
- /*
- * Convert the burst data to internal format. If this succeeds,
- * save the timestamps for later.
- */
- for (i = 0; i < 5; i++) {
- code[2 * i] = hexchar[up->cbuf[i] & 0xf];
- code[2 * i + 1] = hexchar[(up->cbuf[i] >>
- 4) & 0xf];
- }
- if (sscanf((char *)code, "%1x%1d%4d%2d%2x", &up->leap, &up->dut,
- &pp->year, &up->tai, &up->dst) != 5) {
- up->status |= BFORMAT;
- return;
- }
- if (up->leap & 0x8)
- up->dut = -up->dut;
- offset.l_ui = 31;
- offset.l_f = 0;
- for (i = 0; i < nchar && i < 10; i++) {
- up->tstamp[up->ntstamp] = up->cstamp[i];
- L_SUB(&up->tstamp[up->ntstamp], &offset);
- L_ADD(&offset, &up->charstamp);
- if (up->ntstamp < MAXSTAGE)
- up->ntstamp++;
- }
-}
-
-
-/*
- * chu_a - decode format A burst
- */
-static void
-chu_a(
- struct peer *peer,
- int nchar
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
-
- char tbuf[80]; /* trace buffer */
- l_fp offset; /* timestamp offset */
- int val; /* distance */
- int temp;
- int i, j, k;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Determine correct burst phase. There are three cases
- * corresponding to in-phase, one character early or one
- * character late. These cases are distinguished by the position
- * of the framing digits x6 at positions 0 and 5 and x3 at
- * positions 4 and 9. The correct phase is when the distance
- * relative to the framing digits is maximum. The burst is valid
- * only if the maximum distance is at least MINSYNC.
- */
- up->syndist = k = 0;
- val = -16;
- for (i = -1; i < 2; i++) {
- temp = up->cbuf[i + 4] & 0xf;
- if (i >= 0)
- temp |= (up->cbuf[i] & 0xf) << 4;
- val = chu_dist(temp, 0x63);
- temp = (up->cbuf[i + 5] & 0xf) << 4;
- if (i + 9 < nchar)
- temp |= up->cbuf[i + 9] & 0xf;
- val += chu_dist(temp, 0x63);
- if (val > up->syndist) {
- up->syndist = val;
- k = i;
- }
- }
- temp = (up->cbuf[k + 4] >> 4) & 0xf;
- if (temp > 9 || k + 9 >= nchar || temp != ((up->cbuf[k + 9] >>
- 4) & 0xf))
- temp = 0;
-#ifdef HAVE_AUDIO
- if (up->fd_audio)
- sprintf(tbuf, "chuA %04x %4.0f %2d %2d %2d %2d %1d ",
- up->status, up->maxsignal, nchar, up->burdist, k,
- up->syndist, temp);
- else
- sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ",
- up->status, nchar, up->burdist, k, up->syndist,
- temp);
-
-#else
- sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ", up->status,
- nchar, up->burdist, k, up->syndist, temp);
-#endif /* HAVE_AUDIO */
- for (i = 0; i < nchar; i++)
- sprintf(&tbuf[strlen(tbuf)], "%02x",
- up->cbuf[i]);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif
- if (up->syndist < MINSYNC) {
- up->status |= AFRAME;
- return;
- }
-
- /*
- * A valid burst requires the first seconds number to match the
- * last seconds number. If so, the burst timestamps are
- * corrected to the current minute and saved for later
- * processing. In addition, the seconds decode is advanced from
- * the previous burst to the current one.
- */
- if (temp != 0) {
- pp->second = 30 + temp;
- offset.l_ui = 30 + temp;
- offset.l_f = 0;
- i = 0;
- if (k < 0)
- offset = up->charstamp;
- else if (k > 0)
- i = 1;
- for (; i < nchar && i < k + 10; i++) {
- up->tstamp[up->ntstamp] = up->cstamp[i];
- L_SUB(&up->tstamp[up->ntstamp], &offset);
- L_ADD(&offset, &up->charstamp);
- if (up->ntstamp < MAXSTAGE)
- up->ntstamp++;
- }
- while (temp > up->prevsec) {
- for (j = 15; j > 0; j--) {
- up->decode[9][j] = up->decode[9][j - 1];
- up->decode[19][j] =
- up->decode[19][j - 1];
- }
- up->decode[9][j] = up->decode[19][j] = 0;
- up->prevsec++;
- }
- }
- i = -(2 * k);
- for (j = 0; j < nchar; j++) {
- if (i < 0 || i > 19) {
- i += 2;
- continue;
- }
- up->decode[i][up->cbuf[j] & 0xf]++;
- i++;
- up->decode[i][(up->cbuf[j] >> 4) & 0xf]++;
- i++;
- }
- up->status |= AVALID;
- up->burstcnt++;
-}
-
-
-/*
- * chu_poll - called by the transmit procedure
- */
-static void
-chu_poll(
- int unit,
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
- l_fp offset;
- char synchar, qual, leapchar;
- int minset, i;
- double dtemp;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
- if (pp->coderecv == pp->codeproc)
- up->errflg = CEVNT_TIMEOUT;
- else
- pp->polls++;
-
- /*
- * If once in sync and the radio has not been heard for awhile
- * (30 m), it is no longer reachable. If not heard in a long
- * while (one day), turn out the lights and start from scratch.
- */
- minset = ((current_time - peer->update) + 30) / 60;
- if (up->status & INSYNC) {
- if (minset > PANIC)
- up->status = 0;
- else if (minset <= HOLD)
- peer->reach |= 1;
- }
-
- /*
- * Process the last burst, if still in the burst buffer.
- * Don't mess with anything if nothing has been heard. If the
- * minute contains a valid A frame and valid B frame, assume
- * synchronized; however, believe the time only if within metric
- * threshold. Note the quality indicator is only for
- * diagnostics; the data are used only if in sync and above
- * metric threshold.
- */
- chu_burst(peer);
- if (up->burstcnt == 0) {
-#ifdef ICOM
- chu_newchan(peer, 0);
-#endif /* ICOM */
- return;
- }
- dtemp = chu_major(peer);
- qual = 0;
- if (up->status & (BFRAME | AFRAME))
- qual |= SYNERR;
- if (up->status & (BFORMAT | AFORMAT))
- qual |= FMTERR;
- if (up->status & DECODE)
- qual |= DECERR;
- if (up->status & STAMP)
- qual |= TSPERR;
- if (up->status & AVALID && up->status & BVALID)
- up->status |= INSYNC;
- synchar = leapchar = ' ';
- if (!(up->status & INSYNC)) {
- pp->leap = LEAP_NOTINSYNC;
- synchar = '?';
- } else if (up->leap & 0x2) {
- pp->leap = LEAP_ADDSECOND;
- leapchar = 'L';
- } else if (up->leap & 0x4) {
- pp->leap = LEAP_DELSECOND;
- leapchar = 'l';
- } else {
- pp->leap = LEAP_NOWARNING;
- }
-#ifdef HAVE_AUDIO
- if (up->fd_audio)
- sprintf(pp->a_lastcode,
- "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %d %s %.0f %d",
- synchar, qual, pp->year, pp->day, pp->hour,
- pp->minute, pp->second, leapchar, up->dst, up->dut,
- minset, up->gain, up->ident, dtemp, up->ntstamp);
- else
- sprintf(pp->a_lastcode,
- "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %s %.0f %d",
- synchar, qual, pp->year, pp->day, pp->hour,
- pp->minute, pp->second, leapchar, up->dst, up->dut,
- minset, up->ident, dtemp, up->ntstamp);
-#else
- sprintf(pp->a_lastcode,
- "%c%1X %04d %3d %02d:%02d:%02d %c%x %+d %d %s %.0f %d",
- synchar, qual, pp->year, pp->day, pp->hour, pp->minute,
- pp->second, leapchar, up->dst, up->dut, minset, up->ident,
- dtemp, up->ntstamp);
-#endif /* HAVE_AUDIO */
- pp->lencode = strlen(pp->a_lastcode);
-
- /*
- * If in sync and the signal metric is above threshold, the
- * timecode is ipso fatso valid and can be selected to
- * discipline the clock. Be sure not to leave stray timestamps
- * around if signals are too weak or the clock time is invalid.
- */
- if (up->status & INSYNC && dtemp > METRIC) {
- if (!clocktime(pp->day, pp->hour, pp->minute, 0, GMT,
- up->tstamp[0].l_ui, &pp->yearstart, &offset.l_ui)) {
- up->errflg = CEVNT_BADTIME;
- } else {
- offset.l_uf = 0;
- for (i = 0; i < up->ntstamp; i++)
- refclock_process_offset(pp, offset,
- up->tstamp[i], FUDGE +
- pp->fudgetime1);
- pp->lastref = up->timestamp;
- refclock_receive(peer);
- }
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- } else if (pp->sloppyclockflag & CLK_FLAG4) {
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- }
-#ifdef DEBUG
- if (debug)
- printf("chu: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
-#ifdef ICOM
- chu_newchan(peer, dtemp);
-#endif /* ICOM */
- chu_clear(peer);
- if (up->errflg)
- refclock_report(peer, up->errflg);
- up->errflg = 0;
-}
-
-
-/*
- * chu_major - majority decoder
- */
-static double
-chu_major(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
-
- u_char code[11]; /* decoded timecode */
- int mindist; /* minimum distance */
- int val1, val2; /* maximum distance */
- int synchar; /* stray cat */
- int temp;
- int i, j, k;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Majority decoder. Each burst encodes two replications at each
- * digit position in the timecode. Each row of the decoding
- * matrix encodes the number of occurrences of each digit found
- * at the corresponding position. The maximum over all
- * occurrences at each position is the distance for this
- * position and the corresponding digit is the maximum
- * likelihood candidate. If the distance is zero, assume a miss
- * '_'; if the distance is not more than half the total number
- * of occurrences, assume a soft error '*'; if two different
- * digits with the same distance are found, assume a hard error
- * '='. These will later cause a format error when the timecode
- * is interpreted. The decoding distance is defined as the
- * minimum distance over the first nine digits. The tenth digit
- * varies over the seconds, so we don't count it.
- */
- mindist = 16;
- for (i = 0; i < 9; i++) {
- val1 = val2 = 0;
- k = 0;
- for (j = 0; j < 16; j++) {
- temp = up->decode[i][j] + up->decode[i + 10][j];
- if (temp > val1) {
- val2 = val1;
- val1 = temp;
- k = j;
- }
- }
- if (val1 == 0)
- code[i] = HEX_MISS;
- else if (val1 == val2)
- code[i] = HEX_HARD;
- else if (val1 <= up->burstcnt)
- code[i] = HEX_SOFT;
- else
- code[i] = k;
- if (val1 < mindist)
- mindist = val1;
- code[i] = hexchar[code[i]];
- }
- code[i] = 0;
-
- /*
- * A valid timecode requires a minimum distance at least half
- * the total number of occurrences. A valid timecode also
- * requires at least 20 valid timestamps.
- */
- if (up->burstcnt < MINBURST || mindist < up->burstcnt)
- up->status |= DECODE;
- if (up->ntstamp < MINSTAMP)
- up->status |= STAMP;
-
- /*
- * Compute the timecode timestamp from the days, hours and
- * minutes of the timecode. Use clocktime() for the aggregate
- * minutes and the minute offset computed from the burst
- * seconds. Note that this code relies on the filesystem time
- * for the years and does not use the years of the timecode.
- */
- if (sscanf((char *)code, "%1x%3d%2d%2d", &synchar, &pp->day,
- &pp->hour, &pp->minute) != 4) {
- up->status |= AFORMAT;
- return (0);
- }
- if (up->status & (DECODE | STAMP)) {
- up->errflg = CEVNT_BADREPLY;
- return (0);
- }
- return (mindist * 100. / (2. * up->burstcnt));
-}
-
-
-/*
- * chu_clear - clear decoding matrix
- */
-static void
-chu_clear(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
- int i, j;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Clear stuff for the minute.
- */
- up->ndx = up->prevsec = 0;
- up->burstcnt = up->ntstamp = 0;
- up->status &= INSYNC;
- for (i = 0; i < 20; i++) {
- for (j = 0; j < 16; j++)
- up->decode[i][j] = 0;
- }
-}
-
-#ifdef ICOM
-/*
- * chu_newchan - called once per minute to find the best channel;
- * returns zero on success, nonzero if ICOM error.
- */
-static int
-chu_newchan(
- struct peer *peer,
- double met
- )
-{
- struct chuunit *up;
- struct refclockproc *pp;
- struct xmtr *sp;
- char tbuf[80]; /* trace buffer */
- int rval;
- double metric;
- int i, j;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * The radio can be tuned to three channels: 0 (3330 kHz), 1
- * (7335 kHz) and 2 (14670 kHz). There are five one-minute
- * dwells in each cycle. During the first dwell the radio is
- * tuned to one of three probe channels; during the remaining
- * four dwells the radio is tuned to the data channel. The probe
- * channel is selects as the least recently used. At the end of
- * each dwell the channel metrics are measured and the highest
- * one is selected as the data channel.
- */
- if (up->fd_icom <= 0)
- return (0);
-
- sp = &up->xmtr[up->achan];
- sp->metric -= sp->integ[sp->iptr];
- sp->integ[sp->iptr] = met;
- sp->metric += sp->integ[sp->iptr];
- sp->iptr = (sp->iptr + 1) % ISTAGE;
- metric = 0;
- j = 0;
- for (i = 0; i < NCHAN; i++) {
- up->xmtr[i].probe++;
- if (i == up->achan)
- up->xmtr[i].probe = 0;
- if (up->xmtr[i].metric < metric)
- continue;
- metric = up->xmtr[i].metric;
- j = i;
- }
- if (j != up->chan && metric > 0) {
- up->chan = j;
- sprintf(tbuf, "chu: QSY to %.3f MHz metric %.0f",
- qsy[up->chan], metric);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif
- }
-
- /*
- * Start the next dwell. We speed up the initial sync a little.
- * If not in sync and no bursts were heard the previous dwell,
- * restart the probe.
- */
- rval = 0;
- if (up->burstcnt == 0 && !(up->status & INSYNC))
- up->dwell = 0;
-#ifdef DEBUG
- if (debug)
- printf(
- "chu: at %ld dwell %d achan %d metric %.0f chan %d\n",
- current_time, up->dwell, up->achan, sp->metric,
- up->chan);
-#endif
- if (up->dwell == 0) {
- rval = 0;
- for (i = 0; i < NCHAN; i++) {
- if (up->xmtr[i].probe < rval)
- continue;
- rval = up->xmtr[i].probe;
- up->achan = i;
- }
- rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
- qsy[up->achan] + TUNE);
-#ifdef DEBUG
- if (debug)
- printf("chu: at %ld probe channel %d\n",
- current_time, up->achan);
-#endif
- } else {
- if (up->achan != up->chan) {
- rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
- qsy[up->chan] + TUNE);
- up->achan = up->chan;
- }
- }
- sprintf(up->ident, "CHU%d", up->achan);
- memcpy(&peer->refid, up->ident, 4);
- up->dwell = (up->dwell + 1) % DWELL;
- return (rval);
-}
-#endif /* ICOM */
-
-/*
- * chu_dist - determine the distance of two octet arguments
- */
-static int
-chu_dist(
- int x, /* an octet of bits */
- int y /* another octet of bits */
- )
-{
- int val; /* bit count */
- int temp;
- int i;
-
- /*
- * The distance is determined as the weight of the exclusive OR
- * of the two arguments. The weight is determined by the number
- * of one bits in the result. Each one bit increases the weight,
- * while each zero bit decreases it.
- */
- temp = x ^ y;
- val = 0;
- for (i = 0; i < 8; i++) {
- if ((temp & 0x1) == 0)
- val++;
- else
- val--;
- temp >>= 1;
- }
- return (val);
-}
-
-
-#ifdef HAVE_AUDIO
-/*
- * chu_gain - adjust codec gain
- *
- * This routine is called once each second. If the signal envelope
- * amplitude is too low, the codec gain is bumped up by four units; if
- * too high, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
- */
-static void
-chu_gain(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct chuunit *up;
-
- pp = peer->procptr;
- up = (struct chuunit *)pp->unitptr;
-
- /*
- * Apparently, the codec uses only the high order bits of the
- * gain control field. Thus, it may take awhile for changes to
- * wiggle the hardware bits.
- */
- if (up->clipcnt == 0) {
- up->gain += 4;
- if (up->gain > MAXGAIN)
- up->gain = MAXGAIN;
- } else if (up->clipcnt > MAXCLP) {
- up->gain -= 4;
- if (up->gain < 0)
- up->gain = 0;
- }
- audio_gain(up->gain, up->mongain, up->port);
- up->clipcnt = 0;
-}
-#endif /* HAVE_AUDIO */
-
-
-#else
-int refclock_chu_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_conf.c b/contrib/ntp/ntpd/refclock_conf.c
deleted file mode 100644
index 8a424f0..0000000
--- a/contrib/ntp/ntpd/refclock_conf.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * refclock_conf.c - reference clock configuration
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "ntpd.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#ifdef REFCLOCK
-
-static struct refclock refclock_none = {
- noentry, noentry, noentry, noentry, noentry, noentry, NOFLAGS
-};
-
-#ifdef CLOCK_LOCAL
-extern struct refclock refclock_local;
-#else
-#define refclock_local refclock_none
-#endif
-
-#if defined(CLOCK_TRAK) && defined(PPS)
-extern struct refclock refclock_trak;
-#else
-#define refclock_trak refclock_none
-#endif
-
-#ifdef CLOCK_PST
-extern struct refclock refclock_pst;
-#else
-#define refclock_pst refclock_none
-#endif
-
-#ifdef CLOCK_CHU
-extern struct refclock refclock_chu;
-#else
-#define refclock_chu refclock_none
-#endif
-
-#ifdef CLOCK_WWV
-extern struct refclock refclock_wwv;
-#else
-#define refclock_wwv refclock_none
-#endif
-
-#ifdef CLOCK_SPECTRACOM
-extern struct refclock refclock_wwvb;
-#else
-#define refclock_wwvb refclock_none
-#endif
-
-#ifdef CLOCK_PARSE
-extern struct refclock refclock_parse;
-#else
-#define refclock_parse refclock_none
-#endif
-
-#if defined(CLOCK_MX4200) && defined(HAVE_PPSAPI)
-extern struct refclock refclock_mx4200;
-#else
-#define refclock_mx4200 refclock_none
-#endif
-
-#ifdef CLOCK_AS2201
-extern struct refclock refclock_as2201;
-#else
-#define refclock_as2201 refclock_none
-#endif
-
-#ifdef CLOCK_ARBITER
-extern struct refclock refclock_arbiter;
-#else
-#define refclock_arbiter refclock_none
-#endif
-
-#ifdef CLOCK_TPRO
-extern struct refclock refclock_tpro;
-#else
-#define refclock_tpro refclock_none
-#endif
-
-#ifdef CLOCK_LEITCH
-extern struct refclock refclock_leitch;
-#else
-#define refclock_leitch refclock_none
-#endif
-
-#ifdef CLOCK_IRIG
-extern struct refclock refclock_irig;
-#else
-#define refclock_irig refclock_none
-#endif
-
-#if defined(CLOCK_MSFEES) && defined(PPS)
-extern struct refclock refclock_msfees;
-#else
-#define refclock_msfees refclock_none
-#endif
-
-#ifdef CLOCK_BANC
-extern struct refclock refclock_bancomm;
-#else
-#define refclock_bancomm refclock_none
-#endif
-
-#ifdef CLOCK_TRUETIME
-extern struct refclock refclock_true;
-#else
-#define refclock_true refclock_none
-#endif
-
-#ifdef CLOCK_DATUM
-extern struct refclock refclock_datum;
-#else
-#define refclock_datum refclock_none
-#endif
-
-#ifdef CLOCK_ACTS
-extern struct refclock refclock_acts;
-#else
-#define refclock_acts refclock_none
-#endif
-
-#ifdef CLOCK_HEATH
-extern struct refclock refclock_heath;
-#else
-#define refclock_heath refclock_none
-#endif
-
-#ifdef CLOCK_NMEA
-extern struct refclock refclock_nmea;
-#else
-#define refclock_nmea refclock_none
-#endif
-
-#ifdef CLOCK_ATOM
-extern struct refclock refclock_atom;
-#else
-#define refclock_atom refclock_none
-#endif
-
-#ifdef CLOCK_PTBACTS
-extern struct refclock refclock_ptb;
-#else
-#define refclock_ptb refclock_none
-#endif
-
-#ifdef CLOCK_USNO
-extern struct refclock refclock_usno;
-#else
-#define refclock_usno refclock_none
-#endif
-
-#ifdef CLOCK_HPGPS
-extern struct refclock refclock_hpgps;
-#else
-#define refclock_hpgps refclock_none
-#endif
-
-#ifdef CLOCK_GPSVME
-extern struct refclock refclock_gpsvme;
-#else
-#define refclock_gpsvme refclock_none
-#endif
-
-#ifdef CLOCK_ARCRON_MSF
-extern struct refclock refclock_arc;
-#else
-#define refclock_arc refclock_none
-#endif
-
-#ifdef CLOCK_SHM
-extern struct refclock refclock_shm;
-#else
-#define refclock_shm refclock_none
-#endif
-
-#ifdef CLOCK_PALISADE
-extern struct refclock refclock_palisade;
-#else
-#define refclock_palisade refclock_none
-#endif
-
-#if defined(CLOCK_ONCORE) && defined(HAVE_PPSAPI)
-extern struct refclock refclock_oncore;
-#else
-#define refclock_oncore refclock_none
-#endif
-
-#if defined(CLOCK_JUPITER) && defined(HAVE_PPSAPI)
-extern struct refclock refclock_jupiter;
-#else
-#define refclock_jupiter refclock_none
-#endif
-
-#if defined(CLOCK_CHRONOLOG)
-extern struct refclock refclock_chronolog;
-#else
-#define refclock_chronolog refclock_none
-#endif
-
-#if defined(CLOCK_DUMBCLOCK)
-extern struct refclock refclock_dumbclock;
-#else
-#define refclock_dumbclock refclock_none
-#endif
-
-#ifdef CLOCK_ULINK
-extern struct refclock refclock_ulink;
-#else
-#define refclock_ulink refclock_none
-#endif
-
-#ifdef CLOCK_PCF
-extern struct refclock refclock_pcf;
-#else
-#define refclock_pcf refclock_none
-#endif
-
-#ifdef CLOCK_FG
-extern struct refclock refclock_fg;
-#else
-#define refclock_fg refclock_none
-#endif
-
-#ifdef CLOCK_HOPF_SERIAL
-extern struct refclock refclock_hopfser;
-#else
-#define refclock_hopfser refclock_none
-#endif
-
-#ifdef CLOCK_HOPF_PCI
-extern struct refclock refclock_hopfpci;
-#else
-#define refclock_hopfpci refclock_none
-#endif
-
-#ifdef CLOCK_JJY
-extern struct refclock refclock_jjy;
-#else
-#define refclock_jjy refclock_none
-#endif
-
-#ifdef CLOCK_TT560
-extern struct refclock refclock_tt560;
-#else
-#define refclock_tt560 refclock_none
-#endif
-
-#ifdef CLOCK_ZYFER
-extern struct refclock refclock_zyfer;
-#else
-#define refclock_zyfer refclock_none
-#endif
-
-#ifdef CLOCK_RIPENCC
-extern struct refclock refclock_ripencc;
-#else
-#define refclock_ripencc refclock_none
-#endif
-
-#ifdef CLOCK_NEOCLOCK4X
-extern struct refclock refclock_neoclock4x;
-#else
-#define refclock_neoclock4x refclock_none
-#endif
-
-/*
- * Order is clock_start(), clock_shutdown(), clock_poll(),
- * clock_control(), clock_init(), clock_buginfo, clock_flags;
- *
- * Types are defined in ntp.h. The index must match this.
- */
-struct refclock *refclock_conf[] = {
- &refclock_none, /* 0 REFCLK_NONE */
- &refclock_local, /* 1 REFCLK_LOCAL */
- &refclock_trak, /* 2 REFCLK_GPS_TRAK */
- &refclock_pst, /* 3 REFCLK_WWV_PST */
- &refclock_wwvb, /* 4 REFCLK_SPECTRACOM */
- &refclock_true, /* 5 REFCLK_TRUETIME */
- &refclock_irig, /* 6 REFCLK_IRIG_AUDIO */
- &refclock_chu, /* 7 REFCLK_CHU_AUDIO */
- &refclock_parse, /* 8 REFCLK_PARSE */
- &refclock_mx4200, /* 9 REFCLK_GPS_MX4200 */
- &refclock_as2201, /* 10 REFCLK_GPS_AS2201 */
- &refclock_arbiter, /* 11 REFCLK_GPS_ARBITER */
- &refclock_tpro, /* 12 REFCLK_IRIG_TPRO */
- &refclock_leitch, /* 13 REFCLK_ATOM_LEITCH */
- &refclock_msfees, /* 14 REFCLK_MSF_EES */
- &refclock_true, /* 15 alias for REFCLK_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_gpsvme, /* 21 REFCLK_GPS_VME */
- &refclock_atom, /* 22 REFCLK_ATOM_PPS */
- &refclock_ptb, /* 23 REFCLK_PTB_ACTS */
- &refclock_usno, /* 24 REFCLK_USNO */
- &refclock_true, /* 25 alias for REFCLK_TRUETIME */
- &refclock_hpgps, /* 26 REFCLK_GPS_HP */
- &refclock_arc, /* 27 REFCLK_ARCRON_MSF */
- &refclock_shm, /* 28 REFCLK_SHM */
- &refclock_palisade, /* 29 REFCLK_PALISADE */
- &refclock_oncore, /* 30 REFCLK_ONCORE */
- &refclock_jupiter, /* 31 REFCLK_GPS_JUPITER */
- &refclock_chronolog, /* 32 REFCLK_CHRONOLOG */
- &refclock_dumbclock, /* 33 REFCLK_DUMBCLOCK */
- &refclock_ulink, /* 34 REFCLOCK_ULINK */
- &refclock_pcf, /* 35 REFCLOCK_PCF */
- &refclock_wwv, /* 36 REFCLOCK_WWV_AUDIO */
- &refclock_fg, /* 37 REFCLOCK_FG */
- &refclock_hopfser, /* 38 REFCLK_HOPF_SERIAL */
- &refclock_hopfpci, /* 39 REFCLK_HOPF_PCI */
- &refclock_jjy, /* 40 REFCLK_JJY */
- &refclock_tt560, /* 41 REFCLK_TT560 */
- &refclock_zyfer, /* 42 REFCLK_ZYFER */
- &refclock_ripencc, /* 43 REFCLK_RIPENCC */
- &refclock_neoclock4x /* 44 REFCLK_NEOCLOCK4X */
-};
-
-u_char num_refclock_conf = sizeof(refclock_conf)/sizeof(struct refclock *);
-
-#else
-int refclock_conf_bs;
-#endif
diff --git a/contrib/ntp/ntpd/refclock_datum.c b/contrib/ntp/ntpd/refclock_datum.c
deleted file mode 100644
index 82b7369..0000000
--- a/contrib/ntp/ntpd/refclock_datum.c
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
-** 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.
-*/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_DATUM)
-
-/*
-** Include Files
-*/
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.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 */
-
-#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 PRECISION (-10) /* precision assumed 1/1024 ms */
-#define REFID "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)
-
-/*
-** 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 ntp */
- struct refclockio io; /* io structure used by ntp */
- 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 int nunits; /* number of active units */
-static struct datum_pts_unit
-**datum_pts_unit; /* dynamic array of datum PTS structures */
-
-/*
-** Callback function prototypes that ntpd 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 *, struct peer *));
-static void datum_pts_init P((void));
-static void datum_pts_buginfo P((int, struct refclockbug *, struct peer *));
-
-/*
-** This is the call back function structure that ntpd 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 ntpd 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, ntpd
-** 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 ntpd 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 ntpd 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 ntpd.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(
- 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
- if (debug)
- printf("Starting Datum PTS unit %d\n", unit);
-#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
- if (debug)
- printf("Opening RS232 port with file descriptor %d\n",
- datum_pts->PTS_fd);
-#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 this driver cannot be initialized. You can change this
- ** if you want by editing this source. Please give the changes back to the
- ** ntp 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
-
- msyslog(LOG_ERR, "Datum_PTS: Termios not supported in this driver");
- (void)close(datum_pts->PTS_fd);
-
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
-
- return 0;
-
-#endif
-
- /*
- ** Initialize the ntpd IO structure
- */
-
- datum_pts->peer = peer;
- 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
- if (debug)
- printf("Problem adding clock\n");
-#endif
-
- msyslog(LOG_ERR, "Datum_PTS: Problem adding clock");
- (void)close(datum_pts->PTS_fd);
-
- return 0;
- }
-
- /*
- ** 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(
- int unit,
- struct peer *peer
- )
-{
- int i,j;
- struct datum_pts_unit **temp_datum_pts_unit;
-
-#ifdef DEBUG_DATUM_PTC
- if (debug)
- printf("Shutdown Datum PTS\n");
-#endif
-
- msyslog(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
- if (debug)
- printf("Error, could not shut down unit %d\n",unit);
-#endif
-
- msyslog(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(
- int unit,
- struct peer *peer
- )
-{
- int i;
- int unit_index;
- int error_code;
- struct datum_pts_unit *datum_pts;
-
-#ifdef DEBUG_DATUM_PTC
- if (debug)
- printf("Poll Datum PTS\n");
-#endif
-
- /*
- ** Find the right unit and send out a time request once it is found.
- */
-
- unit_index = -1;
- for (i=0; i<nunits; i++) {
- if (datum_pts_unit[i]->unit == 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 (unit_index == -1) {
-
-#ifdef DEBUG_DATUM_PTC
- if (debug)
- printf("Error, could not poll unit %d\n",unit);
-#endif
-
- msyslog(LOG_ERR, "Datum_PTS: Could not poll unit %d",unit);
- return;
-
- }
-
-}
-
-
-/*......................................................................*/
-/* datum_pts_control - not used */
-/*......................................................................*/
-
-static void
-datum_pts_control(
- int unit,
- struct refclockstat *in,
- struct refclockstat *out,
- struct peer *peer
- )
-{
-
-#ifdef DEBUG_DATUM_PTC
- if (debug)
- printf("Control Datum PTS\n");
-#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(void)
-{
-
- /* */
- /*...... 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).
- */
-
-#ifdef DEBUG_DATUM_PTC
- if (debug)
- printf("Init Datum PTS\n");
-#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(
- int unit,
- register struct refclockbug *bug,
- register struct peer *peer
- )
-{
-
-#ifdef DEBUG_DATUM_PTC
- if (debug)
- printf("Buginfo Datum PTS\n");
-#endif
-
-}
-
-
-/*......................................................................*/
-/* datum_pts_receive - receive the time buffer that was read in */
-/* by the ntpd 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 ntpd clock_receive() routine which causes the systems */
-/* clock to be updated (several layers down). */
-/*......................................................................*/
-
-static void
-datum_pts_receive(
- 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;
-#ifdef DEBUG_DATUM_PTC
- double dispersion;
-#endif
- int goodtime;
- /*double doffset;*/
-
- /*
- ** 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
- if (debug)
- printf("Receive Datum PTS: %d bytes\n", dpend);
-#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
- ** ntpd, 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
- if (debug)
- printf("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);
-#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) ) {
-
- datum_pts->lastref.l_uf = 0;
- 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
- if (debug)
- {
- printf("Error: bad clocktime\n");
- printf("GMT %d, lastrec %d, yearstart %d, lastref %d\n",
- tzoff,
- datum_pts->lastrec.l_ui,
- datum_pts->yearstart,
- datum_pts->lastref.l_ui);
- }
-#endif
-
- msyslog(LOG_ERR, "Datum_PTS: Bad clocktime");
-
- return;
-
- }else{
-
-#ifdef DEBUG_DATUM_PTC
- if (debug)
- printf("Good clocktime\n");
-#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 */
-
-#ifdef DEBUG_DATUM_PTC
- dispersion = DATUM_DISPERSION; /* set the dispersion to 0 */
- ftimerr = dispersion;
- ftimerr /= (1024.0 * 64.0);
- if (debug)
- printf("dispersion = %d, %f\n", dispersion, ftimerr);
-#endif
-
- /*
- ** Pass the new time to ntpd 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.
- */
- /*LFPTOD(&tstmp, doffset);*/
- datum_pts->lastref = datum_pts->lastrec;
- refclock_receive(datum_pts->peer);
-
- /*
- ** Compute sigma squared (not used currently). Maybe later, this could be
- ** used for the dispersion estimate. The problem is that ntpd 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
- if (debug)
- printf("Time error = %f seconds\n", ftimerr);
-#endif
-
-#if defined(DEBUG_DATUM_PTC) || defined(LOG_TIME_ERRORS)
- if (debug)
- printf("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);
-#endif
-
-}
-#else
-int refclock_datum_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_dumbclock.c b/contrib/ntp/ntpd/refclock_dumbclock.c
deleted file mode 100644
index 2788649..0000000
--- a/contrib/ntp/ntpd/refclock_dumbclock.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * refclock_dumbclock - clock driver for a unknown time distribution system
- * that only provides hh:mm:ss (in local time, yet!).
- */
-
-/*
- * Must interpolate back to local time. Very annoying.
- */
-#define GET_LOCALTIME
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(SYS_WINNT)
-#undef close
-#define close closesocket
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_DUMBCLOCK)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * This driver supports a generic dumb clock that only outputs hh:mm:ss,
- * in local time, no less.
- *
- * Input format:
- *
- * hh:mm:ss <cr>
- *
- * hh:mm:ss -- what you'd expect, with a 24 hour clock. (Heck, that's the only
- * way it could get stupider.) We take time on the <cr>.
- *
- * The original source of this module was the WWVB module.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/dumbclock%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-13) /* precision assumed (about 100 us) */
-#define REFID "dumbclock" /* reference ID */
-#define DESCRIPTION "Dumb clock" /* WRU */
-
-
-/*
- * Insanity check. Since the time is local, we need to make sure that during midnight
- * transitions, we can convert back to Unix time. If the conversion results in some number
- * worse than this number of seconds away, assume the next day and retry.
- */
-#define INSANE_SECONDS 3600
-
-/*
- * Dumb clock control structure
- */
-struct dumbclock_unit {
- 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 */
- struct tm ymd; /* struct tm for y/m/d only */
-};
-
-/*
- * Function prototypes
- */
-static int dumbclock_start P((int, struct peer *));
-static void dumbclock_shutdown P((int, struct peer *));
-static void dumbclock_receive P((struct recvbuf *));
-#if 0
-static void dumbclock_poll P((int, struct peer *));
-#endif
-
-/*
- * Transfer vector
- */
-struct refclock refclock_dumbclock = {
- dumbclock_start, /* start up driver */
- dumbclock_shutdown, /* shut down driver */
- noentry, /* poll the driver -- a nice fabrication */
- noentry, /* not used */
- noentry, /* not used */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-
-/*
- * dumbclock_start - open the devices and initialize data for processing
- */
-static int
-dumbclock_start(
- int unit,
- struct peer *peer
- )
-{
- register struct dumbclock_unit *up;
- struct refclockproc *pp;
- int fd;
- char device[20];
- struct tm *tm_time_p;
- time_t now;
-
- /*
- * Open serial port. Don't bother with CLK line discipline, since
- * it's not available.
- */
- (void)sprintf(device, DEVICE, unit);
-#ifdef DEBUG
- if (debug)
- printf ("starting Dumbclock with device %s\n",device);
-#endif
- fd = refclock_open(device, SPEED232, 0);
- if (fd < 0)
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- up = (struct dumbclock_unit *)emalloc(sizeof(struct dumbclock_unit));
- if (up == NULL) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct dumbclock_unit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = dumbclock_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);
- }
-
-
- time(&now);
-#ifdef GET_LOCALTIME
- tm_time_p = localtime(&now);
-#else
- tm_time_p = gmtime(&now);
-#endif
- if (tm_time_p)
- {
- up->ymd = *tm_time_p;
- }
- else
- {
- return 0;
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- return (1);
-}
-
-
-/*
- * dumbclock_shutdown - shut down the clock
- */
-static void
-dumbclock_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct dumbclock_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct dumbclock_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * dumbclock_receive - receive data from the serial interface
- */
-static void
-dumbclock_receive(
- struct recvbuf *rbufp
- )
-{
- struct dumbclock_unit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- l_fp trtmp; /* arrival timestamp */
- int hours; /* hour-of-day */
- int minutes; /* minutes-past-the-hour */
- int seconds; /* seconds */
- int temp; /* int temp */
- int got_good; /* got a good time flag */
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct dumbclock_unit *)pp->unitptr;
- temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
-
- if (temp == 0) {
- if (up->tcswitch == 0) {
- up->tcswitch = 1;
- up->laststamp = trtmp;
- } else
- up->tcswitch = 0;
- return;
- }
- pp->lencode = (u_short)temp;
- pp->lastrec = up->laststamp;
- up->laststamp = trtmp;
- up->tcswitch = 1;
-
-#ifdef DEBUG
- if (debug)
- printf("dumbclock: timecode %d %s\n",
- pp->lencode, pp->a_lastcode);
-#endif
-
- /*
- * We get down to business. Check the timecode format...
- */
- got_good=0;
- if (sscanf(pp->a_lastcode,"%02d:%02d:%02d",
- &hours,&minutes,&seconds) == 3)
- {
- struct tm *gmtp;
- struct tm *lt_p;
- time_t asserted_time; /* the SPM time based on the composite time+date */
- struct tm asserted_tm; /* the struct tm of the same */
- int adjyear;
- int adjmon;
- int reality_delta;
- time_t now;
-
-
- /*
- * Convert to GMT for sites that distribute localtime. This
- * means we have to figure out what day it is. Easier said
- * than done...
- */
-
- asserted_tm.tm_year = up->ymd.tm_year;
- asserted_tm.tm_mon = up->ymd.tm_mon;
- asserted_tm.tm_mday = up->ymd.tm_mday;
- asserted_tm.tm_hour = hours;
- asserted_tm.tm_min = minutes;
- asserted_tm.tm_sec = seconds;
- asserted_tm.tm_isdst = -1;
-
-#ifdef GET_LOCALTIME
- asserted_time = mktime (&asserted_tm);
- time(&now);
-#else
-#include "GMT unsupported for dumbclock!"
-#endif
- reality_delta = asserted_time - now;
-
- /*
- * We assume that if the time is grossly wrong, it's because we got the
- * year/month/day wrong.
- */
- if (reality_delta > INSANE_SECONDS)
- {
- asserted_time -= SECSPERDAY; /* local clock behind real time */
- }
- else if (-reality_delta > INSANE_SECONDS)
- {
- asserted_time += SECSPERDAY; /* local clock ahead of real time */
- }
- lt_p = localtime(&asserted_time);
- if (lt_p)
- {
- up->ymd = *lt_p;
- }
- else
- {
- refclock_report (peer, CEVNT_FAULT);
- return;
- }
-
- if ((gmtp = gmtime (&asserted_time)) == NULL)
- {
- refclock_report (peer, CEVNT_FAULT);
- return;
- }
- adjyear = gmtp->tm_year+1900;
- adjmon = gmtp->tm_mon+1;
- pp->day = ymd2yd (adjyear, adjmon, gmtp->tm_mday);
- pp->hour = gmtp->tm_hour;
- pp->minute = gmtp->tm_min;
- pp->second = gmtp->tm_sec;
-#ifdef DEBUG
- if (debug)
- printf ("time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
- adjyear,adjmon,gmtp->tm_mday,pp->hour,pp->minute,
- pp->second);
-#endif
-
- got_good=1;
- }
-
- if (!got_good)
- {
- if (up->linect > 0)
- up->linect--;
- else
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- up->lasthour = (u_char)pp->hour;
-}
-
-#if 0
-/*
- * dumbclock_poll - called by the transmit procedure
- */
-static void
-dumbclock_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct dumbclock_unit *up;
- struct refclockproc *pp;
- char pollchar;
-
- /*
- * Time to poll the clock. The Chrono-log clock is supposed to
- * respond to a 'T' by returning a timecode in the format(s)
- * specified above. Ours does (can?) not, but this seems to be
- * an installation-specific problem. This code is dyked out,
- * but may be re-enabled if anyone ever finds a Chrono-log that
- * actually listens to this command.
- */
-#if 0
- pp = peer->procptr;
- up = (struct dumbclock_unit *)pp->unitptr;
- if (peer->reach == 0)
- refclock_report(peer, CEVNT_TIMEOUT);
- if (up->linect > 0)
- pollchar = 'R';
- else
- pollchar = 'T';
- if (write(pp->io.fd, &pollchar, 1) != 1)
- refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
-#endif
-}
-#endif
-
-#else
-int refclock_dumbclock_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_fg.c b/contrib/ntp/ntpd/refclock_fg.c
deleted file mode 100644
index ebcf1b5..0000000
--- a/contrib/ntp/ntpd/refclock_fg.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * refclock_fg - clock driver for the Forum Graphic GPS datating station
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_FG)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-/*
- * This driver supports the Forum Graphic GPS dating station.
- * More information about FG GPS is available on http://www.forumgraphic.com
- * Contact das@amt.ru for any question about this driver.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/fgclock%d"
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#define REFID "GPS"
-#define DESCRIPTION "Forum Graphic GPS dating station"
-#define LENFG 26 /* timecode length */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-
-/*
- * Function prototypes
- */
-static int fg_init P((int));
-static int fg_start P((int, struct peer *));
-static void fg_shutdown P((int, struct peer *));
-static void fg_poll P((int, struct peer *));
-static void fg_receive P((struct recvbuf *));
-
-/*
- * Forum Graphic unit control structure
- */
-
-struct fgunit {
- int pollnum; /* Use peer.poll instead? */
- int status; /* Hug to check status information on GPS */
- int y2kwarn; /* Y2K bug */
-};
-
-/*
- * Queries definition
- */
-static char fginit[] = { 0x10, 0x48, 0x10, 0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static char fgdate[] = { 0x10, 0x44, 0x10, 0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-/*
- * Transfer vector
- */
-struct refclock refclock_fg = {
- fg_start, /* start up driver */
- fg_shutdown, /* shut down driver */
- fg_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-/*
- * fg_init - Initialization of FG GPS.
- */
-
-static int
-fg_init(
- int fd
- )
-{
- if (write(fd, fginit, LENFG) != LENFG)
- return 0;
-
- return (1);
-
-}
-
-/*
- * fg_start - open the device and initialize data for processing
- */
-static int
-fg_start(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct fgunit *up;
- int fd;
- char device[20];
-
-
- /*
- * Open device file for reading.
- */
- (void)sprintf(device, DEVICE, unit);
-
-#ifdef DEBUG
- if (debug)
- printf ("starting FG with device %s\n",device);
-#endif
- if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
-
- if (!(up = (struct fgunit *)
- emalloc(sizeof(struct fgunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct fgunit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = fg_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
- (void) close(fd);
- return (0);
- }
-
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 3);
- up->pollnum = 0;
-
- /*
- * Setup dating station to use GPS receiver.
- * GPS receiver should work before this operation.
- */
- if(!fg_init(pp->io.fd))
- refclock_report(peer, CEVNT_FAULT);
-
- return (1);
-}
-
-
-/*
- * fg_shutdown - shut down the clock
- */
-static void
-fg_shutdown(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct fgunit *up;
-
- pp = peer->procptr;
- up = (struct fgunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * fg_poll - called by the transmit procedure
- */
-static void
-fg_poll(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
-
- /*
- * Time to poll the clock. The FG clock responds to a
- * "<DLE>D<DLE><CR>" 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.
- */
-
- if (write(pp->io.fd, fgdate, LENFG) != LENFG)
- refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
-
- if (peer->burst > 0)
- return;
- /*
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- */
- peer->burst = NSTAGE;
-
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-
-
- return;
-
-}
-
-/*
- * fg_receive - receive data from the serial interface
- */
-static void
-fg_receive(
- struct recvbuf *rbufp
- )
-{
- struct refclockproc *pp;
- struct fgunit *up;
- struct peer *peer;
- char *bpt;
-
- /*
- * Initialize pointers and read the timecode and timestamp
- * We can't use gtlin function because we need bynary data in buf */
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct fgunit *)pp->unitptr;
-
- /*
- * Below hug to implement receiving of status information
- */
- if(!up->pollnum)
- {
- up->pollnum++;
- return;
- }
-
-
- if (rbufp->recv_length < (LENFG-2))
- {
- refclock_report(peer, CEVNT_BADREPLY);
- return; /* The reply is invalid discard it. */
- }
-
- /* Below I trying to find a correct reply in buffer.
- * Sometime GPS reply located in the beginnig of buffer,
- * sometime you can find it with some offset.
- */
-
- bpt = (char *)rbufp->recv_space.X_recv_buffer;
- while(*bpt != '')
- bpt++;
-
-#define BP2(x) ( bpt[x] & 15 )
-#define BP1(x) (( bpt[x] & 240 ) >> 4)
-
- pp->year = BP1(2)*10 + BP2(2);
-
- if(pp->year == 94)
- {
- refclock_report(peer, CEVNT_BADREPLY);
- if(!fg_init(pp->io.fd))
- refclock_report(peer, CEVNT_FAULT);
- return;
- /* GPS is just powered up. The date is invalid -
- discarding it. Initilize GPS one more time */
- /* Sorry - this driver will broken in 2094 ;) */
- }
-
- if (pp->year < 99)
- pp->year += 100;
-
- pp->year += 1900;
- pp->day = 100 * BP2(3) + 10 * BP1(4) + BP2(4);
-
-/*
- After Jan, 10 2000 Forum Graphic GPS receiver had a very strange
- benahour. It doubles day number for an hours in replys after 10:10:10 UTC
- and doubles min every hour at HH:10:ss for a minute.
- Hope it is a problem of my unit only and not a Y2K problem of FG GPS.
- Below small code to avoid such situation.
-*/
- if(up->y2kwarn > 10)
- pp->hour = BP1(6)*10 + BP2(6);
- else
- pp->hour = BP1(5)*10 + BP2(5);
-
- if((up->y2kwarn > 10) && (pp->hour == 10))
- {
- pp->minute = BP1(7)*10 + BP2(7);
- pp->second = BP1(8)*10 + BP2(8);
- pp->nsec = (BP1(9)*10 + BP2(9)) * 1000000;
- pp->nsec += BP1(10) * 1000;
- } else {
- pp->hour = BP1(5)*10 + BP2(5);
- pp->minute = BP1(6)*10 + BP2(6);
- pp->second = BP1(7)*10 + BP2(7);
- pp->nsec = (BP1(8)*10 + BP2(8)) * 1000000;
- pp->nsec += BP1(9) * 1000;
- }
-
- if((pp->hour == 10) && (pp->minute == 10))
- {
- up->y2kwarn++;
- }
-
- sprintf(pp->a_lastcode, "%d %d %d %d %d", pp->year, pp->day, pp->hour, pp->minute, pp->second);
- pp->lencode = strlen(pp->a_lastcode);
- /*get_systime(&pp->lastrec);*/
-
-#ifdef DEBUG
- if (debug)
- printf ("fg: time is %04d/%03d %02d:%02d:%02d UTC\n",
- pp->year, pp->day, pp->hour, pp->minute, pp->second);
-#endif
-
- if (peer->stratum <= 1)
- peer->refid = pp->refid;
- pp->disp = (10e-6);
- pp->lastrec = rbufp->recv_time; /* Is it better than get_systime()? */
- /* pp->leap = LEAP_NOWARNING; */
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
-
- if (!refclock_process(pp))
- refclock_report(peer, CEVNT_BADTIME);
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- return;
-}
-
-
-#else
-int refclock_fg_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_gpsvme.c b/contrib/ntp/ntpd/refclock_gpsvme.c
deleted file mode 100644
index a7fcf5f..0000000
--- a/contrib/ntp/ntpd/refclock_gpsvme.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * refclock_gpsvme.c NTP clock driver for the TrueTime GPS-VME
- * R. Schmidt, Time Service, US Naval Obs. res@tuttle.usno.navy.mil
- *
- * The refclock type has been defined as 16 (until new id assigned).
- * These DEFS are included in the Makefile:
- * DEFS= -DHAVE_TERMIOS -DSYS_HPUX=9
- * DEFS_LOCAL= -DREFCLOCK
- * CLOCKDEFS= -DGPSVME
- * The file map_vme.c does the VME memory mapping, and includes vme_init().
- * map_vme.c is HP-UX specific, because HPUX cannot mmap() device files! Boo!
- * The file gps.h provides TrueTime register info.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_GPSVME)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <syslog.h>
-#include <ctype.h>
-
-#include "gps.h"
-#include "/etc/conf/h/io.h"
-
-/* GLOBAL STUFF BY RES */
-
-#include <time.h>
-
-#define PRIO 120 /* set the realtime priority */
-#define NREGS 7 /* number of registers we will use */
-
-extern int init_vme(); /* This is just a call to map_vme() */
- /* It doesn't have to be extern */
- /* the map_vme() call */
-extern unsigned short *greg[NREGS]; /* made extern to avoid being in both map_vme.c and this file */
-extern void *gps_base; /* mjb lmco 12/20/99 */
-
-extern caddr_t map_vme ();
-extern void unmap_vme(); /* Unmaps the VME space */
-
-struct vmedate { /* structure needed by ntp */
- unsigned short year; /* *tptr is a pointer to this */
- unsigned short doy;
- unsigned short hr;
- unsigned short mn;
- unsigned short sec;
- unsigned long frac;
- unsigned short status;
-};
-
-struct vmedate *get_gpsvme_time();
-struct vmedate * time_vme; /* added to emulate LM refclock_gpsvme
- (Made global per RES suggestion to fix mem leak DW lmco) mjb lmco 12/15/99 */
-
-/* END OF STUFF FROM RES */
-
-/*
- * Definitions
- */
-#define MAXUNITS 2 /* max number of VME units */
-#define BMAX 50 /* timecode buffer length */
-
-/*
- * VME interface parameters.
- */
-#define VMEPRECISION (-21) /* precision assumed (1 us) */
-#define USNOREFID "USNO\0" /* Or whatever? */
-#define VMEREFID "GPS" /* reference id */
-#define VMEDESCRIPTION "GPS" /* who we are */
-#define VMEHSREFID 0x7f7f1001 /* 127.127.16.01 refid hi strata */
-
-/* I'm using clock type 16 until one is assigned */
-/* This is set also in vme_control, below */
-
-
-#define GMT 0 /* hour offset from Greenwich */
-
-/*
- * 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 (void);
-static int vme_start (int, struct peer *);
-static void vme_shutdown (int, struct peer *);
-static void vme_report_event (struct vmeunit *, int);
-static void vme_receive (struct recvbuf *);
-static void vme_poll (int unit, struct peer *);
-static void vme_control (int, struct refclockstat *, struct refclockstat *, struct peer *);
-static void vme_buginfo (int, struct refclockbug *, struct peer *);
-
-/*
- * Transfer vector
- */
-struct refclock refclock_gpsvme = {
- 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(void)
-{
- 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(
- u_int unit,
- struct peer *peer
- )
-{
- register struct vmeunit *vme;
- register int i;
- int dummy;
- char vmedev[20];
-
- /*
- * Check configuration info.
- */
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_start: unit %d invalid", unit);
- return (0);
- }
- if (unitinuse[unit]) {
- msyslog(LOG_ERR, "vme_start: unit %d in use", unit);
- return (0);
- }
-
- /*
- * Open VME device
- */
-#ifdef DEBUG
-
- printf("Opening VME DEVICE \n");
-#endif
- init_vme(); /* This is in the map_vme.c external file */
-
- /*
- * 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));
- time_vme = (struct vmedate *)malloc(sizeof(struct vmedate)); /* Added to emulate LM's refclock_gpsvme
- (added to fix mem lead DW lmco) mjb lmco 12/22/99 */
- }
- }
- 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.
- */
- peer->precision = VMEPRECISION;
- peer->stratum = stratumtouse[unit];
- memcpy( (char *)&peer->refid, USNOREFID,4);
-
- /* peer->refid = htonl(VMEHSREFID); */
-
- unitinuse[unit] = 1;
- return (1);
-}
-
-
-/*
- * vme_shutdown - shut down a VME clock
- */
-static void
-vme_shutdown(
- int unit
- )
-{
- register struct vmeunit *vme;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- msyslog(LOG_ERR, "vme_shutdown: unit %d not in use", unit);
- return;
- }
-
- /*
- * Tell the I/O module to turn us off. We're history.
- */
- unmap_vme();
- 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(
- 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;
- msyslog(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(
- struct recvbuf *rbufp
- )
-{
-}
-
-/*
- * vme_poll - called by the transmit procedure
- */
-static void
-vme_poll(
- int unit,
- struct peer *peer
- )
-{
- struct vmedate *tptr;
- struct vmeunit *vme;
- l_fp tstmp;
- time_t tloc;
- struct tm *tadr;
- long ltemp;
-
-
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- msyslog(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_gpsvme_time()) == NULL ) {
- vme_report_event(vme, CEVNT_BADREPLY);
- return;
- }
-
- get_systime(&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->nsec = tptr->frac * 1000;
-
-#ifdef DEBUG
- if (debug)
- printf("vme: %3d %02d:%02d:%02d.%06ld %1x\n",
- vme->day, vme->hour, vme->minute, vme->second,
- vme->nsec, 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);
- msyslog(LOG_ERR, "refclock_gpsvme: bad data!!");
- return;
- }
- vme->lastref.l_uf = 0;
- DTOLFP(vme->nsec / 1e9, &ltemp);
- L_ADD(&vme->lastrec, &ltemp);
- tstmp = vme->lastref;
-
- L_SUB(&tstmp, &vme->lastrec);
- vme->coderecv++;
-
- L_ADD(&tstmp, &(fudgefactor[vme->unit]));
- vme->lastref = vme->lastrec;
- refclock_receive(vme->peer);
-}
-
-/*
- * vme_control - set fudge factors, return statistics2
- */
-static void
-vme_control(
- u_int unit,
- struct refclockstat *in,
- struct refclockstat *out,
- struct peer * peer
- )
-{
- register struct vmeunit *vme;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_control: unit %d invalid)", unit);
- return;
- }
-
- if (in != 0) {
- if (in->haveflags & CLK_HAVETIME1)
- DTOLFP(in->fudgetime1, &fudgefactor[unit]); /* added mjb lmco 12/20/99 */
-
- 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)
- memcpy( (char *)&peer->refid, USNOREFID,4);
- else
- peer->refid = htonl(VMEHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
- sloppyclockflag[unit] = in->flags & CLK_FLAG1;
- }
- }
-
- if (out != 0) {
- out->type = 16; /*set by RES SHOULD BE CHANGED */
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1;
- out->clockdesc = VMEDESCRIPTION;
- LFPTOD(&fudgefactor[unit], out->fudgetime1); /* added mjb lmco 12/20/99 */
-
- out ->fudgetime2 = 0; /* should do what above was supposed to do mjb lmco 12/20/99 */
-
- out->fudgeval1 = (long)stratumtouse[unit]; /*changed from above LONG was not
- defined mjb lmco 12/15/99 */
-
- out->fudgeval2 = 0;
- out->flags = sloppyclockflag[unit];
- if (unitinuse[unit]) {
- vme = vmeunits[unit];
- out->lencode = vme->lencode;
- out->p_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->p_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(
- int unit,
- register struct refclockbug *bug,
- struct peer * peer
- )
-{
- register struct vmeunit *vme;
-
- if (unit >= MAXUNITS) {
- msyslog(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->nsec;
- bug->values[9] = vme->yearstart;
- bug->stimes = 0x1c;
- bug->times[0] = vme->lastref;
- bug->times[1] = vme->lastrec;
-}
-/* -------------------------------------------------------*/
-/* get_gpsvme_time() */
-/* R. Schmidt, USNO, 1995 */
-/* It's ugly, but hey, it works and its free */
-
-#include "gps.h" /* defines for TrueTime GPS-VME */
-
-#define PBIAS 193 /* 193 microsecs to read the GPS experimentally found */
-
-struct vmedate *
-get_gpsvme_time(void)
-{
- extern struct vmedate *time_vme;
- unsigned short set, hr, min, sec, ums, hms, status;
- int ret;
- char ti[3];
-
- long tloc ;
- time_t mktime(),time();
- struct tm *gmtime(), *gmt;
- char *gpsmicro;
- gpsmicro = (char *) malloc(7);
-
- *greg = (unsigned short *)malloc(sizeof(short) * NREGS);
-
-
- /* reference the freeze command address general register 1 */
- set = *greg[0];
- /* read the registers : */
- /* get year */
- time_vme->year = (unsigned short) *greg[6];
- /* Get doy */
- time_vme->doy = (unsigned short) (*greg[5] & MASKDAY);
- /* Get hour */
- time_vme->hr = (unsigned short) ((*greg[4] & MASKHI) >>8);
- /* Get minutes */
- time_vme->mn = (unsigned short) (*greg[4] & MASKLO);
- /* Get seconds */
- time_vme->sec = (unsigned short) (*greg[3] & MASKHI) >>8;
- /* get microseconds in 2 parts and put together */
- ums = *greg[2];
- hms = *greg[3] & MASKLO;
-
- time_vme->status = (unsigned short) *greg[5] >>13;
-
- /* reference the unfreeze command address general register 1 */
- set = *greg[1];
-
- sprintf(gpsmicro,"%2.2x%4.4x\0", hms, ums);
- time_vme->frac = (u_long) gpsmicro;
-
- /* unmap_vme(); */
-
- if (!status) {
- return (NULL); /* fixed mjb lmco 12/20/99 */
- }
- else
- return (time_vme);
-}
-
-#else
-int refclock_gpsvme_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_heath.c b/contrib/ntp/ntpd/refclock_heath.c
deleted file mode 100644
index c16cef3..0000000
--- a/contrib/ntp/ntpd/refclock_heath.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * refclock_heath - clock driver for Heath GC-1000 and and GC-1000 II
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_HEATH)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* not HAVE_SYS_IOCTL_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.
- *
- * There are two GC-1000 versions supported by this driver. The original
- * GC-1000 with RS-232 output first appeared in 1983, but dissapeared
- * from the market a few years later. The GC-1000 II with RS-232 output
- * first appeared circa 1990, but apparently is no longer manufactured.
- * The two models differ considerably, both in interface and commands.
- * The GC-1000 has a pseudo-bipolar timecode output triggered by a RTS
- * transition. The timecode includes both the day of year and time of
- * day. The GC-1000 II has a true bipolar output and a complement of
- * single character commands. The timecode includes only the time of
- * day.
- *
- * GC-1000
- *
- * The internal DIPswitches should be set to operate in MANUAL mode. The
- * external DIPswitches should be set to GMT and 24-hour format.
- *
- * 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.
- *
- * GC-1000 II
- *
- * Commands consist of a single letter and are case sensitive. When
- * enterred in lower case, a description of the action performed is
- * displayed. When enterred in upper case the action is performed.
- * Following is a summary of descriptions as displayed by the clock:
- *
- * The clock responds with a command The 'A' command returns an ASCII
- * local time string: HH:MM:SS.T xx<CR>, where
- *
- * HH = hours
- * MM = minutes
- * SS = seconds
- * T = tenths-of-seconds
- * xx = 'AM', 'PM', or ' '
- * <CR> = carriage return
- *
- * The 'D' command returns 24 pairs of bytes containing the variable
- * divisor value at the end of each of the previous 24 hours. This
- * allows the timebase trimming process to be observed. UTC hour 00 is
- * always returned first. The first byte of each pair is the high byte
- * of (variable divisor * 16); the second byte is the low byte of
- * (variable divisor * 16). For example, the byte pair 3C 10 would be
- * returned for a divisor of 03C1 hex (961 decimal).
- *
- * The 'I' command returns: | TH | TL | ER | DH | DL | U1 | I1 | I2 | ,
- * where
- *
- * TH = minutes since timebase last trimmed (high byte)
- * TL = minutes since timebase last trimmed (low byte)
- * ER = last accumulated error in 1.25 ms increments
- * DH = high byte of (current variable divisor * 16)
- * DL = low byte of (current variable divisor * 16)
- * U1 = UT1 offset (/.1 s): | + | 4 | 2 | 1 | 0 | 0 | 0 | 0 |
- * I1 = information byte 1: | W | C | D | I | U | T | Z | 1 | ,
- * where
- *
- * W = set by WWV(H)
- * C = CAPTURE LED on
- * D = TRIM DN LED on
- * I = HI SPEC LED on
- * U = TRIM UP LED on
- * T = DST switch on
- * Z = UTC switch on
- * 1 = UT1 switch on
- *
- * I2 = information byte 2: | 8 | 8 | 4 | 2 | 1 | D | d | S | ,
- * where
- *
- * 8, 8, 4, 2, 1 = TIME ZONE switch settings
- * D = DST bit (#55) in last-received frame
- * d = DST bit (#2) in last-received frame
- * S = clock is in simulation mode
- *
- * The 'P' command returns 24 bytes containing the number of frames
- * received without error during UTC hours 00 through 23, providing an
- * indication of hourly propagation. These bytes are updated each hour
- * to reflect the previous 24 hour period. UTC hour 00 is always
- * returned first.
- *
- * The 'T' command returns the UTC time: | HH | MM | SS | T0 | , where
- * HH = tens-of-hours and hours (packed BCD)
- * MM = tens-of-minutes and minutes (packed BCD)
- * SS = tens-of-seconds and seconds (packed BCD)
- * T = tenths-of-seconds (BCD)
- *
- * 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 PRECISION (-4) /* precision assumed (about 100 ms) */
-#define REFID "WWV\0" /* reference ID */
-#define DESCRIPTION "Heath GC-1000 Most Accurate Clock" /* WRU */
-
-#define LENHEATH1 23 /* min timecode length */
-#define LENHEATH2 13 /* min timecode length */
-
-/*
- * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
- * leap.
- */
-static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/*
- * Baud rate table. The GC-1000 supports 1200, 2400 and 4800; the
- * GC-1000 II supports only 9600.
- */
-static int speed[] = {B1200, B2400, B4800, B9600};
-
-/*
- * 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(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- int fd;
- char device[20];
-
- /*
- * Open serial port
- */
- (void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, speed[peer->ttl & 0x3], 0)))
- return (0);
- 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);
- return (0);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- peer->burst = NSTAGE;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- return (1);
-}
-
-
-/*
- * heath_shutdown - shut down the clock
- */
-static void
-heath_shutdown(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
- io_closeclock(&pp->io);
-}
-
-
-/*
- * heath_receive - receive data from the serial interface
- */
-static void
-heath_receive(
- struct recvbuf *rbufp
- )
-{
- 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;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
- &trtmp);
-
- /*
- * 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.
- */
- switch (pp->lencode) {
-
- /*
- * GC-1000 timecode format: "hh:mm:ss.f AM mm/dd/yy"
- * GC-1000 II timecode format: "hh:mm:ss.f "
- */
- case LENHEATH1:
- if (sscanf(pp->a_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;
- }
- break;
-
- /*
- * GC-1000 II timecode format: "hh:mm:ss.f "
- */
- case LENHEATH2:
- if (sscanf(pp->a_lastcode, "%2d:%2d:%2d.%c", &pp->hour,
- &pp->minute, &pp->second, &dsec) != 4) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- break;
-
- default:
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * 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.
- */
- 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((int)dsec))
- pp->leap = LEAP_NOTINSYNC;
- else {
- pp->nsec = (dsec - '0') * 100000000;
- pp->leap = LEAP_NOWARNING;
- }
- if (!refclock_process(pp))
- refclock_report(peer, CEVNT_BADTIME);
-}
-
-
-/*
- * heath_poll - called by the transmit procedure
- */
-static void
-heath_poll(
- int unit,
- struct peer *peer
- )
-{
- 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.
- * Apparently, the radio takes about a second to make up its
- * mind to send a timecode, so the receive timestamp is
- * worthless.
- */
- pp = peer->procptr;
-
- /*
- * We toggle the RTS modem control lead (GC-1000) and sent a T
- * (GC-1000 II) 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);
- get_systime(&pp->lastrec);
- if (write(pp->io.fd, "T", 1) != 1)
- refclock_report(peer, CEVNT_FAULT);
- ioctl(pp->io.fd, TIOCMBIS, (char *)&bits);
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("heath: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
- peer->burst = MAXSTAGE;
- pp->polls++;
-}
-
-#else
-int refclock_heath_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_hopfpci.c b/contrib/ntp/ntpd/refclock_hopfpci.c
deleted file mode 100644
index 1b02319..0000000
--- a/contrib/ntp/ntpd/refclock_hopfpci.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * refclock_hopfpci.c
- *
- * - clock driver for hopf 6039 PCI board (GPS or DCF77)
- * Bernd Altmeier altmeier@atlsoft.de
- *
- * latest source and further information can be found at:
- * http://www.ATLSoft.de/ntp
- *
- * In order to run this driver you have to install and test
- * the PCI-board driver for your system first.
- *
- * On Linux/UNIX
- *
- * The driver attempts to open the device /dev/hopf6039 .
- * The device entry will be made by the installation process of
- * the kernel module for the PCI-bus board. The driver sources
- * belongs to the delivery equipment of the PCI-board.
- *
- * On Windows NT/2000
- *
- * The driver attempts to open the device by calling the function
- * "OpenHopfDevice()". This function will be installed by the
- * Device Driver for the PCI-bus board. The driver belongs to the
- * delivery equipment of the PCI-board.
- *
- *
- * Start 21.03.2000 Revision: 01.20
- * changes 22.12.2000 Revision: 01.40 flag1 = 1 sync even if Quarz
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_HOPF_PCI)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#undef fileno
-#include <ctype.h>
-#undef fileno
-
-#ifndef SYS_WINNT
-# include <sys/ipc.h>
-# include <sys/ioctl.h>
-# include <assert.h>
-# include <unistd.h>
-# include <stdio.h>
-# include "hopf6039.h"
-#else
-# include "hopf_PCI_io.h"
-#endif
-
-/*
- * hopfpci interface definitions
- */
-#define PRECISION (-10) /* precision assumed (1 ms) */
-#define REFID "hopf" /* reference ID */
-#define DESCRIPTION "hopf Elektronik PCI radio board"
-
-#define NSAMPLES 3 /* stages of median filter */
-#ifndef SYS_WINNT
-# define DEVICE "/dev/hopf6039" /* device name inode*/
-#else
-# define DEVICE "hopf6039" /* device name WinNT */
-#endif
-
-#define LEWAPWAR 0x20 /* leap second warning bit */
-
-#define HOPF_OPMODE 0xC0 /* operation mode mask */
-#define HOPF_INVALID 0x00 /* no time code available */
-#define HOPF_INTERNAL 0x40 /* internal clock */
-#define HOPF_RADIO 0x80 /* radio clock */
-#define HOPF_RADIOHP 0xC0 /* high precision radio clock */
-
-
-/*
- * hopfclock unit control structure.
- */
-struct hopfclock_unit {
- short unit; /* NTP refclock unit number */
- char leap_status; /* leap second flag */
-};
-int fd; /* file descr. */
-
-/*
- * Function prototypes
- */
-static int hopfpci_start (int, struct peer *);
-static void hopfpci_shutdown (int, struct peer *);
-static void hopfpci_poll (int unit, struct peer *);
-
-/*
- * Transfer vector
- */
-struct refclock refclock_hopfpci = {
- hopfpci_start, /* start up driver */
- hopfpci_shutdown, /* shut down driver */
- hopfpci_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-/*
- * hopfpci_start - attach to hopf PCI board 6039
- */
-static int
-hopfpci_start(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct hopfclock_unit *up;
-
- /*
- * Allocate and initialize unit structure
- */
- up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
-
- if (!(up)) {
- msyslog(LOG_ERR, "hopfPCIClock(%d) emalloc: %m",unit);
-#ifdef DEBUG
- printf("hopfPCIClock(%d) emalloc\n",unit);
-#endif
- return (0);
- }
- memset((char *)up, 0, sizeof(struct hopfclock_unit));
-
-#ifndef SYS_WINNT
-
- fd = open(DEVICE,O_RDWR); /* try to open hopf clock device */
-
-#else
- if (!OpenHopfDevice()){
- msyslog(LOG_ERR,"Start: %s unit: %d failed!",DEVICE,unit);
- return (0);
- }
-#endif
-
- pp = peer->procptr;
- pp->io.clock_recv = noentry;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = INVALID_SOCKET;
- pp->unitptr = (caddr_t)up;
-
- get_systime(&pp->lastrec);
-
- /*
- * Initialize miscellaneous peer variables
- */
- if (pp->unitptr!=0) {
- memcpy((char *)&pp->refid, REFID, 4);
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- up->leap_status = 0;
- up->unit = (short) unit;
- return (1);
- }
- else {
- return 0;
- }
-}
-
-
-/*
- * hopfpci_shutdown - shut down the clock
- */
-static void
-hopfpci_shutdown(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- register struct hopfpciTime *up;
-
- pp = peer->procptr;
- up = (struct hopfpciTime *)pp->unitptr;
-
-#ifndef SYS_WINNT
- close(fd);
-#else
- CloseHopfDevice();
-/* UnmapViewOfFile (up); */
-#endif
-}
-
-
-/*
- * hopfpci_poll - called by the transmit procedure
- */
-static void
-hopfpci_poll(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- register struct hopfpciTime *up;
- HOPFTIME m_time;
-
- pp = peer->procptr;
- up = (struct hopfpciTime *)pp->unitptr;
-
-#ifndef SYS_WINNT
- ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
-#else
- GetHopfSystemTime(&m_time);
-#endif
- pp->polls++;
-
- pp->day = ymd2yd(m_time.wYear,m_time.wMonth,m_time.wDay);
- pp->hour = m_time.wHour;
- pp->minute = m_time.wMinute;
- pp->second = m_time.wSecond;
- pp->nsec = m_time.wMilliseconds * 1000000;
- if (m_time.wStatus & LEWAPWAR)
- pp->leap = LEAP_ADDSECOND;
- else
- pp->leap = LEAP_NOWARNING;
-
- sprintf(pp->a_lastcode,"ST: %02X T: %02d:%02d:%02d.%03ld D: %02d.%02d.%04d",
- m_time.wStatus, pp->hour, pp->minute, pp->second,
- pp->nsec / 1000000, m_time.wDay, m_time.wMonth, m_time.wYear);
- pp->lencode = (u_short)strlen(pp->a_lastcode);
-
- get_systime(&pp->lastrec);
-
- /*
- * If clock has no valid status then report error and exit
- */
- if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) { /* time ok? */
- refclock_report(peer, CEVNT_BADTIME);
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
-
- /*
- * Test if time is running on internal quarz
- * if CLK_FLAG1 is set, sychronize even if no radio operation
- */
-
- if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INTERNAL){
- if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
- refclock_report(peer, CEVNT_BADTIME);
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
- }
-
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- return;
-}
-
-#else
-int refclock_hopfpci_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_hopfser.c b/contrib/ntp/ntpd/refclock_hopfser.c
deleted file mode 100644
index 1d27333..0000000
--- a/contrib/ntp/ntpd/refclock_hopfser.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- *
- * refclock_hopfser.c
- * - clock driver for hopf serial boards (GPS or DCF77)
- *
- * Date: 30.03.2000 Revision: 01.10
- *
- * latest source and further information can be found at:
- * http://www.ATLSoft.de/ntp
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#if defined(SYS_WINNT)
-#undef close
-#define close closesocket
-#endif
-
-#if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_control.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#if defined HAVE_SYS_MODEM_H
-# include <sys/modem.h>
-# define TIOCMSET MCSETA
-# define TIOCMGET MCGETA
-# define TIOCM_RTS MRTS
-#endif
-
-#ifdef HAVE_TERMIOS_H
-# ifdef TERMIOS_NEEDS__SVID3
-# define _SVID3
-# endif
-# include <termios.h>
-# ifdef TERMIOS_NEEDS__SVID3
-# undef _SVID3
-# endif
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-
-/*
- * clock definitions
- */
-#define DESCRIPTION "hopf Elektronik serial clock" /* Long name */
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#define REFID "hopf\0" /* reference ID */
-/*
- * I/O definitions
- */
-#define DEVICE "/dev/hopfclock%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-
-
-#define STX 0x02
-#define ETX 0x03
-#define CR 0x0c
-#define LF 0x0a
-
-/* parse states */
-#define REC_QUEUE_EMPTY 0
-#define REC_QUEUE_FULL 1
-
-#define HOPF_OPMODE 0x0C /* operation mode mask */
-#define HOPF_INVALID 0x00 /* no time code available */
-#define HOPF_INTERNAL 0x04 /* internal clock */
-#define HOPF_RADIO 0x08 /* radio clock */
-#define HOPF_RADIOHP 0x0C /* high precision radio clock */
-
-/*
- * hopfclock unit control structure.
- */
-struct hopfclock_unit {
- l_fp laststamp; /* last receive timestamp */
- short unit; /* NTP refclock unit number */
- u_long polled; /* flag to detect noreplies */
- char leap_status; /* leap second flag */
- int rpt_next;
-};
-
-/*
- * Function prototypes
- */
-
-static int hopfserial_start P((int, struct peer *));
-static void hopfserial_shutdown P((int, struct peer *));
-static void hopfserial_receive P((struct recvbuf *));
-static void hopfserial_poll P((int, struct peer *));
-/* static void hopfserial_io P((struct recvbuf *)); */
-/*
- * Transfer vector
- */
-struct refclock refclock_hopfser = {
- hopfserial_start, /* start up driver */
- hopfserial_shutdown, /* shut down driver */
- hopfserial_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-/*
- * hopfserial_start - open the devices and initialize data for processing
- */
-static int
-hopfserial_start (
- int unit,
- struct peer *peer
- )
-{
- register struct hopfclock_unit *up;
- struct refclockproc *pp;
- int fd;
- char gpsdev[20];
-
-#ifdef SYS_WINNT
- (void) sprintf(gpsdev, "COM%d:", unit);
-#else
- (void) sprintf(gpsdev, DEVICE, unit);
-#endif
- /* LDISC_STD, LDISC_RAW
- * Open serial port. Use CLK line discipline, if available.
- */
- fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
- if (fd <= 0) {
-#ifdef DEBUG
- printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
-#endif
- return 0;
- }
-
- msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
- gpsdev);
-
- /*
- * Allocate and initialize unit structure
- */
- up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
-
- if (!(up)) {
- msyslog(LOG_ERR, "hopfSerialClock(%d) emalloc: %m",unit);
-#ifdef DEBUG
- printf("hopfSerialClock(%d) emalloc\n",unit);
-#endif
- (void) close(fd);
- return (0);
- }
-
- memset((char *)up, 0, sizeof(struct hopfclock_unit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = hopfserial_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
-#ifdef DEBUG
- printf("hopfSerialClock(%d) io_addclock\n",unit);
-#endif
- (void) close(fd);
- free(up);
- return (0);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- pp->clockdesc = DESCRIPTION;
- peer->precision = PRECISION;
- peer->burst = NSTAGE;
- memcpy((char *)&pp->refid, REFID, 4);
-
- up->leap_status = 0;
- up->unit = (short) unit;
-
- return (1);
-}
-
-
-/*
- * hopfserial_shutdown - shut down the clock
- */
-static void
-hopfserial_shutdown (
- int unit,
- struct peer *peer
- )
-{
- register struct hopfclock_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct hopfclock_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-
-/*
- * hopfserial_receive - receive data from the serial interface
- */
-
-static void
-hopfserial_receive (
- struct recvbuf *rbufp
- )
-{
- struct hopfclock_unit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- int synch; /* synchhronization indicator */
- int DoW; /* Dow */
-
- int day, month; /* ddd conversion */
-
- /*
- * Initialize pointers and read the timecode and timestamp.
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct hopfclock_unit *)pp->unitptr;
-
- if (up->rpt_next == 0 )
- return;
-
-
- up->rpt_next = 0; /* wait until next poll interval occur */
-
- pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
-
- if (pp->lencode == 0)
- return;
-
- sscanf(pp->a_lastcode,
-#if 1
- "%1x%1x%2d%2d%2d%2d%2d%2d", /* ...cr,lf */
-#else
- "%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
-#endif
- &synch,
- &DoW,
- &pp->hour,
- &pp->minute,
- &pp->second,
- &day,
- &month,
- &pp->year);
-
-
- /*
- Validate received values at least enough to prevent internal
- array-bounds problems, etc.
- */
- if((pp->hour < 0) || (pp->hour > 23) ||
- (pp->minute < 0) || (pp->minute > 59) ||
- (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
- (day < 1) || (day > 31) ||
- (month < 1) || (month > 12) ||
- (pp->year < 0) || (pp->year > 99)) {
- /* Data out of range. */
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- /*
- some preparations
- */
- pp->day = ymd2yd(pp->year,month,day);
- pp->leap=0;
-
- /* Year-2000 check! */
- /* wrap 2-digit date into 4-digit */
-
- if(pp->year < YEAR_PIVOT) { pp->year += 100; } /* < 98 */
- pp->year += 1900;
-
- /* preparation for timecode ntpq rl command ! */
-
-#if 0
- wsprintf(pp->a_lastcode,
- "STATUS: %1X%1X, DATE: %02d.%02d.%04d TIME: %02d:%02d:%02d",
- synch,
- DoW,
- day,
- month,
- pp->year,
- pp->hour,
- pp->minute,
- pp->second);
-
- pp->lencode = strlen(pp->a_lastcode);
- if ((synch && 0xc) == 0 ){ /* time ok? */
- refclock_report(peer, CEVNT_BADTIME);
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
-#endif
- /*
- * If clock has no valid status then report error and exit
- */
- if ((synch & HOPF_OPMODE) == HOPF_INVALID ){ /* time ok? */
- refclock_report(peer, CEVNT_BADTIME);
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
-
- /*
- * Test if time is running on internal quarz
- * if CLK_FLAG1 is set, sychronize even if no radio operation
- */
-
- if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
- if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
- refclock_report(peer, CEVNT_BADTIME);
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
- }
-
-
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-
-#if 0
- msyslog(LOG_ERR, " D:%x D:%d D:%d",synch,pp->minute,pp->second);
-#endif
-
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-
- return;
-}
-
-
-/*
- * hopfserial_poll - called by the transmit procedure
- *
- */
-static void
-hopfserial_poll (
- int unit,
- struct peer *peer
- )
-{
- register struct hopfclock_unit *up;
- struct refclockproc *pp;
- pp = peer->procptr;
-
- up = (struct hopfclock_unit *)pp->unitptr;
-
- pp->polls++;
- up->rpt_next = 1;
-
-#if 0
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#endif
-
- return;
-}
-
-#else
-int refclock_hopfser_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_hpgps.c b/contrib/ntp/ntpd/refclock_hpgps.c
deleted file mode 100644
index 7c801bb..0000000
--- a/contrib/ntp/ntpd/refclock_hpgps.c
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * refclock_hpgps - clock driver for HP 58503A GPS receiver
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_HPGPS)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/* Version 0.1 April 1, 1995
- * 0.2 April 25, 1995
- * tolerant of missing timecode response prompt and sends
- * clear status if prompt indicates error;
- * can use either local time or UTC from receiver;
- * can get receiver status screen via flag4
- *
- * WARNING!: This driver is UNDER CONSTRUCTION
- * Everything in here should be treated with suspicion.
- * If it looks wrong, it probably is.
- *
- * Comments and/or questions to: Dave Vitanye
- * Hewlett Packard Company
- * dave@scd.hp.com
- * (408) 553-2856
- *
- * Thanks to the author of the PST driver, which was the starting point for
- * this one.
- *
- * This driver supports the HP 58503A Time and Frequency Reference Receiver.
- * This receiver uses HP SmartClock (TM) to implement an Enhanced GPS receiver.
- * The receiver accuracy when locked to GPS in normal operation is better
- * than 1 usec. The accuracy when operating in holdover is typically better
- * than 10 usec. per day.
- *
- * The receiver should be operated with factory default settings.
- * Initial driver operation: expects the receiver to be already locked
- * to GPS, configured and able to output timecode format 2 messages.
- *
- * The driver uses the poll sequence :PTIME:TCODE? to get a response from
- * the receiver. The receiver responds with a timecode string of ASCII
- * printing characters, followed by a <cr><lf>, followed by a prompt string
- * issued by the receiver, in the following format:
- * T#yyyymmddhhmmssMFLRVcc<cr><lf>scpi >
- *
- * The driver processes the response at the <cr> and <lf>, so what the
- * driver sees is the prompt from the previous poll, followed by this
- * timecode. The prompt from the current poll is (usually) left unread until
- * the next poll. So (except on the very first poll) the driver sees this:
- *
- * scpi > T#yyyymmddhhmmssMFLRVcc<cr><lf>
- *
- * The T is the on-time character, at 980 msec. before the next 1PPS edge.
- * The # is the timecode format type. We look for format 2.
- * Without any of the CLK or PPS stuff, then, the receiver buffer timestamp
- * at the <cr> is 24 characters later, which is about 25 msec. at 9600 bps,
- * so the first approximation for fudge time1 is nominally -0.955 seconds.
- * This number probably needs adjusting for each machine / OS type, so far:
- * -0.955000 on an HP 9000 Model 712/80 HP-UX 9.05
- * -0.953175 on an HP 9000 Model 370 HP-UX 9.10
- *
- * This receiver also provides a 1PPS signal, but I haven't figured out
- * how to deal with any of the CLK or PPS stuff yet. Stay tuned.
- *
- */
-
-/*
- * Fudge Factors
- *
- * Fudge time1 is used to accomodate the timecode serial interface adjustment.
- * Fudge flag4 can be set to request a receiver status screen summary, which
- * is recorded in the clockstats file.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/hpgps%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 "HP 58503A GPS Time and Frequency Reference Receiver"
-
-#define SMAX 23*80+1 /* for :SYSTEM:PRINT? status screen response */
-
-#define MTZONE 2 /* number of fields in timezone reply */
-#define MTCODET2 12 /* number of fields in timecode format T2 */
-#define NTCODET2 21 /* number of chars to checksum in format T2 */
-
-/*
- * Tables to compute the day of year from yyyymmdd timecode.
- * Viva la leap.
- */
-static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/*
- * Unit control structure
- */
-struct hpgpsunit {
- int pollcnt; /* poll message counter */
- int tzhour; /* timezone offset, hours */
- int tzminute; /* timezone offset, minutes */
- int linecnt; /* set for expected multiple line responses */
- char *lastptr; /* pointer to receiver response data */
- char statscrn[SMAX]; /* receiver status screen buffer */
-};
-
-/*
- * Function prototypes
- */
-static int hpgps_start P((int, struct peer *));
-static void hpgps_shutdown P((int, struct peer *));
-static void hpgps_receive P((struct recvbuf *));
-static void hpgps_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_hpgps = {
- hpgps_start, /* start up driver */
- hpgps_shutdown, /* shut down driver */
- hpgps_poll, /* transmit poll message */
- noentry, /* not used (old hpgps_control) */
- noentry, /* initialize driver */
- noentry, /* not used (old hpgps_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-/*
- * hpgps_start - open the devices and initialize data for processing
- */
-static int
-hpgps_start(
- int unit,
- struct peer *peer
- )
-{
- register struct hpgpsunit *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 hpgpsunit *)
- emalloc(sizeof(struct hpgpsunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct hpgpsunit));
- pp = peer->procptr;
- pp->io.clock_recv = hpgps_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->tzhour = 0;
- up->tzminute = 0;
-
- *up->statscrn = '\0';
- up->lastptr = up->statscrn;
- up->pollcnt = 2;
-
- /*
- * Get the identifier string, which is logged but otherwise ignored,
- * and get the local timezone information
- */
- up->linecnt = 1;
- if (write(pp->io.fd, "*IDN?\r:PTIME:TZONE?\r", 20) != 20)
- refclock_report(peer, CEVNT_FAULT);
-
- return (1);
-}
-
-
-/*
- * hpgps_shutdown - shut down the clock
- */
-static void
-hpgps_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct hpgpsunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct hpgpsunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * hpgps_receive - receive data from the serial interface
- */
-static void
-hpgps_receive(
- struct recvbuf *rbufp
- )
-{
- register struct hpgpsunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- l_fp trtmp;
- char tcodechar1; /* identifies timecode format */
- char tcodechar2; /* identifies timecode format */
- char timequal; /* time figure of merit: 0-9 */
- char freqqual; /* frequency figure of merit: 0-3 */
- char leapchar; /* leapsecond: + or 0 or - */
- char servchar; /* request for service: 0 = no, 1 = yes */
- char syncchar; /* time info is invalid: 0 = no, 1 = yes */
- short expectedsm; /* expected timecode byte checksum */
- short tcodechksm; /* computed timecode byte checksum */
- int i,m,n;
- int month, day, lastday;
- char *tcp; /* timecode pointer (skips over the prompt) */
- char prompt[BMAX]; /* prompt in response from receiver */
-
- /*
- * Initialize pointers and read the receiver response
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct hpgpsunit *)pp->unitptr;
- *pp->a_lastcode = '\0';
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
-
-#ifdef DEBUG
- if (debug)
- printf("hpgps: lencode: %d timecode:%s\n",
- pp->lencode, pp->a_lastcode);
-#endif
-
- /*
- * If there's no characters in the reply, we can quit now
- */
- if (pp->lencode == 0)
- return;
-
- /*
- * If linecnt is greater than zero, we are getting information only,
- * such as the receiver identification string or the receiver status
- * screen, so put the receiver response at the end of the status
- * screen buffer. When we have the last line, write the buffer to
- * the clockstats file and return without further processing.
- *
- * If linecnt is zero, we are expecting either the timezone
- * or a timecode. At this point, also write the response
- * to the clockstats file, and go on to process the prompt (if any),
- * timezone, or timecode and timestamp.
- */
-
-
- if (up->linecnt-- > 0) {
- if ((int)(pp->lencode + 2) <= (SMAX - (up->lastptr - up->statscrn))) {
- *up->lastptr++ = '\n';
- (void)strcpy(up->lastptr, pp->a_lastcode);
- up->lastptr += pp->lencode;
- }
- if (up->linecnt == 0)
- record_clock_stats(&peer->srcadr, up->statscrn);
-
- return;
- }
-
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- pp->lastrec = trtmp;
-
- up->lastptr = up->statscrn;
- *up->lastptr = '\0';
- up->pollcnt = 2;
-
- /*
- * We get down to business: get a prompt if one is there, issue
- * a clear status command if it contains an error indication.
- * Next, check for either the timezone reply or the timecode reply
- * and decode it. If we don't recognize the reply, or don't get the
- * proper number of decoded fields, or get an out of range timezone,
- * or if the timecode checksum is bad, then we declare bad format
- * and exit.
- *
- * Timezone format (including nominal prompt):
- * scpi > -H,-M<cr><lf>
- *
- * Timecode format (including nominal prompt):
- * scpi > T2yyyymmddhhmmssMFLRVcc<cr><lf>
- *
- */
-
- (void)strcpy(prompt,pp->a_lastcode);
- tcp = strrchr(pp->a_lastcode,'>');
- if (tcp == NULL)
- tcp = pp->a_lastcode;
- else
- tcp++;
- prompt[tcp - pp->a_lastcode] = '\0';
- while ((*tcp == ' ') || (*tcp == '\t')) tcp++;
-
- /*
- * deal with an error indication in the prompt here
- */
- if (strrchr(prompt,'E') > strrchr(prompt,'s')){
-#ifdef DEBUG
- if (debug)
- printf("hpgps: error indicated in prompt: %s\n", prompt);
-#endif
- if (write(pp->io.fd, "*CLS\r\r", 6) != 6)
- refclock_report(peer, CEVNT_FAULT);
- }
-
- /*
- * make sure we got a timezone or timecode format and
- * then process accordingly
- */
- m = sscanf(tcp,"%c%c", &tcodechar1, &tcodechar2);
-
- if (m != 2){
-#ifdef DEBUG
- if (debug)
- printf("hpgps: no format indicator\n");
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- switch (tcodechar1) {
-
- case '+':
- case '-':
- m = sscanf(tcp,"%d,%d", &up->tzhour, &up->tzminute);
- if (m != MTZONE) {
-#ifdef DEBUG
- if (debug)
- printf("hpgps: only %d fields recognized in timezone\n", m);
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- if ((up->tzhour < -12) || (up->tzhour > 13) ||
- (up->tzminute < -59) || (up->tzminute > 59)){
-#ifdef DEBUG
- if (debug)
- printf("hpgps: timezone %d, %d out of range\n",
- up->tzhour, up->tzminute);
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- return;
-
- case 'T':
- break;
-
- default:
-#ifdef DEBUG
- if (debug)
- printf("hpgps: unrecognized reply format %c%c\n",
- tcodechar1, tcodechar2);
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- } /* end of tcodechar1 switch */
-
-
- switch (tcodechar2) {
-
- case '2':
- m = sscanf(tcp,"%*c%*c%4d%2d%2d%2d%2d%2d%c%c%c%c%c%2hx",
- &pp->year, &month, &day, &pp->hour, &pp->minute, &pp->second,
- &timequal, &freqqual, &leapchar, &servchar, &syncchar,
- &expectedsm);
- n = NTCODET2;
-
- if (m != MTCODET2){
-#ifdef DEBUG
- if (debug)
- printf("hpgps: only %d fields recognized in timecode\n", m);
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- break;
-
- default:
-#ifdef DEBUG
- if (debug)
- printf("hpgps: unrecognized timecode format %c%c\n",
- tcodechar1, tcodechar2);
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- } /* end of tcodechar2 format switch */
-
- /*
- * Compute and verify the checksum.
- * Characters are summed starting at tcodechar1, ending at just
- * before the expected checksum. Bail out if incorrect.
- */
- tcodechksm = 0;
- while (n-- > 0) tcodechksm += *tcp++;
- tcodechksm &= 0x00ff;
-
- if (tcodechksm != expectedsm) {
-#ifdef DEBUG
- if (debug)
- printf("hpgps: checksum %2hX doesn't match %2hX expected\n",
- tcodechksm, expectedsm);
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Compute the day of year from the yyyymmdd format.
- */
- if (month < 1 || month > 12 || day < 1) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
- if ( ! isleap_4(pp->year) ) { /* Y2KFixes */
- /* not a leap year */
- if (day > day1tab[month - 1]) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- for (i = 0; i < month - 1; i++) day += day1tab[i];
- lastday = 365;
- } else {
- /* a leap year */
- if (day > day2tab[month - 1]) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- for (i = 0; i < month - 1; i++) day += day2tab[i];
- lastday = 366;
- }
-
- /*
- * Deal with the timezone offset here. The receiver timecode is in
- * local time = UTC + :PTIME:TZONE, so SUBTRACT the timezone values.
- * For example, Pacific Standard Time is -8 hours , 0 minutes.
- * Deal with the underflows and overflows.
- */
- pp->minute -= up->tzminute;
- pp->hour -= up->tzhour;
-
- if (pp->minute < 0) {
- pp->minute += 60;
- pp->hour--;
- }
- if (pp->minute > 59) {
- pp->minute -= 60;
- pp->hour++;
- }
- if (pp->hour < 0) {
- pp->hour += 24;
- day--;
- if (day < 1) {
- pp->year--;
- if ( isleap_4(pp->year) ) /* Y2KFixes */
- day = 366;
- else
- day = 365;
- }
- }
-
- if (pp->hour > 23) {
- pp->hour -= 24;
- day++;
- if (day > lastday) {
- pp->year++;
- day = 1;
- }
- }
-
- pp->day = day;
-
- /*
- * Decode the MFLRV indicators.
- * NEED TO FIGURE OUT how to deal with the request for service,
- * time quality, and frequency quality indicators some day.
- */
- if (syncchar != '0') {
- pp->leap = LEAP_NOTINSYNC;
- }
- else {
- switch (leapchar) {
-
- case '+':
- pp->leap = LEAP_ADDSECOND;
- break;
-
- case '0':
- pp->leap = LEAP_NOWARNING;
- break;
-
- case '-':
- pp->leap = LEAP_DELSECOND;
- break;
-
- default:
-#ifdef DEBUG
- if (debug)
- printf("hpgps: unrecognized leap indicator: %c\n",
- leapchar);
-#endif
- refclock_report(peer, CEVNT_BADTIME);
- return;
- } /* end of leapchar switch */
- }
-
- /*
- * 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)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-
- /*
- * If CLK_FLAG4 is set, ask for the status screen response.
- */
- if (pp->sloppyclockflag & CLK_FLAG4){
- up->linecnt = 22;
- if (write(pp->io.fd, ":SYSTEM:PRINT?\r", 15) != 15)
- refclock_report(peer, CEVNT_FAULT);
- }
-}
-
-
-/*
- * hpgps_poll - called by the transmit procedure
- */
-static void
-hpgps_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct hpgpsunit *up;
- struct refclockproc *pp;
-
- /*
- * Time to poll the clock. The HP 58503A responds to a
- * ":PTIME:TCODE?" 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.
- */
- pp = peer->procptr;
- up = (struct hpgpsunit *)pp->unitptr;
- if (up->pollcnt == 0)
- refclock_report(peer, CEVNT_TIMEOUT);
- else
- up->pollcnt--;
- if (write(pp->io.fd, ":PTIME:TCODE?\r", 14) != 14) {
- refclock_report(peer, CEVNT_FAULT);
- }
- else
- pp->polls++;
-}
-
-#else
-int refclock_hpgps_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_irig.c b/contrib/ntp/ntpd/refclock_irig.c
deleted file mode 100644
index 0b35368..0000000
--- a/contrib/ntp/ntpd/refclock_irig.c
+++ /dev/null
@@ -1,1049 +0,0 @@
-/*
- * refclock_irig - audio IRIG-B/E demodulator/decoder
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_IRIG)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <math.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
-#include "audio.h"
-
-/*
- * Audio IRIG-B/E demodulator/decoder
- *
- * This driver receives, demodulates and decodes IRIG-B/E signals when
- * connected to the audio codec /dev/audio. The IRIG signal format is an
- * amplitude-modulated carrier with pulse-width modulated data bits. For
- * IRIG-B, the carrier frequency is 1000 Hz and bit rate 100 b/s; for
- * IRIG-E, the carrier frequenchy is 100 Hz and bit rate 10 b/s. The
- * driver automatically recognizes which format is in use.
- *
- * The program processes 8000-Hz mu-law companded samples using separate
- * signal filters for IRIG-B and IRIG-E, a comb filter, envelope
- * detector and automatic threshold corrector. Cycle crossings relative
- * to the corrected slice level determine the width of each pulse and
- * its value - zero, one or position identifier. The data encode 20 BCD
- * digits which determine the second, minute, hour and day of the year
- * and sometimes the year and synchronization condition. The comb filter
- * exponentially averages the corresponding samples of successive baud
- * intervals in order to reliably identify the reference carrier cycle.
- * A type-II phase-lock loop (PLL) performs additional integration and
- * interpolation to accurately determine the zero crossing of that
- * cycle, which determines the reference timestamp. A pulse-width
- * discriminator demodulates the data pulses, which are then encoded as
- * the BCD digits of the timecode.
- *
- * The timecode and reference timestamp are updated once each second
- * with IRIG-B (ten seconds with IRIG-E) and local clock offset samples
- * saved for later processing. At poll intervals of 64 s, the saved
- * samples are processed by a trimmed-mean filter and used to update the
- * system clock.
- *
- * An automatic gain control feature provides protection against
- * overdriven or underdriven input signal amplitudes. It is designed to
- * maintain adequate demodulator signal amplitude while avoiding
- * occasional noise spikes. In order to assure reliable capture, the
- * decompanded input signal amplitude must be greater than 100 units and
- * the codec sample frequency error less than 250 PPM (.025 percent).
- *
- * The program performs a number of error checks to protect against
- * overdriven or underdriven input signal levels, incorrect signal
- * format or improper hardware configuration. Specifically, if any of
- * the following errors occur for a time measurement, the data are
- * rejected.
- *
- * o The peak carrier amplitude is less than DRPOUT (100). This usually
- * means dead IRIG signal source, broken cable or wrong input port.
- *
- * o The frequency error is greater than MAXFREQ +-250 PPM (.025%). This
- * usually means broken codec hardware or wrong codec configuration.
- *
- * o The modulation index is less than MODMIN (0.5). This usually means
- * overdriven IRIG signal or wrong IRIG format.
- *
- * o A frame synchronization error has occurred. This usually means
- * wrong IRIG signal format or the IRIG signal source has lost
- * synchronization (signature control).
- *
- * o A data decoding error has occurred. This usually means wrong IRIG
- * signal format.
- *
- * o The current second of the day is not exactly one greater than the
- * previous one. This usually means a very noisy IRIG signal or
- * insufficient CPU resources.
- *
- * o An audio codec error (overrun) occurred. This usually means
- * insufficient CPU resources, as sometimes happens with Sun SPARC
- * IPCs when doing something useful.
- *
- * Note that additional checks are done elsewhere in the reference clock
- * interface routines.
- *
- * Debugging aids
- *
- * The timecode format used for debugging and data recording includes
- * data helpful in diagnosing problems with the IRIG signal and codec
- * connections. With debugging enabled (-d on the ntpd command line),
- * the driver produces one line for each timecode in the following
- * format:
- *
- * 00 1 98 23 19:26:52 721 143 0.694 20 0.1 66.5 3094572411.00027
- *
- * The most recent line is also written to the clockstats file at 64-s
- * intervals.
- *
- * The first field contains the error flags in hex, where the hex bits
- * are interpreted as below. This is followed by the IRIG status
- * indicator, year of century, day of year and time of day. The status
- * indicator and year are not produced by some IRIG devices. Following
- * these fields are the signal amplitude (0-8100), codec gain (0-255),
- * modulation index (0-1), time constant (2-20), carrier phase error
- * (us) and carrier frequency error (PPM). The last field is the on-time
- * timestamp in NTP format.
- *
- * The fraction part of the on-time timestamp is a good indicator of how
- * well the driver is doing. With an UltrSPARC 30 and Solaris 2.7, this
- * thing can keep the clock within a few tens of microseconds relative
- * to the IRIG-B signal. Accuracy with IRIG-E is about ten times worse.
- * Unfortunately, Sun broke the 2.7 audio driver in 2.8, which has a
- * 10-ms sawtooth modulation. The driver attempts to remove the
- * modulation by some clever estimation techniques which mostly work.
- * Your experience may vary.
- *
- * Unlike other drivers, which can have multiple instantiations, this
- * one supports only one. It does not seem likely that more than one
- * audio codec would be useful in a single machine. More than one would
- * probably chew up too much CPU time anyway.
- *
- * Fudge factors
- *
- * Fudge flag4 causes the dubugging output described above to be
- * recorded in the clockstats file. When the audio driver is compiled,
- * fudge flag2 selects the audio input port, where 0 is the mike port
- * (default) and 1 is the line-in port. It does not seem useful to
- * select the compact disc player port. Fudge flag3 enables audio
- * monitoring of the input signal. For this purpose, the monitor gain is
- * set to a default value. Fudgetime2 is used as a frequency vernier for
- * broken codec sample frequency.
- */
-/*
- * Interface definitions
- */
-#define DEVICE_AUDIO "/dev/audio" /* audio device name */
-#define PRECISION (-17) /* precision assumed (about 10 us) */
-#define REFID "IRIG" /* reference ID */
-#define DESCRIPTION "Generic IRIG Audio Driver" /* WRU */
-#define AUDIO_BUFSIZ 320 /* audio buffer size (40 ms) */
-#define SECOND 8000 /* nominal sample rate (Hz) */
-#define BAUD 80 /* samples per baud interval */
-#define OFFSET 128 /* companded sample offset */
-#define SIZE 256 /* decompanding table size */
-#define CYCLE 8 /* samples per carrier cycle */
-#define SUBFLD 10 /* bits per subfield */
-#define FIELD 10 /* subfields per field */
-#define MINTC 2 /* min PLL time constant */
-#define MAXTC 20 /* max PLL time constant max */
-#define MAXSIG 6000. /* maximum signal level */
-#define MAXCLP 100 /* max clips above reference per s */
-#define DRPOUT 100. /* dropout signal level */
-#define MODMIN 0.5 /* minimum modulation index */
-#define MAXFREQ (250e-6 * SECOND) /* freq tolerance (.025%) */
-#define PI 3.1415926535 /* the real thing */
-#ifdef IRIG_SUCKS
-#define WIGGLE 11 /* wiggle filter length */
-#endif /* IRIG_SUCKS */
-
-/*
- * Experimentally determined filter delays
- */
-#define IRIG_B .0019 /* IRIG-B filter delay */
-#define IRIG_E .0019 /* IRIG-E filter delay */
-
-/*
- * Data bit definitions
- */
-#define BIT0 0 /* zero */
-#define BIT1 1 /* one */
-#define BITP 2 /* position identifier */
-
-/*
- * Error flags (up->errflg)
- */
-#define IRIG_ERR_AMP 0x01 /* low carrier amplitude */
-#define IRIG_ERR_FREQ 0x02 /* frequency tolerance exceeded */
-#define IRIG_ERR_MOD 0x04 /* low modulation index */
-#define IRIG_ERR_SYNCH 0x08 /* frame synch error */
-#define IRIG_ERR_DECODE 0x10 /* frame decoding error */
-#define IRIG_ERR_CHECK 0x20 /* second numbering discrepancy */
-#define IRIG_ERR_ERROR 0x40 /* codec error (overrun) */
-#define IRIG_ERR_SIGERR 0x80 /* IRIG status error (Spectracom) */
-
-/*
- * IRIG unit control structure
- */
-struct irigunit {
- u_char timecode[21]; /* timecode string */
- l_fp timestamp; /* audio sample timestamp */
- l_fp tick; /* audio sample increment */
- double integ[BAUD]; /* baud integrator */
- double phase, freq; /* logical clock phase and frequency */
- double zxing; /* phase detector integrator */
- double yxing; /* cycle phase */
- double exing; /* envelope phase */
- double modndx; /* modulation index */
- double irig_b; /* IRIG-B signal amplitude */
- double irig_e; /* IRIG-E signal amplitude */
- int errflg; /* error flags */
- /*
- * Audio codec variables
- */
- double comp[SIZE]; /* decompanding table */
- int port; /* codec port */
- int gain; /* codec gain */
- int mongain; /* codec monitor gain */
- int clipcnt; /* sample clipped count */
- int seccnt; /* second interval counter */
-
- /*
- * RF variables
- */
- double hpf[5]; /* IRIG-B filter shift register */
- double lpf[5]; /* IRIG-E filter shift register */
- double intmin, intmax; /* integrated envelope min and max */
- double envmax; /* peak amplitude */
- double envmin; /* noise amplitude */
- double maxsignal; /* integrated peak amplitude */
- double noise; /* integrated noise amplitude */
- double lastenv[CYCLE]; /* last cycle amplitudes */
- double lastint[CYCLE]; /* last integrated cycle amplitudes */
- double lastsig; /* last carrier sample */
- double fdelay; /* filter delay */
- int decim; /* sample decimation factor */
- int envphase; /* envelope phase */
- int envptr; /* envelope phase pointer */
- int carphase; /* carrier phase */
- int envsw; /* envelope state */
- int envxing; /* envelope slice crossing */
- int tc; /* time constant */
- int tcount; /* time constant counter */
- int badcnt; /* decimation interval counter */
-
- /*
- * Decoder variables
- */
- int pulse; /* cycle counter */
- int cycles; /* carrier cycles */
- int dcycles; /* data cycles */
- int xptr; /* translate table pointer */
- int lastbit; /* last code element length */
- int second; /* previous second */
- int fieldcnt; /* subfield count in field */
- int bits; /* demodulated bits */
- int bitcnt; /* bit count in subfield */
-#ifdef IRIG_SUCKS
- l_fp wigwag; /* wiggle accumulator */
- int wp; /* wiggle filter pointer */
- l_fp wiggle[WIGGLE]; /* wiggle filter */
- l_fp wigbot[WIGGLE]; /* wiggle bottom fisher*/
-#endif /* IRIG_SUCKS */
- l_fp wuggle;
-};
-
-/*
- * Function prototypes
- */
-static int irig_start P((int, struct peer *));
-static void irig_shutdown P((int, struct peer *));
-static void irig_receive P((struct recvbuf *));
-static void irig_poll P((int, struct peer *));
-
-/*
- * More function prototypes
- */
-static void irig_base P((struct peer *, double));
-static void irig_rf P((struct peer *, double));
-static void irig_decode P((struct peer *, int));
-static void irig_gain P((struct peer *));
-
-/*
- * Transfer vector
- */
-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 */
-};
-
-/*
- * Global variables
- */
-static char hexchar[] = { /* really quick decoding table */
- '0', '8', '4', 'c', /* 0000 0001 0010 0011 */
- '2', 'a', '6', 'e', /* 0100 0101 0110 0111 */
- '1', '9', '5', 'd', /* 1000 1001 1010 1011 */
- '3', 'b', '7', 'f' /* 1100 1101 1110 1111 */
-};
-
-
-/*
- * irig_start - open the devices and initialize data for processing
- */
-static int
-irig_start(
- int unit, /* instance number (used for PCM) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct irigunit *up;
-
- /*
- * Local variables
- */
- int fd; /* file descriptor */
- int i; /* index */
- double step; /* codec adjustment */
-
- /*
- * Open audio device
- */
- fd = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
- if (fd < 0)
- return (0);
-#ifdef DEBUG
- if (debug)
- audio_show();
-#endif
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct irigunit *)
- emalloc(sizeof(struct irigunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct irigunit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = irig_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);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- up->tc = MINTC;
- up->decim = 1;
- up->fdelay = IRIG_B;
- up->gain = 127;
-
- /*
- * The companded samples are encoded sign-magnitude. The table
- * contains all the 256 values in the interest of speed.
- */
- up->comp[0] = up->comp[OFFSET] = 0.;
- up->comp[1] = 1; up->comp[OFFSET + 1] = -1.;
- up->comp[2] = 3; up->comp[OFFSET + 2] = -3.;
- step = 2.;
- for (i = 3; i < OFFSET; i++) {
- up->comp[i] = up->comp[i - 1] + step;
- up->comp[OFFSET + i] = -up->comp[i];
- if (i % 16 == 0)
- step *= 2.;
- }
- DTOLFP(1. / SECOND, &up->tick);
- return (1);
-}
-
-
-/*
- * irig_shutdown - shut down the clock
- */
-static void
-irig_shutdown(
- int unit, /* instance number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct irigunit *up;
-
- pp = peer->procptr;
- up = (struct irigunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * irig_receive - receive data from the audio device
- *
- * This routine reads input samples and adjusts the logical clock to
- * track the irig clock by dropping or duplicating codec samples.
- */
-static void
-irig_receive(
- struct recvbuf *rbufp /* receive buffer structure pointer */
- )
-{
- struct peer *peer;
- struct refclockproc *pp;
- struct irigunit *up;
-
- /*
- * Local variables
- */
- double sample; /* codec sample */
- u_char *dpt; /* buffer pointer */
- int bufcnt; /* buffer counter */
- l_fp ltemp; /* l_fp temp */
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct irigunit *)pp->unitptr;
-
- /*
- * Main loop - read until there ain't no more. Note codec
- * samples are bit-inverted.
- */
- DTOLFP((double)rbufp->recv_length / SECOND, &ltemp);
- L_SUB(&rbufp->recv_time, &ltemp);
- up->timestamp = rbufp->recv_time;
- dpt = rbufp->recv_buffer;
- for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
- sample = up->comp[~*dpt++ & 0xff];
-
- /*
- * Clip noise spikes greater than MAXSIG. If no clips,
- * increase the gain a tad; if the clips are too high,
- * decrease a tad.
- */
- if (sample > MAXSIG) {
- sample = MAXSIG;
- up->clipcnt++;
- } else if (sample < -MAXSIG) {
- sample = -MAXSIG;
- up->clipcnt++;
- }
-
- /*
- * Variable frequency oscillator. The codec oscillator
- * runs at the nominal rate of 8000 samples per second,
- * or 125 us per sample. A frequency change of one unit
- * results in either duplicating or deleting one sample
- * per second, which results in a frequency change of
- * 125 PPM.
- */
- up->phase += up->freq / SECOND;
- up->phase += pp->fudgetime2 / 1e6;
- if (up->phase >= .5) {
- up->phase -= 1.;
- } else if (up->phase < -.5) {
- up->phase += 1.;
- irig_rf(peer, sample);
- irig_rf(peer, sample);
- } else {
- irig_rf(peer, sample);
- }
- L_ADD(&up->timestamp, &up->tick);
-
- /*
- * Once each second, determine the IRIG format and gain.
- */
- up->seccnt = (up->seccnt + 1) % SECOND;
- if (up->seccnt == 0) {
- if (up->irig_b > up->irig_e) {
- up->decim = 1;
- up->fdelay = IRIG_B;
- } else {
- up->decim = 10;
- up->fdelay = IRIG_E;
- }
- irig_gain(peer);
- up->irig_b = up->irig_e = 0;
- }
- }
-
- /*
- * Set the input port and monitor gain for the next buffer.
- */
- if (pp->sloppyclockflag & CLK_FLAG2)
- up->port = 2;
- else
- up->port = 1;
- if (pp->sloppyclockflag & CLK_FLAG3)
- up->mongain = MONGAIN;
- else
- up->mongain = 0;
-}
-
-/*
- * irig_rf - RF processing
- *
- * This routine filters the RF signal using a highpass filter for IRIG-B
- * and a lowpass filter for IRIG-E. In case of IRIG-E, the samples are
- * decimated by a factor of ten. The lowpass filter functions also as a
- * decimation filter in this case. Note that the codec filters function
- * as roofing filters to attenuate both the high and low ends of the
- * passband. IIR filter coefficients were determined using Matlab Signal
- * Processing Toolkit.
- */
-static void
-irig_rf(
- struct peer *peer, /* peer structure pointer */
- double sample /* current signal sample */
- )
-{
- struct refclockproc *pp;
- struct irigunit *up;
-
- /*
- * Local variables
- */
- double irig_b, irig_e; /* irig filter outputs */
-
- pp = peer->procptr;
- up = (struct irigunit *)pp->unitptr;
-
- /*
- * IRIG-B filter. 4th-order elliptic, 800-Hz highpass, 0.3 dB
- * passband ripple, -50 dB stopband ripple, phase delay .0022
- * s)
- */
- irig_b = (up->hpf[4] = up->hpf[3]) * 2.322484e-01;
- irig_b += (up->hpf[3] = up->hpf[2]) * -1.103929e+00;
- irig_b += (up->hpf[2] = up->hpf[1]) * 2.351081e+00;
- irig_b += (up->hpf[1] = up->hpf[0]) * -2.335036e+00;
- up->hpf[0] = sample - irig_b;
- irig_b = up->hpf[0] * 4.335855e-01
- + up->hpf[1] * -1.695859e+00
- + up->hpf[2] * 2.525004e+00
- + up->hpf[3] * -1.695859e+00
- + up->hpf[4] * 4.335855e-01;
- up->irig_b += irig_b * irig_b;
-
- /*
- * IRIG-E filter. 4th-order elliptic, 130-Hz lowpass, 0.3 dB
- * passband ripple, -50 dB stopband ripple, phase delay .0219 s.
- */
- irig_e = (up->lpf[4] = up->lpf[3]) * 8.694604e-01;
- irig_e += (up->lpf[3] = up->lpf[2]) * -3.589893e+00;
- irig_e += (up->lpf[2] = up->lpf[1]) * 5.570154e+00;
- irig_e += (up->lpf[1] = up->lpf[0]) * -3.849667e+00;
- up->lpf[0] = sample - irig_e;
- irig_e = up->lpf[0] * 3.215696e-03
- + up->lpf[1] * -1.174951e-02
- + up->lpf[2] * 1.712074e-02
- + up->lpf[3] * -1.174951e-02
- + up->lpf[4] * 3.215696e-03;
- up->irig_e += irig_e * irig_e;
-
- /*
- * Decimate by a factor of either 1 (IRIG-B) or 10 (IRIG-E).
- */
- up->badcnt = (up->badcnt + 1) % up->decim;
- if (up->badcnt == 0) {
- if (up->decim == 1)
- irig_base(peer, irig_b);
- else
- irig_base(peer, irig_e);
- }
-}
-
-/*
- * irig_base - baseband processing
- *
- * This routine processes the baseband signal and demodulates the AM
- * carrier using a synchronous detector. It then synchronizes to the
- * data frame at the baud rate and decodes the data pulses.
- */
-static void
-irig_base(
- struct peer *peer, /* peer structure pointer */
- double sample /* current signal sample */
- )
-{
- struct refclockproc *pp;
- struct irigunit *up;
-
- /*
- * Local variables
- */
- double xxing; /* phase detector interpolated output */
- double lope; /* integrator output */
- double env; /* envelope detector output */
- double dtemp; /* double temp */
-
- pp = peer->procptr;
- up = (struct irigunit *)pp->unitptr;
-
- /*
- * Synchronous baud integrator. Corresponding samples of current
- * and past baud intervals are integrated to refine the envelope
- * amplitude and phase estimate. We keep one cycle of both the
- * raw and integrated data for later use.
- */
- up->envphase = (up->envphase + 1) % BAUD;
- up->carphase = (up->carphase + 1) % CYCLE;
- up->integ[up->envphase] += (sample - up->integ[up->envphase]) /
- (5 * up->tc);
- lope = up->integ[up->envphase];
- up->lastenv[up->carphase] = sample;
- up->lastint[up->carphase] = lope;
-
- /*
- * Phase detector. Sample amplitudes are integrated over the
- * baud interval. Cycle phase is determined from these
- * amplitudes using an eight-sample cyclic buffer. A phase
- * change of 360 degrees produces an output change of one unit.
- */
- if (up->lastsig > 0 && lope <= 0) {
- xxing = lope / (up->lastsig - lope);
- up->zxing += (up->carphase - 4 + xxing) / CYCLE;
- }
- up->lastsig = lope;
-
- /*
- * Update signal/noise estimates and PLL phase/frequency.
- */
- if (up->envphase == 0) {
-
- /*
- * Update envelope signal and noise estimates and mess
- * with error bits.
- */
- up->maxsignal = up->intmax;
- up->noise = up->intmin;
- if (up->maxsignal < DRPOUT)
- up->errflg |= IRIG_ERR_AMP;
- if (up->maxsignal > 0)
- up->modndx = (up->intmax - up->intmin) /
- up->intmax;
- else
- up->modndx = 0;
- if (up->modndx < MODMIN)
- up->errflg |= IRIG_ERR_MOD;
- up->intmin = 1e6; up->intmax = 0;
- if (up->errflg & (IRIG_ERR_AMP | IRIG_ERR_FREQ |
- IRIG_ERR_MOD | IRIG_ERR_SYNCH)) {
- up->tc = MINTC;
- up->tcount = 0;
- }
-
- /*
- * Update PLL phase and frequency. The PLL time constant
- * is set initially to stabilize the frequency within a
- * minute or two, then increases to the maximum. The
- * frequency is clamped so that the PLL capture range
- * cannot be exceeded.
- */
- dtemp = up->zxing * up->decim / BAUD;
- up->yxing = dtemp;
- up->zxing = 0.;
- up->phase += dtemp / up->tc;
- up->freq += dtemp / (4. * up->tc * up->tc);
- if (up->freq > MAXFREQ) {
- up->freq = MAXFREQ;
- up->errflg |= IRIG_ERR_FREQ;
- } else if (up->freq < -MAXFREQ) {
- up->freq = -MAXFREQ;
- up->errflg |= IRIG_ERR_FREQ;
- }
- }
-
- /*
- * Synchronous demodulator. There are eight samples in the cycle
- * and ten cycles in the baud interval. The amplitude of each
- * cycle is determined at the last sample in the cycle. The
- * beginning of the data pulse is determined from the integrated
- * samples, while the end of the pulse is determined from the
- * raw samples. The raw data bits are demodulated relative to
- * the slice level and left-shifted in the decoding register.
- */
- if (up->carphase != 7)
- return;
- env = (up->lastenv[2] - up->lastenv[6]) / 2.;
- lope = (up->lastint[2] - up->lastint[6]) / 2.;
- if (lope > up->intmax)
- up->intmax = lope;
- if (lope < up->intmin)
- up->intmin = lope;
-
- /*
- * Pulse code demodulator and reference timestamp. The decoder
- * looks for a sequence of ten bits; the first two bits must be
- * one, the last two bits must be zero. Frame synch is asserted
- * when three correct frames have been found.
- */
- up->pulse = (up->pulse + 1) % 10;
- if (up->pulse == 1)
- up->envmax = env;
- else if (up->pulse == 9)
- up->envmin = env;
- up->dcycles <<= 1;
- if (env >= (up->envmax + up->envmin) / 2.)
- up->dcycles |= 1;
- up->cycles <<= 1;
- if (lope >= (up->maxsignal + up->noise) / 2.)
- up->cycles |= 1;
- if ((up->cycles & 0x303c0f03) == 0x300c0300) {
- l_fp ltemp;
- int bitz;
-
- /*
- * The PLL time constant starts out small, in order to
- * sustain a frequency tolerance of 250 PPM. It
- * gradually increases as the loop settles down. Note
- * that small wiggles are not believed, unless they
- * persist for lots of samples.
- */
- if (up->pulse != 9)
- up->errflg |= IRIG_ERR_SYNCH;
- up->pulse = 9;
- up->exing = -up->yxing;
- if (fabs(up->envxing - up->envphase) <= 1) {
- up->tcount++;
- if (up->tcount > 50 * up->tc) {
- up->tc++;
- if (up->tc > MAXTC)
- up->tc = MAXTC;
- up->tcount = 0;
- up->envxing = up->envphase;
- } else {
- up->exing -= up->envxing - up->envphase;
- }
- } else {
- up->tcount = 0;
- up->envxing = up->envphase;
- }
-
- /*
- * Determine a reference timestamp, accounting for the
- * codec delay and filter delay. Note the timestamp is
- * for the previous frame, so we have to backtrack for
- * this plus the delay since the last carrier positive
- * zero crossing.
- */
- dtemp = up->decim * ((up->exing + BAUD) / SECOND + 1.) +
- up->fdelay;
- DTOLFP(dtemp, &ltemp);
- pp->lastrec = up->timestamp;
- L_SUB(&pp->lastrec, &ltemp);
-
- /*
- * The data bits are collected in ten-bit frames. The
- * first two and last two bits are determined by frame
- * sync and ignored here; the resulting patterns
- * represent zero (0-1 bits), one (2-4 bits) and
- * position identifier (5-6 bits). The remaining
- * patterns represent errors and are treated as zeros.
- */
- bitz = up->dcycles & 0xfc;
- switch(bitz) {
-
- case 0x00:
- case 0x80:
- irig_decode(peer, BIT0);
- break;
-
- case 0xc0:
- case 0xe0:
- case 0xf0:
- irig_decode(peer, BIT1);
- break;
-
- case 0xf8:
- case 0xfc:
- irig_decode(peer, BITP);
- break;
-
- default:
- irig_decode(peer, 0);
- up->errflg |= IRIG_ERR_DECODE;
- }
- }
-}
-
-
-/*
- * irig_decode - decode the data
- *
- * This routine assembles bits into digits, digits into subfields and
- * subfields into the timecode field. Bits can have values of zero, one
- * or position identifier. There are four bits per digit, two digits per
- * subfield and ten subfields per field. The last bit in every subfield
- * and the first bit in the first subfield are position identifiers.
- */
-static void
-irig_decode(
- struct peer *peer, /* peer structure pointer */
- int bit /* data bit (0, 1 or 2) */
- )
-{
- struct refclockproc *pp;
- struct irigunit *up;
-#ifdef IRIG_SUCKS
- int i;
-#endif /* IRIG_SUCKS */
-
- /*
- * Local variables
- */
- char syncchar; /* sync character (Spectracom) */
- char sbs[6]; /* binary seconds since 0h */
- char spare[2]; /* mulligan digits */
-
- pp = peer->procptr;
- up = (struct irigunit *)pp->unitptr;
-
- /*
- * Assemble subfield bits.
- */
- up->bits <<= 1;
- if (bit == BIT1) {
- up->bits |= 1;
- } else if (bit == BITP && up->lastbit == BITP) {
-
- /*
- * Frame sync - two adjacent position identifiers.
- * Monitor the reference timestamp and wiggle the
- * clock, but only if no errors have occurred.
- */
- up->bitcnt = 1;
- up->fieldcnt = 0;
- up->lastbit = 0;
- if (up->errflg == 0) {
-#ifdef IRIG_SUCKS
- l_fp ltemp;
-
- /*
- * You really don't wanna know what comes down
- * here. Leave it to say Solaris 2.8 broke the
- * nice clean audio stream, apparently affected
- * by a 5-ms sawtooth jitter. Sundown on
- * Solaris. This leaves a little twilight.
- *
- * The scheme involves differentiation, forward
- * learning and integration. The sawtooth has a
- * period of 11 seconds. The timestamp
- * differences are integrated and subtracted
- * from the signal.
- */
- ltemp = pp->lastrec;
- L_SUB(&ltemp, &pp->lastref);
- if (ltemp.l_f < 0)
- ltemp.l_i = -1;
- else
- ltemp.l_i = 0;
- pp->lastref = pp->lastrec;
- if (!L_ISNEG(&ltemp))
- L_CLR(&up->wigwag);
- else
- L_ADD(&up->wigwag, &ltemp);
- L_SUB(&pp->lastrec, &up->wigwag);
- up->wiggle[up->wp] = ltemp;
-
- /*
- * Bottom fisher. To understand this, you have
- * to know about velocity microphones and AM
- * transmitters. No further explanation is
- * offered, as this is truly a black art.
- */
- up->wigbot[up->wp] = pp->lastrec;
- for (i = 0; i < WIGGLE; i++) {
- if (i != up->wp)
- up->wigbot[i].l_ui++;
- L_SUB(&pp->lastrec, &up->wigbot[i]);
- if (L_ISNEG(&pp->lastrec))
- L_ADD(&pp->lastrec,
- &up->wigbot[i]);
- else
- pp->lastrec = up->wigbot[i];
- }
- up->wp++;
- up->wp %= WIGGLE;
- up->wuggle = pp->lastrec;
- refclock_process(pp);
-#else /* IRIG_SUCKS */
- pp->lastref = pp->lastrec;
- up->wuggle = pp->lastrec;
- refclock_process(pp);
-#endif /* IRIG_SUCKS */
- }
- up->errflg = 0;
- }
- up->bitcnt = (up->bitcnt + 1) % SUBFLD;
- if (up->bitcnt == 0) {
-
- /*
- * End of subfield. Encode two hexadecimal digits in
- * little-endian timecode field.
- */
- if (up->fieldcnt == 0)
- up->bits <<= 1;
- if (up->xptr < 2)
- up->xptr = 2 * FIELD;
- up->timecode[--up->xptr] = hexchar[(up->bits >> 5) &
- 0xf];
- up->timecode[--up->xptr] = hexchar[up->bits & 0xf];
- up->fieldcnt = (up->fieldcnt + 1) % FIELD;
- if (up->fieldcnt == 0) {
-
- /*
- * End of field. Decode the timecode and wind
- * the clock. Not all IRIG generators have the
- * year; if so, it is nonzero after year 2000.
- * Not all have the hardware status bit; if so,
- * it is lit when the source is okay and dim
- * when bad. We watch this only if the year is
- * nonzero. Not all are configured for signature
- * control. If so, all BCD digits are set to
- * zero if the source is bad. In this case the
- * refclock_process() will reject the timecode
- * as invalid.
- */
- up->xptr = 2 * FIELD;
- if (sscanf((char *)up->timecode,
- "%6s%2d%c%2s%3d%2d%2d%2d", sbs, &pp->year,
- &syncchar, spare, &pp->day, &pp->hour,
- &pp->minute, &pp->second) != 8)
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
- up->second = (up->second + up->decim) % 60;
- if (pp->year > 0) {
- pp->year += 2000;
- if (syncchar == '0')
- up->errflg |= IRIG_ERR_CHECK;
- }
- if (pp->second != up->second)
- up->errflg |= IRIG_ERR_CHECK;
- up->second = pp->second;
- sprintf(pp->a_lastcode,
- "%02x %c %2d %3d %02d:%02d:%02d %4.0f %3d %6.3f %2d %6.1f %6.1f %s",
- up->errflg, syncchar, pp->year, pp->day,
- pp->hour, pp->minute, pp->second,
- up->maxsignal, up->gain, up->modndx,
- up->tc, up->exing * 1e6 / SECOND, up->freq *
- 1e6 / SECOND, ulfptoa(&up->wuggle, 6));
- pp->lencode = strlen(pp->a_lastcode);
- if (pp->sloppyclockflag & CLK_FLAG4) {
- record_clock_stats(&peer->srcadr,
- pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("irig: %s\n",
- pp->a_lastcode);
-#endif /* DEBUG */
- }
- }
- }
- up->lastbit = bit;
-}
-
-
-/*
- * irig_poll - called by the transmit procedure
- *
- * This routine sweeps up the timecode updates since the last poll. For
- * IRIG-B there should be at least 60 updates; for IRIG-E there should
- * be at least 6. If nothing is heard, a timeout event is declared and
- * any orphaned timecode updates are sent to foster care.
- */
-static void
-irig_poll(
- int unit, /* instance number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct irigunit *up;
-
- pp = peer->procptr;
- up = (struct irigunit *)pp->unitptr;
-
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- } else {
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("irig: %s\n", pp->a_lastcode);
-#endif /* DEBUG */
- }
- pp->polls++;
-
-}
-
-
-/*
- * irig_gain - adjust codec gain
- *
- * This routine is called once each second. If the signal envelope
- * amplitude is too low, the codec gain is bumped up by four units; if
- * too high, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
- */
-static void
-irig_gain(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct irigunit *up;
-
- pp = peer->procptr;
- up = (struct irigunit *)pp->unitptr;
-
- /*
- * Apparently, the codec uses only the high order bits of the
- * gain control field. Thus, it may take awhile for changes to
- * wiggle the hardware bits.
- */
- if (up->clipcnt == 0) {
- up->gain += 4;
- if (up->gain > MAXGAIN)
- up->gain = MAXGAIN;
- } else if (up->clipcnt > MAXCLP) {
- up->gain -= 4;
- if (up->gain < 0)
- up->gain = 0;
- }
- audio_gain(up->gain, up->mongain, up->port);
- up->clipcnt = 0;
-}
-
-#else
-int refclock_irig_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_jjy.c b/contrib/ntp/ntpd/refclock_jjy.c
deleted file mode 100644
index 2aa9d6a..0000000
--- a/contrib/ntp/ntpd/refclock_jjy.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * refclock_jjy - clock driver for JJY receivers
- */
-
-/**********************************************************************/
-/* */
-/* Copyright (C) 2001, Takao Abe. All rights reserved. */
-/* */
-/* Permission to use, copy, modify, and distribute this software */
-/* and its documentation for any purpose is hereby granted */
-/* without fee, provided that the following conditions are met: */
-/* */
-/* One retains the entire copyright notice properly, and both the */
-/* copyright notice and this license. in the documentation and/or */
-/* other materials provided with the distribution. */
-/* */
-/* This software and the name of the author must not be used to */
-/* endorse or promote products derived from this software without */
-/* prior written permission. */
-/* */
-/* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESSED OR IMPLIED */
-/* WARRANTIES OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, THE */
-/* IMPLIED WARRANTIES OF MERCHANTABLILITY AND FITNESS FOR A */
-/* PARTICULAR PURPOSE. */
-/* IN NO EVENT SHALL THE AUTHOR TAKAO ABE BE LIABLE FOR ANY DIRECT, */
-/* INDIRECT, GENERAL, 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. */
-/* */
-/* This driver is developed in my private time, and is opened as */
-/* voluntary contributions for the NTP. */
-/* The manufacturer of the JJY receiver has not participated in */
-/* a development of this driver. */
-/* The manufacturer does not warrant anything about this driver, */
-/* and is not liable for anything about this driver. */
-/* */
-/**********************************************************************/
-/* */
-/* Author Takao Abe */
-/* Email abetakao@bea.hi-ho.ne.jp */
-/* Homepage http://www.bea.hi-ho.ne.jp/abetakao/ */
-/* */
-/**********************************************************************/
-/* */
-/* History */
-/* */
-/* 2001/07/15 */
-/* [New] Support the Tristate Ltd. JJY receiver */
-/* */
-/* 2001/08/04 */
-/* [Change] Log to clockstats even if bad reply */
-/* [Fix] PRECISION = (-3) (about 100 ms) */
-/* [Add] Support the C-DEX Co.Ltd. JJY receiver */
-/* 2001/12/04 */
-/* [Fix] C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp ) */
-/* */
-/**********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_JJY)
-
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <sys/time.h>
-#include <time.h>
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_tty.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-/**********************************************************************/
-/* */
-/* The Tristate Ltd. JJY receiver JJY01 */
-/* */
-/* Command Response Remarks */
-/* ------------ ---------------------- --------------------- */
-/* date<CR><LF> YYYY/MM/DD XXX<CR><LF> */
-/* time<CR><LF> HH:MM:SS<CR><LF> */
-/* stim<CR><LF> HH:MM:SS<CR><LF> Reply at just second */
-/* */
-/* During synchronization after a receiver is turned on, */
-/* It replies the past time from 2000/01/01 00:00:00. */
-/* The function "refclock_process" checks the time and tells */
-/* as an insanity time. */
-/* */
-/**********************************************************************/
-/* */
-/* The C-DEX Co. Ltd. JJY receiver JST2000 */
-/* */
-/* Command Response Remarks */
-/* ------------ ---------------------- --------------------- */
-/* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> */
-/* */
-/**********************************************************************/
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/jjy%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define REFID "JJY" /* reference ID */
-#define DESCRIPTION "JJY Receiver"
-#define PRECISION (-3) /* precision assumed (about 100 ms) */
-
-/*
- * JJY unit control structure
- */
-struct jjyunit {
- char unittype ; /* UNITTYPE_XXXXXXXXXX */
- short version ;
- short linediscipline ; /* LDISC_CLK or LDISC_RAW */
- int linecount ;
- int lineerror ;
- int year, month, day, hour, minute, second, msecond ;
-/* LDISC_RAW only */
-#define MAX_LINECOUNT 8
-#define MAX_RAWBUF 64
- int lineexpect ;
- int charexpect [ MAX_LINECOUNT ] ;
- int charcount ;
- char rawbuf [ MAX_RAWBUF ] ;
-};
-
-#define UNITTYPE_TRISTATE_JJY01 1
-#define UNITTYPE_CDEX_JST2000 2
-
-/*
- * Function prototypes
- */
-static int jjy_start P((int, struct peer *));
-static void jjy_shutdown P((int, struct peer *));
-static void jjy_poll P((int, struct peer *));
-static void jjy_poll_tristate_jjy01 P((int, struct peer *));
-static void jjy_poll_cdex_jst2000 P((int, struct peer *));
-static void jjy_receive P((struct recvbuf *));
-static int jjy_receive_tristate_jjy01 P((struct recvbuf *));
-static int jjy_receive_cdex_jst2000 P((struct recvbuf *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_jjy = {
- jjy_start, /* start up driver */
- jjy_shutdown, /* shutdown driver */
- jjy_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* not used */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-/*
- * Start up driver return code
- */
-#define RC_START_SUCCESS 1
-#define RC_START_ERROR 0
-
-/*
- * Local constants definition
- */
-
-#define MAX_LOGTEXT 64
-
-
-/**************************************************************************************************/
-/* jjy_start - open the devices and initialize data for processing */
-/**************************************************************************************************/
-static int
-jjy_start ( int unit, struct peer *peer )
-{
-
- struct jjyunit *up ;
- struct refclockproc *pp ;
- int fd ;
- char *pDeviceName ;
- short iDiscipline ;
-
-#ifdef DEBUG
- if ( debug ) {
- printf ( "jjy_start (refclock_jjy.c) : %s mode=%d ", ntoa(&peer->srcadr), peer->ttl ) ;
- printf ( DEVICE, unit ) ;
- printf ( "\n" ) ;
- }
-#endif
- /*
- * Open serial port
- */
- if ( ! ( pDeviceName = (char*) emalloc ( strlen(DEVICE) + 10 ) ) ) {
- return RC_START_ERROR ;
- }
- sprintf ( pDeviceName, DEVICE, unit ) ;
-
- /*
- * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
- */
- switch ( peer->ttl ) {
- case 0 :
- case 1 : iDiscipline = LDISC_CLK ; break ;
- case 2 : iDiscipline = LDISC_RAW ; break ;
- default :
- msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
- ntoa(&peer->srcadr), peer->ttl ) ;
- free ( (void*) pDeviceName ) ;
- return RC_START_ERROR ;
- }
-
- if ( ! ( fd = refclock_open ( pDeviceName, SPEED232, iDiscipline ) ) ) {
- free ( (void*) pDeviceName ) ;
- return RC_START_ERROR ;
- }
- free ( (void*) pDeviceName ) ;
-
- /*
- * Allocate and initialize unit structure
- */
- if ( ! ( up = (struct jjyunit *) emalloc (sizeof(struct jjyunit)) ) ) {
- close ( fd ) ;
- return RC_START_ERROR ;
- }
-
- memset ( (char*)up, 0, sizeof(struct jjyunit) ) ;
- up->linediscipline = iDiscipline ;
-
- /*
- * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
- */
- switch ( peer->ttl ) {
- case 0 :
- /*
- * The mode 0 is a default clock type at this time.
- * But this will be change to auto-detect mode in the future.
- */
- case 1 :
- up->unittype = UNITTYPE_TRISTATE_JJY01 ;
- up->version = 100 ;
- up->lineexpect = 2 ;
- up->charexpect[0] = 14 ; /* YYYY/MM/DD WWW<CR><LF> */
- up->charexpect[1] = 8 ; /* HH:MM:SS<CR><LF> */
- break ;
- case 2 :
- up->unittype = UNITTYPE_CDEX_JST2000 ;
- up->lineexpect = 1 ;
- up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
- break ;
- default :
- msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
- ntoa(&peer->srcadr), peer->ttl ) ;
- close ( fd ) ;
- free ( (void*) up ) ;
- return RC_START_ERROR ;
- }
-
- pp = peer->procptr ;
- pp->unitptr = (caddr_t) up ;
- pp->io.clock_recv = jjy_receive ;
- pp->io.srcclock = (caddr_t) peer ;
- pp->io.datalen = 0 ;
- pp->io.fd = fd ;
- if ( ! io_addclock(&pp->io) ) {
- close ( fd ) ;
- free ( (void*) up ) ;
- return RC_START_ERROR ;
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION ;
- peer->burst = 1 ;
- pp->clockdesc = DESCRIPTION ;
- memcpy ( (char*)&pp->refid, REFID, strlen(REFID) ) ;
-
- return RC_START_SUCCESS ;
-
-}
-
-
-/**************************************************************************************************/
-/* jjy_shutdown - shutdown the clock */
-/**************************************************************************************************/
-static void
-jjy_shutdown ( int unit, struct peer *peer )
-{
-
- struct jjyunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr ;
- up = (struct jjyunit *) pp->unitptr ;
- io_closeclock ( &pp->io ) ;
- free ( (void*) up ) ;
-
-}
-
-
-/**************************************************************************************************/
-/* jjy_receive - receive data from the serial interface */
-/**************************************************************************************************/
-static void
-jjy_receive ( struct recvbuf *rbufp )
-{
-
- struct jjyunit *up ;
- struct refclockproc *pp ;
- struct peer *peer;
-
- l_fp tRecvTimestamp; /* arrival timestamp */
- int rc ;
- char sLogText [ MAX_LOGTEXT ] ;
- int i, bCntrlChar ;
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *) rbufp->recv_srcclock ;
- pp = peer->procptr ;
- up = (struct jjyunit *) pp->unitptr ;
-
- /*
- * Get next input line
- */
- pp->lencode = refclock_gtlin ( rbufp, pp->a_lastcode, BMAX, &tRecvTimestamp ) ;
-
- if ( up->linediscipline == LDISC_RAW ) {
- /*
- * The reply with <STX> and <ETX> may give a blank line
- */
- if ( pp->lencode == 0 && up->charcount == 0 ) return ;
- /*
- * Copy received charaters to temporary buffer
- */
- for ( i = 0 ; i < pp->lencode && up->charcount < MAX_RAWBUF - 2 ; i ++ , up->charcount ++ ) {
- up->rawbuf[up->charcount] = pp->a_lastcode[i] ;
- }
- while ( up->charcount > 0 && up->rawbuf[0] < ' ' ) {
- for ( i = 0 ; i < up->charcount - 1 ; i ++ ) up->rawbuf[i] = up->rawbuf[i+1] ;
- up->charcount -- ;
- }
- bCntrlChar = 0 ;
- for ( i = 0 ; i < up->charcount ; i ++ ) {
- if ( up->rawbuf[i] < ' ' ) {
- bCntrlChar = 1 ;
- break ;
- }
- }
- if ( pp->lencode > 0 && up->linecount < up->lineexpect ) {
- if ( bCntrlChar == 0 && up->charcount < up->charexpect[up->linecount] ) return ;
- }
- up->rawbuf[up->charcount] = 0 ;
- } else {
- /*
- * The reply with <CR><LF> gives a blank line
- */
- if ( pp->lencode == 0 ) return ;
- }
- /*
- * We get down to business
- */
-
- pp->lastrec = tRecvTimestamp ;
-
- up->linecount ++ ;
-
- if ( up->lineerror != 0 ) return ;
-
- switch ( up->unittype ) {
-
- case UNITTYPE_TRISTATE_JJY01 :
- rc = jjy_receive_tristate_jjy01 ( rbufp ) ;
- break ;
-
- case UNITTYPE_CDEX_JST2000 :
- rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
- break ;
-
- default :
- rc = 0 ;
- break ;
-
- }
-
- if ( up->linediscipline == LDISC_RAW ) {
- if ( up->linecount <= up->lineexpect && up->charcount > up->charexpect[up->linecount-1] ) {
- for ( i = 0 ; i < up->charcount - up->charexpect[up->linecount-1] ; i ++ ) {
- up->rawbuf[i] = up->rawbuf[i+up->charexpect[up->linecount-1]] ;
- }
- up->charcount -= up->charexpect[up->linecount-1] ;
- } else {
- up->charcount = 0 ;
- }
- }
-
- if ( rc == 0 ) return ;
-
- if ( up->lineerror != 0 ) {
- refclock_report ( peer, CEVNT_BADREPLY ) ;
- strcpy ( sLogText, "BAD REPLY [" ) ;
- if ( up->linediscipline == LDISC_RAW ) {
- strncat ( sLogText, up->rawbuf, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
- } else {
- strncat ( sLogText, pp->a_lastcode, MAX_LOGTEXT - strlen ( sLogText ) - 1 ) ;
- }
- sLogText[MAX_LOGTEXT-1] = 0 ;
- if ( strlen ( sLogText ) < MAX_LOGTEXT - 2 ) strcat ( sLogText, "]" ) ;
- record_clock_stats ( &peer->srcadr, sLogText ) ;
- return ;
- }
-
- pp->year = up->year ;
- pp->day = ymd2yd ( up->year, up->month, up->day ) ;
- pp->hour = up->hour ;
- pp->minute = up->minute ;
- pp->second = up->second ;
- pp->nsec = up->msecond * 1000000;
-
- /*
- * JST to UTC
- */
- pp->hour -= 9 ;
- if ( pp->hour < 0 ) {
- pp->hour += 24 ;
- pp->day -- ;
- if ( pp->day < 1 ) {
- pp->year -- ;
- pp->day = ymd2yd ( pp->year, 12, 31 ) ;
- }
- }
-#ifdef DEBUG
- if ( debug ) {
- printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d JST ",
- up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
- printf ( "( %04d/%03d %02d:%02d:%02d UTC )\n",
- pp->year, pp->day, pp->hour, pp->minute, pp->second ) ;
- }
-#endif
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if ( ! refclock_process ( pp ) ) {
- refclock_report(peer, CEVNT_BADTIME);
- sprintf ( sLogText, "BAD TIME %04d/%02d/%02d %02d:%02d:%02d JST",
- up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
- record_clock_stats ( &peer->srcadr, sLogText ) ;
- return ;
- }
-
- sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d JST",
- up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats ( &peer->srcadr, sLogText ) ;
-}
-
-/**************************************************************************************************/
-
-static int
-jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
-{
-
- struct jjyunit *up ;
- struct refclockproc *pp ;
- struct peer *peer;
-
- char *pBuf ;
- int iLen ;
- int rc ;
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *) rbufp->recv_srcclock ;
- pp = peer->procptr ;
- up = (struct jjyunit *) pp->unitptr ;
-
- if ( up->linediscipline == LDISC_RAW ) {
- pBuf = up->rawbuf ;
- iLen = up->charcount ;
- } else {
- pBuf = pp->a_lastcode ;
- iLen = pp->lencode ;
- }
-
- switch ( up->linecount ) {
-
- case 1 : /* YYYY/MM/DD */
-
- if ( iLen < 10 ) {
- up->lineerror = 1 ;
- break ;
- }
- rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
- if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) {
- up->lineerror = 1 ;
- break ;
- }
- return 0 ;
-
- case 2 : /* HH:MM:SS */
-
- if ( iLen < 8 ) {
- up->lineerror = 1 ;
- break ;
- }
- rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
- if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
- up->lineerror = 1 ;
- break ;
- }
- up->msecond = 0 ;
- if ( up->hour == 0 && up->minute == 0 && up->second <= 2 ) {
- /*
- * The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously.
- * But the JJY receiver replies a date and time separately.
- * Just after midnight transtions, we ignore this time.
- */
- return 0 ;
- }
- break ;
-
- default : /* Unexpected reply */
-
- up->lineerror = 1 ;
- break ;
-
- }
-
- return 1 ;
-
-}
-
-/**************************************************************************************************/
-
-static int
-jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
-{
-
- struct jjyunit *up ;
- struct refclockproc *pp ;
- struct peer *peer;
-
- char *pBuf ;
- int iLen ;
- int rc ;
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *) rbufp->recv_srcclock ;
- pp = peer->procptr ;
- up = (struct jjyunit *) pp->unitptr ;
-
- if ( up->linediscipline == LDISC_RAW ) {
- pBuf = up->rawbuf ;
- iLen = up->charcount ;
- } else {
- pBuf = pp->a_lastcode ;
- iLen = pp->lencode ;
- }
-
- switch ( up->linecount ) {
-
- case 1 : /* JYYMMDD HHMMSSS */
-
- if ( iLen < 15 ) {
- up->lineerror = 1 ;
- break ;
- }
- rc = sscanf ( pBuf, "J%2d%2d%2d%*1d%2d%2d%2d%1d",
- &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ;
- if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
- || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
- up->lineerror = 1 ;
- break ;
- }
- up->year += 2000 ;
- up->msecond *= 100 ;
- break ;
-
- default : /* Unexpected reply */
-
- up->lineerror = 1 ;
- break ;
-
- }
-
- return 1 ;
-
-}
-
-/**************************************************************************************************/
-/* jjy_poll - called by the transmit procedure */
-/**************************************************************************************************/
-static void
-jjy_poll ( int unit, struct peer *peer )
-{
-
- struct jjyunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct jjyunit *) pp->unitptr ;
-
- if ( pp->polls > 0 && up->linecount == 0 ) {
- /*
- * No reply for last command
- */
- refclock_report ( peer, CEVNT_TIMEOUT ) ;
- }
-
-#ifdef DEBUG
- if ( debug ) {
- printf ( "jjy_poll (refclock_jjy.c) : %ld\n", pp->polls ) ;
- }
-#endif
-
- pp->polls ++ ;
-
- up->linecount = 0 ;
- up->lineerror = 0 ;
- up->charcount = 0 ;
-
- switch ( up->unittype ) {
-
- case UNITTYPE_TRISTATE_JJY01 :
- jjy_poll_tristate_jjy01 ( unit, peer ) ;
- break ;
-
- case UNITTYPE_CDEX_JST2000 :
- jjy_poll_cdex_jst2000 ( unit, peer ) ;
- break ;
-
- default :
- break ;
-
- }
-
-}
-
-/**************************************************************************************************/
-
-static void
-jjy_poll_tristate_jjy01 ( int unit, struct peer *peer )
-{
-
- struct jjyunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct jjyunit *) pp->unitptr ;
-
- /*
- * Send "date<CR><LF>" command
- */
-
- if ( write ( pp->io.fd, "date\r\n",6 ) != 6 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
-
- /*
- * Send "stim<CR><LF>" or "time<CR><LF>" command
- */
-
- if ( up->version >= 100 ) {
- if ( write ( pp->io.fd, "stim\r\n",6 ) != 6 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
- } else {
- if ( write ( pp->io.fd, "time\r\n",6 ) != 6 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
- }
-
-}
-
-/**************************************************************************************************/
-
-static void
-jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
-{
-
- struct refclockproc *pp;
-
- pp = peer->procptr;
-
- /*
- * Send "<ENQ>1J<ETX>" command
- */
-
- if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
-
-}
-
-#else
-int refclock_jjy_bs ;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_jupiter.c b/contrib/ntp/ntpd/refclock_jupiter.c
deleted file mode 100644
index eff088b..0000000
--- a/contrib/ntp/ntpd/refclock_jupiter.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*
- * Copyright (c) 1997, 1998, 2003
- * 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.
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(HAVE_PPSAPI)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include "jupiter.h"
-
-#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
-#endif
-
-#ifdef XNTP_BIG_ENDIAN
-#define getshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
-#define putshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
-#else
-#define getshort(s) (s)
-#define putshort(s) (s)
-#endif
-
-/* XXX */
-#ifdef sun
-char *strerror(int);
-#endif
-
-/*
- * This driver supports the Rockwell Jupiter GPS Receiver board
- * adapted to precision timing applications. It requires the
- * ppsclock line discipline or streams module described in the
- * Line Disciplines and Streams Drivers page. It also requires a
- * gadget box and 1-PPS level converter, such as described in the
- * Pulse-per-second (PPS) Signal Interfacing page.
- *
- * It may work (with minor modifications) with other Rockwell GPS
- * receivers such as the CityTracker.
- */
-
-/*
- * GPS Definitions
- */
-#define DEVICE "/dev/gps%d" /* device name and unit */
-#define SPEED232 B9600 /* baud */
-
-/*
- * Radio interface parameters
- */
-#define PRECISION (-18) /* precision assumed (about 4 us) */
-#define REFID "GPS\0" /* reference id */
-#define DESCRIPTION "Rockwell Jupiter GPS Receiver" /* who we are */
-#define DEFFUDGETIME 0 /* default fudge time (ms) */
-
-/* Unix timestamp for the GPS epoch: January 6, 1980 */
-#define GPS_EPOCH 315964800
-
-/* Double short to unsigned int */
-#define DS2UI(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
-
-/* Double short to signed int */
-#define DS2I(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
-
-/* One week's worth of seconds */
-#define WEEKSECS (7 * 24 * 60 * 60)
-
-/*
- * Jupiter unit control structure.
- */
-struct instance {
- struct peer *peer; /* peer */
- u_int pollcnt; /* poll message counter */
- u_int polled; /* Hand in a time sample? */
-#ifdef HAVE_PPSAPI
- pps_params_t pps_params; /* pps parameters */
- pps_info_t pps_info; /* last pps data */
- pps_handle_t pps_handle; /* pps handle */
- u_int assert; /* pps edge to use */
- struct timespec ts; /* last timestamp */
-#endif
- l_fp limit;
- u_int gpos_gweek; /* Current GPOS GPS week number */
- u_int gpos_sweek; /* Current GPOS GPS seconds into week */
- u_int gweek; /* current GPS week number */
- u_int32 lastsweek; /* last seconds into GPS week */
- time_t timecode; /* current ntp timecode */
- u_int32 stime; /* used to detect firmware bug */
- int wantid; /* don't reconfig on channel id msg */
- u_int moving; /* mobile platform? */
- u_char sloppyclockflag; /* fudge flags */
- u_short sbuf[512]; /* local input buffer */
- int ssize; /* space used in sbuf */
-};
-
-/*
- * Function prototypes
- */
-static void jupiter_canmsg P((struct instance *, u_int));
-static u_short jupiter_cksum P((u_short *, u_int));
-static int jupiter_config P((struct instance *));
-static void jupiter_debug P((struct peer *, char *, char *, ...))
- __attribute__ ((format (printf, 3, 4)));
-static char * jupiter_parse_t P((struct instance *, u_short *));
-static char * jupiter_parse_gpos P((struct instance *, u_short *));
-static void jupiter_platform P((struct instance *, u_int));
-static void jupiter_poll P((int, struct peer *));
-static void jupiter_control P((int, struct refclockstat *, struct
- refclockstat *, struct peer *));
-#ifdef HAVE_PPSAPI
-static int jupiter_ppsapi P((struct instance *, int, int));
-static int jupiter_pps P((struct instance *));
-#endif /* HAVE_PPSAPI */
-static int jupiter_recv P((struct instance *));
-static void jupiter_receive P((struct recvbuf *rbufp));
-static void jupiter_reqmsg P((struct instance *, u_int, u_int));
-static void jupiter_reqonemsg P((struct instance *, u_int));
-static char * jupiter_send P((struct instance *, struct jheader *));
-static void jupiter_shutdown P((int, struct peer *));
-static int jupiter_start P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_jupiter = {
- jupiter_start, /* start up driver */
- jupiter_shutdown, /* shut down driver */
- jupiter_poll, /* transmit poll message */
- jupiter_control, /* (clock control) */
- noentry, /* (clock init) */
- noentry, /* (clock buginfo) */
- NOFLAGS /* not used */
-};
-
-/*
- * jupiter_start - open the devices and initialize data for processing
- */
-static int
-jupiter_start(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct instance *instance;
- int fd = -1;
- char gpsdev[20];
-
- /*
- * Open serial port
- */
- (void)sprintf(gpsdev, DEVICE, unit);
- fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
- if (fd == 0) {
- jupiter_debug(peer, "jupiter_start", "open %s: %s",
- gpsdev, strerror(errno));
- return (0);
- }
-
- /* Allocate unit structure */
- if ((instance = (struct instance *)
- emalloc(sizeof(struct instance))) == NULL) {
- (void) close(fd);
- return (0);
- }
- memset((char *)instance, 0, sizeof(struct instance));
- instance->peer = peer;
- pp = peer->procptr;
- pp->io.clock_recv = jupiter_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
- (void) close(fd);
- free(instance);
- return (0);
- }
- pp->unitptr = (caddr_t)instance;
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
-
-#ifdef HAVE_PPSAPI
- /*
- * Start the PPSAPI interface if it is there. Default to use
- * the assert edge and do not enable the kernel hardpps.
- */
- if (time_pps_create(fd, &instance->pps_handle) < 0) {
- instance->pps_handle = 0;
- msyslog(LOG_ERR,
- "refclock_jupiter: time_pps_create failed: %m");
- }
- else if (!jupiter_ppsapi(instance, 0, 0))
- goto clean_up;
-#endif /* HAVE_PPSAPI */
-
- /* Ensure the receiver is properly configured */
- if (!jupiter_config(instance))
- goto clean_up;
-
- return (1);
-
-clean_up:
- jupiter_shutdown(unit, peer);
- pp->unitptr = 0;
- return (0);
-}
-
-/*
- * jupiter_shutdown - shut down the clock
- */
-static void
-jupiter_shutdown(int unit, struct peer *peer)
-{
- struct instance *instance;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- instance = (struct instance *)pp->unitptr;
- if(!instance)
- return;
-
-#ifdef HAVE_PPSAPI
- if (instance->pps_handle) {
- time_pps_destroy(instance->pps_handle);
- instance->pps_handle = 0;
- }
-#endif /* HAVE_PPSAPI */
-
- io_closeclock(&pp->io);
- free(instance);
-}
-
-/*
- * jupiter_config - Configure the receiver
- */
-static int
-jupiter_config(struct instance *instance)
-{
- jupiter_debug(instance->peer, "jupiter_config", "init receiver");
-
- /*
- * Initialize the unit variables
- */
- instance->sloppyclockflag = instance->peer->procptr->sloppyclockflag;
- instance->moving = !!(instance->sloppyclockflag & CLK_FLAG2);
- if (instance->moving)
- jupiter_debug(instance->peer, "jupiter_config",
- "mobile platform");
-
- instance->pollcnt = 2;
- instance->polled = 0;
- instance->gpos_gweek = 0;
- instance->gpos_sweek = 0;
- instance->gweek = 0;
- instance->lastsweek = 2 * WEEKSECS;
- instance->timecode = 0;
- instance->stime = 0;
- instance->ssize = 0;
-
- /* Stop outputting all messages */
- jupiter_canmsg(instance, JUPITER_ALL);
-
- /* Request the receiver id so we can syslog the firmware version */
- jupiter_reqonemsg(instance, JUPITER_O_ID);
-
- /* Flag that this the id was requested (so we don't get called again) */
- instance->wantid = 1;
-
- /* Request perodic time mark pulse messages */
- jupiter_reqmsg(instance, JUPITER_O_PULSE, 1);
-
- /* Request perodic geodetic position status */
- jupiter_reqmsg(instance, JUPITER_O_GPOS, 1);
-
- /* Set application platform type */
- if (instance->moving)
- jupiter_platform(instance, JUPITER_I_PLAT_MED);
- else
- jupiter_platform(instance, JUPITER_I_PLAT_LOW);
-
- return (1);
-}
-
-#ifdef HAVE_PPSAPI
-/*
- * Initialize PPSAPI
- */
-int
-jupiter_ppsapi(
- struct instance *instance, /* unit structure pointer */
- int enb_clear, /* clear enable */
- int enb_hardpps /* hardpps enable */
- )
-{
- int capability;
-
- if (time_pps_getcap(instance->pps_handle, &capability) < 0) {
- msyslog(LOG_ERR,
- "refclock_jupiter: time_pps_getcap failed: %m");
- return (0);
- }
- memset(&instance->pps_params, 0, sizeof(pps_params_t));
- if (enb_clear)
- instance->pps_params.mode = capability & PPS_CAPTURECLEAR;
- else
- instance->pps_params.mode = capability & PPS_CAPTUREASSERT;
- if (!(instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
- msyslog(LOG_ERR,
- "refclock_jupiter: invalid capture edge %d",
- !enb_clear);
- return (0);
- }
- instance->pps_params.mode |= PPS_TSFMT_TSPEC;
- if (time_pps_setparams(instance->pps_handle, &instance->pps_params) < 0) {
- msyslog(LOG_ERR,
- "refclock_jupiter: time_pps_setparams failed: %m");
- return (0);
- }
- if (enb_hardpps) {
- if (time_pps_kcbind(instance->pps_handle, PPS_KC_HARDPPS,
- instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR),
- PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR,
- "refclock_jupiter: time_pps_kcbind failed: %m");
- return (0);
- }
- pps_enable = 1;
- }
-/* instance->peer->precision = PPS_PRECISION; */
-
-#if DEBUG
- if (debug) {
- time_pps_getparams(instance->pps_handle, &instance->pps_params);
- jupiter_debug(instance->peer, "refclock_jupiter",
- "pps capability 0x%x version %d mode 0x%x kern %d",
- capability, instance->pps_params.api_version,
- instance->pps_params.mode, enb_hardpps);
- }
-#endif
-
- return (1);
-}
-
-/*
- * Get PPSAPI timestamps.
- *
- * Return 0 on failure and 1 on success.
- */
-static int
-jupiter_pps(struct instance *instance)
-{
- pps_info_t pps_info;
- struct timespec timeout, ts;
- double dtemp;
- l_fp tstmp;
-
- /*
- * Convert the timespec nanoseconds field to ntp l_fp units.
- */
- if (instance->pps_handle == 0)
- return 1;
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- memcpy(&pps_info, &instance->pps_info, sizeof(pps_info_t));
- if (time_pps_fetch(instance->pps_handle, PPS_TSFMT_TSPEC, &instance->pps_info,
- &timeout) < 0)
- return 1;
- if (instance->pps_params.mode & PPS_CAPTUREASSERT) {
- if (pps_info.assert_sequence ==
- instance->pps_info.assert_sequence)
- return 1;
- ts = instance->pps_info.assert_timestamp;
- } else if (instance->pps_params.mode & PPS_CAPTURECLEAR) {
- if (pps_info.clear_sequence ==
- instance->pps_info.clear_sequence)
- return 1;
- ts = instance->pps_info.clear_timestamp;
- } else {
- return 1;
- }
- if ((instance->ts.tv_sec == ts.tv_sec) && (instance->ts.tv_nsec == ts.tv_nsec))
- return 1;
- instance->ts = ts;
-
- tstmp.l_ui = ts.tv_sec + JAN_1970;
- dtemp = ts.tv_nsec * FRAC / 1e9;
- tstmp.l_uf = (u_int32)dtemp;
- instance->peer->procptr->lastrec = tstmp;
- return 0;
-}
-#endif /* HAVE_PPSAPI */
-
-/*
- * jupiter_poll - jupiter watchdog routine
- */
-static void
-jupiter_poll(int unit, struct peer *peer)
-{
- struct instance *instance;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- instance = (struct instance *)pp->unitptr;
-
- /*
- * 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 we haven't had a response in a while, reset the receiver.
- */
- if (instance->pollcnt > 0) {
- instance->pollcnt--;
- } else {
- refclock_report(peer, CEVNT_TIMEOUT);
-
- /* Request the receiver id to trigger a reconfig */
- jupiter_reqonemsg(instance, JUPITER_O_ID);
- instance->wantid = 0;
- }
-
- /*
- * polled every 64 seconds. Ask jupiter_receive to hand in
- * a timestamp.
- */
- instance->polled = 1;
- pp->polls++;
-}
-
-/*
- * jupiter_control - fudge control
- */
-static void
-jupiter_control(
- int unit, /* unit (not used) */
- struct refclockstat *in, /* input parameters (not used) */
- struct refclockstat *out, /* output parameters (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct instance *instance;
- u_char sloppyclockflag;
-
- pp = peer->procptr;
- instance = (struct instance *)pp->unitptr;
-
- DTOLFP(pp->fudgetime2, &instance->limit);
- /* Force positive value. */
- if (L_ISNEG(&instance->limit))
- L_NEG(&instance->limit);
-
-#ifdef HAVE_PPSAPI
- instance->assert = !(pp->sloppyclockflag & CLK_FLAG3);
- jupiter_ppsapi(instance, !instance->assert, 0);
-#endif /* HAVE_PPSAPI */
-
- sloppyclockflag = instance->sloppyclockflag;
- instance->sloppyclockflag = pp->sloppyclockflag;
- if ((instance->sloppyclockflag & CLK_FLAG2) !=
- (sloppyclockflag & CLK_FLAG2)) {
- jupiter_debug(peer,
- "jupiter_control",
- "mode switch: reset receiver");
- jupiter_config(instance);
- return;
- }
-}
-
-/*
- * jupiter_receive - receive gps data
- * Gag me!
- */
-static void
-jupiter_receive(struct recvbuf *rbufp)
-{
- int bpcnt, cc, size, ppsret;
- time_t last_timecode;
- u_int32 laststime;
- char *cp;
- u_char *bp;
- u_short *sp;
- struct jid *ip;
- struct jheader *hp;
- struct peer *peer;
- struct refclockproc *pp;
- struct instance *instance;
- l_fp tstamp;
-
- /* Initialize pointers and read the timecode and timestamp */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- instance = (struct instance *)pp->unitptr;
-
- bp = (u_char *)rbufp->recv_buffer;
- bpcnt = rbufp->recv_length;
-
- /* This shouldn't happen */
- if (bpcnt > sizeof(instance->sbuf) - instance->ssize)
- bpcnt = sizeof(instance->sbuf) - instance->ssize;
-
- /* Append to input buffer */
- memcpy((u_char *)instance->sbuf + instance->ssize, bp, bpcnt);
- instance->ssize += bpcnt;
-
- /* While there's at least a header and we parse an intact message */
- while (instance->ssize > sizeof(*hp) && (cc = jupiter_recv(instance)) > 0) {
- instance->pollcnt = 2;
-
- tstamp = rbufp->recv_time;
- hp = (struct jheader *)instance->sbuf;
- sp = (u_short *)(hp + 1);
- size = cc - sizeof(*hp);
- switch (getshort(hp->id)) {
-
- case JUPITER_O_PULSE:
- if (size != sizeof(struct jpulse)) {
- jupiter_debug(peer,
- "jupiter_receive", "pulse: len %d != %u",
- size, (int)sizeof(struct jpulse));
- refclock_report(peer, CEVNT_BADREPLY);
- break;
- }
-
- /*
- * There appears to be a firmware bug related
- * to the pulse message; in addition to the one
- * per second messages, we get an extra pulse
- * message once an hour (on the anniversary of
- * the cold start). It seems to come 200 ms
- * after the one requested. So if we've seen a
- * pulse message in the last 210 ms, we skip
- * this one.
- */
- laststime = instance->stime;
- instance->stime = DS2UI(((struct jpulse *)sp)->stime);
- if (laststime != 0 && instance->stime - laststime <= 21) {
- jupiter_debug(peer, "jupiter_receive",
- "avoided firmware bug (stime %.2f, laststime %.2f)",
- (double)instance->stime * 0.01, (double)laststime * 0.01);
- break;
- }
-
- /* Retrieve pps timestamp */
- ppsret = jupiter_pps(instance);
-
- /*
- * Add one second if msg received early
- * (i.e. before limit, a.k.a. fudgetime2) in
- * the second.
- */
- L_SUB(&tstamp, &pp->lastrec);
- if (!L_ISGEQ(&tstamp, &instance->limit))
- ++pp->lastrec.l_ui;
-
- /* Parse timecode (even when there's no pps) */
- last_timecode = instance->timecode;
- if ((cp = jupiter_parse_t(instance, sp)) != NULL) {
- jupiter_debug(peer,
- "jupiter_receive", "pulse: %s", cp);
- break;
- }
-
- /* Bail if we didn't get a pps timestamp */
- if (ppsret)
- break;
-
- /* Bail if we don't have the last timecode yet */
- if (last_timecode == 0)
- break;
-
- /* Add the new sample to a median filter */
- tstamp.l_ui = JAN_1970 + last_timecode;
- tstamp.l_uf = 0;
-
- refclock_process_offset(pp, tstamp, pp->lastrec, pp->fudgetime1);
-
- /*
- * The clock will blurt a timecode every second
- * but we only want one when polled. If we
- * havn't been polled, bail out.
- */
- if (!instance->polled)
- break;
- instance->polled = 0;
-
- /*
- * It's a live one! Remember this time.
- */
-
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-
- /*
- * If we get here - what we got from the clock is
- * OK, so say so
- */
- refclock_report(peer, CEVNT_NOMINAL);
-
- /*
- * We have succeeded in answering the poll.
- * Turn off the flag and return
- */
- instance->polled = 0;
- break;
-
- case JUPITER_O_GPOS:
- if (size != sizeof(struct jgpos)) {
- jupiter_debug(peer,
- "jupiter_receive", "gpos: len %d != %u",
- size, (int)sizeof(struct jgpos));
- refclock_report(peer, CEVNT_BADREPLY);
- break;
- }
-
- if ((cp = jupiter_parse_gpos(instance, sp)) != NULL) {
- jupiter_debug(peer,
- "jupiter_receive", "gpos: %s", cp);
- break;
- }
- break;
-
- case JUPITER_O_ID:
- if (size != sizeof(struct jid)) {
- jupiter_debug(peer,
- "jupiter_receive", "id: len %d != %u",
- size, (int)sizeof(struct jid));
- refclock_report(peer, CEVNT_BADREPLY);
- break;
- }
- /*
- * If we got this message because the Jupiter
- * just powered instance, it needs to be reconfigured.
- */
- ip = (struct jid *)sp;
- jupiter_debug(peer,
- "jupiter_receive", "%s chan ver %s, %s (%s)",
- ip->chans, ip->vers, ip->date, ip->opts);
- msyslog(LOG_DEBUG,
- "jupiter_receive: %s chan ver %s, %s (%s)\n",
- ip->chans, ip->vers, ip->date, ip->opts);
- if (instance->wantid)
- instance->wantid = 0;
- else {
- jupiter_debug(peer,
- "jupiter_receive", "reset receiver");
- jupiter_config(instance);
- /*
- * Restore since jupiter_config() just
- * zeroed it
- */
- instance->ssize = cc;
- }
- break;
-
- default:
- jupiter_debug(peer,
- "jupiter_receive", "unknown message id %d",
- getshort(hp->id));
- break;
- }
- instance->ssize -= cc;
- if (instance->ssize < 0) {
- fprintf(stderr, "jupiter_recv: negative ssize!\n");
- abort();
- } else if (instance->ssize > 0)
- memcpy(instance->sbuf, (u_char *)instance->sbuf + cc, instance->ssize);
- }
-}
-
-static char *
-jupiter_parse_t(struct instance *instance, u_short *sp)
-{
- struct tm *tm;
- char *cp;
- struct jpulse *jp;
- u_int32 sweek;
- time_t last_timecode;
- u_short flags;
-
- jp = (struct jpulse *)sp;
-
- /* The timecode is presented as seconds into the current GPS week */
- sweek = DS2UI(jp->sweek) % WEEKSECS;
-
- /*
- * If we don't know the current GPS week, calculate it from the
- * current time. (It's too bad they didn't include this
- * important value in the pulse message). We'd like to pick it
- * up from one of the other messages like gpos or chan but they
- * don't appear to be synchronous with time keeping and changes
- * too soon (something like 10 seconds before the new GPS
- * week).
- *
- * If we already know the current GPS week, increment it when
- * we wrap into a new week.
- */
- if (instance->gweek == 0) {
- if (!instance->gpos_gweek) {
- return ("jupiter_parse_t: Unknown gweek");
- }
-
- instance->gweek = instance->gpos_gweek;
-
- /*
- * Fix warps. GPOS has GPS time and PULSE has UTC.
- * Plus, GPOS need not be completely in synch with
- * the PPS signal.
- */
- if (instance->gpos_sweek >= sweek) {
- if ((instance->gpos_sweek - sweek) > WEEKSECS / 2)
- ++instance->gweek;
- }
- else {
- if ((sweek - instance->gpos_sweek) > WEEKSECS / 2)
- --instance->gweek;
- }
- }
- else if (sweek == 0 && instance->lastsweek == WEEKSECS - 1) {
- ++instance->gweek;
- jupiter_debug(instance->peer,
- "jupiter_parse_t", "NEW gps week %u", instance->gweek);
- }
-
- /*
- * See if the sweek stayed the same (this happens when there is
- * no pps pulse).
- *
- * Otherwise, look for time warps:
- *
- * - we have stored at least one lastsweek and
- * - the sweek didn't increase by one and
- * - we didn't wrap to a new GPS week
- *
- * Then we warped.
- */
- if (instance->lastsweek == sweek)
- jupiter_debug(instance->peer,
- "jupiter_parse_t", "gps sweek not incrementing (%d)",
- sweek);
- else if (instance->lastsweek != 2 * WEEKSECS &&
- instance->lastsweek + 1 != sweek &&
- !(sweek == 0 && instance->lastsweek == WEEKSECS - 1))
- jupiter_debug(instance->peer,
- "jupiter_parse_t", "gps sweek jumped (was %d, now %d)",
- instance->lastsweek, sweek);
- instance->lastsweek = sweek;
-
- /* This timecode describes next pulse */
- last_timecode = instance->timecode;
- instance->timecode =
- GPS_EPOCH + (instance->gweek * WEEKSECS) + sweek;
-
- if (last_timecode == 0)
- /* XXX debugging */
- jupiter_debug(instance->peer,
- "jupiter_parse_t", "UTC <none> (gweek/sweek %u/%u)",
- instance->gweek, sweek);
- else {
- /* XXX debugging */
- tm = gmtime(&last_timecode);
- cp = asctime(tm);
-
- jupiter_debug(instance->peer,
- "jupiter_parse_t", "UTC %.24s (gweek/sweek %u/%u)",
- cp, instance->gweek, sweek);
-
- /* Billboard last_timecode (which is now the current time) */
- instance->peer->procptr->year = tm->tm_year + 1900;
- instance->peer->procptr->day = tm->tm_yday + 1;
- instance->peer->procptr->hour = tm->tm_hour;
- instance->peer->procptr->minute = tm->tm_min;
- instance->peer->procptr->second = tm->tm_sec;
- }
-
- flags = getshort(jp->flags);
-
- /* Toss if not designated "valid" by the gps */
- if ((flags & JUPITER_O_PULSE_VALID) == 0) {
- refclock_report(instance->peer, CEVNT_BADTIME);
- return ("time mark not valid");
- }
-
- /* We better be sync'ed to UTC... */
- if ((flags & JUPITER_O_PULSE_UTC) == 0) {
- refclock_report(instance->peer, CEVNT_BADTIME);
- return ("time mark not sync'ed to UTC");
- }
-
- return (NULL);
-}
-
-static char *
-jupiter_parse_gpos(struct instance *instance, u_short *sp)
-{
- struct jgpos *jg;
- time_t t;
- struct tm *tm;
- char *cp;
-
- jg = (struct jgpos *)sp;
-
- if (jg->navval != 0) {
- /*
- * Solution not valid. Use caution and refuse
- * to determine GPS week from this message.
- */
- instance->gpos_gweek = 0;
- instance->gpos_sweek = 0;
- return ("Navigation solution not valid");
- }
-
- instance->gpos_gweek = jg->gweek;
- instance->gpos_sweek = DS2UI(jg->sweek);
- while(instance->gpos_sweek >= WEEKSECS) {
- instance->gpos_sweek -= WEEKSECS;
- ++instance->gpos_gweek;
- }
- instance->gweek = 0;
-
- t = GPS_EPOCH + (instance->gpos_gweek * WEEKSECS) + instance->gpos_sweek;
- tm = gmtime(&t);
- cp = asctime(tm);
-
- jupiter_debug(instance->peer,
- "jupiter_parse_g", "GPS %.24s (gweek/sweek %u/%u)",
- cp, instance->gpos_gweek, instance->gpos_sweek);
- return (NULL);
-}
-
-/*
- * jupiter_debug - print debug messages
- */
-#if defined(__STDC__) || defined(SYS_WINNT)
-static void
-jupiter_debug(struct peer *peer, char *function, char *fmt, ...)
-#else
-static void
-jupiter_debug(peer, function, fmt, va_alist)
- struct peer *peer;
- char *function;
- char *fmt;
-#endif /* __STDC__ */
-{
- char buffer[200];
- va_list ap;
-
-#if defined(__STDC__) || defined(SYS_WINNT)
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif /* __STDC__ */
- /*
- * Print debug message to stdout
- * In the future, we may want to get get more creative...
- */
- vsnprintf(buffer, sizeof(buffer), fmt, ap);
- record_clock_stats(&(peer->srcadr), buffer);
- if (debug) {
- fprintf(stdout, "%s: ", function);
- fprintf(stdout, buffer);
- fprintf(stdout, "\n");
- fflush(stdout);
- }
-
- va_end(ap);
-}
-
-/* Checksum and transmit a message to the Jupiter */
-static char *
-jupiter_send(struct instance *instance, struct jheader *hp)
-{
- u_int len, size;
- int cc;
- u_short *sp;
- static char errstr[132];
-
- size = sizeof(*hp);
- hp->hsum = putshort(jupiter_cksum((u_short *)hp,
- (size / sizeof(u_short)) - 1));
- len = getshort(hp->len);
- if (len > 0) {
- sp = (u_short *)(hp + 1);
- sp[len] = putshort(jupiter_cksum(sp, len));
- size += (len + 1) * sizeof(u_short);
- }
-
- if ((cc = write(instance->peer->procptr->io.fd, (char *)hp, size)) < 0) {
- (void)sprintf(errstr, "write: %s", strerror(errno));
- return (errstr);
- } else if (cc != size) {
- (void)sprintf(errstr, "short write (%d != %d)", cc, size);
- return (errstr);
- }
- return (NULL);
-}
-
-/* Request periodic message output */
-static struct {
- struct jheader jheader;
- struct jrequest jrequest;
-} reqmsg = {
- { putshort(JUPITER_SYNC), 0,
- putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
- 0, (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
- JUPITER_FLAG_CONN | JUPITER_FLAG_LOG), 0 },
- { 0, 0, 0, 0 }
-};
-
-/* An interval of zero means to output on trigger */
-static void
-jupiter_reqmsg(struct instance *instance, u_int id,
- u_int interval)
-{
- struct jheader *hp;
- struct jrequest *rp;
- char *cp;
-
- hp = &reqmsg.jheader;
- hp->id = putshort(id);
- rp = &reqmsg.jrequest;
- rp->trigger = putshort(interval == 0);
- rp->interval = putshort(interval);
- if ((cp = jupiter_send(instance, hp)) != NULL)
- jupiter_debug(instance->peer, "jupiter_reqmsg", "%u: %s", id, cp);
-}
-
-/* Cancel periodic message output */
-static struct jheader canmsg = {
- putshort(JUPITER_SYNC), 0, 0, 0,
- (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC),
- 0
-};
-
-static void
-jupiter_canmsg(struct instance *instance, u_int id)
-{
- struct jheader *hp;
- char *cp;
-
- hp = &canmsg;
- hp->id = putshort(id);
- if ((cp = jupiter_send(instance, hp)) != NULL)
- jupiter_debug(instance->peer, "jupiter_canmsg", "%u: %s", id, cp);
-}
-
-/* Request a single message output */
-static struct jheader reqonemsg = {
- putshort(JUPITER_SYNC), 0, 0, 0,
- (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY),
- 0
-};
-
-static void
-jupiter_reqonemsg(struct instance *instance, u_int id)
-{
- struct jheader *hp;
- char *cp;
-
- hp = &reqonemsg;
- hp->id = putshort(id);
- if ((cp = jupiter_send(instance, hp)) != NULL)
- jupiter_debug(instance->peer, "jupiter_reqonemsg", "%u: %s", id, cp);
-}
-
-/* Set the platform dynamics */
-static struct {
- struct jheader jheader;
- struct jplat jplat;
-} platmsg = {
- { putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
- putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
- (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK), 0 },
- { 0, 0, 0 }
-};
-
-static void
-jupiter_platform(struct instance *instance, u_int platform)
-{
- struct jheader *hp;
- struct jplat *pp;
- char *cp;
-
- hp = &platmsg.jheader;
- pp = &platmsg.jplat;
- pp->platform = putshort(platform);
- if ((cp = jupiter_send(instance, hp)) != NULL)
- jupiter_debug(instance->peer, "jupiter_platform", "%u: %s", platform, cp);
-}
-
-/* Checksum "len" shorts */
-static u_short
-jupiter_cksum(u_short *sp, u_int len)
-{
- u_short sum, x;
-
- sum = 0;
- while (len-- > 0) {
- x = *sp++;
- sum += getshort(x);
- }
- return (~sum + 1);
-}
-
-/* Return the size of the next message (or zero if we don't have it all yet) */
-static int
-jupiter_recv(struct instance *instance)
-{
- int n, len, size, cc;
- struct jheader *hp;
- u_char *bp;
- u_short *sp;
-
- /* Must have at least a header's worth */
- cc = sizeof(*hp);
- size = instance->ssize;
- if (size < cc)
- return (0);
-
- /* Search for the sync short if missing */
- sp = instance->sbuf;
- hp = (struct jheader *)sp;
- if (getshort(hp->sync) != JUPITER_SYNC) {
- /* Wasn't at the front, sync up */
- jupiter_debug(instance->peer, "jupiter_recv", "syncing");
- bp = (u_char *)sp;
- n = size;
- while (n >= 2) {
- if (bp[0] != (JUPITER_SYNC & 0xff)) {
- /*
- jupiter_debug(instance->peer, "{0x%x}", bp[0]);
- */
- ++bp;
- --n;
- continue;
- }
- if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))
- break;
- /*
- jupiter_debug(instance->peer, "{0x%x 0x%x}", bp[0], bp[1]);
- */
- bp += 2;
- n -= 2;
- }
- /*
- jupiter_debug(instance->peer, "\n");
- */
- /* Shuffle data to front of input buffer */
- if (n > 0)
- memcpy(sp, bp, n);
- size = n;
- instance->ssize = size;
- if (size < cc || hp->sync != JUPITER_SYNC)
- return (0);
- }
-
- if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) !=
- getshort(hp->hsum)) {
- jupiter_debug(instance->peer, "jupiter_recv", "bad header checksum!");
- /* This is drastic but checksum errors should be rare */
- instance->ssize = 0;
- return (0);
- }
-
- /* Check for a payload */
- len = getshort(hp->len);
- if (len > 0) {
- n = (len + 1) * sizeof(u_short);
- /* Not enough data yet */
- if (size < cc + n)
- return (0);
-
- /* Check payload checksum */
- sp = (u_short *)(hp + 1);
- if (jupiter_cksum(sp, len) != getshort(sp[len])) {
- jupiter_debug(instance->peer,
- "jupiter_recv", "bad payload checksum!");
- /* This is drastic but checksum errors should be rare */
- instance->ssize = 0;
- return (0);
- }
- cc += n;
- }
- return (cc);
-}
-
-#else /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
-int refclock_jupiter_bs;
-#endif /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
diff --git a/contrib/ntp/ntpd/refclock_leitch.c b/contrib/ntp/ntpd/refclock_leitch.c
deleted file mode 100644
index d7cd9bb..0000000
--- a/contrib/ntp/ntpd/refclock_leitch.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * refclock_leitch - clock driver for the Leitch CSD-5300 Master Clock
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_LEITCH)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#ifdef STREAM
-#include <stropts.h>
-#if defined(LEITCHCLK)
-#include <sys/clkdefs.h>
-#endif /* LEITCHCLK */
-#endif /* STREAM */
-
-#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 \
- msyslog(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
-
-/*
- * LEITCH unit control structure
- */
-struct leitchunit {
- struct peer *peer;
- 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((int, struct peer *));
-static void leitch_shutdown P((int, struct peer *));
-static void leitch_poll P((int, struct peer *));
-static void leitch_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
-#define leitch_buginfo noentry
-static void leitch_receive P((struct recvbuf *));
-static void leitch_process P((struct leitchunit *));
-#if 0
-static void leitch_timeout P((struct peer *));
-#endif
-static int leitch_get_date P((struct recvbuf *, struct leitchunit *));
-static int leitch_get_time P((struct recvbuf *, struct leitchunit *, int));
-static int days_per_year P((int));
-
-static struct leitchunit leitchunits[MAXUNITS];
-static u_char unitinuse[MAXUNITS];
-static u_char stratumtouse[MAXUNITS];
-static u_int32 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(void)
-{
- 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(
- int unit,
- struct peer *peer
- )
-{
-#ifdef DEBUG
- if (debug)
- fprintf(stderr, "leitch_shutdown()\n");
-#endif
-}
-
-/*
- * leitch_poll - called by the transmit procedure
- */
-static void
-leitch_poll(
- 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(
- int unit,
- struct refclockstat *in,
- struct refclockstat *out,
- struct peer *passed_peer
- )
-{
- if (unit >= MAXUNITS) {
- msyslog(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 = (int32)stratumtouse[unit];
- out->fudgeval2 = refid[unit];
- out->p_lastcode = "";
- out->clockdesc = LEITCH_DESCRIPTION;
- }
-}
-
-/*
- * leitch_start - open the LEITCH devices and initialize data for processing
- */
-static int
-leitch_start(
- int unit,
- struct peer *peer
- )
-{
- struct leitchunit *leitch;
- int fd232;
- char leitchdev[20];
-
- /*
- * Check configuration info.
- */
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "leitch_start: unit %d invalid", unit);
- return (0);
- }
-
- if (unitinuse[unit]) {
- msyslog(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) {
- msyslog(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) {
- msyslog(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) {
- msyslog(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.
- */
- { struct termios ttyb, *ttyp;
-
- ttyp = &ttyb;
- if (tcgetattr(fd232, ttyp) < 0) {
- msyslog(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) {
- msyslog(LOG_ERR,
- "leitch_start: tcsetattr(%s): %m", leitchdev);
- goto screwed;
- }
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- msyslog(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)
- msyslog(LOG_ERR,
- "leitch_start: ioctl(%s, I_PUSH, clk): %m", leitchdev);
- if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
- msyslog(LOG_ERR,
- "leitch_start: ioctl(%s, CLK_SETSTR): %m", leitchdev);
-#endif /* LEITCHCLK */
-#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) {
- msyslog(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) {
- msyslog(LOG_ERR,
- "leitch_start: ioctl(%s, TIOCSETP): %m", leitchdev);
- goto screwed;
- }
-#if defined(LEITCHCLK)
- if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
- msyslog(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.
- */
- peer->precision = 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(
- 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, 1, rbufp->recv_time.l_ui,
- &leitch->yearstart, &leitch->reftime1.l_ui)) {
- leitch->state = STATE_IDLE;
- break;
- }
- leitch->reftime1.l_uf = 0;
-#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, 1, 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, GMT, 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:
- msyslog(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(
- struct leitchunit *leitch
- )
-{
- l_fp off;
- l_fp tmp_fp;
- /*double doffset;*/
-
- off = leitch->reftime1;
- L_SUB(&off,&leitch->codetime1);
- tmp_fp = leitch->reftime2;
- L_SUB(&tmp_fp,&leitch->codetime2);
- if (L_ISGEQ(&off,&tmp_fp))
- off = tmp_fp;
- tmp_fp = leitch->reftime3;
- L_SUB(&tmp_fp,&leitch->codetime3);
-
- if (L_ISGEQ(&off,&tmp_fp))
- off = tmp_fp;
- /*LFPTOD(&off, doffset);*/
- refclock_receive(leitch->peer);
-}
-
-/*
- * days_per_year
- */
-static int
-days_per_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(
- struct recvbuf *rbufp,
- struct leitchunit *leitch
- )
-{
- int i;
-
- if (rbufp->recv_length < 6)
- return(0);
-#undef BAD /* confict: defined as (-1) in AIX sys/param.h */
-#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 ((days_per_year((leitch->year>90?1900:2000)+leitch->year)==365) &&
- leitch->month > 2)
- leitch->yearday--;
-
- return(1);
-}
-
-/*
- * leitch_get_time
- */
-static int
-leitch_get_time(
- 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);
-}
-
-#else
-int refclock_leitch_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_local.c b/contrib/ntp/ntpd/refclock_local.c
deleted file mode 100644
index 3478f43..0000000
--- a/contrib/ntp/ntpd/refclock_local.c
+++ /dev/null
@@ -1,264 +0,0 @@
-
-/*
- * refclock_local - local pseudo-clock driver
- *
- * wjm 17-aug-1995: add a hook for special treatment of VMS_LOCALUNIT
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef REFCLOCK
-
-#include "ntpd.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#ifdef KERNEL_PLL
-#include "ntp_syscall.h"
-#endif
-
-/*
- * 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 5) 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.
- *
- * THis driver includes provisions to telegraph synchronization state
- * and related variables by means of kernel variables with specially
- * modified kernels. This is done using the ntp_adjtime() syscall.
- * In the cases where another protocol or device synchronizes the local
- * host, the data given to the kernel can be slurped up by this driver
- * and distributed to clients by ordinary NTP messaging.
- *
- * 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 set at 5 by default, but it can be
- * changed by the fudge command and/or the ntpdc utility. The reference
- * ID is "LCL" by default, but can be changed using the same mechanism.
- * *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. Always remember that
- * an improperly configured local clock driver let loose in the Internet
- * can cause very serious disruption. This is why most of us who care
- * about good time use cryptographic authentication.
- *
- * 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. The fudge time1
- * parameter is additive; that is, it adds an increment to the current
- * time. The fudge time2 parameter directly sets the frequency.
- */
-/*
- * Local interface definitions
- */
-#define PRECISION (-7) /* about 10 ms precision */
-#if defined(VMS) && defined(VMS_LOCALUNIT)
-#define REFID "LCLv" /* reference ID */
-#else /* VMS VMS_LOCALUNIT */
-#define REFID "LCL\0" /* reference ID */
-#endif /* VMS VMS_LOCALUNIT */
-#define DESCRIPTION "Undisciplined local clock" /* WRU */
-
-#define STRATUM 5 /* default stratum */
-#define DISPERSION .01 /* default dispersion (10 ms) */
-
-/*
- * Imported from the timer module
- */
-extern u_long current_time;
-
-/*
- * Imported from ntp_proto
- */
-extern s_char sys_precision;
-
-#ifdef KERNEL_PLL
-/*
- * Imported from ntp_loopfilter
- */
-extern int pll_control; /* kernel pll control */
-extern int kern_enable; /* kernel pll enabled */
-extern int ext_enable; /* external clock enable */
-#endif /* KERNEL_PLL */
-
-/*
- * Function prototypes
- */
-static int local_start P((int, struct peer *));
-static void local_poll P((int, struct peer *));
-
-/*
- * Local variables
- */
-static u_long poll_time; /* last time polled */
-
-/*
- * Transfer vector
- */
-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 the clock
- */
-static int
-local_start(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = sys_precision;
- pp->leap = LEAP_NOTINSYNC;
- peer->stratum = STRATUM;
- pp->stratum = STRATUM;
- pp->clockdesc = DESCRIPTION;
- memcpy(&pp->refid, "INIT", 4);
- poll_time = current_time;
- return (1);
-}
-
-
-/*
- * local_poll - called by the transmit procedure
- *
- * LOCKCLOCK: If the kernel supports the nanokernel or microkernel
- * system calls, the leap bits are extracted from the kernel. If there
- * is a kernel error or the kernel leap bits are set to 11, the NTP leap
- * bits are set to 11 and the stratum is set to infinity. Otherwise, the
- * NTP leap bits are set to the kernel leap bits and the stratum is set
- * as fudged. This behavior does not faithfully follow the
- * specification, but is probably more appropriate in a multiple-server
- * national laboratory network.
- */
-static void
-local_poll(
- int unit,
- struct peer *peer
- )
-{
-#if defined(KERNEL_PLL) && defined(LOCKCLOCK)
- struct timex ntv;
-#endif /* KERNEL_PLL LOCKCLOCK */
- struct refclockproc *pp;
-
-#if defined(VMS) && defined(VMS_LOCALUNIT)
- if (unit == VMS_LOCALUNIT) {
- extern void vms_local_poll(struct peer *);
-
- vms_local_poll(peer);
- return;
- }
-#endif /* VMS && VMS_LOCALUNIT */
- pp = peer->procptr;
- pp->polls++;
-
- /*
- * Ramble through the usual filtering and grooming code, which
- * is essentially a no-op and included mostly for pretty
- * billboards. We allow a one-time time adjustment using fudge
- * time1 (s) and a continuous frequency adjustment using fudge
- * time 2 (ppm).
- */
- get_systime(&pp->lastrec);
- pp->fudgetime1 += pp->fudgetime2 * 1e-6 * (current_time -
- poll_time);
- poll_time = current_time;
- refclock_process_offset(pp, pp->lastrec, pp->lastrec,
- pp->fudgetime1);
-
- /*
- * If another process is disciplining the system clock, we set
- * the leap bits and quality indicators from the kernel.
- */
-#if defined(KERNEL_PLL) && defined(LOCKCLOCK)
- memset(&ntv, 0, sizeof ntv);
- switch (ntp_adjtime(&ntv)) {
- case TIME_OK:
- pp->leap = LEAP_NOWARNING;
- peer->stratum = pp->stratum;
- break;
-
- case TIME_INS:
- pp->leap = LEAP_ADDSECOND;
- peer->stratum = pp->stratum;
- break;
-
- case TIME_DEL:
- pp->leap = LEAP_DELSECOND;
- peer->stratum = pp->stratum;
- break;
-
- default:
- pp->leap = LEAP_NOTINSYNC;
- peer->stratum = STRATUM_UNSPEC;
- }
- pp->disp = 0;
- pp->jitter = 0;
-#else /* KERNEL_PLL LOCKCLOCK */
- pp->leap = LEAP_NOWARNING;
- pp->disp = DISPERSION;
- pp->jitter = 0;
-#endif /* KERNEL_PLL LOCKCLOCK */
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- pp->fudgetime1 = 0;
-}
-#else
-int refclock_local_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_msfees.c b/contrib/ntp/ntpd/refclock_msfees.c
deleted file mode 100644
index ebfb983..0000000
--- a/contrib/ntp/ntpd/refclock_msfees.c
+++ /dev/null
@@ -1,1455 +0,0 @@
-/* refclock_ees - clock driver for the EES M201 receiver */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_MSFEES) && defined(PPS)
-
-/* 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 "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_calendar.h"
-
-#include <ctype.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
-
-#ifdef HAVE_SYS_TERMIOS_H
-# include <sys/termios.h>
-#endif
-#ifdef HAVE_SYS_PPSCLOCK_H
-# include <sys/ppsclock.h>
-#endif
-
-#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 lose 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 }; */
-
-#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)
-
-/*
- * Function prototypes
- */
-
-static int msfees_start P((int unit, struct peer *peer));
-static void msfees_shutdown P((int unit, struct peer *peer));
-static void msfees_poll P((int unit, struct peer *peer));
-static void msfees_init P((void));
-static void dump_buf P((l_fp *coffs, int from, int to, char *text));
-static void ees_report_event P((struct eesunit *ees, int code));
-static void ees_receive P((struct recvbuf *rbufp));
-static void ees_process P((struct eesunit *ees));
-#ifdef QSORT_USES_VOID_P
-static int offcompare P((const void *va, const void *vb));
-#else
-static int offcompare P((const l_fp *a, const l_fp *b));
-#endif /* QSORT_USES_VOID_P */
-
-
-/*
- * Transfer vector
- */
-struct refclock refclock_msfees = {
- msfees_start, /* start up driver */
- msfees_shutdown, /* shut down driver */
- msfees_poll, /* transmit poll message */
- noentry, /* not used */
- msfees_init, /* initialize driver */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-
-static void
-dump_buf(
- 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) msyslog(LOG_DEBUG, "D: %s", ptr=buff);
- sprintf(ptr, " %06d", ((int)coffs[i].l_f) / 4295);
- }
- msyslog(LOG_DEBUG, "D: %s", buff);
-}
-
-/* msfees_init - initialize internal ees driver data */
-static void
-msfees_init(void)
-{
- 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(
- int unit,
- struct peer *peer
- )
-{
- register struct eesunit *ees;
- register int i;
- int fd232 = -1;
- char eesdev[20];
- struct termios ttyb, *ttyp;
- struct refclockproc *pp;
- pp = peer->procptr;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "ees clock: unit number %d invalid (max %d)",
- unit, MAXUNITS-1);
- return 0;
- }
- if (unitinuse[unit]) {
- msyslog(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) {
- msyslog(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) {
- msyslog(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) {
- msyslog(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) {
- msyslog(LOG_ERR, "msfees_start: tcsetattr(%s): %m", eesdev);
- goto screwed;
- }
-
- if (tcflush(fd232, TCIOFLUSH) < 0) {
- msyslog(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.
- */
-
-#ifdef STREAM
- {
- 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) {
- msyslog(LOG_ERR,
- "ees clock: Push of `%s' and `%s' to %s failed %m",
- STREAM_PP1, STREAM_PP2, eesdev);
- goto screwed;
- }
- else {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "I: ees clock: PUSHed %s on %s",
- (rc1 >= 0) ? STREAM_PP1 : STREAM_PP2, eesdev);
- ees->ttytype |= T_PPS;
- }
- }
-#endif /* STREAM */
-
- /* Add the clock */
- if (!io_addclock(&ees->io)) {
- /* Oh shit. Just close and return. */
- msyslog(LOG_ERR, "ees clock: io_addclock(%s): %m", eesdev);
- goto screwed;
- }
-
-
- /* All done. Initialize a few random peer variables, then
- * return success. */
- peer->precision = sys_precision;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1) {
- memcpy((char *)&pp->refid, EESREFID, 4);
- if (unit > 0 && unit < 10)
- ((char *)&pp->refid)[3] = '0' + unit;
- } else {
- peer->refid = htonl(EESHSREFID);
- }
- unitinuse[unit] = 1;
- pp->unitptr = (caddr_t) &eesunits[unit];
- pp->clockdesc = EESDESCRIPTION;
- msyslog(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(
- int unit,
- struct peer *peer
- )
-{
- register struct eesunit *ees;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR,
- "ees clock: INTERNAL ERROR, unit number %d invalid (max %d)",
- unit, MAXUNITS);
- return;
- }
- if (!unitinuse[unit]) {
- msyslog(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(
- 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(
- 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;
- 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;
- int rc;
- int request;
-#ifdef HAVE_CIOGETEV
- request = CIOGETEV;
-#endif
-#ifdef HAVE_TIOCGPPSEV
- request = TIOCGPPSEV;
-#endif
-
- /* 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) {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(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)
- msyslog(LOG_INFO,
- "I: ees clock %d: %p == %p: await more",
- ees->unit, dpt, dpend);
- return;
- }
-
- /* This shouldn't happen ... ! */
- if ((*dpt & 0x7f) != 0x7f) {
- msyslog(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:
- msyslog(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((char *) &ppsclockev, 0, sizeof ppsclockev);
-
- rc = ioctl(ees->io.fd, request, (char *) &ppsclockev);
- if (debug & DB_PRINT_EV) fprintf(stderr,
- "[%x] CIOGETEV u%d %d (%x %d) gave %d (%d): %08lx %08lx %ld\n",
- DB_PRINT_EV, ees->unit, ees->io.fd, request, 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) msyslog(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 %ld (%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 %lx.%08lx and %lx.%08lx -> %lx.%08lx @ %s",
- DB_PRINT_CDT, (long)ees->arrvtime.l_ui, (long)ees->arrvtime.l_uf,
- (long)pps_arrvstamp.l_ui, (long)pps_arrvstamp.l_uf,
- (long)diff.l_ui, (long)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);
- msyslog(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,
- (int)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] %08lx %08lx %d u%d (%d %d)\n",
- DB_PRINT_CDTC, (long)pps_arrvstamp.l_ui,
- (long)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 *cptr=text;
- int i;
- for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) {
- sprintf(cptr, " %d.%04d",
- msec(deltas[i]), subms(deltas[i]));
- while (*cptr) cptr++;
- }
- msyslog(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 idelta = (this_step - other_step);
- if (idelta < 0) idelta = - idelta;
- if (third_step == 0 && (
- (idelta == 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++;
- }
- msyslog(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])
- msyslog(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=%3ld.%04ld@%d :%d:%d:$%d:%d:%d\n",
- ees->unit, (long)msec(delta_sfsec), (long)subms(delta_sfsec),
- ees->second, old_sincelast, ees->last_step_late, count, sum,
- ees->last_step_secs);
- msyslog(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) msyslog(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),
- (int)msec(delta_f_abs),
- (int)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 int ees_step_notes = EES_STEP_NOTES;
- if (ees_step_notes > 0) {
- ees_step_notes--;
- printf("MSF%d: D=%3ld.%04ld@%02d :%d%s\n",
- ees->unit, (long)msec(delta_sfsec), (long)subms(delta_sfsec),
- ees->second, sincelast, ees_step_notes ? "" : " -- NO MORE !");
- msyslog(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) msyslog(LOG_ERR,
- "[%x] MSF%d: %3ld/%03d -> d=%11ld (%d|%ld)",
- 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: %3ld/%03d -> d=%11ld (%ld|%ld)\n",
- ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
- (long)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) msyslog(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);
- /*
- * I had to disable this here, since it appears there is no pointer to the
- * peer structure.
- *
- (void) pps_sample(peer, &pps_arrvstamp);
- */
- }
-
- /* Subtract off the local clock time stamp */
- L_SUB(&ees->codeoffsets[n_sample], &ees->arrvtime);
- if (debug & DB_LOG_SAMPLES) msyslog(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! */
-}
-
-
-/* offcompare - auxiliary comparison routine for offset sort */
-
-#ifdef QSORT_USES_VOID_P
-static int
-offcompare(
- const void *va,
- const void *vb
- )
-{
- const l_fp *a = (const l_fp *)va;
- const l_fp *b = (const l_fp *)vb;
- return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);
-}
-#else
-static int
-offcompare(
- const l_fp *a,
- const l_fp *b
- )
-{
- return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);
-}
-#endif /* QSORT_USES_VOID_P */
-
-
-/* ees_process - process a pile of samples from the clock */
-static void
-ees_process(
- struct eesunit *ees
- )
-{
- static int last_samples = -1;
- register int i, j;
- register int noff;
- register l_fp *coffs = ees->codeoffsets;
- l_fp offset, tmp;
- double dispersion; /* ++++ */
- int lostsync, isinsync;
- int samples = ees->nsamples;
- int samplelog = 0; /* keep "gcc -Wall" happy ! */
- int samplereduce = (samples + 1) / 2;
- double doffset;
-
- /* 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)) {
- msyslog(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, (size_t)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)) msyslog(
- (debug & DB_SYSLOG_SMPLE) ? LOG_ERR : LOG_INFO,
- "I: [%x] Offset=%06d (%d), disp=%f%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 & 0x80000000) !=
- (((long) offset.l_uf) & 0x80000000))
- { NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "I: %lx != %lx (%lx %lx), so add %d",
- new & 0x80000000,
- ((long) offset.l_uf) & 0x80000000,
- 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)) msyslog(
- (debug & DB_SYSLOG_SMTHE) ? LOG_ERR : LOG_INFO,
- "I: [%x] Smooth data: %ld -> %ld, dispersion now %f",
- 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)) msyslog(
- (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
- "[%x] No smooth as delta not %d < %ld < %d",
- debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
- - FRACT_SEC(100), diff, FRACT_SEC(100));
- }
- else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog(
- (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) {
- msyslog(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;
- }
- LFPTOD(&offset, doffset);
- refclock_receive(ees->peer);
- ees_event(ees, lostsync ? CEVNT_PROP : CEVNT_NOMINAL);
-}
-
-/* msfees_poll - called by the transmit procedure */
-static void
-msfees_poll(
- int unit,
- struct peer *peer
- )
-{
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d invalid",
- unit);
- return;
- }
- if (!unitinuse[unit]) {
- msyslog(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);
-}
-
-
-#else
-int refclock_msfees_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_mx4200.c b/contrib/ntp/ntpd/refclock_mx4200.c
deleted file mode 100644
index bc694ad..0000000
--- a/contrib/ntp/ntpd/refclock_mx4200.c
+++ /dev/null
@@ -1,1654 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * Modified: Marc Brett <marc.brett@westgeo.com> Sept, 1999.
- *
- * 1. Added support for alternate PPS schemes, with code mostly
- * copied from the Oncore driver (Thanks, Poul-Henning Kamp).
- * This code runs on SunOS 4.1.3 with ppsclock-1.6a1 and Solaris 7.
- */
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_MX4200) && defined(HAVE_PPSAPI)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include "mx4200.h"
-
-#ifdef HAVE_SYS_TERMIOS_H
-# include <sys/termios.h>
-#endif
-#ifdef HAVE_SYS_PPSCLOCK_H
-# include <sys/ppsclock.h>
-#endif
-
-#include "ntp_sprintf.h"
-
-#ifndef HAVE_STRUCT_PPSCLOCKEV
-struct ppsclockev {
-# ifdef HAVE_STRUCT_TIMESPEC
- struct timespec tv;
-# else
- struct timeval tv;
-# endif
- u_int serial;
-};
-#endif /* ! HAVE_STRUCT_PPSCLOCKEV */
-
-#ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-#else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-#endif
-
-/*
- * This driver supports the Magnavox Model MX 4200 GPS Receiver
- * adapted to precision timing applications. It requires the
- * ppsclock line discipline or streams module described in the
- * Line Disciplines and Streams Drivers page. It also requires a
- * gadget box and 1-PPS level converter, such as described in the
- * Pulse-per-second (PPS) Signal Interfacing page.
- *
- * It's likely that other compatible Magnavox receivers such as the
- * MX 4200D, MX 9212, MX 9012R, MX 9112 will be supported by this code.
- */
-
-/*
- * Check this every time you edit the code!
- */
-#define YEAR_LAST_MODIFIED 2000
-
-/*
- * GPS Definitions
- */
-#define DEVICE "/dev/gps%d" /* device name and unit */
-#define SPEED232 B4800 /* baud */
-
-/*
- * Radio interface parameters
- */
-#define PRECISION (-18) /* precision assumed (about 4 us) */
-#define REFID "GPS\0" /* reference id */
-#define DESCRIPTION "Magnavox MX4200 GPS Receiver" /* who we are */
-#define DEFFUDGETIME 0 /* default fudge time (ms) */
-
-#define SLEEPTIME 32 /* seconds to wait for reconfig to complete */
-
-/*
- * Position Averaging.
- */
-#define INTERVAL 1 /* Interval between position measurements (s) */
-#define AVGING_TIME 24 /* Number of hours to average */
-#define NOT_INITIALIZED -9999. /* initial pivot longitude */
-
-/*
- * MX4200 unit control structure.
- */
-struct mx4200unit {
- u_int pollcnt; /* poll message counter */
- u_int polled; /* Hand in a time sample? */
- u_int lastserial; /* last pps serial number */
- struct ppsclockev ppsev; /* PPS control structure */
- double avg_lat; /* average latitude */
- double avg_lon; /* average longitude */
- double avg_alt; /* average height */
- double central_meridian; /* central meridian */
- double N_fixes; /* Number of position measurements */
- int last_leap; /* leap second warning */
- u_int moving; /* mobile platform? */
- u_long sloppyclockflag; /* fudge flags */
- u_int known; /* position known yet? */
- u_long clamp_time; /* when to stop postion averaging */
- u_long log_time; /* when to print receiver status */
- pps_handle_t pps_h;
- pps_params_t pps_p;
- pps_info_t pps_i;
-};
-
-static char pmvxg[] = "PMVXG";
-
-/* XXX should be somewhere else */
-#ifdef __GNUC__
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
-#ifndef __attribute__
-#define __attribute__(args)
-#endif /* __attribute__ */
-#endif /* __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) */
-#else
-#ifndef __attribute__
-#define __attribute__(args)
-#endif /* __attribute__ */
-#endif /* __GNUC__ */
-/* XXX end */
-
-/*
- * 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_poll P((int, struct peer *));
-
-static char * mx4200_parse_t P((struct peer *));
-static char * mx4200_parse_p P((struct peer *));
-static char * mx4200_parse_s P((struct peer *));
-#ifdef QSORT_USES_VOID_P
-int mx4200_cmpl_fp P((const void *, const void *));
-#else
-int mx4200_cmpl_fp P((const l_fp *, const l_fp *));
-#endif /* not QSORT_USES_VOID_P */
-static int mx4200_config P((struct peer *));
-static void mx4200_ref P((struct peer *));
-static void mx4200_send P((struct peer *, char *, ...))
- __attribute__ ((format (printf, 2, 3)));
-static u_char mx4200_cksum P((char *, int));
-static int mx4200_jday P((int, int, int));
-static void mx4200_debug P((struct peer *, char *, ...))
- __attribute__ ((format (printf, 2, 3)));
-static int mx4200_pps P((struct peer *));
-
-/*
- * 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 */
-};
-
-
-
-/*
- * mx4200_start - open the devices and initialize data for processing
- */
-static int
-mx4200_start(
- int unit,
- struct peer *peer
- )
-{
- register struct mx4200unit *up;
- struct refclockproc *pp;
- int fd;
- char gpsdev[20];
-
- /*
- * Open serial port
- */
- (void)sprintf(gpsdev, DEVICE, unit);
- if (!(fd = refclock_open(gpsdev, SPEED232, LDISC_PPS))) {
- return (0);
- }
-
- /*
- * Allocate unit structure
- */
- if (!(up = (struct mx4200unit *) emalloc(sizeof(struct mx4200unit)))) {
- perror("emalloc");
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct mx4200unit));
- pp = peer->procptr;
- pp->io.clock_recv = mx4200_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);
-
- /* Ensure the receiver is properly configured */
- return mx4200_config(peer);
-}
-
-
-/*
- * mx4200_shutdown - shut down the clock
- */
-static void
-mx4200_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct mx4200unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * mx4200_config - Configure the receiver
- */
-static int
-mx4200_config(
- struct peer *peer
- )
-{
- char tr_mode;
- int add_mode;
- register struct mx4200unit *up;
- struct refclockproc *pp;
- int mode;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- /*
- * Initialize the unit variables
- *
- * STRANGE BEHAVIOUR WARNING: The fudge flags are not available
- * at the time mx4200_start is called. These are set later,
- * and so the code must be prepared to handle changing flags.
- */
- up->sloppyclockflag = pp->sloppyclockflag;
- if (pp->sloppyclockflag & CLK_FLAG2) {
- up->moving = 1; /* Receiver on mobile platform */
- msyslog(LOG_DEBUG, "mx4200_config: mobile platform");
- } else {
- up->moving = 0; /* Static Installation */
- }
- up->pollcnt = 2;
- up->polled = 0;
- up->known = 0;
- up->avg_lat = 0.0;
- up->avg_lon = 0.0;
- up->avg_alt = 0.0;
- up->central_meridian = NOT_INITIALIZED;
- up->N_fixes = 0.0;
- up->last_leap = 0; /* LEAP_NOWARNING */
- up->clamp_time = current_time + (AVGING_TIME * 60 * 60);
- up->log_time = current_time + SLEEPTIME;
-
- if (time_pps_create(pp->io.fd, &up->pps_h) < 0) {
- perror("time_pps_create");
- msyslog(LOG_ERR,
- "mx4200_config: time_pps_create failed: %m");
- return (0);
- }
- if (time_pps_getcap(up->pps_h, &mode) < 0) {
- msyslog(LOG_ERR,
- "mx4200_config: time_pps_getcap failed: %m");
- return (0);
- }
-
- if (time_pps_getparams(up->pps_h, &up->pps_p) < 0) {
- msyslog(LOG_ERR,
- "mx4200_config: time_pps_getparams failed: %m");
- return (0);
- }
-
- /* nb. only turn things on, if someone else has turned something
- * on before we get here, leave it alone!
- */
-
- up->pps_p.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
- up->pps_p.mode &= mode; /* only set what is legal */
-
- if (time_pps_setparams(up->pps_h, &up->pps_p) < 0) {
- perror("time_pps_setparams");
- msyslog(LOG_ERR,
- "mx4200_config: time_pps_setparams failed: %m");
- exit(1);
- }
-
- if (time_pps_kcbind(up->pps_h, PPS_KC_HARDPPS, PPS_CAPTUREASSERT,
- PPS_TSFMT_TSPEC) < 0) {
- perror("time_pps_kcbind");
- msyslog(LOG_ERR,
- "mx4200_config: time_pps_kcbind failed: %m");
- exit(1);
- }
-
-
- /*
- * "007" Control Port Configuration
- * Zero the output list (do it twice to flush possible junk)
- */
- mx4200_send(peer, "%s,%03d,,%d,,,,,,", pmvxg,
- PMVXG_S_PORTCONF,
- /* control port output block Label */
- 1); /* clear current output control list (1=yes) */
- /* add/delete sentences from list */
- /* must be null */
- /* sentence output rate (sec) */
- /* precision for position output */
- /* nmea version for cga & gll output */
- /* pass-through control */
- mx4200_send(peer, "%s,%03d,,%d,,,,,,", pmvxg,
- PMVXG_S_PORTCONF, 1);
-
- /*
- * Request software configuration so we can syslog the firmware version
- */
- mx4200_send(peer, "%s,%03d", "CDGPQ", PMVXG_D_SOFTCONF);
-
- /*
- * "001" Initialization/Mode Control, Part A
- * Where ARE we?
- */
- mx4200_send(peer, "%s,%03d,,,,,,,,,,", pmvxg,
- PMVXG_S_INITMODEA);
- /* day of month */
- /* month of year */
- /* year */
- /* gmt */
- /* latitude DDMM.MMMM */
- /* north/south */
- /* longitude DDDMM.MMMM */
- /* east/west */
- /* height */
- /* Altitude Reference 1=MSL */
-
- /*
- * "001" Initialization/Mode Control, Part B
- * Start off in 2d/3d coast mode, holding altitude to last known
- * value if only 3 satellites available.
- */
- mx4200_send(peer, "%s,%03d,%d,,%.1f,%.1f,%d,%d,%d,%c,%d",
- pmvxg, PMVXG_S_INITMODEB,
- 3, /* 2d/3d coast */
- /* reserved */
- 0.1, /* hor accel fact as per Steve (m/s**2) */
- 0.1, /* ver accel fact as per Steve (m/s**2) */
- 10, /* vdop */
- 10, /* hdop limit as per Steve */
- 5, /* elevation limit as per Steve (deg) */
- 'U', /* time output mode (UTC) */
- 0); /* local time offset from gmt (HHHMM) */
-
- /*
- * "023" Time Recovery Configuration
- * Get UTC time from a stationary receiver.
- * (Set field 1 'D' == dynamic if we are on a moving platform).
- * (Set field 1 'S' == static if we are not moving).
- * (Set field 1 'K' == known position if we can initialize lat/lon/alt).
- */
-
- if (pp->sloppyclockflag & CLK_FLAG2)
- up->moving = 1; /* Receiver on mobile platform */
- else
- up->moving = 0; /* Static Installation */
-
- up->pollcnt = 2;
- if (up->moving) {
- /* dynamic: solve for pos, alt, time, while moving */
- tr_mode = 'D';
- } else {
- /* static: solve for pos, alt, time, while stationary */
- tr_mode = 'S';
- }
- mx4200_send(peer, "%s,%03d,%c,%c,%c,%d,%d,%d,", pmvxg,
- PMVXG_S_TRECOVCONF,
- tr_mode, /* time recovery mode (see above ) */
- 'U', /* synchronize to UTC */
- 'A', /* always output a time pulse */
- 500, /* max time error in ns */
- 0, /* user bias in ns */
- 1); /* output "830" sentences to control port */
- /* Multi-satellite mode */
-
- /*
- * Output position information (to calculate fixed installation
- * location) only if we are not moving
- */
- if (up->moving) {
- add_mode = 2; /* delete from list */
- } else {
- add_mode = 1; /* add to list */
- }
-
-
- /*
- * "007" Control Port Configuration
- * Output "021" position, height, velocity reports
- */
- mx4200_send(peer, "%s,%03d,%03d,%d,%d,,%d,,,", pmvxg,
- PMVXG_S_PORTCONF,
- PMVXG_D_PHV, /* control port output block Label */
- 0, /* clear current output control list (0=no) */
- add_mode, /* add/delete sentences from list (1=add, 2=del) */
- /* must be null */
- INTERVAL); /* sentence output rate (sec) */
- /* precision for position output */
- /* nmea version for cga & gll output */
- /* pass-through control */
-
- return (1);
-}
-
-/*
- * mx4200_ref - Reconfigure unit as a reference station at a known position.
- */
-static void
-mx4200_ref(
- struct peer *peer
- )
-{
- register struct mx4200unit *up;
- struct refclockproc *pp;
- double minute, lat, lon, alt;
- char lats[16], lons[16];
- char nsc, ewc;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- /* Should never happen! */
- if (up->moving) return;
-
- /*
- * Set up to output status information in the near future
- */
- up->log_time = current_time + SLEEPTIME;
-
- /*
- * "007" Control Port Configuration
- * Stop outputting "021" position, height, velocity reports
- */
- mx4200_send(peer, "%s,%03d,%03d,%d,%d,,,,,", pmvxg,
- PMVXG_S_PORTCONF,
- PMVXG_D_PHV, /* control port output block Label */
- 0, /* clear current output control list (0=no) */
- 2); /* add/delete sentences from list (2=delete) */
- /* must be null */
- /* sentence output rate (sec) */
- /* precision for position output */
- /* nmea version for cga & gll output */
- /* pass-through control */
-
- /*
- * "001" Initialization/Mode Control, Part B
- * Put receiver in fully-constrained 2d nav mode
- */
- mx4200_send(peer, "%s,%03d,%d,,%.1f,%.1f,%d,%d,%d,%c,%d",
- pmvxg, PMVXG_S_INITMODEB,
- 2, /* 2d nav */
- /* reserved */
- 0.1, /* hor accel fact as per Steve (m/s**2) */
- 0.1, /* ver accel fact as per Steve (m/s**2) */
- 10, /* vdop */
- 10, /* hdop limit as per Steve */
- 5, /* elevation limit as per Steve (deg) */
- 'U', /* time output mode (UTC) */
- 0); /* local time offset from gmt (HHHMM) */
-
- /*
- * "023" Time Recovery Configuration
- * Get UTC time from a stationary receiver. Solve for time only.
- * This should improve the time resolution dramatically.
- */
- mx4200_send(peer, "%s,%03d,%c,%c,%c,%d,%d,%d,", pmvxg,
- PMVXG_S_TRECOVCONF,
- 'K', /* known position: solve for time only */
- 'U', /* synchronize to UTC */
- 'A', /* always output a time pulse */
- 500, /* max time error in ns */
- 0, /* user bias in ns */
- 1); /* output "830" sentences to control port */
- /* Multi-satellite mode */
-
- /*
- * "000" Initialization/Mode Control - Part A
- * Fix to our averaged position.
- */
- if (up->central_meridian != NOT_INITIALIZED) {
- up->avg_lon += up->central_meridian;
- if (up->avg_lon < -180.0) up->avg_lon += 360.0;
- if (up->avg_lon > 180.0) up->avg_lon -= 360.0;
- }
-
- if (up->avg_lat >= 0.0) {
- lat = up->avg_lat;
- nsc = 'N';
- } else {
- lat = up->avg_lat * (-1.0);
- nsc = 'S';
- }
- if (up->avg_lon >= 0.0) {
- lon = up->avg_lon;
- ewc = 'E';
- } else {
- lon = up->avg_lon * (-1.0);
- ewc = 'W';
- }
- alt = up->avg_alt;
- minute = (lat - (double)(int)lat) * 60.0;
- sprintf(lats,"%02d%02.4f", (int)lat, minute);
- minute = (lon - (double)(int)lon) * 60.0;
- sprintf(lons,"%03d%02.4f", (int)lon, minute);
-
- mx4200_send(peer, "%s,%03d,,,,,%s,%c,%s,%c,%.2f,%d", pmvxg,
- PMVXG_S_INITMODEA,
- /* day of month */
- /* month of year */
- /* year */
- /* gmt */
- lats, /* latitude DDMM.MMMM */
- nsc, /* north/south */
- lons, /* longitude DDDMM.MMMM */
- ewc, /* east/west */
- alt, /* Altitude */
- 1); /* Altitude Reference (0=WGS84 ellipsoid, 1=MSL geoid)*/
-
- msyslog(LOG_DEBUG,
- "mx4200: reconfig to fixed location: %s %c, %s %c, %.2f m",
- lats, nsc, lons, ewc, alt );
-
-}
-
-/*
- * mx4200_poll - mx4200 watchdog routine
- */
-static void
-mx4200_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct mx4200unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- /*
- * 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 we haven't had a response in a while, reset the receiver.
- */
- if (up->pollcnt > 0) {
- up->pollcnt--;
- } else {
- refclock_report(peer, CEVNT_TIMEOUT);
-
- /*
- * Request a "000" status message which should trigger a
- * reconfig
- */
- mx4200_send(peer, "%s,%03d",
- "CDGPQ", /* query from CDU to GPS */
- PMVXG_D_STATUS); /* label of desired sentence */
- }
-
- /*
- * polled every 64 seconds. Ask mx4200_receive to hand in
- * a timestamp.
- */
- up->polled = 1;
- pp->polls++;
-
- /*
- * Output receiver status information.
- */
- if ((up->log_time > 0) && (current_time > up->log_time)) {
- up->log_time = 0;
- /*
- * Output the following messages once, for debugging.
- * "004" Mode Data
- * "523" Time Recovery Parameters
- */
- mx4200_send(peer, "%s,%03d", "CDGPQ", PMVXG_D_MODEDATA);
- mx4200_send(peer, "%s,%03d", "CDGPQ", PMVXG_D_TRECOVUSEAGE);
- }
-}
-
-static char char2hex[] = "0123456789ABCDEF";
-
-/*
- * mx4200_receive - receive gps data
- */
-static void
-mx4200_receive(
- struct recvbuf *rbufp
- )
-{
- register struct mx4200unit *up;
- struct refclockproc *pp;
- struct peer *peer;
- char *cp;
- int sentence_type;
- u_char ck;
-
- /*
- * Initialize pointers and read the timecode and timestamp.
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- /*
- * If operating mode has been changed, then reinitialize the receiver
- * before doing anything else.
- */
- if ((pp->sloppyclockflag & CLK_FLAG2) !=
- (up->sloppyclockflag & CLK_FLAG2)) {
- up->sloppyclockflag = pp->sloppyclockflag;
- mx4200_debug(peer,
- "mx4200_receive: mode switch: reset receiver\n");
- mx4200_config(peer);
- return;
- }
- up->sloppyclockflag = pp->sloppyclockflag;
-
- /*
- * Read clock output. Automatically handles STREAMS, CLKLDISC.
- */
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
-
- /*
- * There is a case where <cr><lf> generates 2 timestamps.
- */
- if (pp->lencode == 0)
- return;
-
- up->pollcnt = 2;
- pp->a_lastcode[pp->lencode] = '\0';
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- mx4200_debug(peer, "mx4200_receive: %d %s\n",
- pp->lencode, pp->a_lastcode);
-
- /*
- * The structure of the control port sentences is based on the
- * NMEA-0183 Standard for interfacing Marine Electronics
- * Navigation Devices (Version 1.5)
- *
- * $PMVXG,XXX, ....................*CK<cr><lf>
- *
- * $ Sentence Start Identifier (reserved char)
- * (Start-of-Sentence Identifier)
- * P Special ID (Proprietary)
- * MVX Originator ID (Magnavox)
- * G Interface ID (GPS)
- * , Field Delimiters (reserved char)
- * XXX Sentence Type
- * ...... Data
- * * Checksum Field Delimiter (reserved char)
- * CK Checksum
- * <cr><lf> Carriage-Return/Line Feed (reserved chars)
- * (End-of-Sentence Identifier)
- *
- * Reject if any important landmarks are missing.
- */
- cp = pp->a_lastcode + pp->lencode - 3;
- if (cp < pp->a_lastcode || *pp->a_lastcode != '$' || cp[0] != '*' ) {
- mx4200_debug(peer, "mx4200_receive: bad format\n");
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Check and discard the checksum
- */
- ck = mx4200_cksum(&pp->a_lastcode[1], pp->lencode - 4);
- if (char2hex[ck >> 4] != cp[1] || char2hex[ck & 0xf] != cp[2]) {
- mx4200_debug(peer, "mx4200_receive: bad checksum\n");
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- *cp = '\0';
-
- /*
- * Get the sentence type.
- */
- sentence_type = 0;
- if ((cp = strchr(pp->a_lastcode, ',')) == NULL) {
- mx4200_debug(peer, "mx4200_receive: no sentence\n");
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- cp++;
- sentence_type = strtol(cp, &cp, 10);
-
- /*
- * Process the sentence according to its type.
- */
- switch (sentence_type) {
-
- /*
- * "000" Status message
- */
- case PMVXG_D_STATUS:
- /*
- * 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.
- */
- if ((cp = mx4200_parse_s(peer)) != NULL) {
- mx4200_debug(peer,
- "mx4200_receive: status: %s\n", cp);
- }
- mx4200_debug(peer, "mx4200_receive: reset receiver\n");
- mx4200_config(peer);
- break;
-
- /*
- * "021" Position, Height, Velocity message,
- * if we are still averaging our position
- */
- case PMVXG_D_PHV:
- if (!up->known) {
- /*
- * Parse the message, calculating our averaged position.
- */
- if ((cp = mx4200_parse_p(peer)) != NULL) {
- mx4200_debug(peer, "mx4200_receive: pos: %s\n", cp);
- return;
- }
- mx4200_debug(peer,
- "mx4200_receive: position avg %f %.9f %.9f %.4f\n",
- up->N_fixes, up->avg_lat, up->avg_lon, up->avg_alt);
- /*
- * Reinitialize as a reference station
- * if position is well known.
- */
- if (current_time > up->clamp_time) {
- up->known++;
- mx4200_debug(peer, "mx4200_receive: reconfiguring!\n");
- mx4200_ref(peer);
- }
- }
- break;
-
- /*
- * Print to the syslog:
- * "004" Mode Data
- * "030" Software Configuration
- * "523" Time Recovery Parameters Currently in Use
- */
- case PMVXG_D_MODEDATA:
- case PMVXG_D_SOFTCONF:
- case PMVXG_D_TRECOVUSEAGE:
-
- if ((cp = mx4200_parse_s(peer)) != NULL) {
- mx4200_debug(peer,
- "mx4200_receive: multi-record: %s\n", cp);
- }
- break;
-
- /*
- * "830" Time Recovery Results message
- */
- case PMVXG_D_TRECOVOUT:
-
- /*
- * Capture the last PPS signal.
- * Precision timestamp is returned in pp->lastrec
- */
- if (mx4200_pps(peer) != NULL) {
- mx4200_debug(peer, "mx4200_receive: pps failure\n");
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
-
-
- /*
- * Parse the time recovery message, and keep the info
- * to print the pretty billboards.
- */
- if ((cp = mx4200_parse_t(peer)) != NULL) {
- mx4200_debug(peer, "mx4200_receive: time: %s\n", cp);
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Add the new sample to a median filter.
- */
- if (!refclock_process(pp)) {
- mx4200_debug(peer,"mx4200_receive: offset: %.6f\n",
- pp->offset);
- refclock_report(peer, CEVNT_BADTIME);
- 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 (!up->polled)
- return;
-
- /*
- * Return offset and dispersion to control module. 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.
- */
- mx4200_debug(peer, "mx4200_receive: process time: ");
- mx4200_debug(peer, "%4d-%03d %02d:%02d:%02d at %s, %.6f\n",
- pp->year, pp->day, pp->hour, pp->minute, pp->second,
- prettydate(&pp->lastrec), pp->offset);
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-
- /*
- * We have succeeded in answering the poll.
- * Turn off the flag and return
- */
- up->polled = 0;
- break;
-
- /*
- * Ignore all other sentence types
- */
- default:
- break;
-
- } /* switch (sentence_type) */
-
- return;
-}
-
-
-/*
- * Parse a mx4200 time recovery message. Returns a string if error.
- *
- * A typical message looks like this. Checksum has already been stripped.
- *
- * $PMVXG,830,T,YYYY,MM,DD,HH:MM:SS,U,S,FFFFFF,PPPPP,BBBBBB,LL
- *
- * Field Field Contents
- * ----- --------------
- * Block Label: $PMVXG
- * Sentence Type: 830=Time Recovery Results
- * This sentence is output approximately 1 second
- * preceding the 1PPS output. It indicates the
- * exact time of the next pulse, whether or not the
- * time mark will be valid (based on operator-specified
- * error tolerance), the time to which the pulse is
- * synchronized, the receiver operating mode,
- * and the time error of the *last* 1PPS output.
- * 1 char Time Mark Valid: T=Valid, F=Not Valid
- * 2 int Year: 1993-
- * 3 int Month of Year: 1-12
- * 4 int Day of Month: 1-31
- * 5 int Time of Day: HH:MM:SS
- * 6 char Time Synchronization: U=UTC, G=GPS
- * 7 char Time Recovery Mode: D=Dynamic, S=Static,
- * K=Known Position, N=No Time Recovery
- * 8 int Oscillator Offset: The filter's estimate of the oscillator
- * frequency error, in parts per billion (ppb).
- * 9 int Time Mark Error: The computed error of the *last* pulse
- * output, in nanoseconds.
- * 10 int User Time Bias: Operator specified bias, in nanoseconds
- * 11 int Leap Second Flag: Indicates that a leap second will
- * occur. This value is usually zero, except during
- * the week prior to the leap second occurrence, when
- * this value will be set to +1 or -1. A value of
- * +1 indicates that GPS time will be 1 second
- * further ahead of UTC time.
- *
- */
-static char *
-mx4200_parse_t(
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct mx4200unit *up;
- char time_mark_valid, time_sync, op_mode;
- int sentence_type, valid;
- int year, day_of_year, month, day_of_month;
- int hour, minute, second, leapsec;
- int oscillator_offset, time_mark_error, time_bias;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- leapsec = 0; /* Not all receivers output leap second warnings (!) */
- sscanf(pp->a_lastcode,
- "$PMVXG,%d,%c,%d,%d,%d,%d:%d:%d,%c,%c,%d,%d,%d,%d",
- &sentence_type, &time_mark_valid, &year, &month, &day_of_month,
- &hour, &minute, &second, &time_sync, &op_mode,
- &oscillator_offset, &time_mark_error, &time_bias, &leapsec);
-
- if (sentence_type != PMVXG_D_TRECOVOUT)
- return ("wrong rec-type");
-
- switch (time_mark_valid) {
- case 'T':
- valid = 1;
- break;
- case 'F':
- valid = 0;
- break;
- default:
- return ("bad pulse-valid");
- }
-
- switch (time_sync) {
- case 'G':
- return ("synchronized to GPS; should be UTC");
- case 'U':
- break; /* UTC -> ok */
- default:
- return ("not synchronized to UTC");
- }
-
- /*
- * Check for insane time (allow for possible leap seconds)
- */
- if (second > 60 || minute > 59 || hour > 23 ||
- second < 0 || minute < 0 || hour < 0) {
- mx4200_debug(peer,
- "mx4200_parse_t: bad time %02d:%02d:%02d",
- hour, minute, second);
- if (leapsec != 0)
- mx4200_debug(peer, " (leap %+d\n)", leapsec);
- mx4200_debug(peer, "\n");
- refclock_report(peer, CEVNT_BADTIME);
- return ("bad time");
- }
- if ( second == 60 ) {
- msyslog(LOG_DEBUG,
- "mx4200: leap second! %02d:%02d:%02d",
- hour, minute, second);
- }
-
- /*
- * Check for insane date
- * (Certainly can't be any year before this code was last altered!)
- */
- if (day_of_month > 31 || month > 12 ||
- day_of_month < 1 || month < 1 || year < YEAR_LAST_MODIFIED) {
- mx4200_debug(peer,
- "mx4200_parse_t: bad date (%4d-%02d-%02d)\n",
- year, month, day_of_month);
- refclock_report(peer, CEVNT_BADDATE);
- return ("bad date");
- }
-
- /*
- * Silly Hack for MX4200:
- * ASCII message is for *next* 1PPS signal, but we have the
- * timestamp for the *last* 1PPS signal. So we have to subtract
- * a second. Discard if we are on a month boundary to avoid
- * possible leap seconds and leap days.
- */
- second--;
- if (second < 0) {
- second = 59;
- minute--;
- if (minute < 0) {
- minute = 59;
- hour--;
- if (hour < 0) {
- hour = 23;
- day_of_month--;
- if (day_of_month < 1) {
- return ("sorry, month boundary");
- }
- }
- }
- }
-
- /*
- * Calculate Julian date
- */
- if (!(day_of_year = mx4200_jday(year, month, day_of_month))) {
- mx4200_debug(peer,
- "mx4200_parse_t: bad julian date %d (%4d-%02d-%02d)\n",
- day_of_year, year, month, day_of_month);
- refclock_report(peer, CEVNT_BADDATE);
- return("invalid julian date");
- }
-
- /*
- * Setup leap second indicator
- */
- switch (leapsec) {
- case 0:
- pp->leap = LEAP_NOWARNING;
- break;
- case 1:
- pp->leap = LEAP_ADDSECOND;
- break;
- case -1:
- pp->leap = LEAP_DELSECOND;
- break;
- default:
- pp->leap = LEAP_NOTINSYNC;
- }
-
- /*
- * Any change to the leap second warning status?
- */
- if (leapsec != up->last_leap ) {
- msyslog(LOG_DEBUG,
- "mx4200: leap second warning: %d to %d (%d)",
- up->last_leap, leapsec, pp->leap);
- }
- up->last_leap = leapsec;
-
- /*
- * Copy time data for billboard monitoring.
- */
-
- pp->year = year;
- pp->day = day_of_year;
- pp->hour = hour;
- pp->minute = minute;
- pp->second = second;
-
- /*
- * Toss if sentence is marked invalid
- */
- if (!valid || pp->leap == LEAP_NOTINSYNC) {
- mx4200_debug(peer, "mx4200_parse_t: time mark not valid\n");
- refclock_report(peer, CEVNT_BADTIME);
- return ("pulse invalid");
- }
-
- return (NULL);
-}
-
-/*
- * Calculate the checksum
- */
-static u_char
-mx4200_cksum(
- register char *cp,
- register int n
- )
-{
- register u_char ck;
-
- for (ck = 0; n-- > 0; cp++)
- ck ^= *cp;
- return (ck);
-}
-
-/*
- * Tables to compute the day of year. Viva la leap.
- */
-static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/*
- * Calculate the the Julian Day
- */
-static int
-mx4200_jday(
- int year,
- int month,
- int day_of_month
- )
-{
- register int day, i;
- int leap_year;
-
- /*
- * Is this a leap year ?
- */
- if (year % 4) {
- leap_year = 0; /* FALSE */
- } else {
- if (year % 100) {
- leap_year = 1; /* TRUE */
- } else {
- if (year % 400) {
- leap_year = 0; /* FALSE */
- } else {
- leap_year = 1; /* TRUE */
- }
- }
- }
-
- /*
- * Calculate the Julian Date
- */
- day = day_of_month;
-
- if (leap_year) {
- /* a leap year */
- if (day > day2tab[month - 1]) {
- return (0);
- }
- for (i = 0; i < month - 1; i++)
- day += day2tab[i];
- } else {
- /* not a leap year */
- if (day > day1tab[month - 1]) {
- return (0);
- }
- for (i = 0; i < month - 1; i++)
- day += day1tab[i];
- }
- return (day);
-}
-
-/*
- * Parse a mx4200 position/height/velocity sentence.
- *
- * A typical message looks like this. Checksum has already been stripped.
- *
- * $PMVXG,021,SSSSSS.SS,DDMM.MMMM,N,DDDMM.MMMM,E,HHHHH.H,GGGG.G,EEEE.E,WWWW.W,MM
- *
- * Field Field Contents
- * ----- --------------
- * Block Label: $PMVXG
- * Sentence Type: 021=Position, Height Velocity Data
- * This sentence gives the receiver position, height,
- * navigation mode, and velocity north/east.
- * *This sentence is intended for post-analysis
- * applications.*
- * 1 float UTC measurement time (seconds into week)
- * 2 float WGS-84 Lattitude (degrees, minutes)
- * 3 char N=North, S=South
- * 4 float WGS-84 Longitude (degrees, minutes)
- * 5 char E=East, W=West
- * 6 float Altitude (meters above mean sea level)
- * 7 float Geoidal height (meters)
- * 8 float East velocity (m/sec)
- * 9 float West Velocity (m/sec)
- * 10 int Navigation Mode
- * Mode if navigating:
- * 1 = Position from remote device
- * 2 = 2-D position
- * 3 = 3-D position
- * 4 = 2-D differential position
- * 5 = 3-D differential position
- * 6 = Static
- * 8 = Position known -- reference station
- * 9 = Position known -- Navigator
- * Mode if not navigating:
- * 51 = Too few satellites
- * 52 = DOPs too large
- * 53 = Position STD too large
- * 54 = Velocity STD too large
- * 55 = Too many iterations for velocity
- * 56 = Too many iterations for position
- * 57 = 3 sat startup failed
- * 58 = Command abort
- */
-static char *
-mx4200_parse_p(
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct mx4200unit *up;
- int sentence_type, mode;
- double mtime, lat, lon, alt, geoid, vele, veln;
- char north_south, east_west;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- /* Should never happen! */
- if (up->moving) return ("mobile platform - no pos!");
-
- sscanf ( pp->a_lastcode,
- "$PMVXG,%d,%lf,%lf,%c,%lf,%c,%lf,%lf,%lf,%lf,%d",
- &sentence_type, &mtime, &lat, &north_south, &lon, &east_west,
- &alt, &geoid, &vele, &veln, &mode);
-
- /* Sentence type */
- if (sentence_type != PMVXG_D_PHV)
- return ("wrong rec-type");
-
- /*
- * return if not navigating
- */
- if (mode > 10)
- return ("not navigating");
- if (mode != 3 && mode != 5)
- return ("not navigating in 3D");
-
- /* Latitude (always +ve) and convert DDMM.MMMM to decimal */
- if (lat < 0.0) return ("negative latitude");
- if (lat > 9000.0) lat = 9000.0;
- lat *= 0.01;
- lat = ((int)lat) + (((lat - (int)lat)) * 1.6666666666666666);
-
- /* North/South */
- switch (north_south) {
- case 'N':
- break;
- case 'S':
- lat *= -1.0;
- break;
- default:
- return ("invalid north/south indicator");
- }
-
- /* Longitude (always +ve) and convert DDDMM.MMMM to decimal */
- if (lon < 0.0) return ("negative longitude");
- if (lon > 180.0) lon = 180.0;
- lon *= 0.01;
- lon = ((int)lon) + (((lon - (int)lon)) * 1.6666666666666666);
-
- /* East/West */
- switch (east_west) {
- case 'E':
- break;
- case 'W':
- lon *= -1.0;
- break;
- default:
- return ("invalid east/west indicator");
- }
-
- /*
- * Normalize longitude to near 0 degrees.
- * Assume all data are clustered around first reading.
- */
- if (up->central_meridian == NOT_INITIALIZED) {
- up->central_meridian = lon;
- mx4200_debug(peer,
- "mx4200_receive: central meridian = %.9f \n",
- up->central_meridian);
- }
- lon -= up->central_meridian;
- if (lon < -180.0) lon += 360.0;
- if (lon > 180.0) lon -= 360.0;
-
- /*
- * Calculate running averages
- */
-
- up->avg_lon = (up->N_fixes * up->avg_lon) + lon;
- up->avg_lat = (up->N_fixes * up->avg_lat) + lat;
- up->avg_alt = (up->N_fixes * up->avg_alt) + alt;
-
- up->N_fixes += 1.0;
-
- up->avg_lon /= up->N_fixes;
- up->avg_lat /= up->N_fixes;
- up->avg_alt /= up->N_fixes;
-
- mx4200_debug(peer,
- "mx4200_receive: position rdg %.0f: %.9f %.9f %.4f (CM=%.9f)\n",
- up->N_fixes, lat, lon, alt, up->central_meridian);
-
- return (NULL);
-}
-
-/*
- * Parse a mx4200 Status sentence
- * Parse a mx4200 Mode Data sentence
- * Parse a mx4200 Software Configuration sentence
- * Parse a mx4200 Time Recovery Parameters Currently in Use sentence
- * (used only for logging raw strings)
- *
- * A typical message looks like this. Checksum has already been stripped.
- *
- * $PMVXG,000,XXX,XX,X,HHMM,X
- *
- * Field Field Contents
- * ----- --------------
- * Block Label: $PMVXG
- * Sentence Type: 000=Status.
- * Returns status of the receiver to the controller.
- * 1 Current Receiver Status:
- * ACQ = Satellite re-acquisition
- * ALT = Constellation selection
- * COR = Providing corrections (for reference stations only)
- * IAC = Initial acquisition
- * IDL = Idle, no satellites
- * NAV = Navigation
- * STS = Search the Sky (no almanac available)
- * TRK = Tracking
- * 2 Number of satellites that should be visible
- * 3 Number of satellites being tracked
- * 4 Time since last navigation status if not currently navigating
- * (hours, minutes)
- * 5 Initialization status:
- * 0 = Waiting for initialization parameters
- * 1 = Initialization completed
- *
- * A typical message looks like this. Checksum has already been stripped.
- *
- * $PMVXG,004,C,R,D,H.HH,V.VV,TT,HHHH,VVVV,T
- *
- * Field Field Contents
- * ----- --------------
- * Block Label: $PMVXG
- * Sentence Type: 004=Software Configuration.
- * Defines the navigation mode and criteria for
- * acceptable navigation for the receiver.
- * 1 Constrain Altitude Mode:
- * 0 = Auto. Constrain altitude (2-D solution) and use
- * manual altitude input when 3 sats avalable. Do
- * not constrain altitude (3-D solution) when 4 sats
- * available.
- * 1 = Always constrain altitude (2-D solution).
- * 2 = Never constrain altitude (3-D solution).
- * 3 = Coast. Constrain altitude (2-D solution) and use
- * last GPS altitude calculation when 3 sats avalable.
- * Do not constrain altitude (3-D solution) when 4 sats
- * available.
- * 2 Altitude Reference: (always 0 for MX4200)
- * 0 = Ellipsoid
- * 1 = Geoid (MSL)
- * 3 Differential Navigation Control:
- * 0 = Disabled
- * 1 = Enabled
- * 4 Horizontal Acceleration Constant (m/sec**2)
- * 5 Vertical Acceleration Constant (m/sec**2) (0 for MX4200)
- * 6 Tracking Elevation Limit (degrees)
- * 7 HDOP Limit
- * 8 VDOP Limit
- * 9 Time Output Mode:
- * U = UTC
- * L = Local time
- * 10 Local Time Offset (minutes) (absent on MX4200)
- *
- * A typical message looks like this. Checksum has already been stripped.
- *
- * $PMVXG,030,NNNN,FFF
- *
- * Field Field Contents
- * ----- --------------
- * Block Label: $PMVXG
- * Sentence Type: 030=Software Configuration.
- * This sentence contains the navigation processor
- * and baseband firmware version numbers.
- * 1 Nav Processor Version Number
- * 2 Baseband Firmware Version Number
- *
- * A typical message looks like this. Checksum has already been stripped.
- *
- * $PMVXG,523,M,S,M,EEEE,BBBBBB,C,R
- *
- * Field Field Contents
- * ----- --------------
- * Block Label: $PMVXG
- * Sentence Type: 523=Time Recovery Parameters Currently in Use.
- * This sentence contains the configuration of the
- * time recovery feature of the receiver.
- * 1 Time Recovery Mode:
- * D = Dynamic; solve for position and time while moving
- * S = Static; solve for position and time while stationary
- * K = Known position input, solve for time only
- * N = No time recovery
- * 2 Time Synchronization:
- * U = UTC time
- * G = GPS time
- * 3 Time Mark Mode:
- * A = Always output a time pulse
- * V = Only output time pulse if time is valid (as determined
- * by Maximum Time Error)
- * 4 Maximum Time Error - the maximum error (in nanoseconds) for
- * which a time mark will be considered valid.
- * 5 User Time Bias - external bias in nanoseconds
- * 6 Time Message Control:
- * 0 = Do not output the time recovery message
- * 1 = Output the time recovery message (record 830) to
- * Control port
- * 2 = Output the time recovery message (record 830) to
- * Equipment port
- * 7 Reserved
- * 8 Position Known PRN (absent on MX 4200)
- *
- */
-static char *
-mx4200_parse_s(
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct mx4200unit *up;
- int sentence_type;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- sscanf ( pp->a_lastcode, "$PMVXG,%d", &sentence_type);
-
- /* Sentence type */
- switch (sentence_type) {
-
- case PMVXG_D_STATUS:
- msyslog(LOG_DEBUG,
- "mx4200: status: %s", pp->a_lastcode);
- break;
- case PMVXG_D_MODEDATA:
- msyslog(LOG_DEBUG,
- "mx4200: mode data: %s", pp->a_lastcode);
- break;
- case PMVXG_D_SOFTCONF:
- msyslog(LOG_DEBUG,
- "mx4200: firmware configuration: %s", pp->a_lastcode);
- break;
- case PMVXG_D_TRECOVUSEAGE:
- msyslog(LOG_DEBUG,
- "mx4200: time recovery parms: %s", pp->a_lastcode);
- break;
- default:
- return ("wrong rec-type");
- }
-
- return (NULL);
-}
-
-/*
- * Process a PPS signal, placing a timestamp in pp->lastrec.
- */
-static int
-mx4200_pps(
- struct peer *peer
- )
-{
- int temp_serial;
- struct refclockproc *pp;
- struct mx4200unit *up;
-
- struct timespec timeout;
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- /*
- * Grab the timestamp of the PPS signal.
- */
- temp_serial = up->pps_i.assert_sequence;
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- if (time_pps_fetch(up->pps_h, PPS_TSFMT_TSPEC, &(up->pps_i),
- &timeout) < 0) {
- mx4200_debug(peer,
- "mx4200_pps: time_pps_fetch: serial=%d, %s\n",
- up->pps_i.assert_sequence, strerror(errno));
- refclock_report(peer, CEVNT_FAULT);
- return(1);
- }
- if (temp_serial == up->pps_i.assert_sequence) {
- mx4200_debug(peer,
- "mx4200_pps: assert_sequence serial not incrementing: %d\n",
- up->pps_i.assert_sequence);
- refclock_report(peer, CEVNT_FAULT);
- return(1);
- }
- /*
- * Check pps serial number against last one
- */
- if (up->lastserial + 1 != up->pps_i.assert_sequence &&
- up->lastserial != 0) {
- if (up->pps_i.assert_sequence == up->lastserial) {
- mx4200_debug(peer, "mx4200_pps: no new pps event\n");
- } else {
- mx4200_debug(peer, "mx4200_pps: missed %d pps events\n",
- up->pps_i.assert_sequence - up->lastserial - 1);
- }
- refclock_report(peer, CEVNT_FAULT);
- }
- up->lastserial = up->pps_i.assert_sequence;
-
- /*
- * Return the timestamp in pp->lastrec
- */
-
- pp->lastrec.l_ui = up->pps_i.assert_timestamp.tv_sec +
- (u_int32) JAN_1970;
- pp->lastrec.l_uf = ((double)(up->pps_i.assert_timestamp.tv_nsec) *
- 4.2949672960) + 0.5;
-
- return(0);
-}
-
-/*
- * mx4200_debug - print debug messages
- */
-#if defined(__STDC__)
-static void
-mx4200_debug(struct peer *peer, char *fmt, ...)
-#else
-static void
-mx4200_debug(peer, fmt, va_alist)
- struct peer *peer;
- char *fmt;
-#endif /* __STDC__ */
-{
- va_list ap;
- struct refclockproc *pp;
- struct mx4200unit *up;
-
- if (debug) {
-
-#if defined(__STDC__)
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif /* __STDC__ */
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
-
- /*
- * Print debug message to stdout
- * In the future, we may want to get get more creative...
- */
- vprintf(fmt, ap);
-
- va_end(ap);
- }
-}
-
-/*
- * Send a character string to the receiver. Checksum is appended here.
- */
-#if defined(__STDC__)
-static void
-mx4200_send(struct peer *peer, char *fmt, ...)
-#else
-static void
-mx4200_send(peer, fmt, va_alist)
- struct peer *peer;
- char *fmt;
- va_dcl
-#endif /* __STDC__ */
-{
- struct refclockproc *pp;
- struct mx4200unit *up;
-
- register char *cp;
- register int n, m;
- va_list ap;
- char buf[1024];
- u_char ck;
-
-#if defined(__STDC__)
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif /* __STDC__ */
-
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- cp = buf;
- *cp++ = '$';
- n = VSNPRINTF((cp, sizeof(buf) - 1, fmt, ap));
- ck = mx4200_cksum(cp, n);
- cp += n;
- ++n;
- n += SNPRINTF((cp, sizeof(buf) - n - 5, "*%02X\r\n", ck));
-
- m = write(pp->io.fd, buf, (unsigned)n);
- if (m < 0)
- msyslog(LOG_ERR, "mx4200_send: write: %m (%s)", buf);
- mx4200_debug(peer, "mx4200_send: %d %s\n", m, buf);
- va_end(ap);
-}
-
-#else
-int refclock_mx4200_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_neoclock4x.c b/contrib/ntp/ntpd/refclock_neoclock4x.c
deleted file mode 100644
index 082b1cf..0000000
--- a/contrib/ntp/ntpd/refclock_neoclock4x.c
+++ /dev/null
@@ -1,1068 +0,0 @@
-/*
- *
- * Refclock_neoclock4x.c
- * - NeoClock4X driver for DCF77 or FIA Timecode
- *
- * Date: 2003-07-07 v1.13
- *
- * see http://www.linum.com/redir/jump/id=neoclock4x&action=redir
- * for details about the NeoClock4X device
- *
- * Copyright (C) 2002-2003 by Linum Software GmbH <neoclock4x@linum.com>
- *
- * 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.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#if defined(REFCLOCK) && (defined(CLOCK_NEOCLOCK4X))
-
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <ctype.h>
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_control.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#if defined HAVE_SYS_MODEM_H
-# include <sys/modem.h>
-# define TIOCMSET MCSETA
-# define TIOCMGET MCGETA
-# define TIOCM_RTS MRTS
-#endif
-
-#ifdef HAVE_TERMIOS_H
-# ifdef TERMIOS_NEEDS__SVID3
-# define _SVID3
-# endif
-# include <termios.h>
-# ifdef TERMIOS_NEEDS__SVID3
-# undef _SVID3
-# endif
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-
-/*
- * If you want the driver for whatever reason to not use
- * the TX line to send anything to your NeoClock4X
- * device you must tell the NTP refclock driver which
- * firmware you NeoClock4X device uses.
- *
- * If you want to enable this feature change the "#if 0"
- * line to "#if 1" and make sure that the defined firmware
- * matches the firmware off your NeoClock4X receiver!
- *
- */
-
-#if 0
-#define NEOCLOCK4X_FIRMWARE NEOCLOCK4X_FIRMWARE_VERSION_A
-#endif
-
-#define NEOCLOCK4X_FIRMWARE_VERSION_A 'A'
-
-#define NEOCLOCK4X_TIMECODELEN 37
-
-#define NEOCLOCK4X_OFFSET_SERIAL 3
-#define NEOCLOCK4X_OFFSET_RADIOSIGNAL 9
-#define NEOCLOCK4X_OFFSET_DAY 12
-#define NEOCLOCK4X_OFFSET_MONTH 14
-#define NEOCLOCK4X_OFFSET_YEAR 16
-#define NEOCLOCK4X_OFFSET_HOUR 18
-#define NEOCLOCK4X_OFFSET_MINUTE 20
-#define NEOCLOCK4X_OFFSET_SECOND 22
-#define NEOCLOCK4X_OFFSET_HSEC 24
-#define NEOCLOCK4X_OFFSET_DOW 26
-#define NEOCLOCK4X_OFFSET_TIMESOURCE 28
-#define NEOCLOCK4X_OFFSET_DSTSTATUS 29
-#define NEOCLOCK4X_OFFSET_QUARZSTATUS 30
-#define NEOCLOCK4X_OFFSET_ANTENNA1 31
-#define NEOCLOCK4X_OFFSET_ANTENNA2 33
-#define NEOCLOCK4X_OFFSET_CRC 35
-
-#define NEOCLOCK4X_DRIVER_VERSION "1.12 (2003-01-10)"
-
-struct neoclock4x_unit {
- l_fp laststamp; /* last receive timestamp */
- short unit; /* NTP refclock unit number */
- u_long polled; /* flag to detect noreplies */
- char leap_status; /* leap second flag */
- int recvnow;
-
- char firmware[80];
- char firmwaretag;
- char serial[7];
- char radiosignal[4];
- char timesource;
- char dststatus;
- char quarzstatus;
- int antenna1;
- int antenna2;
- int utc_year;
- int utc_month;
- int utc_day;
- int utc_hour;
- int utc_minute;
- int utc_second;
- int utc_msec;
-};
-
-static int neoclock4x_start P((int, struct peer *));
-static void neoclock4x_shutdown P((int, struct peer *));
-static void neoclock4x_receive P((struct recvbuf *));
-static void neoclock4x_poll P((int, struct peer *));
-static void neoclock4x_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
-
-static int neol_atoi_len P((const char str[], int *, int));
-static int neol_hexatoi_len P((const char str[], int *, int));
-static void neol_jdn_to_ymd P((unsigned long, int *, int *, int *));
-static void neol_localtime P((unsigned long, int* , int*, int*, int*, int*, int*));
-static unsigned long neol_mktime P((int, int, int, int, int, int));
-#if 0
-static void neol_mdelay P((int));
-#endif
-#if !defined(NEOCLOCK4X_FIRMWARE)
-static int neol_query_firmware P((int, int, char *, int));
-static int neol_check_firmware P((int, const char*, char *));
-#endif
-
-struct refclock refclock_neoclock4x = {
- neoclock4x_start, /* start up driver */
- neoclock4x_shutdown, /* shut down driver */
- neoclock4x_poll, /* transmit poll message */
- neoclock4x_control,
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-static int
-neoclock4x_start(int unit,
- struct peer *peer)
-{
- struct neoclock4x_unit *up;
- struct refclockproc *pp;
- int fd;
- char dev[20];
- int sl232;
-#if defined(HAVE_TERMIOS)
- struct termios termsettings;
-#endif
-#if !defined(NEOCLOCK4X_FIRMWARE)
- int tries;
-#endif
-
- (void) snprintf(dev, sizeof(dev)-1, "/dev/neoclock4x-%d", unit);
-
- /* LDISC_STD, LDISC_RAW
- * Open serial port. Use CLK line discipline, if available.
- */
- fd = refclock_open(dev, B2400, LDISC_CLK);
- if(fd <= 0)
- {
- return (0);
- }
-
-#if defined(HAVE_TERMIOS)
- if(tcgetattr(fd, &termsettings) < 0)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): (tcgetattr) can't query serial port settings: %m", unit);
- (void) close(fd);
- return (0);
- }
-
- /* 2400 Baud 8N2 */
- termsettings.c_cflag &= ~PARENB;
- termsettings.c_cflag |= CSTOPB;
- termsettings.c_cflag &= ~CSIZE;
- termsettings.c_cflag |= CS8;
-
- if(tcsetattr(fd, TCSANOW, &termsettings) < 0)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): (tcsetattr) can't set serial port 2400 8N2: %m", unit);
- (void) close(fd);
- return (0);
- }
-#elif defined(HAVE_SYSV_TTYS)
- if(ioctl(fd, TCGETA, &termsettings) < 0)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): (TCGETA) can't query serial port settings: %m", unit);
- (void) close(fd);
- return (0);
- }
-
- /* 2400 Baud 8N2 */
- termsettings.c_cflag &= ~PARENB;
- termsettings.c_cflag |= CSTOPB;
- termsettings.c_cflag &= ~CSIZE;
- termsettings.c_cflag |= CS8;
-
- if(ioctl(fd, TCSETA, &termsettings) < 0)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): (TSGETA) can't set serial port 2400 8N2: %m", unit);
- (void) close(fd);
- return (0);
- }
-#else
- msyslog(LOG_EMERG, "NeoClock4X(%d): don't know how to set port to 2400 8N2 with this OS!", unit);
- (void) close(fd);
- return (0);
-#endif
-
-#if defined(TIOCMSET) && (defined(TIOCM_RTS) || defined(CIOCM_RTS))
- /* turn on RTS, and DTR for power supply */
- /* NeoClock4x is powered from serial line */
- if(ioctl(fd, TIOCMGET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): can't query RTS/DTR state: %m", unit);
- (void) close(fd);
- return (0);
- }
-#ifdef TIOCM_RTS
- sl232 = sl232 | TIOCM_DTR | TIOCM_RTS; /* turn on RTS, and DTR for power supply */
-#else
- sl232 = sl232 | CIOCM_DTR | CIOCM_RTS; /* turn on RTS, and DTR for power supply */
-#endif
- if(ioctl(fd, TIOCMSET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): can't set RTS/DTR to power neoclock4x: %m", unit);
- (void) close(fd);
- return (0);
- }
-#else
- msyslog(LOG_EMERG, "NeoClock4X(%d): don't know how to set DTR/RTS to power NeoClock4X with this OS!",
- unit);
- (void) close(fd);
- return (0);
-#endif
-
- up = (struct neoclock4x_unit *) emalloc(sizeof(struct neoclock4x_unit));
- if(!(up))
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): can't allocate memory for: %m",unit);
- (void) close(fd);
- return (0);
- }
-
- memset((char *)up, 0, sizeof(struct neoclock4x_unit));
- pp = peer->procptr;
- pp->clockdesc = "NeoClock4X";
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = neoclock4x_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- /*
- * no fudge time is given by user!
- * use 169.583333 ms to compensate the serial line delay
- * formula is:
- * 2400 Baud / 11 bit = 218.18 charaters per second
- * (NeoClock4X timecode len)
- */
- pp->fudgetime1 = (NEOCLOCK4X_TIMECODELEN * 11) / 2400.0;
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = -10;
- peer->burst = NSTAGE;
- memcpy((char *)&pp->refid, "neol", 4);
-
- up->leap_status = 0;
- up->unit = unit;
- strcpy(up->firmware, "?");
- up->firmwaretag = '?';
- strcpy(up->serial, "?");
- strcpy(up->radiosignal, "?");
- up->timesource = '?';
- up->dststatus = '?';
- up->quarzstatus = '?';
- up->antenna1 = -1;
- up->antenna2 = -1;
- up->utc_year = 0;
- up->utc_month = 0;
- up->utc_day = 0;
- up->utc_hour = 0;
- up->utc_minute = 0;
- up->utc_second = 0;
- up->utc_msec = 0;
-
-#if defined(NEOCLOCK4X_FIRMWARE)
-#if NEOCLOCK4X_FIRMWARE == NEOCLOCK4X_FIRMWARE_VERSION_A
- strcpy(up->firmware, "(c) 2002 NEOL S.A. FRANCE / L0.01 NDF:A:* (compile time)");
- up->firmwaretag = 'A';
-#else
- msyslog(LOG_EMERG, "NeoClock4X(%d): Unkown firmware defined at compile time for NeoClock4X",
- unit);
- (void) close(fd);
- pp->io.fd = -1;
- free(pp->unitptr);
- pp->unitptr = NULL;
- return (0);
-#endif
-#else
- for(tries=0; tries < 5; tries++)
- {
- NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_INFO, "NeoClock4X(%d): checking NeoClock4X firmware version (%d/5)", unit, tries);
- /* wait 3 seconds for receiver to power up */
- sleep(3);
- if(neol_query_firmware(pp->io.fd, up->unit, up->firmware, sizeof(up->firmware)))
- {
- break;
- }
- }
-
- /* can I handle this firmware version? */
- if(!neol_check_firmware(up->unit, up->firmware, &up->firmwaretag))
- {
- (void) close(fd);
- pp->io.fd = -1;
- free(pp->unitptr);
- pp->unitptr = NULL;
- return (0);
- }
-#endif
-
- if(!io_addclock(&pp->io))
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): error add peer to ntpd: %m", unit);
- (void) close(fd);
- pp->io.fd = -1;
- free(pp->unitptr);
- pp->unitptr = NULL;
- return (0);
- }
-
- NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_INFO, "NeoClock4X(%d): receiver setup successful done", unit);
-
- return (1);
-}
-
-static void
-neoclock4x_shutdown(int unit,
- struct peer *peer)
-{
- struct neoclock4x_unit *up;
- struct refclockproc *pp;
- int sl232;
-
- if(NULL != peer)
- {
- pp = peer->procptr;
- if(pp != NULL)
- {
- up = (struct neoclock4x_unit *)pp->unitptr;
- if(up != NULL)
- {
- if(-1 != pp->io.fd)
- {
-#if defined(TIOCMSET) && (defined(TIOCM_RTS) || defined(CIOCM_RTS))
- /* turn on RTS, and DTR for power supply */
- /* NeoClock4x is powered from serial line */
- if(ioctl(pp->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): can't query RTS/DTR state: %m",
- unit);
- }
-#ifdef TIOCM_RTS
- /* turn on RTS, and DTR for power supply */
- sl232 &= ~(TIOCM_DTR | TIOCM_RTS);
-#else
- /* turn on RTS, and DTR for power supply */
- sl232 &= ~(CIOCM_DTR | CIOCM_RTS);
-#endif
- if(ioctl(pp->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): can't set RTS/DTR to power neoclock4x: %m",
- unit);
- }
-#endif
- io_closeclock(&pp->io);
- }
- free(up);
- pp->unitptr = NULL;
- }
- }
- }
-
- msyslog(LOG_ERR, "NeoClock4X(%d): shutdown", unit);
-
- NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_INFO, "NeoClock4X(%d): receiver shutdown done", unit);
-}
-
-static void
-neoclock4x_receive(struct recvbuf *rbufp)
-{
- struct neoclock4x_unit *up;
- struct refclockproc *pp;
- struct peer *peer;
- unsigned long calc_utc;
- int day;
- int month; /* ddd conversion */
- int c;
- int dsec;
- unsigned char calc_chksum;
- int recv_chksum;
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct neoclock4x_unit *)pp->unitptr;
-
- /* wait till poll interval is reached */
- if(0 == up->recvnow)
- return;
-
- /* reset poll interval flag */
- up->recvnow = 0;
-
- /* read last received timecode */
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
- pp->leap = LEAP_NOWARNING;
-
- if(NEOCLOCK4X_TIMECODELEN != pp->lencode)
- {
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_WARNING, "NeoClock4X(%d): received data has invalid length, expected %d bytes, received %d bytes: %s",
- up->unit, NEOCLOCK4X_TIMECODELEN, pp->lencode, pp->a_lastcode);
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- neol_hexatoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_CRC], &recv_chksum, 2);
-
- /* calculate checksum */
- calc_chksum = 0;
- for(c=0; c < NEOCLOCK4X_OFFSET_CRC; c++)
- {
- calc_chksum += pp->a_lastcode[c];
- }
- if(recv_chksum != calc_chksum)
- {
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_WARNING, "NeoClock4X(%d): received data has invalid chksum: %s",
- up->unit, pp->a_lastcode);
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /* Allow synchronization even is quartz clock is
- * never initialized.
- * WARNING: This is dangerous!
- */
- up->quarzstatus = pp->a_lastcode[NEOCLOCK4X_OFFSET_QUARZSTATUS];
- if(0==(pp->sloppyclockflag & CLK_FLAG2))
- {
- if('I' != up->quarzstatus)
- {
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_NOTICE, "NeoClock4X(%d): quartz clock is not initialized: %s",
- up->unit, pp->a_lastcode);
- pp->leap = LEAP_NOTINSYNC;
- refclock_report(peer, CEVNT_BADDATE);
- return;
- }
- }
- if('I' != up->quarzstatus)
- {
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_NOTICE, "NeoClock4X(%d): using uninitialized quartz clock for time synchronization: %s",
- up->unit, pp->a_lastcode);
- }
-
- /*
- * If NeoClock4X is not synchronized to a radio clock
- * check if we're allowed to synchronize with the quartz
- * clock.
- */
- up->timesource = pp->a_lastcode[NEOCLOCK4X_OFFSET_TIMESOURCE];
- if(0==(pp->sloppyclockflag & CLK_FLAG2))
- {
- if('A' != up->timesource)
- {
- /* not allowed to sync with quartz clock */
- if(0==(pp->sloppyclockflag & CLK_FLAG1))
- {
- refclock_report(peer, CEVNT_BADTIME);
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
- }
- }
-
- /* this should only used when first install is done */
- if(pp->sloppyclockflag & CLK_FLAG4)
- {
- msyslog(LOG_DEBUG, "NeoClock4X(%d): received data: %s",
- up->unit, pp->a_lastcode);
- }
-
- /* 123456789012345678901234567890123456789012345 */
- /* S/N123456DCF1004021010001202ASX1213CR\r\n */
-
- neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_YEAR], &pp->year, 2);
- neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_MONTH], &month, 2);
- neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_DAY], &day, 2);
- neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_HOUR], &pp->hour, 2);
- neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_MINUTE], &pp->minute, 2);
- neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_SECOND], &pp->second, 2);
- neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_HSEC], &dsec, 2);
- pp->nsec = dsec * 10000; /* convert 1/100s from neoclock to nanoseconds */
-
- memcpy(up->radiosignal, &pp->a_lastcode[NEOCLOCK4X_OFFSET_RADIOSIGNAL], 3);
- up->radiosignal[3] = 0;
- memcpy(up->serial, &pp->a_lastcode[NEOCLOCK4X_OFFSET_SERIAL], 6);
- up->serial[6] = 0;
- up->dststatus = pp->a_lastcode[NEOCLOCK4X_OFFSET_DSTSTATUS];
- neol_hexatoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_ANTENNA1], &up->antenna1, 2);
- neol_hexatoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_ANTENNA2], &up->antenna2, 2);
-
- /*
- Validate received values at least enough to prevent internal
- array-bounds problems, etc.
- */
- if((pp->hour < 0) || (pp->hour > 23) ||
- (pp->minute < 0) || (pp->minute > 59) ||
- (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
- (day < 1) || (day > 31) ||
- (month < 1) || (month > 12) ||
- (pp->year < 0) || (pp->year > 99)) {
- /* Data out of range. */
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_WARNING, "NeoClock4X(%d): date/time out of range: %s",
- up->unit, pp->a_lastcode);
- refclock_report(peer, CEVNT_BADDATE);
- return;
- }
-
- /* Year-2000 check not needed anymore. Same problem
- * will arise at 2099 but what should we do...?
- *
- * wrap 2-digit date into 4-digit
- *
- * if(pp->year < YEAR_PIVOT)
- * {
- * pp->year += 100;
- * }
- */
- pp->year += 2000;
-
- /* adjust NeoClock4X local time to UTC */
- calc_utc = neol_mktime(pp->year, month, day, pp->hour, pp->minute, pp->second);
- calc_utc -= 3600;
- /* adjust NeoClock4X daylight saving time if needed */
- if('S' == up->dststatus)
- calc_utc -= 3600;
- neol_localtime(calc_utc, &pp->year, &month, &day, &pp->hour, &pp->minute, &pp->second);
-
- /*
- some preparations
- */
- pp->day = ymd2yd(pp->year, month, day);
- pp->leap = 0;
-
- if(pp->sloppyclockflag & CLK_FLAG4)
- {
- msyslog(LOG_DEBUG, "NeoClock4X(%d): calculated UTC date/time: %04d-%02d-%02d %02d:%02d:%02d.%03ld",
- up->unit,
- pp->year, month, day,
- pp->hour, pp->minute, pp->second, pp->nsec/1000);
- }
-
- up->utc_year = pp->year;
- up->utc_month = month;
- up->utc_day = day;
- up->utc_hour = pp->hour;
- up->utc_minute = pp->minute;
- up->utc_second = pp->second;
- up->utc_msec = pp->nsec/1000;
-
- if(!refclock_process(pp))
- {
- NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_WARNING, "NeoClock4X(%d): refclock_process failed!", up->unit);
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- refclock_receive(peer);
-
- /* report good status */
- refclock_report(peer, CEVNT_NOMINAL);
-
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-}
-
-static void
-neoclock4x_poll(int unit,
- struct peer *peer)
-{
- struct neoclock4x_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct neoclock4x_unit *)pp->unitptr;
-
- pp->polls++;
- up->recvnow = 1;
-}
-
-static void
-neoclock4x_control(int unit,
- struct refclockstat *in,
- struct refclockstat *out,
- struct peer *peer)
-{
- struct neoclock4x_unit *up;
- struct refclockproc *pp;
-
- if(NULL == peer)
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): control: unit invalid/inactive", unit);
- return;
- }
-
- pp = peer->procptr;
- if(NULL == pp)
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): control: unit invalid/inactive", unit);
- return;
- }
-
- up = (struct neoclock4x_unit *)pp->unitptr;
- if(NULL == up)
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): control: unit invalid/inactive", unit);
- return;
- }
-
- if(NULL != in)
- {
- /* check to see if a user supplied time offset is given */
- if(in->haveflags & CLK_HAVETIME1)
- {
- pp->fudgetime1 = in->fudgetime1;
- NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_NOTICE, "NeoClock4X(%d): using fudgetime1 with %0.5fs from ntp.conf.",
- unit, pp->fudgetime1);
- }
-
- /* notify */
- if(pp->sloppyclockflag & CLK_FLAG1)
- {
- NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_NOTICE, "NeoClock4X(%d): quartz clock is used to synchronize time if radio clock has no reception.", unit);
- }
- else
- {
- NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_NOTICE, "NeoClock4X(%d): time is only adjusted with radio signal reception.", unit);
- }
- }
-
- if(NULL != out)
- {
- static char outstatus[800]; /* status output buffer */
- char *tt;
- char tmpbuf[80];
-
- outstatus[0] = '\0';
- out->kv_list = (struct ctl_var *)0;
- out->type = REFCLK_NEOCLOCK4X;
-
- snprintf(tmpbuf, sizeof(tmpbuf)-1,
- "%04d-%02d-%02d %02d:%02d:%02d.%03d",
- up->utc_year, up->utc_month, up->utc_day,
- up->utc_hour, up->utc_minute, up->utc_second,
- up->utc_msec);
- tt = add_var(&out->kv_list, sizeof(tmpbuf)-1, RO|DEF);
- snprintf(tt, sizeof(tmpbuf)-1, "calc_utc=\"%s\"", tmpbuf);
-
- tt = add_var(&out->kv_list, 40, RO|DEF);
- snprintf(tt, 39, "radiosignal=\"%s\"", up->radiosignal);
- tt = add_var(&out->kv_list, 40, RO|DEF);
- snprintf(tt, 39, "antenna1=\"%d\"", up->antenna1);
- tt = add_var(&out->kv_list, 40, RO|DEF);
- snprintf(tt, 39, "antenna2=\"%d\"", up->antenna2);
- tt = add_var(&out->kv_list, 40, RO|DEF);
- if('A' == up->timesource)
- snprintf(tt, 39, "timesource=\"radio\"");
- else if('C' == up->timesource)
- snprintf(tt, 39, "timesource=\"quartz\"");
- else
- snprintf(tt, 39, "timesource=\"unknown\"");
- tt = add_var(&out->kv_list, 40, RO|DEF);
- if('I' == up->quarzstatus)
- snprintf(tt, 39, "quartzstatus=\"synchronized\"");
- else if('X' == up->quarzstatus)
- snprintf(tt, 39, "quartzstatus=\"not synchronized\"");
- else
- snprintf(tt, 39, "quartzstatus=\"unknown\"");
- tt = add_var(&out->kv_list, 40, RO|DEF);
- if('S' == up->dststatus)
- snprintf(tt, 39, "dststatus=\"summer\"");
- else if('W' == up->dststatus)
- snprintf(tt, 39, "dststatus=\"winter\"");
- else
- snprintf(tt, 39, "dststatus=\"unknown\"");
- tt = add_var(&out->kv_list, 80, RO|DEF);
- snprintf(tt, 79, "firmware=\"%s\"", up->firmware);
- tt = add_var(&out->kv_list, 40, RO|DEF);
- snprintf(tt, 39, "firmwaretag=\"%c\"", up->firmwaretag);
- tt = add_var(&out->kv_list, 80, RO|DEF);
- snprintf(tt, 79, "driver version=\"%s\"", NEOCLOCK4X_DRIVER_VERSION);
- tt = add_var(&out->kv_list, 80, RO|DEF);
- snprintf(tt, 79, "serialnumber=\"%s\"", up->serial);
- }
-}
-
-static int
-neol_hexatoi_len(const char str[],
- int *result,
- int maxlen)
-{
- int hexdigit;
- int i;
- int n = 0;
-
- for(i=0; isxdigit(str[i]) && i < maxlen; i++)
- {
- hexdigit = isdigit(str[i]) ? toupper(str[i]) - '0' : toupper(str[i]) - 'A' + 10;
- n = 16 * n + hexdigit;
- }
- *result = n;
- return (n);
-}
-
-static int
-neol_atoi_len(const char str[],
- int *result,
- int maxlen)
-{
- int digit;
- int i;
- int n = 0;
-
- for(i=0; isdigit(str[i]) && i < maxlen; i++)
- {
- digit = str[i] - '0';
- n = 10 * n + digit;
- }
- *result = n;
- return (n);
-}
-
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-static unsigned long
-neol_mktime(int year,
- int mon,
- int day,
- int hour,
- int min,
- int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 . 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return (((
- (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
-
-static void
-neol_localtime(unsigned long utc,
- int* year,
- int* month,
- int* day,
- int* hour,
- int* min,
- int* sec)
-{
- *sec = utc % 60;
- utc /= 60;
- *min = utc % 60;
- utc /= 60;
- *hour = utc % 24;
- utc /= 24;
-
- /* JDN Date 1/1/1970 */
- neol_jdn_to_ymd(utc + 2440588L, year, month, day);
-}
-
-static void
-neol_jdn_to_ymd(unsigned long jdn,
- int *yy,
- int *mm,
- int *dd)
-{
- unsigned long x, z, m, d, y;
- unsigned long daysPer400Years = 146097UL;
- unsigned long fudgedDaysPer4000Years = 1460970UL + 31UL;
-
- x = jdn + 68569UL;
- z = 4UL * x / daysPer400Years;
- x = x - (daysPer400Years * z + 3UL) / 4UL;
- y = 4000UL * (x + 1) / fudgedDaysPer4000Years;
- x = x - 1461UL * y / 4UL + 31UL;
- m = 80UL * x / 2447UL;
- d = x - 2447UL * m / 80UL;
- x = m / 11UL;
- m = m + 2UL - 12UL * x;
- y = 100UL * (z - 49UL) + y + x;
-
- *yy = (int)y;
- *mm = (int)m;
- *dd = (int)d;
-}
-
-#if 0
-/*
- * delay in milliseconds
- */
-static void
-neol_mdelay(int milliseconds)
-{
- struct timeval tv;
-
- if(milliseconds)
- {
- tv.tv_sec = 0;
- tv.tv_usec = milliseconds * 1000;
- select(1, NULL, NULL, NULL, &tv);
- }
-}
-#endif
-
-#if !defined(NEOCLOCK4X_FIRMWARE)
-static int
-neol_query_firmware(int fd,
- int unit,
- char *firmware,
- int maxlen)
-{
- char tmpbuf[256];
- int len;
- int lastsearch;
- unsigned char c;
- int last_c_was_crlf;
- int last_crlf_conv_len;
- int init;
- int read_errors;
- int flag = 0;
- int chars_read;
-
- /* wait a little bit */
- sleep(1);
- if(-1 != write(fd, "V", 1))
- {
- /* wait a little bit */
- sleep(1);
- memset(tmpbuf, 0x00, sizeof(tmpbuf));
-
- len = 0;
- lastsearch = 0;
- last_c_was_crlf = 0;
- last_crlf_conv_len = 0;
- init = 1;
- read_errors = 0;
- chars_read = 0;
- for(;;)
- {
- if(read_errors > 5)
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): can't read firmware version (timeout)", unit);
- strcpy(tmpbuf, "unknown due to timeout");
- break;
- }
- if(chars_read > 500)
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): can't read firmware version (garbage)", unit);
- strcpy(tmpbuf, "unknown due to garbage input");
- break;
- }
- if(-1 == read(fd, &c, 1))
- {
- if(EAGAIN != errno)
- {
- msyslog(LOG_DEBUG, "NeoClock4x(%d): read: %s", unit ,strerror(errno));
- read_errors++;
- }
- else
- {
- sleep(1);
- }
- continue;
- }
- else
- {
- chars_read++;
- }
-
- if(init)
- {
- if(0xA9 != c) /* wait for (c) char in input stream */
- continue;
-
- strcpy(tmpbuf, "(c)");
- len = 3;
- init = 0;
- continue;
- }
-
-#if 0
- msyslog(LOG_NOTICE, "NeoClock4X(%d): firmware %c = %02Xh", unit, c, c);
-#endif
-
- if(0x0A == c || 0x0D == c)
- {
- if(last_c_was_crlf)
- {
- char *ptr;
- ptr = strstr(&tmpbuf[lastsearch], "S/N");
- if(NULL != ptr)
- {
- tmpbuf[last_crlf_conv_len] = 0;
- flag = 1;
- break;
- }
- /* convert \n to / */
- last_crlf_conv_len = len;
- tmpbuf[len++] = ' ';
- tmpbuf[len++] = '/';
- tmpbuf[len++] = ' ';
- lastsearch = len;
- }
- last_c_was_crlf = 1;
- }
- else
- {
- last_c_was_crlf = 0;
- if(0x00 != c)
- tmpbuf[len++] = (char) c;
- }
- tmpbuf[len] = '\0';
- if(len > sizeof(tmpbuf)-5)
- break;
- }
- }
- else
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): can't query firmware version", unit);
- strcpy(tmpbuf, "unknown error");
- }
- strncpy(firmware, tmpbuf, maxlen);
- firmware[maxlen] = '\0';
-
- if(flag)
- {
- NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_INFO, "NeoClock4X(%d): firmware version: %s", unit, firmware);
- }
-
- return (flag);
-}
-
-static int
-neol_check_firmware(int unit,
- const char *firmware,
- char *firmwaretag)
-{
- char *ptr;
-
- *firmwaretag = '?';
- ptr = strstr(firmware, "NDF:");
- if(NULL != ptr)
- {
- if((strlen(firmware) - strlen(ptr)) >= 7)
- {
- if(':' == *(ptr+5) && '*' == *(ptr+6))
- *firmwaretag = *(ptr+4);
- }
- }
-
- if('A' != *firmwaretag)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): firmware version \"%c\" not supported with this driver version!", unit, *firmwaretag);
- return (0);
- }
-
- return (1);
-}
-#endif
-
-#else
-int refclock_neoclock4x_bs;
-#endif /* REFCLOCK */
-
-/*
- * History:
- * refclock_neoclock4x.c
- *
- * 2002/04/27 cjh
- * Revision 1.0 first release
- *
- * 2002/07/15 cjh
- * preparing for bitkeeper reposity
- *
- * 2002/09/09 cjh
- * Revision 1.1
- * - don't assume sprintf returns an int anymore
- * - change the way the firmware version is read
- * - some customers would like to put a device called
- * data diode to the NeoClock4X device to disable
- * the write line. We need to now the firmware
- * version even in this case. We made a compile time
- * definition in this case. The code was previously
- * only available on request.
- *
- * 2003/01/08 cjh
- * Revision 1.11
- * - changing xprinf to xnprinf to avoid buffer overflows
- * - change some logic
- * - fixed memory leaks if drivers can't initialize
- *
- * 2003/01/10 cjh
- * Revision 1.12
- * - replaced ldiv
- * - add code to support FreeBSD
- *
- * 2003/07/07 cjh
- * Revision 1.13
- * - fix reporting of clock status
- * changes. previously a bad clock
- * status was never reset.
- */
diff --git a/contrib/ntp/ntpd/refclock_nmea.c b/contrib/ntp/ntpd/refclock_nmea.c
deleted file mode 100644
index 28d6263..0000000
--- a/contrib/ntp/ntpd/refclock_nmea.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * refclock_nmea.c - clock driver for an NMEA GPS CLOCK
- * Michael Petry Jun 20, 1994
- * based on refclock_heathn.c
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(SYS_WINNT)
-#undef close
-#define close closesocket
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_NMEA)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
-#endif /* HAVE_PPSAPI */
-
-/*
- * This driver supports the NMEA GPS Receiver with
- *
- * Protype was refclock_trak.c, Thanks a lot.
- *
- * The receiver 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.
- *
- * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in.
- * On startup if initialization of the PPSAPI fails, it will fall back
- * to the "normal" timestamps.
- *
- * The PPSAPI part of the driver understands fudge flag2 and flag3. If
- * flag2 is set, it will use the clear edge of the pulse. If flag3 is
- * set, kernel hardpps is enabled.
- *
- * GPS sentences other than RMC (the default) may be enabled by setting
- * the relevent bits of 'mode' in the server configuration line
- * server 127.127.20.x mode X
- *
- * bit 0 - enables RMC (1)
- * bit 1 - enables GGA (2)
- * bit 2 - enables GLL (4)
- * multiple sentences may be selected
- */
-
-/*
- * Definitions
- */
-#ifdef SYS_WINNT
-# define DEVICE "COM%d:" /* COM 1 - 3 supported */
-#else
-# define DEVICE "/dev/gps%d" /* name of radio device */
-#endif
-#define SPEED232 B4800 /* uart speed (4800 bps) */
-#define PRECISION (-9) /* precision assumed (about 2 ms) */
-#define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS\0" /* reference id */
-#define DESCRIPTION "NMEA GPS Clock" /* who we are */
-#define NANOSECOND 1000000000 /* one second (ns) */
-#define RANGEGATE 500000 /* range gate (ns) */
-
-#define LENNMEA 75 /* min timecode length */
-
-/*
- * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
- * leap.
- */
-static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/*
- * Unit control structure
- */
-struct nmeaunit {
- int pollcnt; /* poll message counter */
- int polled; /* Hand in a sample? */
- l_fp tstamp; /* timestamp of last poll */
-#ifdef HAVE_PPSAPI
- struct timespec ts; /* last timestamp */
- pps_params_t pps_params; /* pps parameters */
- pps_info_t pps_info; /* last pps data */
- pps_handle_t handle; /* pps handlebars */
-#endif /* HAVE_PPSAPI */
-};
-
-/*
- * Function prototypes
- */
-static int nmea_start P((int, struct peer *));
-static void nmea_shutdown P((int, struct peer *));
-#ifdef HAVE_PPSAPI
-static void nmea_control P((int, struct refclockstat *, struct
- refclockstat *, struct peer *));
-static int nmea_ppsapi P((struct peer *, int, int));
-static int nmea_pps P((struct nmeaunit *, l_fp *));
-#endif /* HAVE_PPSAPI */
-static void nmea_receive P((struct recvbuf *));
-static void nmea_poll P((int, struct peer *));
-static void gps_send P((int, const char *, struct peer *));
-static char *field_parse P((char *, int));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_nmea = {
- nmea_start, /* start up driver */
- nmea_shutdown, /* shut down driver */
- nmea_poll, /* transmit poll message */
-#ifdef HAVE_PPSAPI
- nmea_control, /* fudge control */
-#else
- noentry, /* fudge control */
-#endif /* HAVE_PPSAPI */
- noentry, /* initialize driver */
- noentry, /* buginfo */
- NOFLAGS /* not used */
-};
-
-/*
- * nmea_start - open the GPS devices and initialize data for processing
- */
-static int
-nmea_start(
- 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);
-
- fd = refclock_open(device, SPEED232, LDISC_CLK);
- if (fd < 0)
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- up = (struct nmeaunit *)emalloc(sizeof(struct nmeaunit));
- if (up == NULL) {
- (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*1D\r\n", peer);
-
-#ifdef HAVE_PPSAPI
- /*
- * Start the PPSAPI interface if it is there. Default to use
- * the assert edge and do not enable the kernel hardpps.
- */
- if (time_pps_create(fd, &up->handle) < 0) {
- up->handle = 0;
- msyslog(LOG_ERR,
- "refclock_nmea: time_pps_create failed: %m");
- return (1);
- }
- return(nmea_ppsapi(peer, 0, 0));
-#else
- return (1);
-#endif /* HAVE_PPSAPI */
-}
-
-/*
- * nmea_shutdown - shut down a GPS clock
- */
-static void
-nmea_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct nmeaunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct nmeaunit *)pp->unitptr;
-#ifdef HAVE_PPSAPI
- if (up->handle != 0)
- time_pps_destroy(up->handle);
-#endif /* HAVE_PPSAPI */
- io_closeclock(&pp->io);
- free(up);
-}
-
-#ifdef HAVE_PPSAPI
-/*
- * nmea_control - fudge control
- */
-static void
-nmea_control(
- int unit, /* unit (not used */
- struct refclockstat *in, /* input parameters (not uded) */
- struct refclockstat *out, /* output parameters (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
- nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
- pp->sloppyclockflag & CLK_FLAG3);
-}
-
-
-/*
- * Initialize PPSAPI
- */
-int
-nmea_ppsapi(
- struct peer *peer, /* peer structure pointer */
- int enb_clear, /* clear enable */
- int enb_hardpps /* hardpps enable */
- )
-{
- struct refclockproc *pp;
- struct nmeaunit *up;
- int capability;
-
- pp = peer->procptr;
- up = (struct nmeaunit *)pp->unitptr;
- if (time_pps_getcap(up->handle, &capability) < 0) {
- msyslog(LOG_ERR,
- "refclock_nmea: time_pps_getcap failed: %m");
- return (0);
- }
- memset(&up->pps_params, 0, sizeof(pps_params_t));
- if (enb_clear)
- up->pps_params.mode = capability & PPS_CAPTURECLEAR;
- else
- up->pps_params.mode = capability & PPS_CAPTUREASSERT;
- if (!up->pps_params.mode) {
- msyslog(LOG_ERR,
- "refclock_nmea: invalid capture edge %d",
- !enb_clear);
- return (0);
- }
- up->pps_params.mode |= PPS_TSFMT_TSPEC;
- if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
- msyslog(LOG_ERR,
- "refclock_nmea: time_pps_setparams failed: %m");
- return (0);
- }
- if (enb_hardpps) {
- if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
- up->pps_params.mode & ~PPS_TSFMT_TSPEC,
- PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR,
- "refclock_nmea: time_pps_kcbind failed: %m");
- return (0);
- }
- pps_enable = 1;
- }
- peer->precision = PPS_PRECISION;
-
-#if DEBUG
- if (debug) {
- time_pps_getparams(up->handle, &up->pps_params);
- printf(
- "refclock_ppsapi: capability 0x%x version %d mode 0x%x kern %d\n",
- capability, up->pps_params.api_version,
- up->pps_params.mode, enb_hardpps);
- }
-#endif
-
- return (1);
-}
-
-/*
- * Get PPSAPI timestamps.
- *
- * Return 0 on failure and 1 on success.
- */
-static int
-nmea_pps(
- struct nmeaunit *up,
- l_fp *tsptr
- )
-{
- pps_info_t pps_info;
- struct timespec timeout, ts;
- double dtemp;
- l_fp tstmp;
-
- /*
- * Convert the timespec nanoseconds field to ntp l_fp units.
- */
- if (up->handle == 0)
- return (0);
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
- if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
- &timeout) < 0)
- return (0);
- if (up->pps_params.mode & PPS_CAPTUREASSERT) {
- if (pps_info.assert_sequence ==
- up->pps_info.assert_sequence)
- return (0);
- ts = up->pps_info.assert_timestamp;
- } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
- if (pps_info.clear_sequence ==
- up->pps_info.clear_sequence)
- return (0);
- ts = up->pps_info.clear_timestamp;
- } else {
- return (0);
- }
- if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
- return (0);
- up->ts = ts;
-
- tstmp.l_ui = ts.tv_sec + JAN_1970;
- dtemp = ts.tv_nsec * FRAC / 1e9;
- tstmp.l_uf = (u_int32)dtemp;
- *tsptr = tstmp;
- return (1);
-}
-#endif /* HAVE_PPSAPI */
-
-/*
- * nmea_receive - receive data from the serial interface
- */
-static void
-nmea_receive(
- struct recvbuf *rbufp
- )
-{
- register struct nmeaunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- int month, day;
- int i;
- char *cp, *dp;
- int cmdtype;
- /* Use these variables to hold data until we decide its worth keeping */
- char rd_lastcode[BMAX];
- l_fp rd_tmp;
- u_short rd_lencode;
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct nmeaunit *)pp->unitptr;
- rd_lencode = (u_short)refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
-
- /*
- * There is a case that a <CR><LF> gives back a "blank" line
- */
- if (rd_lencode == 0)
- return;
-
-#ifdef DEBUG
- if (debug)
- printf("nmea: gpsread %d %s\n", rd_lencode,
- rd_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
- * For Magellan (ColorTrak) GLL probably datum (order of sentences)
- * also mode (0,1,2,3) select sentence ANY/ALL, RMC, GGA, GLL
- * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21
- * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
- * $GPRMB,...
- * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
- * $GPAPB,...
- * $GPGSA,...
- * $GPGSV,...
- * $GPGSV,...
- */
-#define GPXXX 0
-#define GPRMC 1
-#define GPGGA 2
-#define GPGLL 4
- cp = rd_lastcode;
- cmdtype=0;
- if(strncmp(cp,"$GPRMC",6)==0) {
- cmdtype=GPRMC;
- }
- else if(strncmp(cp,"$GPGGA",6)==0) {
- cmdtype=GPGGA;
- }
- else if(strncmp(cp,"$GPGLL",6)==0) {
- cmdtype=GPGLL;
- }
- else if(strncmp(cp,"$GPXXX",6)==0) {
- cmdtype=GPXXX;
- }
- else
- return;
-
-
- /* See if I want to process this message type */
- if ( ((peer->ttl == 0) && (cmdtype != GPRMC))
- || ((peer->ttl != 0) && !(cmdtype & peer->ttl)) )
- return;
-
- pp->lencode = rd_lencode;
- strcpy(pp->a_lastcode,rd_lastcode);
- cp = pp->a_lastcode;
-
- pp->lastrec = up->tstamp = rd_tmp;
- up->pollcnt = 2;
-
-#ifdef DEBUG
- if (debug)
- printf("nmea: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
-
-
- /* Grab field depending on clock string type */
- switch( cmdtype ) {
- case GPRMC:
- /*
- * Test for synchronization. Check for quality byte.
- */
- dp = field_parse(cp,2);
- if( dp[0] != 'A')
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
-
- /* Now point at the time field */
- dp = field_parse(cp,1);
- break;
-
-
- case GPGGA:
- /*
- * Test for synchronization. Check for quality byte.
- */
- dp = field_parse(cp,6);
- if( dp[0] == '0')
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
-
- /* Now point at the time field */
- dp = field_parse(cp,1);
- break;
-
-
- case GPGLL:
- /*
- * Test for synchronization. Check for quality byte.
- */
- dp = field_parse(cp,6);
- if( dp[0] != 'A')
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
-
- /* Now point at the time field */
- dp = field_parse(cp,5);
- break;
-
-
- case GPXXX:
- return;
- default:
- return;
-
- }
-
- /*
- * Check time code format of NMEA
- */
-
- if( !isdigit((int)dp[0]) ||
- !isdigit((int)dp[1]) ||
- !isdigit((int)dp[2]) ||
- !isdigit((int)dp[3]) ||
- !isdigit((int)dp[4]) ||
- !isdigit((int)dp[5])
- ) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
-
- /*
- * 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';
- /* Default to 0 milliseconds, if decimal convert milliseconds in
- one, two or three digits
- */
- pp->nsec = 0;
- if (dp[6] == '.') {
- if (isdigit((int)dp[7])) {
- pp->nsec = (dp[7] - '0') * 100000000;
- if (isdigit((int)dp[8])) {
- pp->nsec += (dp[8] - '0') * 10000000;
- if (isdigit((int)dp[9])) {
- pp->nsec += (dp[9] - '0') * 1000000;
- }
- }
- }
- }
-
- if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
- || pp->nsec > 1000000000) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
-
- /*
- * Convert date and check values.
- */
- if (cmdtype==GPRMC) {
- dp = field_parse(cp,9);
- 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';
- }
- else {
- /* only time */
- time_t tt = time(NULL);
- struct tm * t = gmtime(&tt);
- day = t->tm_mday;
- month = t->tm_mon + 1;
- pp->year= t->tm_year;
- }
-
- if (month < 1 || month > 12 || day < 1) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
- /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */
- /* good thing that 2000 is a leap year */
- /* pp->year will be 00-99 if read from GPS, 00-> (years since 1900) from tm_year */
- 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;
-
-
-#ifdef HAVE_PPSAPI
- /*
- * If the PPSAPI is working, rather use its timestamps.
- * assume that the PPS occurs on the second so blow any msec
- */
- if (nmea_pps(up, &rd_tmp) == 1) {
- pp->lastrec = up->tstamp = rd_tmp;
- pp->nsec = 0;
- }
-#endif /* HAVE_PPSAPI */
-
- /*
- * 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)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
-
-
- /*
- * Only go on if we had been polled.
- */
- if (!up->polled)
- return;
- up->polled = 0;
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-
- /* If we get here - what we got from the clock is OK, so say so */
- refclock_report(peer, CEVNT_NOMINAL);
-
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-
-}
-
-/*
- * 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(
- 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++;
- up->polled = 1;
-
- /*
- * usually nmea_receive can get a timestamp every second
- */
-
- gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\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(
- int fd,
- const char *cmd,
- struct peer *peer
- )
-{
-
- if (write(fd, cmd, strlen(cmd)) == -1) {
- refclock_report(peer, CEVNT_FAULT);
- }
-}
-
-static char *
-field_parse(
- char *cp,
- int fn
- )
-{
- char *tp;
- int i = fn;
-
- for (tp = cp; *tp != '\0'; tp++) {
- if (*tp == ',')
- i--;
- if (i == 0)
- break;
- }
- return (++tp);
-}
-#else
-int refclock_nmea_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_oncore.c b/contrib/ntp/ntpd/refclock_oncore.c
deleted file mode 100644
index 14db92f..0000000
--- a/contrib/ntp/ntpd/refclock_oncore.c
+++ /dev/null
@@ -1,3723 +0,0 @@
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- * ----------------------------------------------------------------------------
- *
- * refclock_oncore.c
- *
- * Driver for some of the various the Motorola Oncore GPS receivers.
- * should work with Basic, PVT6, VP, UT, UT+, GT, GT+, SL, M12, M12+T
- * The receivers with TRAIM (VP, UT, UT+, M12+T), will be more accurate
- * than the others.
- * The receivers without position hold (GT, GT+) will be less accurate.
- *
- * Tested with:
- *
- * (UT) (VP)
- * COPYRIGHT 1991-1997 MOTOROLA INC. COPYRIGHT 1991-1996 MOTOROLA INC.
- * SFTW P/N # 98-P36848P SFTW P/N # 98-P36830P
- * SOFTWARE VER # 2 SOFTWARE VER # 8
- * SOFTWARE REV # 2 SOFTWARE REV # 8
- * SOFTWARE DATE APR 24 1998 SOFTWARE DATE 06 Aug 1996
- * MODEL # R1121N1114 MODEL # B4121P1155
- * HWDR P/N # 1 HDWR P/N # _
- * SERIAL # R0010A SERIAL # SSG0226478
- * MANUFACTUR DATE 6H07 MANUFACTUR DATE 7E02
- * OPTIONS LIST IB
- *
- * (Basic) (M12)
- * COPYRIGHT 1991-1994 MOTOROLA INC. COPYRIGHT 1991-2000 MOTOROLA INC.
- * SFTW P/N # 98-P39949M SFTW P/N # 61-G10002A
- * SOFTWARE VER # 5 SOFTWARE VER # 1
- * SOFTWARE REV # 0 SOFTWARE REV # 3
- * SOFTWARE DATE 20 JAN 1994 SOFTWARE DATE Mar 13 2000
- * MODEL # A11121P116 MODEL # P143T12NR1
- * HDWR P/N # _ HWDR P/N # 1
- * SERIAL # SSG0049809 SERIAL # P003UD
- * MANUFACTUR DATE 417AMA199 MANUFACTUR DATE 0C27
- * OPTIONS LIST AB
- *
- * --------------------------------------------------------------------------
- * This code uses the two devices
- * /dev/oncore.serial.n
- * /dev/oncore.pps.n
- * which may be linked to the same device.
- * and can read initialization data from the file
- * /etc/ntp.oncoreN, /etc/ntp.oncore.N, or /etc/ntp.oncore, where
- * n or N are the unit number, viz 127.127.30.N.
- * --------------------------------------------------------------------------
- * Reg.Clemens <reg@dwf.com> Sep98.
- * Original code written for FreeBSD.
- * With these mods it works on FreeBSD, SunOS, Solaris and Linux
- * (SunOS 4.1.3 + ppsclock)
- * (Solaris7 + MU4)
- * (RedHat 5.1 2.0.35 + PPSKit, 2.1.126 + or later).
- *
- * Lat,Long,Ht, cable-delay, offset, and the ReceiverID (along with the
- * state machine state) are printed to CLOCKSTATS if that file is enabled
- * in /etc/ntp.conf.
- *
- * --------------------------------------------------------------------------
- *
- * According to the ONCORE manual (TRM0003, Rev 3.2, June 1998, page 3.13)
- * doing an average of 10000 valid 2D and 3D fixes is what the automatic
- * site survey mode does. Looking at the output from the receiver
- * it seems like it is only using 3D fixes.
- * When we do it ourselves, take 10000 3D fixes.
- */
-
-#define POS_HOLD_AVERAGE 10000 /* nb, 10000s ~= 2h45m */
-
-/*
- * ONCORE_SHMEM_STATUS will create a mmap(2)'ed file named according to a
- * "STATUS" line in the oncore config file, which contains the most recent
- * copy of all types of messages we recognize. This file can be mmap(2)'ed
- * by monitoring and statistics programs.
- *
- * See separate HTML documentation for this option.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_ONCORE) && defined(HAVE_PPSAPI)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/stat.h>
-#ifdef ONCORE_SHMEM_STATUS
-# ifdef HAVE_SYS_MMAN_H
-# include <sys/mman.h>
-# ifndef MAP_FAILED
-# define MAP_FAILED ((u_char *) -1)
-# endif /* not MAP_FAILED */
-# endif /* HAVE_SYS_MMAN_H */
-#endif /* ONCORE_SHMEM_STATUS */
-
-#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
-#endif
-
-#ifdef HAVE_SYS_SIO_H
-# include <sys/sio.h>
-#endif
-
-#ifdef HAVE_SYS_TERMIOS_H
-# include <sys/termios.h>
-#endif
-
-#ifdef HAVE_SYS_PPSCLOCK_H
-# include <sys/ppsclock.h>
-#endif
-
-#ifndef HAVE_STRUCT_PPSCLOCKEV
-struct ppsclockev {
-# ifdef HAVE_STRUCT_TIMESPEC
- struct timespec tv;
-# else
- struct timeval tv;
-# endif
- u_int serial;
-};
-#endif /* not HAVE_STRUCT_PPSCLOCKEV */
-
-enum receive_state {
- ONCORE_NO_IDEA,
- ONCORE_CHECK_ID,
- ONCORE_CHECK_CHAN,
- ONCORE_HAVE_CHAN,
- ONCORE_RESET_SENT,
- ONCORE_TEST_SENT,
- ONCORE_INIT,
- ONCORE_ALMANAC,
- ONCORE_RUN
-};
-
-enum site_survey_state {
- ONCORE_SS_UNKNOWN,
- ONCORE_SS_TESTING,
- ONCORE_SS_HW,
- ONCORE_SS_SW,
- ONCORE_SS_DONE
-};
-
-enum antenna_state {
- ONCORE_ANTENNA_UNKNOWN = -1,
- ONCORE_ANTENNA_OK = 0,
- ONCORE_ANTENNA_OC = 1,
- ONCORE_ANTENNA_UC = 2,
- ONCORE_ANTENNA_NV = 3
-};
-
-/* Model Name, derived from the @@Cj message.
- * Used to initialize some variables.
- */
-
-enum oncore_model {
- ONCORE_BASIC,
- ONCORE_PVT6,
- ONCORE_VP,
- ONCORE_UT,
- ONCORE_UTPLUS,
- ONCORE_GT,
- ONCORE_GTPLUS,
- ONCORE_SL,
- ONCORE_M12,
- ONCORE_UNKNOWN
-};
-
-/* the bits that describe these properties are in the same place
- * on the VP/UT, but have moved on the M12. As such we extract
- * them, and use them from this struct.
- *
- */
-
-struct RSM {
- u_char posn0D;
- u_char posn2D;
- u_char posn3D;
- u_char bad_almanac;
- u_char bad_fix;
-};
-
-/* It is possible to test the VP/UT each cycle (@@Ea or equivalent) to
- * see what mode it is in. The bits on the M12 are multiplexed with
- * other messages, so we have to 'keep' the last known mode here.
- */
-
-enum posn_mode {
- MODE_UNKNOWN,
- MODE_0D,
- MODE_2D,
- MODE_3D
-};
-
-struct instance {
- int unit; /* 127.127.30.unit */
- struct refclockproc *pp;
- struct peer *peer;
-
- int ttyfd; /* TTY file descriptor */
- int ppsfd; /* PPS file descriptor */
- int shmemfd; /* Status shm descriptor */
-#ifdef HAVE_PPSAPI
- pps_handle_t pps_h;
- pps_params_t pps_p;
-#endif
- enum receive_state o_state; /* Receive state */
- enum posn_mode mode; /* 0D, 2D, 3D */
- enum site_survey_state site_survey; /* Site Survey state */
- enum antenna_state ant_state; /* antenna state */
-
- int Bj_day;
-
- u_long delay; /* ns */
- long offset; /* ns */
-
- u_char *shmem;
- char *shmem_fname;
- u_int shmem_Cb;
- u_int shmem_Ba;
- u_int shmem_Ea;
- u_int shmem_Ha;
- u_char shmem_reset;
- u_char shmem_Posn;
- u_char shmem_bad_Ea;
- u_char almanac_from_shmem;
-
- double ss_lat;
- double ss_long;
- double ss_ht;
- double dH;
- int ss_count;
- u_char posn_set;
-
- enum oncore_model model;
- u_int version;
- u_int revision;
-
- u_char chan; /* 6 for PVT6 or BASIC, 8 for UT/VP, 12 for m12, 0 if unknown */
- s_char traim; /* do we have traim? yes UT/VP, no BASIC, GT, M12+T, -1 unknown, 0 no, +1 yes */
-
- /* the following 7 are all timing counters */
- u_char traim_delay; /* seconds counter, waiting for reply */
- u_char count; /* cycles thru Ea before starting */
- u_char count1; /* cycles thru Ea after SS_TESTING, waiting for SS_HW */
- u_char count2; /* cycles thru Ea after count, to check for @@Ea */
- u_char count3; /* cycles thru Ea checking for # channels */
- u_char count4; /* cycles thru leap after Gj to issue Bj */
- u_char pollcnt;
- u_char timeout; /* count to retry Cj after Fa self-test */
-
- struct RSM rsm; /* bits extracted from Receiver Status Msg in @@Ea */
- u_char printed;
- u_char polled;
- u_long ev_serial;
- int Rcvptr;
- u_char Rcvbuf[500];
- u_char BEHa[160]; /* Ba, Ea or Ha */
- u_char BEHn[80]; /* Bn , En , or Hn */
- u_char Cj[300];
- u_char Ag; /* Satellite mask angle */
- u_char saw_At;
- u_char saw_Ay;
- u_char saw_Az;
- s_char saw_Gj;
- u_char have_dH;
- u_char init_type;
- s_char saw_tooth;
- s_char chan_in; /* chan number from INPUT, will always use it */
- u_char chan_id; /* chan number determined from part number */
- u_char chan_ck; /* chan number determined by sending commands to hardware */
- s_char traim_in; /* TRAIM from INPUT, will always use it */
- s_char traim_id; /* TRAIM determined from part number */
- u_char traim_ck; /* TRAIM determined by sending commands to hardware */
- u_char once; /* one pass code at top of BaEaHa */
- s_char assert;
- u_char hardpps;
-};
-
-#define rcvbuf instance->Rcvbuf
-#define rcvptr instance->Rcvptr
-
-static int oncore_start P((int, struct peer *));
-static void oncore_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
-static void oncore_poll P((int, struct peer *));
-static void oncore_shutdown P((int, struct peer *));
-static void oncore_consume P((struct instance *));
-static void oncore_read_config P((struct instance *));
-static void oncore_receive P((struct recvbuf *));
-static int oncore_ppsapi P((struct instance *));
-static void oncore_get_timestamp P((struct instance *, long, long));
-static void oncore_init_shmem P((struct instance *));
-
-static void oncore_antenna_report P((struct instance *, enum antenna_state));
-static void oncore_chan_test P((struct instance *));
-static void oncore_check_almanac P((struct instance *));
-static void oncore_check_antenna P((struct instance *));
-static void oncore_check_leap_sec P((struct instance *));
-static int oncore_checksum_ok P((u_char *, int));
-static void oncore_compute_dH P((struct instance *));
-static void oncore_load_almanac P((struct instance *));
-static void oncore_print_Cb P((struct instance *, u_char *));
-/* static void oncore_print_array P((u_char *, int)); */
-static void oncore_print_posn P((struct instance *));
-static void oncore_sendmsg P((int, u_char *, size_t));
-static void oncore_set_posn P((struct instance *));
-static void oncore_set_traim P((struct instance *));
-static void oncore_shmem_get_3D P((struct instance *));
-static void oncore_ss P((struct instance *));
-static int oncore_wait_almanac P((struct instance *));
-
-static void oncore_msg_any P((struct instance *, u_char *, size_t, int));
-static void oncore_msg_Adef P((struct instance *, u_char *, size_t));
-static void oncore_msg_Ag P((struct instance *, u_char *, size_t));
-static void oncore_msg_As P((struct instance *, u_char *, size_t));
-static void oncore_msg_At P((struct instance *, u_char *, size_t));
-static void oncore_msg_Ay P((struct instance *, u_char *, size_t));
-static void oncore_msg_Az P((struct instance *, u_char *, size_t));
-static void oncore_msg_BaEaHa P((struct instance *, u_char *, size_t));
-static void oncore_msg_Bd P((struct instance *, u_char *, size_t));
-static void oncore_msg_Bj P((struct instance *, u_char *, size_t));
-static void oncore_msg_BnEnHn P((struct instance *, u_char *, size_t));
-static void oncore_msg_CaFaIa P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cb P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cf P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cj P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cj_id P((struct instance *, u_char *, size_t));
-static void oncore_msg_Cj_init P((struct instance *, u_char *, size_t));
-static void oncore_msg_Ga P((struct instance *, u_char *, size_t));
-static void oncore_msg_Gb P((struct instance *, u_char *, size_t));
-static void oncore_msg_Gd P((struct instance *, u_char *, size_t));
-static void oncore_msg_Gj P((struct instance *, u_char *, size_t));
-static void oncore_msg_Sz P((struct instance *, u_char *, size_t));
-
-struct refclock refclock_oncore = {
- oncore_start, /* start up driver */
- oncore_shutdown, /* shut down driver */
- oncore_poll, /* transmit poll message */
- oncore_control, /* fudge (flag) control messages */
- noentry, /* not used */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-/*
- * Understanding the next bit here is not easy unless you have a manual
- * for the the various Oncore Models.
- */
-
-static struct msg_desc {
- const char flag[3];
- const int len;
- void (*handler) P((struct instance *, u_char *, size_t));
- const char *fmt;
- int shmem;
-} oncore_messages[] = {
- /* Ea and En first since they're most common */
- { "Ea", 76, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" },
- { "Ba", 68, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdsC" },
- { "Ha", 154, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmaaaaoooohhhhmmmmVVvvhhddntimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddssrrccooooTTushmvvvvvvC" },
- { "Bn", 59, oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffC" },
- { "En", 69, oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC" },
- { "Hn", 78, oncore_msg_BnEnHn, "" },
- { "Ab", 10, 0, "" },
- { "Ac", 11, 0, "" },
- { "Ad", 11, oncore_msg_Adef, "" },
- { "Ae", 11, oncore_msg_Adef, "" },
- { "Af", 15, oncore_msg_Adef, "" },
- { "Ag", 8, oncore_msg_Ag, "" }, /* Satellite mask angle */
- { "As", 20, oncore_msg_As, "" },
- { "At", 8, oncore_msg_At, "" },
- { "Au", 12, 0, "" },
- { "Av", 8, 0, "" },
- { "Aw", 8, 0, "" },
- { "Ay", 11, oncore_msg_Ay, "" },
- { "Az", 11, oncore_msg_Az, "" },
- { "AB", 8, 0, "" },
- { "Bb", 92, 0, "" },
- { "Bd", 23, oncore_msg_Bd, "" },
- { "Bj", 8, oncore_msg_Bj, "" },
- { "Ca", 9, oncore_msg_CaFaIa, "" },
- { "Cb", 33, oncore_msg_Cb, "" },
- { "Cf", 7, oncore_msg_Cf, "" },
- { "Cg", 8, 0, "" },
- { "Ch", 9, 0, "" },
- { "Cj", 294, oncore_msg_Cj, "" },
- { "Ek", 71, 0, "" },
- { "Fa", 9, oncore_msg_CaFaIa, "" },
- { "Ga", 20, oncore_msg_Ga, "" },
- { "Gb", 17, oncore_msg_Gb, "" },
- { "Gc", 8, 0, "" },
- { "Gd", 8, oncore_msg_Gd, "" },
- { "Ge", 8, 0, "" },
- { "Gj", 21, oncore_msg_Gj, "" },
- { "Ia", 10, oncore_msg_CaFaIa, "" },
- { "Sz", 8, oncore_msg_Sz, "" },
- { {0}, 7, 0, "" }
-};
-
-
-static u_char oncore_cmd_Aa[] = { 'A', 'a', 0, 0, 0 }; /* 6/8 Time of Day */
-static u_char oncore_cmd_Ab[] = { 'A', 'b', 0, 0, 0 }; /* 6/8 GMT Correction */
-static u_char oncore_cmd_AB[] = { 'A', 'B', 4 }; /* VP Application Type: Static */
-static u_char oncore_cmd_Ac[] = { 'A', 'c', 0, 0, 0, 0 }; /* 6/8 Date */
-static u_char oncore_cmd_Ad[] = { 'A', 'd', 0,0,0,0 }; /* 6/8 Latitude */
-static u_char oncore_cmd_Ae[] = { 'A', 'e', 0,0,0,0 }; /* 6/8 Longitude */
-static u_char oncore_cmd_Af[] = { 'A', 'f', 0,0,0,0, 0 }; /* 6/8 Height */
-static u_char oncore_cmd_Ag[] = { 'A', 'g', 0 }; /* 6/8/12 Satellite Mask Angle */
-static u_char oncore_cmd_Agx[] = { 'A', 'g', 0xff }; /* 6/8/12 Satellite Mask Angle: read */
-static u_char oncore_cmd_As[] = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 }; /* 6/8/12 Posn Hold Parameters */
-static u_char oncore_cmd_Asx[] = { 'A', 's', 0x7f,0xff,0xff,0xff, /* 6/8/12 Posn Hold Readback */
- 0x7f,0xff,0xff,0xff, /* on UT+ this doesnt work with 0xff */
- 0x7f,0xff,0xff,0xff, 0xff }; /* but does work with 0x7f (sigh). */
-static u_char oncore_cmd_At0[] = { 'A', 't', 0 }; /* 6/8 Posn Hold: off */
-static u_char oncore_cmd_At1[] = { 'A', 't', 1 }; /* 6/8 Posn Hold: on */
-static u_char oncore_cmd_At2[] = { 'A', 't', 2 }; /* 6/8 Posn Hold: Start Site Survey */
-static u_char oncore_cmd_Atx[] = { 'A', 't', 0xff }; /* 6/8 Posn Hold: Read Back */
-static u_char oncore_cmd_Au[] = { 'A', 'u', 0,0,0,0, 0 }; /* GT/M12 Altitude Hold Ht. */
-static u_char oncore_cmd_Av0[] = { 'A', 'v', 0 }; /* VP/GT Altitude Hold: off */
-static u_char oncore_cmd_Av1[] = { 'A', 'v', 1 }; /* VP/GT Altitude Hold: on */
-static u_char oncore_cmd_Aw[] = { 'A', 'w', 1 }; /* 6/8/12 UTC/GPS time selection */
-static u_char oncore_cmd_Ay[] = { 'A', 'y', 0, 0, 0, 0 }; /* Timing 1PPS time offset: set */
-static u_char oncore_cmd_Ayx[] = { 'A', 'y', 0xff, 0xff, 0xff, 0xff }; /* Timing 1PPS time offset: Read */
-static u_char oncore_cmd_Az[] = { 'A', 'z', 0, 0, 0, 0 }; /* 6/8UT/12 1PPS Cable Delay: set */
-static u_char oncore_cmd_Azx[] = { 'A', 'z', 0xff, 0xff, 0xff, 0xff }; /* 6/8UT/12 1PPS Cable Delay: Read */
-static u_char oncore_cmd_Ba0[] = { 'B', 'a', 0 }; /* 6 Position/Data/Status: off */
-static u_char oncore_cmd_Ba[] = { 'B', 'a', 1 }; /* 6 Position/Data/Status: on */
-static u_char oncore_cmd_Bb[] = { 'B', 'b', 1 }; /* 6/8/12 Visible Satellites */
-static u_char oncore_cmd_Bd[] = { 'B', 'd', 1 }; /* 6/8/12? Almanac Status Msg. */
-static u_char oncore_cmd_Be[] = { 'B', 'e', 1 }; /* 6/8/12 Request Almanac Data */
-static u_char oncore_cmd_Bj[] = { 'B', 'j', 0 }; /* 6/8 Leap Second Pending */
-static u_char oncore_cmd_Bn0[] = { 'B', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg off, traim on */
-static u_char oncore_cmd_Bn[] = { 'B', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg on traim on */
-static u_char oncore_cmd_Bnx[] = { 'B', 'n', 1, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg on traim off */
-static u_char oncore_cmd_Ca[] = { 'C', 'a' }; /* 6 Self Test */
-static u_char oncore_cmd_Cf[] = { 'C', 'f' }; /* 6/8/12 Set to Defaults */
-static u_char oncore_cmd_Cg[] = { 'C', 'g', 1 }; /* VP Posn Fix/Idle Mode */
-static u_char oncore_cmd_Cj[] = { 'C', 'j' }; /* 6/8/12 Receiver ID */
-static u_char oncore_cmd_Ea0[] = { 'E', 'a', 0 }; /* 8 Position/Data/Status: off */
-static u_char oncore_cmd_Ea[] = { 'E', 'a', 1 }; /* 8 Position/Data/Status: on */
-static u_char oncore_cmd_Ek[] = { 'E', 'k', 0 }; /* just turn off */ /* 8 Posn/Status/Data - extension */
-static u_char oncore_cmd_En0[] = { 'E', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT TRAIM setup/status: msg off, traim on */
-static u_char oncore_cmd_En[] = { 'E', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT TRAIM setup/status: msg on traim on */
-static u_char oncore_cmd_Enx[] = { 'E', 'n', 1, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT TRAIM setup/status: msg on traim off */
-static u_char oncore_cmd_Fa[] = { 'F', 'a' }; /* 8 Self Test */
-static u_char oncore_cmd_Ga[] = { 'G', 'a', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 }; /* 12 Position Set */
-static u_char oncore_cmd_Gax[] = { 'G', 'a', 0xff, 0xff, 0xff, 0xff, /* 12 Position Set: Read */
- 0xff, 0xff, 0xff, 0xff, /* */
- 0xff, 0xff, 0xff, 0xff, 0xff }; /* */
-static u_char oncore_cmd_Gb[] = { 'G', 'b', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 12 set Date/Time */
-static u_char oncore_cmd_Gc[] = { 'G', 'c', 1 }; /* 12 PPS Control: On Cont */
-static u_char oncore_cmd_Gd0[] = { 'G', 'd', 0 }; /* 12 Position Control: 3D (no hold) */
-static u_char oncore_cmd_Gd1[] = { 'G', 'd', 1 }; /* 12 Position Control: 0D (3D hold) */
-static u_char oncore_cmd_Gd2[] = { 'G', 'd', 2 }; /* 12 Position Control: 2D (Alt Hold) */
-static u_char oncore_cmd_Gd3[] = { 'G', 'd', 3 }; /* 12 Position Coltrol: Start Site Survey */
-static u_char oncore_cmd_Ge0[] = { 'G', 'e', 0 }; /* M12+T TRAIM: off */
-static u_char oncore_cmd_Ge[] = { 'G', 'e', 1 }; /* M12+T TRAIM: on */
-static u_char oncore_cmd_Gj[] = { 'G', 'j' }; /* 8?/12 Leap Second Pending */
-static u_char oncore_cmd_Ha0[] = { 'H', 'a', 0 }; /* 12 Position/Data/Status: off */
-static u_char oncore_cmd_Ha[] = { 'H', 'a', 1 }; /* 12 Position/Data/Status: on */
-static u_char oncore_cmd_Hn0[] = { 'H', 'n', 0 }; /* 12 TRAIM Status: off */
-static u_char oncore_cmd_Hn[] = { 'H', 'n', 1 }; /* 12 TRAIM Status: on */
-static u_char oncore_cmd_Ia[] = { 'I', 'a' }; /* 12 Self Test */
-
-/* it appears that as of 1997/1998, the UT had As,At, but not Au,Av
- * the GT had Au,Av, but not As,At
- * This was as of v2.0 of both firmware sets. possibly 1.3 for UT.
- * Bj in UT at v1.3
- * dont see Bd in UT/GT thru 1999
- * Gj in UT as of 3.0, 1999 , Bj as of 1.3
- */
-
-static char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly",
- "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-#define DEVICE1 "/dev/oncore.serial.%d" /* name of serial device */
-#define DEVICE2 "/dev/oncore.pps.%d" /* name of pps device */
-#define INIT_FILE "/etc/ntp.oncore" /* optional init file */
-
-#define SPEED B9600 /* Oncore Binary speed (9600 bps) */
-
-/*
- * Assemble and disassemble 32bit signed quantities from a buffer.
- *
- */
-
- /* to buffer, int w, u_char *buf */
-#define w32_buf(buf,w) { u_int i_tmp; \
- i_tmp = (w<0) ? (~(-w)+1) : (w); \
- (buf)[0] = (i_tmp >> 24) & 0xff; \
- (buf)[1] = (i_tmp >> 16) & 0xff; \
- (buf)[2] = (i_tmp >> 8) & 0xff; \
- (buf)[3] = (i_tmp ) & 0xff; \
- }
-
-#define w32(buf) (((buf)[0]&0xff) << 24 | \
- ((buf)[1]&0xff) << 16 | \
- ((buf)[2]&0xff) << 8 | \
- ((buf)[3]&0xff) )
-
- /* from buffer, char *buf, result to an int */
-#define buf_w32(buf) (((buf)[0]&0200) ? (-(~w32(buf)+1)) : w32(buf))
-
-
-/*
- * oncore_start - initialize data for processing
- */
-
-static int
-oncore_start(
- int unit,
- struct peer *peer
- )
-{
- register struct instance *instance;
- struct refclockproc *pp;
- int fd1, fd2;
- char device1[30], device2[30];
- const char *cp;
- struct stat stat1, stat2;
-
- /* OPEN DEVICES */
- /* opening different devices for fd1 and fd2 presents no problems */
- /* opening the SAME device twice, seems to be OS dependent.
- (a) on Linux (no streams) no problem
- (b) on SunOS (and possibly Solaris, untested), (streams)
- never see the line discipline.
- Since things ALWAYS work if we only open the device once, we check
- to see if the two devices are in fact the same, then proceed to
- do one open or two.
- */
-
- (void)sprintf(device1, DEVICE1, unit);
- (void)sprintf(device2, DEVICE2, unit);
-
- if (stat(device1, &stat1)) {
- perror("ONCORE: stat fd1");
- exit(1);
- }
-
- if (stat(device2, &stat2)) {
- perror("ONCORE: stat fd2");
- exit(1);
- }
-
- /* create instance structure for this unit */
-
- if (!(instance = (struct instance *) malloc(sizeof *instance))) {
- perror("malloc");
- return (0);
- }
- memset((char *) instance, 0, sizeof *instance);
-
- if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino)) {
- /* same device here */
- if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW
-#if !defined(HAVE_PPSAPI) && !defined(TIOCDCDTIMESTAMP)
- | LDISC_PPS
-#endif
- ))) {
- perror("ONCORE: fd1");
- exit(1);
- }
- fd2 = fd1;
- } else { /* different devices here */
- if (!(fd1=refclock_open(device1, SPEED, LDISC_RAW))) {
- perror("ONCORE: fd1");
- exit(1);
- }
- if ((fd2=open(device2, O_RDWR)) < 0) {
- perror("ONCORE: fd2");
- exit(1);
- }
- }
-
- /* initialize miscellaneous variables */
-
- pp = peer->procptr;
- pp->unitptr = (caddr_t) instance;
- instance->pp = pp;
- instance->unit = unit;
- instance->peer = peer;
- instance->assert = 1;
- instance->once = 1;
-
- cp = "ONCORE DRIVER -- CONFIGURING";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->o_state = ONCORE_NO_IDEA;
- cp = "state = ONCORE_NO_IDEA";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->ttyfd = fd1;
- instance->ppsfd = fd2;
-
- instance->Bj_day = -1;
- instance->traim = -1;
- instance->traim_in = -1;
- instance->chan_in = -1;
- instance->model = ONCORE_UNKNOWN;
- instance->mode = MODE_UNKNOWN;
- instance->site_survey = ONCORE_SS_UNKNOWN;
- instance->Ag = 0xff; /* Satellite mask angle, unset by user */
- instance->ant_state = ONCORE_ANTENNA_UNKNOWN;
-
- peer->precision = -26;
- peer->minpoll = 4;
- peer->maxpoll = 4;
- pp->clockdesc = "Motorola Oncore GPS Receiver";
- memcpy((char *)&pp->refid, "GPS\0", (size_t) 4);
-
- /* go read any input data in /etc/ntp.oncoreX or /etc/ntp/oncore.X */
-
- oncore_read_config(instance);
-
-#ifdef HAVE_PPSAPI
- if (time_pps_create(fd2, &instance->pps_h) < 0) {
- perror("time_pps_create");
- return(0);
- }
-
- if (instance->assert)
- cp = "Initializing timing to Assert.";
- else
- cp = "Initializing timing to Clear.";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- if (instance->hardpps) {
- cp = "HARDPPS Set.";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
-
- if (!oncore_ppsapi(instance))
- return(0);
-#endif
-
- pp->io.clock_recv = oncore_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd1;
- if (!io_addclock(&pp->io)) {
- perror("io_addclock");
- (void) close(fd1);
- free(instance);
- return (0);
- }
-
-#ifdef ONCORE_SHMEM_STATUS
- /*
- * Before starting ONCORE, lets setup SHMEM
- * This will include merging an old SHMEM into the new one if
- * an old one is found.
- */
-
- oncore_init_shmem(instance);
-#endif
-
- /*
- * This will return the Model of the Oncore receiver.
- * and start the Initialization loop in oncore_msg_Cj.
- */
-
- instance->o_state = ONCORE_CHECK_ID;
- cp = "state = ONCORE_CHECK_ID";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->timeout = 4;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Set Posn Fix mode (not Idle (VP)) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
-
- instance->pollcnt = 2;
- return (1);
-}
-
-
-/*
- * Fudge control (get Flag2 and Flag3, not available at oncore_start time.
- */
-
-static void
-oncore_control(
- int unit, /* unit (not used) */
- struct refclockstat *in, /* input parameters (not used) */
- struct refclockstat *out, /* output parameters (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- char *cp;
- struct refclockproc *pp;
- struct instance *instance;
-
- pp = peer->procptr;
- instance = (struct instance *) pp->unitptr;
-
- instance->assert = !(pp->sloppyclockflag & CLK_FLAG2);
- instance->hardpps = pp->sloppyclockflag & CLK_FLAG3;
-
- if (instance->assert)
- cp = "Resetting timing to Assert.";
- else
- cp = "Resetting timing to Clear.";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- if (instance->hardpps) {
- cp = "HARDPPS Set.";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
-
- (void) oncore_ppsapi(instance);
-}
-
-
-
-/*
- * oncore_shutdown - shut down the clock
- */
-
-static void
-oncore_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct instance *instance;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- instance = (struct instance *) pp->unitptr;
-
- io_closeclock(&pp->io);
-
- close(instance->ttyfd);
- close(instance->ppsfd);
- if (instance->shmemfd)
- close(instance->shmemfd);
- free(instance);
-}
-
-
-
-/*
- * oncore_poll - called by the transmit procedure
- */
-
-static void
-oncore_poll(
- int unit,
- struct peer *peer
- )
-{
- struct instance *instance;
-
- instance = (struct instance *) peer->procptr->unitptr;
- if (instance->timeout) {
- char *cp;
-
- instance->timeout--;
- if (instance->timeout == 0) {
- cp = "Oncore: No response from @@Cj, shutting down driver";
- record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_shutdown(unit, peer);
- } else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
- cp = "Oncore: Resend @@Cj";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
- return;
- }
-
- if (!instance->pollcnt)
- refclock_report(peer, CEVNT_TIMEOUT);
- else
- instance->pollcnt--;
- peer->procptr->polls++;
- instance->polled = 1;
-}
-
-
-
-/*
- * Initialize PPSAPI
- */
-
-#ifdef HAVE_PPSAPI
-static int
-oncore_ppsapi(
- struct instance *instance
- )
-{
- int mode;
-
- if (time_pps_getcap(instance->pps_h, &mode) < 0) {
- msyslog(LOG_ERR, "refclock_ioctl: time_pps_getcap failed: %m");
- return (0);
- }
-
- if (time_pps_getparams(instance->pps_h, &instance->pps_p) < 0) {
- msyslog(LOG_ERR, "refclock_ioctl: time_pps_getparams failed: %m");
- return (0);
- }
-
- /* nb. only turn things on, if someone else has turned something
- * on before we get here, leave it alone!
- */
-
- if (instance->assert) { /* nb, default or ON */
- instance->pps_p.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
- instance->pps_p.assert_offset.tv_sec = 0;
- instance->pps_p.assert_offset.tv_nsec = 0;
- } else {
- instance->pps_p.mode = PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
- instance->pps_p.clear_offset.tv_sec = 0;
- instance->pps_p.clear_offset.tv_nsec = 0;
- }
- instance->pps_p.mode |= PPS_TSFMT_TSPEC;
- instance->pps_p.mode &= mode; /* only set what is legal */
-
- if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) {
- perror("time_pps_setparams");
- exit(1);
- }
-
- /* If HARDPPS is on, we tell kernel */
-
- if (instance->hardpps) {
- int i;
-
- if (instance->assert)
- i = PPS_CAPTUREASSERT;
- else
- i = PPS_CAPTURECLEAR;
-
- if (i&mode) {
- if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i,
- PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR, "refclock_ioctl: time_pps_kcbind failed: %m");
- return (0);
- }
- pps_enable = 1;
- }
- }
- return(1);
-}
-#endif
-
-
-
-#ifdef ONCORE_SHMEM_STATUS
-static void
-oncore_init_shmem(
- struct instance *instance
- )
-{
- int i, l, n, fd, shmem_old_size, n1;
- char *buf, Msg[160];
- u_char *cp, *cp1, *shmem_old;
- struct msg_desc *mp;
- struct stat sbuf;
- size_t shmem_length;
-
- /*
- * The first thing we do is see if there is an instance->shmem_fname file (still)
- * out there from a previous run. If so, we copy it in and use it to initialize
- * shmem (so we won't lose our almanac if we need it).
- */
-
- shmem_old = 0;
- if ((fd = open(instance->shmem_fname, O_RDONLY)) < 0)
- perror("LOAD:SHMEM");
- else {
- fstat(fd, &sbuf);
- shmem_old_size = sbuf.st_size;
- shmem_old = (u_char *) malloc((unsigned) sbuf.st_size);
- if (shmem_old == NULL) {
- perror("malloc");
- close(fd);
- return;
- }
-
- read(fd, shmem_old, shmem_old_size);
- close(fd);
- }
-
- /* OK, we now create the NEW SHMEM. */
-
- if ((instance->shmemfd = open(instance->shmem_fname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
- perror(instance->shmem_fname);
- return;
- }
-
- /* see how big it needs to be */
-
- n = 1;
- for (mp=oncore_messages; mp->flag[0]; mp++) {
- mp->shmem = n;
- /* Allocate space for multiplexed almanac, and 0D/2D/3D @@Ea records */
- if (!strcmp(mp->flag, "Cb")) {
- instance->shmem_Cb = n;
- n += (mp->len + 3) * 34;
- }
- if (!strcmp(mp->flag, "Ba")) {
- instance->shmem_Ba = n;
- n += (mp->len + 3) * 3;
- }
- if (!strcmp(mp->flag, "Ea")) {
- instance->shmem_Ea = n;
- n += (mp->len + 3) * 3;
- }
- if (!strcmp(mp->flag, "Ha")) {
- instance->shmem_Ha = n;
- n += (mp->len + 3) * 3;
- }
- n += (mp->len + 3);
- }
- shmem_length = n + 2;
- fprintf(stderr, "ONCORE: SHMEM length: %d bytes\n", (int) shmem_length);
-
- buf = malloc(shmem_length);
- if (buf == NULL) {
- perror("malloc");
- close(instance->shmemfd);
- return;
- }
-
- memset(buf, 0, shmem_length);
-
- /* next build the new SHMEM buffer in memory */
-
- for (mp=oncore_messages; mp->flag[0]; mp++) {
- l = mp->shmem;
- buf[l + 0] = mp->len >> 8;
- buf[l + 1] = mp->len & 0xff;
- buf[l + 2] = 0;
- buf[l + 3] = '@';
- buf[l + 4] = '@';
- buf[l + 5] = mp->flag[0];
- buf[l + 6] = mp->flag[1];
- if (!strcmp(mp->flag, "Cb") || !strcmp(mp->flag, "Ba") || !strcmp(mp->flag, "Ea") || !strcmp(mp->flag, "Ha")) {
- if (!strcmp(mp->flag, "Cb"))
- n = 35;
- else
- n = 4;
- for (i=1; i<n; i++) {
- buf[l + i * (mp->len+3) + 0] = mp->len >> 8;
- buf[l + i * (mp->len+3) + 1] = mp->len & 0xff;
- buf[l + i * (mp->len+3) + 2] = 0;
- buf[l + i * (mp->len+3) + 3] = '@';
- buf[l + i * (mp->len+3) + 4] = '@';
- buf[l + i * (mp->len+3) + 5] = mp->flag[0];
- buf[l + i * (mp->len+3) + 6] = mp->flag[1];
- }
- }
- }
-
- /* we now walk thru the two buffers (shmem_old and buf, soon to become shmem)
- * copying the data in shmem_old to buf. When we are done we write it out
- * and free both buffers.
- * If the structures change (an addition or deletion) I will stop copying.
- * The two will be the same unless we add/subtract from the oncore_messages list
- * so this should work most of the time, and takes a lot less code than doing it right.
- */
-
- if (shmem_old) {
- for (cp=buf+4, cp1=shmem_old+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3), cp1+=(n+3)) {
- n1 = 256*(*(cp1-3)) + *(cp1-2);
- if (n1 != n || strncmp(cp, cp1, 4))
- break;
-
- memcpy(cp, cp1, (size_t) n);
- }
- free(shmem_old);
- }
-
- i = write(instance->shmemfd, buf, shmem_length);
- free(buf);
-
- if (i != shmem_length) {
- perror(instance->shmem_fname);
- close(instance->shmemfd);
- return;
- }
-
- instance->shmem = (u_char *) mmap(0, shmem_length,
- PROT_READ | PROT_WRITE,
-#ifdef MAP_HASSEMAPHORE
- MAP_HASSEMAPHORE |
-#endif
- MAP_SHARED, instance->shmemfd, (off_t)0);
-
- if (instance->shmem == (u_char *)MAP_FAILED) {
- instance->shmem = 0;
- close(instance->shmemfd);
- return;
- }
-
- sprintf(Msg, "SHMEM (size = %d) is CONFIGURED and available as %s", shmem_length, instance->shmem_fname);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-#endif /* ONCORE_SHMEM_STATUS */
-
-
-
-/*
- * Read Input file if it exists.
- */
-
-static void
-oncore_read_config(
- struct instance *instance
- )
-{
-/*
- * First we try to open the configuration file
- * /etc/oncoreN
- * where N is the unit number viz 127.127.30.N.
- * If we don't find it we try
- * /etc/ntp.oncore.N
- * and then
- * /etc/ntp.oncore
- *
- * If we don't find any then we don't have the cable delay or PPS offset
- * and we choose MODE (4) below.
- *
- * Five Choices for MODE
- * (0) ONCORE is preinitialized, don't do anything to change it.
- * nb, DON'T set 0D mode, DON'T set Delay, position...
- * (1) NO RESET, Read Position, delays from data file, lock it in, go to 0D mode.
- * (2) NO RESET, Read Delays from data file, do SITE SURVEY to get position,
- * lock this in, go to 0D mode.
- * (3) HARD RESET, Read Position, delays from data file, lock it in, go to 0D mode.
- * (4) HARD RESET, Read Delays from data file, do SITE SURVEY to get position,
- * lock this in, go to 0D mode.
- * NB. If a POSITION is specified in the config file with mode=(2,4) [SITE SURVEY]
- * then this position is set as the INITIAL position of the ONCORE.
- * This can reduce the time to first fix.
- * -------------------------------------------------------------------------------
- * Note that an Oncore UT without a battery backup retains NO information if it is
- * power cycled, with a Battery Backup it remembers the almanac, etc.
- * For an Oncore VP, there is an eeprom that will contain this data, along with the
- * option of Battery Backup.
- * So a UT without Battery Backup is equivalent to doing a HARD RESET on each
- * power cycle, since there is nowhere to store the data.
- * -------------------------------------------------------------------------------
- *
- * If we open one or the other of the files, we read it looking for
- * MODE, LAT, LON, (HT, HTGPS, HTMSL), DELAY, OFFSET, ASSERT, CLEAR, HARDPPS,
- * STATUS, POSN3D, POSN2D, CHAN, TRAIM
- * then initialize using method MODE. For Mode = (1,3) all of (LAT, LON, HT) must
- * be present or mode reverts to (2,4).
- *
- * Read input file.
- *
- * # is comment to end of line
- * = allowed between 1st and 2nd fields.
- *
- * Expect to see one line with 'MODE' as first field, followed by an integer
- * in the range 0-4 (default = 4).
- *
- * Expect to see two lines with 'LONG', 'LAT' followed by 1-3 fields.
- * All numbers are floating point.
- * DDD.ddd
- * DDD MMM.mmm
- * DDD MMM SSS.sss
- *
- * Expect to see one line with 'HT' as first field,
- * followed by 1-2 fields. First is a number, the second is 'FT' or 'M'
- * for feet or meters. HT is the height above the GPS ellipsoid.
- * If the receiver reports height in both GPS and MSL, then we will report
- * the difference GPS-MSL on the clockstats file.
- *
- * There is an optional line, starting with DELAY, followed
- * by 1 or two fields. The first is a number (a time) the second is
- * 'MS', 'US' or 'NS' for miliseconds, microseconds or nanoseconds.
- * DELAY is cable delay, typically a few tens of ns.
- *
- * There is an optional line, starting with OFFSET, followed
- * by 1 or two fields. The first is a number (a time) the second is
- * 'MS', 'US' or 'NS' for miliseconds, microseconds or nanoseconds.
- * OFFSET is the offset of the PPS pulse from 0. (only fully implemented
- * with the PPSAPI, we need to be able to tell the Kernel about this
- * offset if the Kernel PLL is in use, but can only do this presently
- * when using the PPSAPI interface. If not using the Kernel PLL,
- * then there is no problem.
- *
- * There is an optional line, with either ASSERT or CLEAR on it, which
- * determine which transition of the PPS signal is used for timing by the
- * PPSAPI. If neither is present, then ASSERT is assumed.
- * ASSERT/CLEAR can also be set with FLAG2 of the ntp.conf input.
- * For Flag2, ASSERT=0, and hence is default.
- *
- * There is an optional line, with HARDPPS on it. Including this line causes
- * the PPS signal to control the kernel PLL.
- * HARDPPS can also be set with FLAG3 of the ntp.conf input.
- * For Flag3, 0 is disabled, and the default.
- *
- * There are three options that have to do with using the shared memory option.
- * First, to enable the option there must be a SHMEM line with a file name.
- * The file name is the file associated with the shared memory.
- *
- * In shared memory, there is one 'record' for each returned variable.
- * For the @@Ea data there are three 'records' containing position data.
- * There will always be data in the record corresponding to the '0D' @@Ea record,
- * and the user has a choice of filling the '3D' record by specifying POSN3D,
- * or the '2D' record by specifying POSN2D. In either case the '2D' or '3D'
- * record is filled once every 15s.
- *
- * Two additional variables that can be set are CHAN and TRAIM. These should be
- * set correctly by the code examining the @@Cj record, but we bring them out here
- * to allow the user to override either the # of channels, or the existence of TRAIM.
- * CHAN expects to be followed by in integer: 6, 8, or 12. TRAIM expects to be
- * followed by YES or NO.
- *
- * There is an optional line with MASK on it followed by one integer field in the
- * range 0 to 89. This sets the satellite mask angle and will determine the minimum
- * elevation angle for satellites to be tracked by the receiver. The default value
- * is 10 deg for the VP and 0 deg for all other receivers.
- *
- * So acceptable input would be
- * # these are my coordinates (RWC)
- * LON -106 34.610
- * LAT 35 08.999
- * HT 1589 # could equally well say HT 5215 FT
- * DELAY 60 ns
- */
-
- FILE *fd;
- char *cp, *cc, *ca, line[100], units[2], device[20], Msg[160];
- int i, sign, lat_flg, long_flg, ht_flg, mode, mask;
- double f1, f2, f3;
-
- sprintf(device, "%s%d", INIT_FILE, instance->unit); /* try "ntp.oncore0" first */
- if ((fd=fopen(device, "r")) == NULL) { /* it was in the original documentation */
- sprintf(device, "%s.%d", INIT_FILE, instance->unit); /* then try "ntp.oncore.0 */
- if ((fd=fopen(device, "r")) == NULL) {
- if ((fd=fopen(INIT_FILE, "r")) == NULL) { /* and finally "ntp.oncore" */
- instance->init_type = 4;
- return;
- }
- }
- }
-
- mode = mask = 0;
- lat_flg = long_flg = ht_flg = 0;
- while (fgets(line, 100, fd)) {
-
- /* Remove comments */
- if ((cp = strchr(line, '#')))
- *cp = '\0';
-
- /* Remove trailing space */
- for (i = strlen(line);
- i > 0 && isascii((int)line[i - 1]) && isspace((int)line[i - 1]);
- )
- line[--i] = '\0';
-
- /* Remove leading space */
- for (cc = line; *cc && isascii((int)*cc) && isspace((int)*cc); cc++)
- continue;
-
- /* Stop if nothing left */
- if (!*cc)
- continue;
-
- /* Uppercase the command and find the arg */
- for (ca = cc; *ca; ca++) {
- if (isascii((int)*ca)) {
- if (islower((int)*ca)) {
- *ca = toupper(*ca);
- } else if (isspace((int)*ca) || (*ca == '='))
- break;
- }
- }
-
- /* Remove space (and possible =) leading the arg */
- for (; *ca && isascii((int)*ca) && (isspace((int)*ca) || (*ca == '=')); ca++)
- continue;
-
- if (!strncmp(cc, "STATUS", (size_t) 6) || !strncmp(cc, "SHMEM", (size_t) 5)) {
- i = strlen(ca);
- instance->shmem_fname = (char *) malloc((unsigned) (i+1));
- strcpy(instance->shmem_fname, ca);
- continue;
- }
-
- /* Uppercase argument as well */
- for (cp = ca; *cp; cp++)
- if (isascii((int)*cp) && islower((int)*cp))
- *cp = toupper(*cp);
-
- if (!strncmp(cc, "LAT", (size_t) 3)) {
- f1 = f2 = f3 = 0;
- sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3);
- sign = 1;
- if (f1 < 0) {
- f1 = -f1;
- sign = -1;
- }
- instance->ss_lat = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/
- lat_flg++;
- } else if (!strncmp(cc, "LON", (size_t) 3)) {
- f1 = f2 = f3 = 0;
- sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3);
- sign = 1;
- if (f1 < 0) {
- f1 = -f1;
- sign = -1;
- }
- instance->ss_long = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/
- long_flg++;
- } else if (!strncmp(cc, "HT", (size_t) 2)) {
- f1 = 0;
- units[0] = '\0';
- sscanf(ca, "%lf %1s", &f1, units);
- if (units[0] == 'F')
- f1 = 0.3048 * f1;
- instance->ss_ht = 100 * f1; /* cm */
- ht_flg++;
- } else if (!strncmp(cc, "DELAY", (size_t) 5)) {
- f1 = 0;
- units[0] = '\0';
- sscanf(ca, "%lf %1s", &f1, units);
- if (units[0] == 'N')
- ;
- else if (units[0] == 'U')
- f1 = 1000 * f1;
- else if (units[0] == 'M')
- f1 = 1000000 * f1;
- else
- f1 = 1000000000 * f1;
- if (f1 < 0 || f1 > 1.e9)
- f1 = 0;
- if (f1 < 0 || f1 > 999999) {
- sprintf(Msg, "PPS Cable delay of %fns out of Range, ignored", f1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- } else
- instance->delay = f1; /* delay in ns */
- } else if (!strncmp(cc, "OFFSET", (size_t) 6)) {
- f1 = 0;
- units[0] = '\0';
- sscanf(ca, "%lf %1s", &f1, units);
- if (units[0] == 'N')
- ;
- else if (units[0] == 'U')
- f1 = 1000 * f1;
- else if (units[0] == 'M')
- f1 = 1000000 * f1;
- else
- f1 = 1000000000 * f1;
- if (f1 < 0 || f1 > 1.e9)
- f1 = 0;
- if (f1 < 0 || f1 > 999999999.) {
- sprintf(Msg, "PPS Offset of %fns out of Range, ignored", f1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- } else
- instance->offset = f1; /* offset in ns */
- } else if (!strncmp(cc, "MODE", (size_t) 4)) {
- sscanf(ca, "%d", &mode);
- if (mode < 0 || mode > 4)
- mode = 4;
- } else if (!strncmp(cc, "ASSERT", (size_t) 6)) {
- instance->assert = 1;
- } else if (!strncmp(cc, "CLEAR", (size_t) 5)) {
- instance->assert = 0;
- } else if (!strncmp(cc, "HARDPPS", (size_t) 7)) {
- instance->hardpps = 1;
- } else if (!strncmp(cc, "POSN2D", (size_t) 6)) {
- instance->shmem_Posn = 2;
- } else if (!strncmp(cc, "POSN3D", (size_t) 6)) {
- instance->shmem_Posn = 3;
- } else if (!strncmp(cc, "CHAN", (size_t) 4)) {
- sscanf(ca, "%d", &i);
- if ((i == 6) || (i == 8) || (i == 12))
- instance->chan_in = i;
- } else if (!strncmp(cc, "TRAIM", (size_t) 5)) {
- instance->traim_in = 1; /* so TRAIM alone is YES */
- if (!strcmp(ca, "NO") || !strcmp(ca, "OFF")) /* Yes/No, On/Off */
- instance->traim_in = 0;
- } else if (!strncmp(cc, "MASK", (size_t) 4)) {
- sscanf(ca, "%d", &mask);
- if (mask > -1 && mask < 90)
- instance->Ag = mask; /* Satellite mask angle */
- }
- }
- fclose(fd);
-
- /*
- * OK, have read all of data file, and extracted the good stuff.
- * If lat/long/ht specified they ALL must be specified for mode = (1,3).
- */
-
- instance->posn_set = 1;
- if (!( lat_flg && long_flg && ht_flg )) {
- printf("ONCORE: incomplete data on %s\n", INIT_FILE);
- instance->posn_set = 0;
- if (mode == 1 || mode == 3) {
- sprintf(Msg, "Input Mode = %d, but no/incomplete position, mode set to %d", mode, mode+1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- mode++;
- }
- }
- instance->init_type = mode;
-
- sprintf(Msg, "Input mode = %d", mode);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/*
- * move data from NTP to buffer (toss the extra in the unlikely case it won't fit)
- */
-
-static void
-oncore_receive(
- struct recvbuf *rbufp
- )
-{
- size_t i;
- u_char *p;
- struct peer *peer;
- struct instance *instance;
-
- peer = (struct peer *)rbufp->recv_srcclock;
- instance = (struct instance *) peer->procptr->unitptr;
- p = (u_char *) &rbufp->recv_space;
-
-#if 0
- if (debug > 4) {
- int i;
- printf("ONCORE: >>>");
- for(i=0; i<rbufp->recv_length; i++)
- printf("%02x ", p[i]);
- printf("\n");
- printf("ONCORE: >>>");
- for(i=0; i<rbufp->recv_length; i++)
- printf("%03o ", p[i]);
- printf("\n");
- }
-#endif
-
- i = rbufp->recv_length;
- if (rcvbuf+rcvptr+i > &rcvbuf[sizeof rcvbuf])
- i = sizeof(rcvbuf) - rcvptr; /* and some char will be lost */
- memcpy(rcvbuf+rcvptr, p, i);
- rcvptr += i;
- oncore_consume(instance);
-}
-
-
-
-/*
- * Deal with any complete messages
- */
-
-static void
-oncore_consume(
- struct instance *instance
- )
-{
- int i, m;
- unsigned l;
-
- while (rcvptr >= 7) {
- if (rcvbuf[0] != '@' || rcvbuf[1] != '@') {
- /* We're not in sync, lets try to get there */
- for (i=1; i < rcvptr-1; i++)
- if (rcvbuf[i] == '@' && rcvbuf[i+1] == '@')
- break;
- if (debug > 4)
- printf("ONCORE[%d]: >>> skipping %d chars\n", instance->unit, i);
- if (i != rcvptr)
- memcpy(rcvbuf, rcvbuf+i, (size_t)(rcvptr-i));
- rcvptr -= i;
- continue;
- }
-
- /* Ok, we have a header now */
- l = sizeof(oncore_messages)/sizeof(oncore_messages[0]) -1;
- for(m=0; m<l; m++)
- if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), (size_t) 2))
- break;
- if (m == l) {
- if (debug > 4)
- printf("ONCORE[%d]: >>> Unknown MSG, skipping 4 (%c%c)\n", instance->unit, rcvbuf[2], rcvbuf[3]);
- memcpy(rcvbuf, rcvbuf+4, (size_t) 4);
- rcvptr -= 4;
- continue;
- }
-
- l = oncore_messages[m].len;
-#if 0
- if (debug > 3)
- printf("ONCORE[%d]: GOT: %c%c %d of %d entry %d\n", instance->unit, rcvbuf[2], rcvbuf[3], rcvptr, l, m);
-#endif
- /* Got the entire message ? */
-
- if (rcvptr < l)
- return;
-
- /* are we at the end of message? should be <Cksum><CR><LF> */
-
- if (rcvbuf[l-2] != '\r' || rcvbuf[l-1] != '\n') {
- if (debug)
- printf("ONCORE[%d]: NO <CR><LF> at end of message\n", instance->unit);
- } else { /* check the CheckSum */
- if (oncore_checksum_ok(rcvbuf, l)) {
- if (instance->shmem != NULL) {
- instance->shmem[oncore_messages[m].shmem + 2]++;
- memcpy(instance->shmem + oncore_messages[m].shmem + 3,
- rcvbuf, (size_t) l);
- }
- oncore_msg_any(instance, rcvbuf, (size_t) (l-3), m);
- if (oncore_messages[m].handler)
- oncore_messages[m].handler(instance, rcvbuf, (size_t) (l-3));
- } else if (debug) {
- printf("ONCORE[%d]: Checksum mismatch!\n", instance->unit);
- printf("ONCORE[%d]: @@%c%c ", instance->unit, rcvbuf[2], rcvbuf[3]);
- for (i=4; i<l; i++)
- printf("%03o ", rcvbuf[i]);
- printf("\n");
- }
- }
-
- if (l != rcvptr)
- memcpy(rcvbuf, rcvbuf+l, (size_t) (rcvptr-l));
- rcvptr -= l;
- }
-}
-
-
-
-static void
-oncore_get_timestamp(
- struct instance *instance,
- long dt1, /* tick offset THIS time step */
- long dt2 /* tick offset NEXT time step */
- )
-{
- int Rsm;
- u_long i, j;
- l_fp ts, ts_tmp;
- double dmy;
-#ifdef HAVE_STRUCT_TIMESPEC
- struct timespec *tsp = 0;
-#else
- struct timeval *tsp = 0;
-#endif
-#ifdef HAVE_PPSAPI
- int current_mode;
- pps_params_t current_params;
- struct timespec timeout;
- pps_info_t pps_i;
-#else /* ! HAVE_PPSAPI */
-#ifdef HAVE_CIOGETEV
- struct ppsclockev ev;
- int r = CIOGETEV;
-#endif
-#ifdef HAVE_TIOCGPPSEV
- struct ppsclockev ev;
- int r = TIOCGPPSEV;
-#endif
-#if TIOCDCDTIMESTAMP
- struct timeval tv;
-#endif
-#endif /* ! HAVE_PPS_API */
-
-#if 1
- /* If we are in SiteSurvey mode, then we are in 3D mode, and we fall thru.
- * If we have Finished the SiteSurvey, then we fall thru for the 14/15
- * times we get here in 0D mode (the 1/15 is in 3D for SHMEM).
- * This gives good time, which gets better when the SS is done.
- */
-
- if ((instance->site_survey == ONCORE_SS_DONE) && (instance->mode != MODE_0D))
-#else
- /* old check, only fall thru for SS_DONE and 0D mode, 2h45m wait for ticks */
-
- if ((instance->site_survey != ONCORE_SS_DONE) || (instance->mode != MODE_0D))
-#endif
- return;
-
- /* Don't do anything without an almanac to define the GPS->UTC delta */
-
- if (instance->rsm.bad_almanac)
- return;
-
-#ifdef HAVE_PPSAPI
- j = instance->ev_serial;
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- if (time_pps_fetch(instance->pps_h, PPS_TSFMT_TSPEC, &pps_i,
- &timeout) < 0) {
- printf("ONCORE: time_pps_fetch failed\n");
- return;
- }
-
- if (instance->assert) {
- tsp = &pps_i.assert_timestamp;
-
- if (debug > 2) {
- i = (u_long) pps_i.assert_sequence;
-#ifdef HAVE_STRUCT_TIMESPEC
- printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%09ld\n",
- instance->unit, i, j,
- (long)tsp->tv_sec, (long)tsp->tv_nsec);
-#else
- printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%06ld\n",
- instance->unit, i, j,
- (long)tsp->tv_sec, (long)tsp->tv_usec);
-#endif
- }
-
- if (pps_i.assert_sequence == j) {
- printf("ONCORE: oncore_get_timestamp, error serial pps\n");
- return;
- }
- instance->ev_serial = pps_i.assert_sequence;
- } else {
- tsp = &pps_i.clear_timestamp;
-
- if (debug > 2) {
- i = (u_long) pps_i.clear_sequence;
-#ifdef HAVE_STRUCT_TIMESPEC
- printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%09ld\n",
- instance->unit, i, j, (long)tsp->tv_sec, (long)tsp->tv_nsec);
-#else
- printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%06ld\n",
- instance->unit, i, j, (long)tsp->tv_sec, (long)tsp->tv_usec);
-#endif
- }
-
- if (pps_i.clear_sequence == j) {
- printf("ONCORE: oncore_get_timestamp, error serial pps\n");
- return;
- }
- instance->ev_serial = pps_i.clear_sequence;
- }
-
- /* convert timespec -> ntp l_fp */
-
- dmy = tsp->tv_nsec;
- dmy /= 1e9;
- ts.l_uf = dmy * 4294967296.0;
- ts.l_ui = tsp->tv_sec;
-#if 0
- alternate code for previous 4 lines is
- dmy = 1.0e-9*tsp->tv_nsec; /* fractional part */
- DTOLFP(dmy, &ts);
- dmy = tsp->tv_sec; /* integer part */
- DTOLFP(dmy, &ts_tmp);
- L_ADD(&ts, &ts_tmp);
- or more simply
- dmy = 1.0e-9*tsp->tv_nsec; /* fractional part */
- DTOLFP(dmy, &ts);
- ts.l_ui = tsp->tv_sec;
-#endif /* 0 */
-#else
-# if defined(HAVE_TIOCGPPSEV) || defined(HAVE_CIOGETEV)
- j = instance->ev_serial;
- if (ioctl(instance->ppsfd, r, (caddr_t) &ev) < 0) {
- perror("ONCORE: IOCTL:");
- return;
- }
-
- tsp = &ev.tv;
-
- if (debug > 2)
-#ifdef HAVE_STRUCT_TIMESPEC
- printf("ONCORE: serial/j (%d, %d) %ld.%09ld\n",
- ev.serial, j, tsp->tv_sec, tsp->tv_nsec);
-#else
- printf("ONCORE: serial/j (%d, %d) %ld.%06ld\n",
- ev.serial, j, tsp->tv_sec, tsp->tv_usec);
-#endif
-
- if (ev.serial == j) {
- printf("ONCORE: oncore_get_timestamp, error serial pps\n");
- return;
- }
- instance->ev_serial = ev.serial;
-
- /* convert timeval -> ntp l_fp */
-
- TVTOTS(tsp, &ts);
-# else
-# if defined(TIOCDCDTIMESTAMP)
- if(ioctl(instance->ppsfd, TIOCDCDTIMESTAMP, &tv) < 0) {
- perror("ONCORE: ioctl(TIOCDCDTIMESTAMP)");
- return;
- }
- tsp = &tv;
- TVTOTS(tsp, &ts);
-# else
-#error "Cannot compile -- no PPS mechanism configured!"
-# endif
-# endif
-#endif
- /* now have timestamp in ts */
- /* add in saw_tooth and offset, these will be ZERO if no TRAIM */
-
- /* saw_tooth not really necessary if using TIMEVAL */
- /* since its only precise to us, but do it anyway. */
-
- /* offset in ns, and is positive (late), we subtract */
- /* to put the PPS time transition back where it belongs */
-
-#ifdef HAVE_PPSAPI
- /* must hand the offset for the NEXT sec off to the Kernel to do */
- /* the addition, so that the Kernel PLL sees the offset too */
-
- if (instance->assert)
- instance->pps_p.assert_offset.tv_nsec = -dt2;
- else
- instance->pps_p.clear_offset.tv_nsec = -dt2;
-
- /* The following code is necessary, and not just a time_pps_setparams,
- * using the saved instance->pps_p, since some other process on the
- * machine may have diddled with the mode bits (say adding something
- * that it needs). We take what is there and ADD what we need.
- * [[ The results from the time_pps_getcap is unlikely to change so
- * we could probably just save it, but I choose to do the call ]]
- * Unfortunately, there is only ONE set of mode bits in the kernel per
- * interface, and not one set for each open handle.
- *
- * There is still a race condition here where we might mess up someone
- * elses mode, but if he is being careful too, he should survive.
- */
-
- if (time_pps_getcap(instance->pps_h, &current_mode) < 0) {
- msyslog(LOG_ERR, "refclock_ioctl: time_pps_getcap failed: %m");
- return;
- }
-
- if (time_pps_getparams(instance->pps_h, &current_params) < 0) {
- msyslog(LOG_ERR, "refclock_ioctl: time_pps_getparams failed: %m");
- return;
- }
-
- /* or current and mine */
- current_params.mode |= instance->pps_p.mode;
- /* but only set whats legal */
- current_params.mode &= current_mode;
-
- current_params.assert_offset.tv_sec = 0;
- current_params.assert_offset.tv_nsec = -dt2;
- current_params.clear_offset.tv_sec = 0;
- current_params.clear_offset.tv_nsec = -dt2;
-
- if (time_pps_setparams(instance->pps_h, &current_params))
- perror("time_pps_setparams");
-#else
- /* if not PPSAPI, no way to inform kernel of OFFSET, just add the */
- /* offset for THIS second */
-
- dmy = -1.0e-9*dt1;
- DTOLFP(dmy, &ts_tmp);
- L_ADD(&ts, &ts_tmp);
-#endif
- /* have time from UNIX origin, convert to NTP origin. */
-
- ts.l_ui += JAN_1970;
- instance->pp->lastrec = ts;
-
- /* print out information about this timestamp (long line) */
-
- ts_tmp = ts;
- ts_tmp.l_ui = 0; /* zero integer part */
- LFPTOD(&ts_tmp, dmy); /* convert fractional part to a double */
- j = 1.0e9*dmy; /* then to integer ns */
-
- Rsm = 0;
- if (instance->chan == 6)
- Rsm = instance->BEHa[64];
- else if (instance->chan == 8)
- Rsm = instance->BEHa[72];
- else if (instance->chan == 12)
- Rsm = ((instance->BEHa[129]<<8) | instance->BEHa[130]);
-
- if (instance->chan == 6 || instance->chan == 8) {
- sprintf(instance->pp->a_lastcode, /* MAX length 128, currently at 117 */
- "%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d sigma %2d neg-sawtooth %3d sat %d%d%d%d%d%d%d%d",
- ts.l_ui, j,
- instance->pp->year, instance->pp->day,
- instance->pp->hour, instance->pp->minute, instance->pp->second,
- (long) tsp->tv_sec % 60,
- Rsm, 0.1*(256*instance->BEHa[35]+instance->BEHa[36]),
- /*rsat dop */
- instance->BEHa[38], instance->BEHa[39], instance->BEHn[21],
- /* nsat visible, nsat tracked, traim */
- instance->BEHn[23]*256+instance->BEHn[24], (s_char) instance->BEHn[25],
- /* sigma neg-sawtooth */
- /*sat*/ instance->BEHa[41], instance->BEHa[45], instance->BEHa[49], instance->BEHa[53],
- instance->BEHa[57], instance->BEHa[61], instance->BEHa[65], instance->BEHa[69]
- ); /* will be 0 for 6 chan */
- } else if (instance->chan == 12) {
- sprintf(instance->pp->a_lastcode,
- "%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d sigma %d neg-sawtooth %3d sat %d%d%d%d%d%d%d%d%d%d%d%d",
- ts.l_ui, j,
- instance->pp->year, instance->pp->day,
- instance->pp->hour, instance->pp->minute, instance->pp->second,
- (long) tsp->tv_sec % 60,
- Rsm, 0.1*(256*instance->BEHa[53]+instance->BEHa[54]),
- /*rsat dop */
- instance->BEHa[55], instance->BEHa[56], instance->BEHn[6],
- /* nsat visible, nsat tracked traim */
- instance->BEHn[12]*256+instance->BEHn[13], (s_char) instance->BEHn[14],
- /* sigma neg-sawtooth */
- /*sat*/ instance->BEHa[58], instance->BEHa[64], instance->BEHa[70], instance->BEHa[76],
- instance->BEHa[82], instance->BEHa[88], instance->BEHa[94], instance->BEHa[100],
- instance->BEHa[106], instance->BEHa[112], instance->BEHa[118], instance->BEHa[124]
- );
- }
-
- if (debug > 2) {
- int n;
- n = strlen(instance->pp->a_lastcode);
- printf("ONCORE[%d]: len = %d %s\n", instance->unit, n, instance->pp->a_lastcode);
- }
-
- /* and some things I dont understnd (magic ntp things) */
-
- if (!refclock_process(instance->pp)) {
- refclock_report(instance->peer, CEVNT_BADTIME);
- return;
- }
-
- record_clock_stats(&(instance->peer->srcadr), instance->pp->a_lastcode);
- instance->pollcnt = 2;
-
- if (instance->polled) {
- instance->polled = 0;
-/*
- instance->pp->dispersion = instance->pp->skew = 0;
-*/
- instance->pp->lastref = instance->pp->lastrec;
- refclock_receive(instance->peer);
- }
-}
-
-
-/*************** oncore_msg_XX routines start here *******************/
-
-
-/*
- * print Oncore response message.
- */
-
-static void
-oncore_msg_any(
- struct instance *instance,
- u_char *buf,
- size_t len,
- int idx
- )
-{
- int i;
- const char *fmt = oncore_messages[idx].fmt;
- const char *p;
-#ifdef HAVE_GETCLOCK
- struct timespec ts;
-#endif
- struct timeval tv;
-
- if (debug > 3) {
-#ifdef HAVE_GETCLOCK
- (void) getclock(TIMEOFDAY, &ts);
- tv.tv_sec = ts.tv_sec;
- tv.tv_usec = ts.tv_nsec / 1000;
-#else
- GETTIMEOFDAY(&tv, 0);
-#endif
- printf("ONCORE[%d]: %ld.%06ld\n", instance->unit, (long) tv.tv_sec, (long) tv.tv_usec);
-
- if (!*fmt) {
- printf(">>@@%c%c ", buf[2], buf[3]);
- for(i=2; i < len && i < 2400 ; i++)
- printf("%02x", buf[i]);
- printf("\n");
- return;
- } else {
- printf("##");
- for (p = fmt; *p; p++) {
- putchar(*p);
- putchar('_');
- }
- printf("\n%c%c", buf[2], buf[3]);
- i = 4;
- for (p = fmt; *p; p++) {
- printf("%02x", buf[i++]);
- }
- printf("\n");
- }
- }
-}
-
-
-
-/* Latitude, Longitude, Height */
-
-static void
-oncore_msg_Adef(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
-}
-
-
-
-/* Mask Angle */
-
-static void
-oncore_msg_Ag(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{ char Msg[160], *cp;
-
- cp = "set to";
- if (instance->o_state == ONCORE_RUN)
- cp = "is";
-
- instance->Ag = buf[4];
- sprintf(Msg, "Satellite mask angle %s %d degrees", cp, (int) instance->Ag);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/*
- * get Position hold position
- */
-
-static void
-oncore_msg_As(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- instance->ss_lat = buf_w32(&buf[4]);
- instance->ss_long = buf_w32(&buf[8]);
- instance->ss_ht = buf_w32(&buf[12]);
-
- /* Print out Position */
- oncore_print_posn(instance);
-}
-
-
-
-/*
- * Try to use Oncore UT+ Auto Survey Feature
- * If its not there (VP), set flag to do it ourselves.
- */
-
-static void
-oncore_msg_At(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char *cp;
-
- instance->saw_At = 1;
- if (instance->site_survey == ONCORE_SS_TESTING) {
- if (buf[4] == 2) {
- record_clock_stats(&(instance->peer->srcadr),
- "Initiating hardware 3D site survey");
-
- cp = "SSstate = ONCORE_SS_HW";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->site_survey = ONCORE_SS_HW;
- }
- }
-}
-
-
-
-/*
- * get PPS Offset
- * Nb. @@Ay is not supported for early UT (no plus) model
- */
-
-static void
-oncore_msg_Ay(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char Msg[120];
-
- if (instance->saw_Ay)
- return;
-
- instance->saw_Ay = 1;
-
- instance->offset = buf_w32(&buf[4]);
-
- sprintf(Msg, "PPS Offset is set to %ld ns", instance->offset);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/*
- * get Cable Delay
- */
-
-static void
-oncore_msg_Az(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char Msg[120];
-
- if (instance->saw_Az)
- return;
-
- instance->saw_Az = 1;
-
- instance->delay = buf_w32(&buf[4]);
-
- sprintf(Msg, "Cable delay is set to %ld ns", instance->delay);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/* Ba, Ea and Ha come here, these contain Position */
-
-static void
-oncore_msg_BaEaHa(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- const char *cp;
- char Msg[160];
- int mode;
-
- /* OK, we are close to the RUN state now.
- * But we have a few more items to initialize first.
- *
- * At the beginning of this routine there are several 'timers'.
- * We enter this routine 1/sec, and since the upper levels of NTP have usurped
- * the use of timers, we use the 1/sec entry to do things that
- * we would normally do with timers...
- */
-
- if (instance->o_state == ONCORE_CHECK_CHAN) { /* here while checking for the # chan */
- if (buf[2] == 'B') { /* 6chan */
- if (instance->chan_ck < 6) instance->chan_ck = 6;
- } else if (buf[2] == 'E') { /* 8chan */
- if (instance->chan_ck < 8) instance->chan_ck = 8;
- } else if (buf[2] == 'H') { /* 12chan */
- if (instance->chan_ck < 12) instance->chan_ck = 12;
- }
-
- if (instance->count3++ < 5)
- return;
-
- instance->count3 = 0;
-
- if (instance->chan_in != -1) /* set in Input */
- instance->chan = instance->chan_in;
- else /* set from test */
- instance->chan = instance->chan_ck;
-
- sprintf(Msg, "Input says chan = %d", instance->chan_in);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Model # says chan = %d", instance->chan_id);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Testing says chan = %d", instance->chan_ck);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Using chan = %d", instance->chan);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- instance->o_state = ONCORE_HAVE_CHAN;
- cp = "state = ONCORE_HAVE_CHAN";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->timeout = 4;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
- return;
- }
-
- if (instance->o_state != ONCORE_ALMANAC && instance->o_state != ONCORE_RUN)
- return;
-
- /* PAUSE 5sec */
-
- if (instance->count) {
- if (instance->count++ < 5) /* make sure results are stable, using position */
- return;
- instance->count = 0;
- }
-
- memcpy(instance->BEHa, buf, (size_t) (len+3)); /* Ba, Ea or Ha */
-
- /* check the antenna and almanac for changes (did it get unplugged, is it ready?) */
-
- oncore_check_almanac(instance);
- oncore_check_antenna(instance);
-
- /* Almanac mode, waiting for Almanac, we can't do anything till we have it */
- /* When we have an almanac, we will start the Bn/En/@@Hn messages */
-
- if (instance->o_state == ONCORE_ALMANAC)
- if (oncore_wait_almanac(instance))
- return;
-
- /* do some things once when we get this far in BaEaHa */
-
- if (instance->once) {
- instance->once = 0;
- instance->count2 = 1;
-
- /* Have we seen an @@At (position hold) command response */
- /* if not, message out */
-
- if (instance->chan != 12 && !instance->saw_At) {
- cp = "Not Good, no @@At command (no Position Hold), must be a GT/GT+";
- record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
- }
-
- /* have an Almanac, can start the SiteSurvey
- * (actually only need to get past the almanac_load where we diddle with At
- * command,- we can't change it after we start the HW_SS below
- */
-
- mode = instance->init_type;
- switch (mode) {
- case 0: /* NO initialization, don't change anything */
- case 1: /* Use given Position */
- case 3:
- instance->site_survey = ONCORE_SS_DONE;
- cp = "SSstate = ONCORE_SS_DONE";
- record_clock_stats(&(instance->peer->srcadr), cp);
- break;
-
- case 2:
- case 4: /* Site Survey */
- cp = "SSstate = ONCORE_SS_TESTING";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->site_survey = ONCORE_SS_TESTING;
- instance->count1 = 1;
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd3, sizeof(oncore_cmd_Gd3)); /* M12+T */
- else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At2, sizeof(oncore_cmd_At2)); /* not GT, arg not VP */
- break;
- }
-
- /* Read back PPS Offset for Output */
- /* Nb. This will fail silently for early UT (no plus) and M12 models */
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ayx, sizeof(oncore_cmd_Ayx));
-
- /* Read back Cable Delay for Output */
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Azx, sizeof(oncore_cmd_Azx));
-
- /* Read back Satellite Mask Angle for Output */
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Agx, sizeof(oncore_cmd_Agx));
- }
-
- if (instance->count1) {
- if (instance->count1++ > 5 || instance->site_survey == ONCORE_SS_HW) {
- instance->count1 = 0;
- if (instance->site_survey == ONCORE_SS_TESTING) {
- /*
- * For instance->site_survey to still be ONCORE_SS_TESTING, then after a 5sec
- * wait after the @@At2/@@Gd3 command we have not changed the state to
- * ONCORE_SS_HW. If the Hardware is capable of doing a Site Survey, then
- * the variable would have been changed by now.
- * There are three possibilities:
- * 6/8chan
- * (a) We did not get a response to the @@At0 or @@At2 commands,
- * and it must be a GT/GT+/SL with no position hold mode.
- * We will have to do it ourselves.
- * (b) We saw the @@At0, @@At2 commands, but @@At2 failed,
- * must be a VP or older UT which doesn't have Site Survey mode.
- * We will have to do it ourselves.
- * 12chan
- * (c) We saw the @@Gd command, but @@Gd3 failed,
- * We will have to do it ourselves.
- */
-
- sprintf(Msg, "Initiating software 3D site survey (%d samples)",
- POS_HOLD_AVERAGE);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_SW");
- instance->site_survey = ONCORE_SS_SW;
-
- instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* disable */
- else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* disable */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* disable */
- }
- }
- }
- }
-
- /* check the mode we are in 0/2/3D */
-
- if (instance->chan == 6) {
- if (instance->BEHa[64]&0x8)
- instance->mode = MODE_0D;
- else if (instance->BEHa[64]&0x10)
- instance->mode = MODE_2D;
- else if (instance->BEHa[64]&0x20)
- instance->mode = MODE_3D;
- } else if (instance->chan == 8) {
- if (instance->BEHa[72]&0x8)
- instance->mode = MODE_0D;
- else if (instance->BEHa[72]&0x10)
- instance->mode = MODE_2D;
- else if (instance->BEHa[72]&0x20)
- instance->mode = MODE_3D;
- } else if (instance->chan == 12) {
- int bits;
-
- bits = (instance->BEHa[129]>>5) & 0x7; /* actually Ha */
- if (bits == 0x4)
- instance->mode = MODE_0D;
- else if (bits == 0x6)
- instance->mode = MODE_2D;
- else if (bits == 0x7)
- instance->mode = MODE_3D;
- }
-
- /* copy the record to the (extra) location in SHMEM */
-
- if (instance->shmem) {
- int i;
- u_char *smp; /* pointer to start of shared mem for Ba/Ea/Ha */
-
- switch(instance->chan) {
- case 6: smp = &instance->shmem[instance->shmem_Ba]; break;
- case 8: smp = &instance->shmem[instance->shmem_Ea]; break;
- case 12: smp = &instance->shmem[instance->shmem_Ha]; break;
- default: smp = (u_char) 0; break;
- }
-
- switch (instance->mode) {
- case MODE_0D: i = 1; break; /* 0D, Position Hold */
- case MODE_2D: i = 2; break; /* 2D, Altitude Hold */
- case MODE_3D: i = 3; break; /* 3D fix */
- default: i = 0; break;
- }
-
- if (i) {
- i *= (len+6);
- smp[i + 2]++;
- memcpy(&smp[i+3], buf, (size_t) (len+3));
- }
- }
-
- /*
- * check if timer active
- * if it hasn't been cleared, then @@Bn/@@En/@@Hn did not respond
- */
-
- if (instance->traim_delay) {
- if (instance->traim_delay++ > 5) {
- instance->traim = 0;
- instance->traim_delay = 0;
- cp = "ONCORE: Did not detect TRAIM response, TRAIM = OFF";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- oncore_set_traim(instance);
- } else
- return;
-
- }
-
- /* by now should have a @@Ba/@@Ea/@@Ha with good data in it */
-
- if (!instance->have_dH && !instance->traim_delay)
- oncore_compute_dH(instance);
-
- /*
- * must be ONCORE_RUN if we are here.
- * Have # chan and TRAIM by now.
- */
-
- instance->pp->year = buf[6]*256+buf[7];
- instance->pp->day = ymd2yd(buf[6]*256+buf[7], buf[4], buf[5]);
- instance->pp->hour = buf[8];
- instance->pp->minute = buf[9];
- instance->pp->second = buf[10];
-
- /*
- * Are we doing a Hardware or Software Site Survey?
- */
-
- if (instance->site_survey == ONCORE_SS_HW || instance->site_survey == ONCORE_SS_SW)
- oncore_ss(instance);
-
- /* see if we ever saw a response from the @@Ayx above */
-
- if (instance->count2) {
- if (instance->count2++ > 5) { /* this delay to check on @@Ay command */
- instance->count2 = 0;
-
- /* Have we seen an Ay (1PPS time offset) command response */
- /* if not, and non-zero offset, zero the offset, and send message */
-
- if (!instance->saw_Ay && instance->offset) {
- cp = "No @@Ay command, PPS OFFSET ignored";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->offset = 0;
- }
- }
- }
-
- /*
- * Check the leap second status once per day.
- */
-
- oncore_check_leap_sec(instance);
-
- /*
- * if SHMEM active, every 15s, steal one 'tick' to get 2D or 3D posn.
- */
-
- if (instance->shmem && !instance->shmem_bad_Ea && instance->shmem_Posn && (instance->site_survey == ONCORE_SS_DONE))
- oncore_shmem_get_3D(instance);
-
- if (!instance->traim) /* NO traim, no BnEnHn, go get tick */
- oncore_get_timestamp(instance, instance->offset, instance->offset);
-}
-
-
-
-/* Almanac Status */
-
-static void
-oncore_msg_Bd(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char Msg[160];
-
- sprintf(Msg, "Bd: Almanac %s, week = %d, t = %d, %d SVs: %x",
- ((buf[4]) ? "LOADED" : "(NONE)"), buf[5], buf[6], buf[7], w32(&buf[8]) );
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/* get leap-second warning message */
-
-/*
- * @@Bj does NOT behave as documented in current Oncore firmware.
- * It turns on the LEAP indicator when the data is set, and does not,
- * as documented, wait until the beginning of the month when the
- * leap second will occur.
- * Since this firmware bug will never be fixed in all the outstanding Oncore receivers
- * @@Bj is only called in June/December.
- */
-
-static void
-oncore_msg_Bj(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- const char *cp;
-
- switch(buf[4]) {
- case 1:
- instance->peer->leap = LEAP_ADDSECOND;
- cp = "Set peer.leap to LEAP_ADDSECOND";
- break;
- case 2:
- instance->peer->leap = LEAP_DELSECOND;
- cp = "Set peer.leap to LEAP_DELSECOND";
- break;
- case 0:
- default:
- instance->peer->leap = LEAP_NOWARNING;
- cp = "Set peer.leap to LEAP_NOWARNING";
- break;
- }
- record_clock_stats(&(instance->peer->srcadr), cp);
-}
-
-
-
-static void
-oncore_msg_BnEnHn(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- long dt1, dt2;
- char *cp;
-
- if (instance->o_state != ONCORE_RUN)
- return;
-
- if (instance->traim_delay) { /* flag that @@Bn/@@En/Hn returned */
- instance->traim_ck = 1;
- instance->traim_delay = 0;
- cp = "ONCORE: Detected TRAIM, TRAIM = ON";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- oncore_set_traim(instance);
- }
-
- memcpy(instance->BEHn, buf, (size_t) len); /* Bn or En or Hn */
-
- /* If Time RAIM doesn't like it, don't trust it */
-
- if (buf[2] == 'H') {
- if (instance->BEHn[6]) /* bad TRAIM */
- return;
-
- dt1 = instance->saw_tooth + instance->offset; /* dt this time step */
- instance->saw_tooth = (s_char) instance->BEHn[10]; /* update for next time Hn[10] */
- dt2 = instance->saw_tooth + instance->offset; /* dt next time step */
- } else {
- if (instance->BEHn[21]) /* bad TRAIM */
- return;
-
- dt1 = instance->saw_tooth + instance->offset; /* dt this time step */
- instance->saw_tooth = (s_char) instance->BEHn[25]; /* update for next time */
- dt2 = instance->saw_tooth + instance->offset; /* dt next time step */
- }
-
- oncore_get_timestamp(instance, dt1, dt2);
-}
-
-
-
-/* Here for @@Ca, @@Fa and @@Ia messages */
-
-/* These are Self test Commands for 6, 8, and 12 chan receivers.
- * There are good reasons NOT to do a @@Ca, @@Fa or @@Ia command with the ONCORE.
- * It was found that under some circumstances the following
- * command would fail if issued immediately after the return from the
- * @@Fa, but a 2sec delay seemed to fix things. Since simply calling
- * sleep(2) is wasteful, and may cause trouble for some OS's, repeating
- * itimer, we set a flag, and test it at the next POLL. If it hasn't
- * been cleared, we reissue the @@Cj that is issued below.
- * Note that we do a @@Cj at the beginning, and again here.
- * The first is to get the info, the 2nd is just used as a safe command
- * after the @@Fa for all Oncores (and it was in this posn in the
- * original code).
- */
-
-static void
-oncore_msg_CaFaIa(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char *cp;
- int i;
-
- if (instance->o_state == ONCORE_TEST_SENT) {
- enum antenna_state antenna;
-
- instance->timeout = 0;
-
- if (debug > 2) {
- if (buf[2] == 'I')
- printf("ONCORE[%d]: >>@@%ca %x %x %x\n", instance->unit, buf[2], buf[4], buf[5], buf[6]);
- else
- printf("ONCORE[%d]: >>@@%ca %x %x\n", instance->unit, buf[2], buf[4], buf[5]);
- }
-
- antenna = (buf[4] & 0xc0) >> 6;
- buf[4] &= ~0xc0;
-
- i = buf[4] || buf[5];
- if (buf[2] == 'I') i = i || buf[6];
- if (i) {
- if (buf[2] == 'I') {
- msyslog(LOG_ERR, "ONCORE[%d]: self test failed: result %02x %02x %02x",
- instance->unit, buf[4], buf[5], buf[6]);
- } else {
- msyslog(LOG_ERR, "ONCORE[%d]: self test failed: result %02x %02x",
- instance->unit, buf[4], buf[5]);
- }
- cp = "ONCORE: self test failed, shutting down driver";
- record_clock_stats(&instance->peer->srcadr, cp);
-
- refclock_report(instance->peer, CEVNT_FAULT);
- oncore_shutdown(instance->unit, instance->peer);
- return;
- }
-
- /* report the current antenna state */
-
- oncore_antenna_report(instance, antenna);
-
- instance->o_state = ONCORE_INIT;
- cp = "state = ONCORE_INIT";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->timeout = 4;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
- }
-}
-
-
-
-/*
- * Demultiplex the almanac into shmem
- */
-
-static void
-oncore_msg_Cb(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- int i;
-
- if (instance->shmem == NULL)
- return;
-
- if (buf[4] == 5 && buf[5] > 0 && buf[5] < 26)
- i = buf[5];
- else if (buf[4] == 4 && buf[5] <= 5)
- i = buf[5] + 24;
- else if (buf[4] == 4 && buf[5] <= 10)
- i = buf[5] + 23;
- else if (buf[4] == 4 && buf[5] == 25)
- i = 34;
- else {
- char *cp;
-
- cp = "Cb: Response is NO ALMANAC";
- record_clock_stats(&(instance->peer->srcadr), cp);
- return;
- }
-
- i *= 36;
- instance->shmem[instance->shmem_Cb + i + 2]++;
- memcpy(instance->shmem + instance->shmem_Cb + i + 3, buf, (size_t) (len + 3));
-
-#if 1
- {
- char Msg[160];
- sprintf(Msg, "See Cb [%d,%d]", buf[4], buf[5]);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- }
-#endif
-}
-
-
-
-/*
- * Set to Factory Defaults (Reasonable for UT w/ no Battery Backup
- * not so for VP (eeprom) or any unit with a battery
- */
-
-static void
-oncore_msg_Cf(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- const char *cp;
-
- if (instance->o_state == ONCORE_RESET_SENT) {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to Posn Fix mode */
- /* Reset set VP to IDLE */
- instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
- }
-}
-
-
-
-/*
- * This is the Grand Central Station for the Preliminary Initialization.
- * Once done here we move on to oncore_msg_BaEaHa for final Initialization and Running.
- *
- * We do an @@Cj whenever we need a safe command for all Oncores.
- * The @@Cj gets us back here where we can switch to the next phase of setup.
- *
- * o Once at the very beginning (in start) to get the Model number.
- * This info is printed, but no longer used.
- * o Again after we have determined the number of Channels in the receiver.
- * o And once later after we have done a reset and test, (which may hang),
- * as we are about to initialize the Oncore and start it running.
- * o We have one routine below for each case.
- */
-
-static void
-oncore_msg_Cj(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- int mode;
- char *cp;
-
- memcpy(instance->Cj, buf, len);
-
- instance->timeout = 0;
- if (instance->o_state == ONCORE_CHECK_ID) {
- oncore_msg_Cj_id(instance, buf, len);
- oncore_chan_test(instance);
- } else if (instance->o_state == ONCORE_HAVE_CHAN) {
- mode = instance->init_type;
- if (mode == 3 || mode == 4) { /* Cf will return here to check for TEST */
- instance->o_state = ONCORE_RESET_SENT;
- cp = "state = ONCORE_RESET_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cf, sizeof(oncore_cmd_Cf));
- } else {
- instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
- }
-
- if (instance->o_state == ONCORE_TEST_SENT) {
- if (instance->chan == 6)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ca, sizeof(oncore_cmd_Ca));
- else if (instance->chan == 8)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof(oncore_cmd_Fa));
- else if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ia, sizeof(oncore_cmd_Ia));
- } else if (instance->o_state == ONCORE_INIT)
- oncore_msg_Cj_init(instance, buf, len);
-}
-
-
-
-/* The information on determining a Oncore 'Model', viz VP, UT, etc, from
- * the Model Number comes from "Richard M. Hambly" <rick@cnssys.com>
- * and from Motorola. Until recently Rick was the only source of
- * this information as Motorola didn't give the information out.
- *
- * Determine the Type from the Model #, this determines #chan and if TRAIM is
- * available.
- *
- * The Information from this routine is NO LONGER USED.
- * The RESULTS are PRINTED, BUT NOT USED, and the routine COULD BE DELETED
- */
-
-static void
-oncore_msg_Cj_id(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char *cp, *cp1, *cp2, Model[21], Msg[160];
-
- /* Write Receiver ID message to clockstats file */
-
- instance->Cj[294] = '\0';
- for (cp=(char *)instance->Cj; cp< (char *) &instance->Cj[294]; ) {
- cp1 = strchr(cp, '\r');
- if (!cp1)
- cp1 = (char *)&instance->Cj[294];
- *cp1 = '\0';
- record_clock_stats(&(instance->peer->srcadr), cp);
- *cp1 = '\r';
- cp = cp1+2;
- }
-
- /* next, the Firmware Version and Revision numbers */
-
- instance->version = atoi(&instance->Cj[83]);
- instance->revision = atoi(&instance->Cj[111]);
-
- /* from model number decide which Oncore this is,
- and then the number of channels */
-
- for (cp=&instance->Cj[160]; *cp == ' '; cp++) /* start right after 'Model #' */
- ;
- cp1 = cp;
- cp2 = Model;
- for (; !isspace((int)*cp) && cp-cp1 < 20; cp++, cp2++)
- *cp2 = *cp;
- *cp2 = '\0';
-
- cp = 0;
- if (!strncmp(Model, "PVT6", (size_t) 4)) {
- cp = "PVT6";
- instance->model = ONCORE_PVT6;
- } else if (Model[0] == 'A') {
- cp = "Basic";
- instance->model = ONCORE_BASIC;
- } else if (Model[0] == 'B' || !strncmp(Model, "T8", (size_t) 2)) {
- cp = "VP";
- instance->model = ONCORE_VP;
- } else if (Model[0] == 'P') {
- cp = "M12";
- instance->model = ONCORE_M12;
- } else if (Model[0] == 'R' || Model[0] == 'D' || Model[0] == 'S') {
- if (Model[5] == 'N') {
- cp = "GT";
- instance->model = ONCORE_GT;
- } else if ((Model[1] == '3' || Model[1] == '4') && Model[5] == 'G') {
- cp = "GT+";
- instance->model = ONCORE_GTPLUS;
- } else if ((Model[1] == '5' && Model[5] == 'U') || (Model[1] == '1' && Model[5] == 'A')) {
- cp = "UT";
- instance->model = ONCORE_UT;
- } else if (Model[1] == '5' && Model[5] == 'G') {
- cp = "UT+";
- instance->model = ONCORE_UTPLUS;
- } else if (Model[1] == '6' && Model[5] == 'G') {
- cp = "SL";
- instance->model = ONCORE_SL;
- } else {
- cp = "Unknown";
- instance->model = ONCORE_UNKNOWN;
- }
- } else {
- cp = "Unknown";
- instance->model = ONCORE_UNKNOWN;
- }
-
- /* use MODEL to set CHAN and TRAIM and possibly zero SHMEM */
-
- sprintf(Msg, "This looks like an Oncore %s with version %d.%d firmware.", cp, instance->version, instance->revision);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- instance->chan_id = 8; /* default */
- if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
- instance->chan_id = 6;
- else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
- instance->chan_id = 8;
- else if (instance->model == ONCORE_M12)
- instance->chan_id = 12;
-
- instance->traim_id = 0; /* default */
- if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
- instance->traim_id = 0;
- else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
- instance->traim_id = 1;
- else if (instance->model == ONCORE_M12)
- instance->traim_id = -1;
-
- sprintf(Msg, "Channels = %d, TRAIM = %s", instance->chan_id,
- ((instance->traim_id < 0) ? "UNKNOWN" : ((instance->traim_id > 0) ? "ON" : "OFF")));
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/* OK, know type of Oncore, have possibly reset it, and have tested it.
- * We know the number of channels.
- * We will determine whether we have TRAIM before we actually start.
- * Now initialize.
- */
-
-static void
-oncore_msg_Cj_init(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char *cp, Cmd[20], Msg[160];
- int mode;
-
-
- /* The M12 with 1.3 or 2.0 Firmware, loses track of all Satellites and has to
- * start again if we go from 0D -> 3D, then loses them again when we
- * go from 3D -> 0D. We do this to get a @@Ea message for SHMEM.
- * For NOW we will turn this aspect of filling SHMEM off for the M12
- */
-
- if (instance->chan == 12) {
- instance->shmem_bad_Ea = 1;
- sprintf(Msg, "*** SHMEM partially enabled for ONCORE M12 s/w v%d.%d ***", instance->version, instance->revision);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- }
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to Posn Fix mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bb, sizeof(oncore_cmd_Bb)); /* turn on for shmem (6/8/12) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ek, sizeof(oncore_cmd_Ek)); /* turn off (VP) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Aw, sizeof(oncore_cmd_Aw)); /* UTC time (6/8/12) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_AB, sizeof(oncore_cmd_AB)); /* Appl type static (VP) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Be, sizeof(oncore_cmd_Be)); /* Tell us the Almanac for shmem (6/8/12) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bd, sizeof(oncore_cmd_Bd)); /* Tell us when Almanac changes */
-
- mode = instance->init_type;
-
- /* If there is Position input in the Config file
- * and mode = (1,3) set it as posn hold posn, goto 0D mode.
- * or mode = (2,4) set it as INITIAL position, and do Site Survey.
- */
-
- if (instance->posn_set) {
- record_clock_stats(&(instance->peer->srcadr), "Setting Posn from input data");
- oncore_set_posn(instance); /* this should print posn indirectly thru the As cmd */
- } else /* must issue an @@At here to check on 6/8 Position Hold, set_posn would have */
- if (instance->chan != 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Atx, sizeof(oncore_cmd_Atx));
-
- if (mode != 0) {
- /* cable delay in ns */
- memcpy(Cmd, oncore_cmd_Az, (size_t) sizeof(oncore_cmd_Az));
- w32_buf(&Cmd[-2+4], instance->delay);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Az)); /* 6,8,12 */
-
- /* PPS offset in ns */
- if (instance->offset) {
- memcpy(Cmd, oncore_cmd_Ay, (size_t) sizeof(oncore_cmd_Ay)); /* some have it, some don't */
- w32_buf(&Cmd[-2+4], instance->offset); /* will check for hw response */
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ay));
- }
-
- /* Satellite mask angle */
-
- if (instance->Ag != 0xff) { /* will have 0xff in it if not set by user */
- memcpy(Cmd, oncore_cmd_Ag, (size_t) sizeof(oncore_cmd_Ag));
- Cmd[-2+4] = instance->Ag;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ag));
- }
- }
-
- /* 6, 8 12 chan - Position/Status/Data Output Message, 1/s
- * now we're really running
- * these were ALL started in the chan test,
- * However, if we had mode=3,4 then commands got turned off, so we turn
- * them on again here just in case
- */
-
- if (instance->chan == 6) { /* start 6chan, kill 8,12chan commands, possibly testing VP in 6chan mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En0, sizeof(oncore_cmd_En0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba, sizeof(oncore_cmd_Ba ));
- } else if (instance->chan == 8) { /* start 8chan, kill 6,12chan commands */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof(oncore_cmd_Ea ));
- } else if (instance->chan == 12){ /* start 12chan, kill 6,12chan commands */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En0, sizeof(oncore_cmd_En0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha, sizeof(oncore_cmd_Ha ));
- }
-
- instance->count = 1;
- instance->o_state = ONCORE_ALMANAC;
- cp = "state = ONCORE_ALMANAC";
- record_clock_stats(&(instance->peer->srcadr), cp);
-}
-
-
-
-/* 12chan position */
-
-static void
-oncore_msg_Ga(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char Msg[160];
- long lat, lon, ht;
- double Lat, Lon, Ht;
-
-
- lat = buf_w32(&buf[4]);
- lon = buf_w32(&buf[8]);
- ht = buf_w32(&buf[12]); /* GPS ellipsoid */
-
- Lat = lat;
- Lon = lon;
- Ht = ht;
-
- Lat /= 3600000;
- Lon /= 3600000;
- Ht /= 100;
-
-
- sprintf(Msg, "Ga Posn Lat = %.7f, Lon = %.7f, Ht = %.2f", Lat, Lon, Ht);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- instance->ss_lat = lat;
- instance->ss_long = lon;
- instance->ss_ht = ht;
-
- oncore_print_posn(instance);
-}
-
-
-
-/* 12 chan time/date */
-
-static void
-oncore_msg_Gb(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char Msg[160], *gmts;
- int mo, d, y, h, m, s, gmth, gmtm;
-
- mo = buf[4];
- d = buf[5];
- y = 256*buf[6]+buf[7];
-
- h = buf[8];
- m = buf[9];
- s = buf[10];
-
- gmts = ((buf[11] == 0) ? "+" : "-");
- gmth = buf[12];
- gmtm = buf[13];
-
- sprintf(Msg, "Date/Time set to: %d%s%d %2d:%02d:%02d GMT (GMT offset is %s%02d:%02d)",
- d, Month[mo+1], y, h, m, s, gmts, gmth, gmtm);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/*
- * Try to use Oncore M12+Timing Auto Survey Feature
- * If its not there (M12), set flag to do it ourselves.
- */
-
-static void
-oncore_msg_Gd(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char *cp;
-
- if (instance->site_survey == ONCORE_SS_TESTING) {
- if (buf[4] == 3) {
- record_clock_stats(&(instance->peer->srcadr),
- "Initiating hardware 3D site survey");
-
- cp = "SSstate = ONCORE_SS_HW";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->site_survey = ONCORE_SS_HW;
- }
- }
-}
-
-
-
-/* Leap Second for M12, gives all info from satellite message */
-/* also in UT v3.0 */
-
-static void
-oncore_msg_Gj(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- int dt;
- char Msg[160], *cp;
-
- instance->saw_Gj = 1; /* flag, saw_Gj, dont need to try Bj in check_leap */
-
- /* print the message to verify whats there */
-
- dt = buf[5] - buf[4];
-
-#if 1
- sprintf(Msg, "ONCORE[%d]: Leap Sec Msg: %d %d %d %d %d %d %d %d %d %d",
- instance->unit,
- buf[4], buf[5], 256*buf[6]+buf[7], buf[8], buf[9], buf[10],
- (buf[14]+256*(buf[13]+256*(buf[12]+256*buf[11]))),
- buf[15], buf[16], buf[17]);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-#endif
- if (dt) {
- sprintf(Msg, "ONCORE[%d]: Leap second (%d) scheduled for %d%s%d at %d:%d:%d",
- instance->unit,
- dt, buf[9], Month[buf[8]], 256*buf[6]+buf[7],
- buf[15], buf[16], buf[17]);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- }
-
- /* Only raise warning within a month of the leap second */
-
- instance->peer->leap = LEAP_NOWARNING;
- cp = "Set peer.leap to LEAP_NOWARNING";
-
- if (buf[6] == instance->BEHa[6] && buf[7] == instance->BEHa[7] && /* year */
- buf[8] == instance->BEHa[4]) { /* month */
- if (dt) {
- if (dt < 0) {
- instance->peer->leap = LEAP_DELSECOND;
- cp = "Set peer.leap to LEAP_DELSECOND";
- } else {
- instance->peer->leap = LEAP_ADDSECOND;
- cp = "Set peer.leap to LEAP_ADDSECOND";
- }
- }
- }
- record_clock_stats(&(instance->peer->srcadr), cp);
-}
-
-
-
-/* Power on failure */
-
-static void
-oncore_msg_Sz(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- const char *cp;
-
- cp = "Oncore: System Failure at Power On";
- if (instance && instance->peer) {
- record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_shutdown(instance->unit, instance->peer);
- }
-}
-
-/************** Small Subroutines ***************/
-
-
-static void
-oncore_antenna_report(
- struct instance *instance,
- enum antenna_state new_state)
-{
- char *cp;
-
- if (instance->ant_state == new_state)
- return;
-
- switch (new_state) {
- case ONCORE_ANTENNA_OK: cp = "GPS antenna: OK"; break;
- case ONCORE_ANTENNA_OC: cp = "GPS antenna: short (overcurrent)"; break;
- case ONCORE_ANTENNA_UC: cp = "GPS antenna: open (not connected)"; break;
- case ONCORE_ANTENNA_NV: cp = "GPS antenna: short (no voltage)"; break;
- default: cp = "GPS antenna: ?"; break;
- }
-
- instance->ant_state = new_state;
- record_clock_stats(&instance->peer->srcadr, cp);
-}
-
-
-
-static void
-oncore_chan_test(
- struct instance *instance
- )
-{
- char *cp;
-
- /* subroutine oncore_Cj_id has determined the number of channels from the
- * model number of the attached oncore. This is not always correct since
- * the oncore could have non-standard firmware. Here we check (independently) by
- * trying a 6, 8, and 12 chan command, and see which responds.
- * Caution: more than one CAN respond.
- *
- * This #chan is used by the code rather than that calculated from the model number.
- */
-
- instance->o_state = ONCORE_CHECK_CHAN;
- cp = "state = ONCORE_CHECK_CHAN";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->count3 = 1;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba, sizeof(oncore_cmd_Ba));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof(oncore_cmd_Ea));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha, sizeof(oncore_cmd_Ha));
-}
-
-
-
-/* check for a GOOD Almanac, have we got one yet? */
-
-static void
-oncore_check_almanac(
- struct instance *instance
- )
-{
- if (instance->chan == 6) {
- instance->rsm.bad_almanac = instance->BEHa[64]&0x1;
- instance->rsm.bad_fix = instance->BEHa[64]&0x52;
- } else if (instance->chan == 8) {
- instance->rsm.bad_almanac = instance->BEHa[72]&0x1;
- instance->rsm.bad_fix = instance->BEHa[72]&0x52;
- } else if (instance->chan == 12) {
- int bits1, bits2;
-
- bits1 = (instance->BEHa[129]>>5) & 0x7; /* actually Ha */
- bits2 = instance->BEHa[130];
- instance->rsm.bad_almanac = (bits2 & 0x80);
- instance->rsm.bad_fix = (bits2 & 0x8) || (bits1 == 0x2);
- /* too few sat Bad Geom */
-#if 0
- fprintf(stderr, "ONCORE[%d]: DEBUG BITS: (%x %x), (%x %x), %x %x %x %x %x\n",
- instance->unit,
- instance->BEHa[129], instance->BEHa[130], bits1, bits2, instance->mode == MODE_0D,
- instance->mode == MODE_2D, instance->mode == MODE_3D,
- instance->rsm.bad_almanac, instance->rsm.bad_fix);
-#endif
- }
-}
-
-
-
-/* check the antenna for changes (did it get unplugged?) */
-
-static void
-oncore_check_antenna(
- struct instance *instance
- )
-{
- enum antenna_state antenna; /* antenna state */
-
- antenna = instance->ant_state;
- if (instance->chan == 12)
- antenna = (instance->BEHa[130] & 0x6 ) >> 1;
- else
- antenna = (instance->BEHa[37] & 0xc0) >> 6; /* prob unset 6, set GT, UT unset VP */
-
- oncore_antenna_report (instance, antenna);
-}
-
-
-
-/*
- * Check the leap second status once per day.
- *
- * Note that the ONCORE firmware for the Bj command is wrong at
- * least in the VP.
- * It starts advertising a LEAP SECOND as soon as the GPS satellite
- * data message (page 18, subframe 4) is updated to a date in the
- * future, and does not wait for the month that it will occur.
- * The event will usually be advertised several months in advance.
- * Since there is a one bit flag, there is no way to tell if it is
- * this month, or when...
- *
- * As such, we have the workaround below, of only checking for leap
- * seconds with the Bj command in June/December.
- *
- * The Gj command gives more information, and we can tell in which
- * month to apply the correction.
- *
- * Note that with the VP we COULD read the raw data message, and
- * interpret it ourselves, but since this is specific to this receiver
- * only, and the above workaround is adequate, we don't bother.
- */
-
-static void
-oncore_check_leap_sec(
- struct instance *instance
- )
-{
- if (instance->Bj_day != instance->BEHa[5]) { /* do this 1/day */
- instance->Bj_day = instance->BEHa[5];
-
- if (instance->saw_Gj < 0) { /* -1 DONT have Gj use Bj */
- if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12))
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
- return;
- }
-
- if (instance->saw_Gj == 0) /* 0 is dont know if we have Gj */
- instance->count4 = 1;
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gj, sizeof(oncore_cmd_Gj));
- return;
- }
-
- /* Gj works for some 6/8 chan UT and the M12 */
- /* if no response from Gj in 5 sec, we try Bj */
- /* which isnt implemented in all the GT/UT either */
-
- if (instance->count4) { /* delay, waiting for Gj response */
- if (instance->saw_Gj == 1)
- instance->count4 = 0;
- else if (instance->count4++ > 5) { /* delay, waiting for Gj response */
- instance->saw_Gj = -1; /* didnt see it, will use Bj */
- instance->count4 = 0;
- if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12))
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
- }
- }
-}
-
-
-
-/* check the message checksum,
- * buf points to START of message ( @@ )
- * len is length WITH CR/LF.
- */
-
-static int
-oncore_checksum_ok(
- u_char *buf,
- int len
- )
-{
- int i, j;
-
- j = 0;
- for (i = 2; i < len-3; i++)
- j ^= buf[i];
-
- return(j == buf[len-3]);
-}
-
-
-
-static void
-oncore_compute_dH(
- struct instance *instance
- )
-{
- int GPS, MSL;
- char Msg[160];
-
- /* Here calculate dH = GPS - MSL for output message */
- /* also set Altitude Hold mode if GT */
-
- instance->have_dH = 1;
- if (instance->chan == 12) {
- GPS = buf_w32(&instance->BEHa[39]);
- MSL = buf_w32(&instance->BEHa[43]);
- } else {
- GPS = buf_w32(&instance->BEHa[23]);
- MSL = buf_w32(&instance->BEHa[27]);
- }
- instance->dH = GPS - MSL;
- instance->dH /= 100.;
-
- /* if MSL is not set, the calculation is meaningless */
-
- if (MSL) { /* not set ! */
- sprintf(Msg, "dH = (GPS - MSL) = %.2fm", instance->dH);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- }
-}
-
-
-
-/*
- * try loading Almanac from shmem (where it was copied from shmem_old
- */
-
-static void
-oncore_load_almanac(
- struct instance *instance
- )
-{
- u_char *cp, Cmd[20];
- int n;
- struct timeval tv;
- struct tm *tm;
-
- if (!instance->shmem)
- return;
-
-#if 1
- for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
- if (!strncmp(cp, "@@Cb", 4) &&
- oncore_checksum_ok(cp, 33) &&
- (*(cp+4) == 4 || *(cp+4) == 5)) {
- write(instance->ttyfd, cp, n);
-#if 1
- oncore_print_Cb(instance, cp);
-#endif
- }
- }
-#else
-/************DEBUG************/
- for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
- char Msg[160];
-
- sprintf(Msg, "See %c%c%c%c %d", *(cp), *(cp+1), *(cp+2), *(cp+3), *(cp+4));
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- if (!strncmp(cp, "@@Cb", 4)) {
- oncore_print_Cb(instance, cp);
- if (oncore_checksum_ok(cp, 33)) {
- if (*(cp+4) == 4 || *(cp+4) == 5) {
- record_clock_stats(&(instance->peer->srcadr), "GOOD SF");
- write(instance->ttyfd, cp, n);
- } else
- record_clock_stats(&(instance->peer->srcadr), "BAD SF");
- } else
- record_clock_stats(&(instance->peer->srcadr), "BAD CHECKSUM");
- }
- }
-/************DEBUG************/
-#endif
-
- /* Must load position and time or the Almanac doesn't do us any good */
-
- if (!instance->posn_set) { /* if we input a posn use it, else from SHMEM */
- record_clock_stats(&(instance->peer->srcadr), "Loading Posn from SHMEM");
- for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
- if ((instance->chan == 6 && (!strncmp(cp, "@@Ba", 4) && oncore_checksum_ok(cp, 68))) ||
- (instance->chan == 8 && (!strncmp(cp, "@@Ea", 4) && oncore_checksum_ok(cp, 76))) ||
- (instance->chan == 12 && (!strncmp(cp, "@@Ha", 4) && oncore_checksum_ok(cp, 154)))) {
- int ii, jj, kk;
-
- instance->posn_set = 1;
- ii = buf_w32(cp + 15);
- jj = buf_w32(cp + 19);
- kk = buf_w32(cp + 23);
-{
-char Msg[160];
-sprintf(Msg, "SHMEM posn = %d (%d, %d, %d)", cp-instance->shmem, ii, jj, kk);
-record_clock_stats(&(instance->peer->srcadr), Msg);
-}
- if (ii != 0 || jj != 0 || kk != 0) { /* phk asked for this test */
- instance->ss_lat = ii;
- instance->ss_long = jj;
- instance->ss_ht = kk;
- }
- }
- }
- }
- oncore_set_posn(instance);
-
- /* and set time to time from Computer clock */
-
- gettimeofday(&tv, 0);
- tm = gmtime((const time_t *) &tv.tv_sec);
-#if 1
- {
- char Msg[160];
- sprintf(Msg, "DATE %d %d %d, %d %d %d", 1900+tm->tm_year, tm->tm_mon, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- }
-#endif
- if (instance->chan == 12) {
- memcpy(Cmd, oncore_cmd_Gb, (size_t) sizeof(oncore_cmd_Gb));
- Cmd[-2+4] = tm->tm_mon;
- Cmd[-2+5] = tm->tm_mday;
- Cmd[-2+6] = (1900+tm->tm_year)/256;
- Cmd[-2+7] = (1900+tm->tm_year)%256;
- Cmd[-2+8] = tm->tm_hour;
- Cmd[-2+9] = tm->tm_min;
- Cmd[-2+10] = tm->tm_sec;
- Cmd[-2+11] = 0;
- Cmd[-2+12] = 0;
- Cmd[-2+13] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Gb));
- } else {
- /* First set GMT offset to zero */
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ab, sizeof(oncore_cmd_Ab));
-
- memcpy(Cmd, oncore_cmd_Ac, (size_t) sizeof(oncore_cmd_Ac));
- Cmd[-2+4] = tm->tm_mon;
- Cmd[-2+5] = tm->tm_mday;
- Cmd[-2+6] = (1900+tm->tm_year)/256;
- Cmd[-2+7] = (1900+tm->tm_year)%256;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ac));
-
- memcpy(Cmd, oncore_cmd_Aa, (size_t) sizeof(oncore_cmd_Aa));
- Cmd[-2+4] = tm->tm_hour;
- Cmd[-2+5] = tm->tm_min;
- Cmd[-2+6] = tm->tm_sec;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Aa));
- }
-
- record_clock_stats(&(instance->peer->srcadr), "Setting Posn and Time after Loading Almanac");
-}
-
-
-
-/* Almanac data input */
-
-static void
-oncore_print_Cb(
- struct instance *instance,
- u_char *cp
- )
-{
-#if 0
- int ii;
- char Msg[160];
-
- printf("DEBUG: See: %c%c%c%c\n", *(cp), *(cp+1), *(cp+2), *(cp+3));
- printf("DEBUG: Cb: [%d,%d]", *(cp+4), *(cp+5));
- for(ii=0; ii<33; ii++)
- printf(" %d", *(cp+ii));
- printf("\n");
-
- sprintf(Msg, "Debug: Cb: [%d,%d]", *(cp+4), *(cp+5));
- record_clock_stats(&(instance->peer->srcadr), Msg);
-#endif
-}
-
-
-#if 0
-static void
-oncore_print_array(
- u_char *cp,
- int n
- )
-{
- int jj, i, j, nn;
-
- nn = 0;
- printf("\nTOP\n");
- jj = n/16;
- for (j=0; j<jj; j++) {
- printf("%4d: ", nn);
- nn += 16;
- for (i=0; i<16; i++)
- printf(" %o", *cp++);
- printf("\n");
- }
-}
-#endif
-
-
-static void
-oncore_print_posn(
- struct instance *instance
- )
-{
- char Msg[120], ew, ns;
- double xd, xm, xs, yd, ym, ys, hm, hft;
- int idx, idy, is, imx, imy;
- long lat, lon;
-
- record_clock_stats(&(instance->peer->srcadr), "Posn:");
- ew = 'E';
- lon = instance->ss_long;
- if (lon < 0) {
- ew = 'W';
- lon = -lon;
- }
-
- ns = 'N';
- lat = instance->ss_lat;
- if (lat < 0) {
- ns = 'S';
- lat = -lat;
- }
-
- hm = instance->ss_ht/100.;
- hft= hm/0.3048;
-
- xd = lat/3600000.; /* lat, lon in int msec arc, ht in cm. */
- yd = lon/3600000.;
- sprintf(Msg, "Lat = %c %11.7fdeg, Long = %c %11.7fdeg, Alt = %5.2fm (%5.2fft) GPS", ns, xd, ew, yd, hm, hft);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- idx = xd;
- idy = yd;
- imx = lat%3600000;
- imy = lon%3600000;
- xm = imx/60000.;
- ym = imy/60000.;
- sprintf(Msg,
- "Lat = %c %3ddeg %7.4fm, Long = %c %3ddeg %8.5fm, Alt = %7.2fm (%7.2fft) GPS", ns, idx, xm, ew, idy, ym, hm, hft);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- imx = xm;
- imy = ym;
- is = lat%60000;
- xs = is/1000.;
- is = lon%60000;
- ys = is/1000.;
- sprintf(Msg,
- "Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %7.2fm (%7.2fft) GPS", ns, idx, imx, xs, ew, idy, imy, ys, hm, hft);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-}
-
-
-
-/*
- * write message to Oncore.
- */
-
-static void
-oncore_sendmsg(
- int fd,
- u_char *ptr,
- size_t len
- )
-{
- u_char cs = 0;
-
- if (debug > 4)
- printf("ONCORE: Send @@%c%c %d\n", ptr[0], ptr[1], (int) len);
- write(fd, "@@", (size_t) 2);
- write(fd, ptr, len);
- while (len--)
- cs ^= *ptr++;
- write(fd, &cs, (size_t) 1);
- write(fd, "\r\n", (size_t) 2);
-}
-
-
-
-static void
-oncore_set_posn(
- struct instance *instance
- )
-{
- int mode;
- char Cmd[20];
-
- /* Turn OFF position hold, it needs to be off to set position (for some units),
- will get set ON in @@Ea later */
-
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* (12) */
- else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* (6/8) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* (6/8) */
- }
-
- mode = instance->init_type;
-
- if (mode != 0) { /* first set posn hold position */
- memcpy(Cmd, oncore_cmd_As, (size_t) sizeof(oncore_cmd_As)); /* don't modify static variables */
- w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
- w32_buf(&Cmd[-2+8], (int) instance->ss_long);
- w32_buf(&Cmd[-2+12], (int) instance->ss_ht);
- Cmd[-2+16] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_As)); /* posn hold 3D posn (6/8/12) */
-
- memcpy(Cmd, oncore_cmd_Au, (size_t) sizeof(oncore_cmd_Au));
- w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
- Cmd[-2+8] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Au)); /* altitude hold (6/8/12 not UT, M12T) */
-
- /* next set current position */
-
- if (instance->chan == 12) {
- memcpy(Cmd, oncore_cmd_Ga, (size_t) sizeof(oncore_cmd_Ga));
- w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
- w32_buf(&Cmd[-2+8], (int) instance->ss_long);
- w32_buf(&Cmd[-2+12],(int) instance->ss_ht);
- Cmd[-2+16] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ga)); /* 3d posn (12) */
- } else {
- memcpy(Cmd, oncore_cmd_Ad, (size_t) sizeof(oncore_cmd_Ad));
- w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ad)); /* lat (6/8) */
-
- memcpy(Cmd, oncore_cmd_Ae, (size_t) sizeof(oncore_cmd_Ae));
- w32_buf(&Cmd[-2+4], (int) instance->ss_long);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ae)); /* long (6/8) */
-
- memcpy(Cmd, oncore_cmd_Af, (size_t) sizeof(oncore_cmd_Af));
- w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
- Cmd[-2+8] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Af)); /* ht (6/8) */
- }
-
- /* Finally, turn on position hold */
-
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
- else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1));
- }
-}
-
-
-
-static void
-oncore_set_traim(
- struct instance *instance
- )
-{
- char Msg[160];
-
- if (instance->traim_in != -1) /* set in Input */
- instance->traim = instance->traim_in;
- else
- instance->traim = instance->traim_ck;
-
- sprintf(Msg, "Input says TRAIM = %d", instance->traim_in);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Model # says TRAIM = %d", instance->traim_id);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Testing says TRAIM = %d", instance->traim_ck);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- sprintf(Msg, "Using TRAIM = %d", instance->traim);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- if (instance->traim_ck == 1 && instance->traim == 0) {
- /* if it should be off, and I turned it on during testing,
- then turn it off again */
- if (instance->chan == 6)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bnx, sizeof(oncore_cmd_Bnx));
- else if (instance->chan == 8)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Enx, sizeof(oncore_cmd_Enx));
- else /* chan == 12 */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ge0, sizeof(oncore_cmd_Ge0));
- }
-}
-
-
-
-/*
- * if SHMEM active, every 15s, steal one 'tick' to get 2D or 3D posn.
- */
-
-static void
-oncore_shmem_get_3D(
- struct instance *instance
- )
-{
- if (instance->pp->second%15 == 3) { /* start the sequence */ /* by changing mode */
- instance->shmem_reset = 1;
- if (instance->chan == 12) {
- if (instance->shmem_Posn == 2)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd2, sizeof(oncore_cmd_Gd2)); /* 2D */
- else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* 3D */
- } else {
- if (instance->saw_At) { /* out of 0D -> 3D mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0));
- if (instance->shmem_Posn == 2) /* 3D -> 2D mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
- } else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
- }
- } else if (instance->shmem_reset || (instance->mode != MODE_0D)) {
- instance->shmem_reset = 0;
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1)); /* 0D */
- else {
- if (instance->saw_At) {
- if (instance->mode == MODE_2D) /* 2D -> 3D or 0D mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1)); /* to 0D mode */
- } else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
- }
- }
-}
-
-
-
-/*
- * Here we do the Software SiteSurvey.
- * We have to average our own position for the Position Hold Mode
- * We use Heights from the GPS ellipsoid.
- * We check for the END of either HW or SW SiteSurvey.
- */
-
-static void
-oncore_ss(
- struct instance *instance
- )
-{
- char *cp, Msg[160];
- double lat, lon, ht;
-
-
- if (instance->site_survey == ONCORE_SS_HW) {
-
- /*
- * Check to see if Hardware SiteSurvey has Finished.
- */
-
- if ((instance->chan == 8 && !(instance->BEHa[37] & 0x20)) ||
- (instance->chan == 12 && !(instance->BEHa[130] & 0x10))) {
- record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
-
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gax, sizeof(oncore_cmd_Gax));
- else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Asx, sizeof(oncore_cmd_Asx));
-
- cp = "SSstate = ONCORE_SS_DONE";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->site_survey = ONCORE_SS_DONE;
- }
- } else {
- /*
- * Must be a Software Site Survey.
- */
-
- if (instance->rsm.bad_fix) /* Not if poor geometry or less than 3 sats */
- return;
-
- if (instance->mode != MODE_3D) /* Use only 3D Fixes */
- return;
-
- instance->ss_lat += buf_w32(&instance->BEHa[15]);
- instance->ss_long += buf_w32(&instance->BEHa[19]);
- instance->ss_ht += buf_w32(&instance->BEHa[23]); /* GPS ellipsoid */
- instance->ss_count++;
-
- if (instance->ss_count != POS_HOLD_AVERAGE)
- return;
-
- instance->ss_lat /= POS_HOLD_AVERAGE;
- instance->ss_long /= POS_HOLD_AVERAGE;
- instance->ss_ht /= POS_HOLD_AVERAGE;
-
- sprintf(Msg, "Surveyed posn: lat %.3f (mas) long %.3f (mas) ht %.3f (cm)",
- instance->ss_lat, instance->ss_long, instance->ss_ht);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- lat = instance->ss_lat/3600000.;
- lon = instance->ss_long/3600000.;
- ht = instance->ss_ht/100;
- sprintf(Msg, "Surveyed posn: lat %.7f (deg) long %.7f (deg) ht %.2f (m)",
- lat, lon, ht);
- record_clock_stats(&(instance->peer->srcadr), Msg);
-
- oncore_set_posn(instance);
-
- record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
-
- cp = "SSstate = ONCORE_SS_DONE";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->site_survey = ONCORE_SS_DONE;
- }
-}
-
-
-
-static int
-oncore_wait_almanac(
- struct instance *instance
- )
-{
- if (instance->rsm.bad_almanac) {
- if (debug)
- printf("ONCORE[%d]: waiting for almanac\n", instance->unit);
-
- /*
- * If we get here (first time) then we don't have an almanac in memory.
- * Check if we have a SHMEM, and if so try to load whatever is there.
- */
-
- if (!instance->almanac_from_shmem) {
- instance->almanac_from_shmem = 1;
- oncore_load_almanac(instance);
- }
- return(1);
- } else { /* Here we have the Almanac, we will be starting the @@Bn/@@En/@@Hn
- commands, and can finally check for TRAIM. Again, we set a delay
- (5sec) and wait for things to settle down */
-
- if (instance->chan == 6)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn, sizeof(oncore_cmd_Bn));
- else if (instance->chan == 8)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En, sizeof(oncore_cmd_En));
- else if (instance->chan == 12) {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gc, sizeof(oncore_cmd_Gc)); /* 1PPS on, continuous */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ge, sizeof(oncore_cmd_Ge)); /* TRAIM on */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn, sizeof(oncore_cmd_Hn)); /* TRAIM status 1/s */
- }
- instance->traim_delay = 1;
-
- record_clock_stats(&(instance->peer->srcadr), "Have now loaded an ALMANAC");
-
- instance->o_state = ONCORE_RUN;
- record_clock_stats(&(instance->peer->srcadr), "state = ONCORE_RUN");
- }
- return(0);
-}
-
-
-
-#else
-int refclock_oncore_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_palisade.c b/contrib/ntp/ntpd/refclock_palisade.c
deleted file mode 100644
index 897221b..0000000
--- a/contrib/ntp/ntpd/refclock_palisade.c
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * This software was developed by the Software and Component Technologies
- * group of Trimble Navigation, Ltd.
- *
- * Copyright (c) 1997, 1998, 1999, 2000 Trimble Navigation Ltd.
- * 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 Trimble Navigation, Ltd.
- * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``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 TRIMBLE NAVIGATION LTD. 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.
- */
-
-/*
- * refclock_palisade - clock driver for the Trimble Palisade GPS
- * timing receiver
- *
- * For detailed information on this program, please refer to the html
- * Refclock 29 page accompanying the NTP distribution.
- *
- * for questions / bugs / comments, contact:
- * sven_dietrich@trimble.com
- *
- * Sven-Thorsten Dietrich
- * 645 North Mary Avenue
- * Post Office Box 3642
- * Sunnyvale, CA 94088-3642
- *
- * Version 2.45; July 14, 1999
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if defined(SYS_WINNT)
-#undef close
-#define close closesocket
-#endif
-
-#if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE))
-
-#include "refclock_palisade.h"
-/* Table to get from month to day of the year */
-const int days_of_year [12] = {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
-};
-
-#ifdef DEBUG
-const char * Tracking_Status[15][15] = {
- { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
- {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
- { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
- { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
- { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
-#endif
-
-/*
- * Transfer vector
- */
-struct refclock refclock_palisade = {
- palisade_start, /* start up driver */
- palisade_shutdown, /* shut down driver */
- palisade_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-int day_of_year P((char *dt));
-
-/* Extract the clock type from the mode setting */
-#define CLK_TYPE(x) ((int)(((x)->ttl) & 0x7F))
-
-/* Supported clock types */
-#define CLK_TRIMBLE 0 /* Trimble Palisade */
-#define CLK_PRAECIS 1 /* Endrun Technologies Praecis */
-
-int praecis_msg;
-static void praecis_parse(struct recvbuf *rbufp, struct peer *peer);
-
-/*
- * palisade_start - open the devices and initialize data for processing
- */
-static int
-palisade_start (
-#ifdef PALISADE
- unit, peer
- )
- int unit;
- struct peer *peer;
-#else /* ANSI */
- int unit,
- struct peer *peer
- )
-#endif
-{
- struct palisade_unit *up;
- struct refclockproc *pp;
- int fd;
- char gpsdev[20];
-
- struct termios tio;
-#ifdef SYS_WINNT
- (void) sprintf(gpsdev, "COM%d:", unit);
-#else
- (void) sprintf(gpsdev, DEVICE, unit);
-#endif
- /*
- * Open serial port.
- */
-#if defined PALISADE
- fd = open(gpsdev, O_RDWR
-#ifdef O_NONBLOCK
- | O_NONBLOCK
-#endif
- );
-#else /* NTP 4.x */
- fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
-#endif
- if (fd <= 0) {
-#ifdef DEBUG
- printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
-#endif
- return 0;
- }
-
- msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
- gpsdev);
-
-#if defined PALISADE
- tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
- tio.c_iflag = (IGNBRK);
- tio.c_oflag = (0);
- tio.c_lflag = (0);
-
- if (cfsetispeed(&tio, SPEED232) == -1) {
- msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit);
-#ifdef DEBUG
- printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit);
-#endif
- return 0;
- }
- if (cfsetospeed(&tio, SPEED232) == -1) {
-#ifdef DEBUG
- printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit);
-#endif
- msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit);
- return 0;
- }
-#else /* NTP 4.x */
- if (tcgetattr(fd, &tio) < 0) {
- msyslog(LOG_ERR,
- "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
-#ifdef DEBUG
- printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
-#endif
- return (0);
- }
-
- tio.c_cflag |= (PARENB|PARODD);
- tio.c_iflag &= ~ICRNL;
-#endif /* NTP 4.x */
-
- if (tcsetattr(fd, TCSANOW, &tio) == -1) {
- msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
-#ifdef DEBUG
- printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
-#endif
- return 0;
- }
-
- /*
- * Allocate and initialize unit structure
- */
- up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit));
-
- if (!(up)) {
- msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit);
-#ifdef DEBUG
- printf("Palisade(%d) emalloc\n",unit);
-#endif
- (void) close(fd);
- return (0);
- }
-
- memset((char *)up, 0, sizeof(struct palisade_unit));
-
- up->type = CLK_TYPE(peer);
- switch (up->type) {
- case CLK_TRIMBLE:
- /* Normal mode, do nothing */
- break;
- case CLK_PRAECIS:
- msyslog(LOG_NOTICE, "Palisade(%d) Praecis mode enabled\n",unit);
- break;
- default:
- msyslog(LOG_NOTICE, "Palisade(%d) mode unknown\n",unit);
- break;
- }
-
- pp = peer->procptr;
- pp->io.clock_recv = palisade_io;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
-#ifdef DEBUG
- printf("Palisade(%d) io_addclock\n",unit);
-#endif
- (void) close(fd);
- free(up);
- return (0);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- pp->unitptr = (caddr_t)up;
- pp->clockdesc = DESCRIPTION;
-
- peer->precision = PRECISION;
- peer->sstclktype = CTL_SST_TS_UHF;
- peer->minpoll = TRMB_MINPOLL;
- peer->maxpoll = TRMB_MAXPOLL;
- memcpy((char *)&pp->refid, REFID, 4);
-
- up->leap_status = 0;
- up->unit = (short) unit;
- up->rpt_status = TSIP_PARSED_EMPTY;
- up->rpt_cnt = 0;
-
- return 1;
-}
-
-
-/*
- * palisade_shutdown - shut down the clock
- */
-static void
-palisade_shutdown (
-#ifdef PALISADE
- unit, peer
- )
- int unit;
- struct peer *peer;
-#else /* ANSI */
- int unit,
- struct peer *peer
- )
-#endif
-{
- struct palisade_unit *up;
- struct refclockproc *pp;
- pp = peer->procptr;
- up = (struct palisade_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-
-/*
- * unpack_date - get day and year from date
- */
-int
-day_of_year (
-#ifdef PALISADE
- dt
- )
- char * dt;
-#else
- char * dt
- )
-#endif
-{
- int day, mon, year;
-
- mon = dt[1];
- /* Check month is inside array bounds */
- if ((mon < 1) || (mon > 12))
- return -1;
-
- day = dt[0] + days_of_year[mon - 1];
- year = getint((u_char *) (dt + 2));
-
- if ( !(year % 4) && ((year % 100) ||
- (!(year % 100) && !(year%400)))
- &&(mon > 2))
- day ++; /* leap year and March or later */
-
- return day;
-}
-
-
-/*
- * TSIP_decode - decode the TSIP data packets
- */
-int
-TSIP_decode (
-#ifdef PALISADE
- peer
- )
- struct peer *peer;
-#else
- struct peer *peer
- )
-#endif
-{
- int st;
- long secint;
- double secs;
- double secfrac;
- unsigned short event = 0;
-
- struct palisade_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct palisade_unit *)pp->unitptr;
-
- /*
- * Check the time packet, decode its contents.
- * If the timecode has invalid length or is not in
- * proper format, declare bad format and exit.
- */
-
- if ((up->rpt_buf[0] == (char) 0x41) ||
- (up->rpt_buf[0] == (char) 0x46) ||
- (up->rpt_buf[0] == (char) 0x54) ||
- (up->rpt_buf[0] == (char) 0x4B) ||
- (up->rpt_buf[0] == (char) 0x6D)) {
-
- /* standard time packet - GPS time and GPS week number */
-#ifdef DEBUG
- printf("Palisade Port B packets detected. Connect to Port A\n");
-#endif
-
- return 0;
- }
-
- /*
- * We cast both to u_char to as 0x8f uses the sign bit on a char
- */
- if ((u_char) up->rpt_buf[0] == (u_char) 0x8f) {
- /*
- * Superpackets
- */
- event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
- if (!((pp->sloppyclockflag & CLK_FLAG2) || event))
- /* Ignore Packet */
- return 0;
-
- switch (mb(0) & 0xff) {
- int GPS_UTC_Offset;
- case PACKET_8F0B:
-
- if (up->polled <= 0)
- return 0;
-
- if (up->rpt_cnt != LENCODE_8F0B) /* check length */
- break;
-
-#ifdef DEBUG
-if (debug > 1) {
- int ts;
- double lat, lon, alt;
- lat = getdbl((u_char *) &mb(42)) * R2D;
- lon = getdbl((u_char *) &mb(50)) * R2D;
- alt = getdbl((u_char *) &mb(58));
-
- printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
- up->unit, lat,lon,alt);
- printf("TSIP_decode: unit %d: Sats:", up->unit);
- for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) {
- if (mb(st) > 0) ts++;
- printf(" %02d", mb(st));
- }
- printf(" : Tracking %d\n", ts);
- }
-#endif
-
- GPS_UTC_Offset = getint((u_char *) &mb(16));
- if (GPS_UTC_Offset == 0) { /* Check UTC offset */
-#ifdef DEBUG
- printf("TSIP_decode: UTC Offset Unknown\n");
-#endif
- break;
- }
-
- secs = getdbl((u_char *) &mb(3));
- secint = (long) secs;
- secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
-
- pp->nsec = (long) (secfrac * 1000000000);
-
- secint %= 86400; /* Only care about today */
- pp->hour = secint / 3600;
- secint %= 3600;
- pp->minute = secint / 60;
- secint %= 60;
- pp->second = secint % 60;
-
- if ((pp->day = day_of_year(&mb(11))) < 0) break;
-
- pp->year = getint((u_char *) &mb(13));
-
-#ifdef DEBUG
- if (debug > 1)
- printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
- up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
- pp->second, pp->nsec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
-#endif
- /* Only use this packet when no
- * 8F-AD's are being received
- */
-
- if (up->leap_status) {
- up->leap_status = 0;
- return 0;
- }
-
- return 2;
- break;
-
- case PACKET_NTP:
- /* Palisade-NTP Packet */
-
- if (up->rpt_cnt != LENCODE_NTP) /* check length */
- break;
-
- up->leap_status = mb(19);
-
- if (up->polled <= 0)
- return 0;
-
- /* Check Tracking Status */
- st = mb(18);
- if (st < 0 || st > 14) st = 14;
- if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
-#ifdef DEBUG
- printf("TSIP_decode: Not Tracking Sats : %s\n",
- *Tracking_Status[st]);
-#endif
- refclock_report(peer, CEVNT_BADTIME);
- up->polled = -1;
- return 0;
- break;
- }
-
- if (up->leap_status & PALISADE_LEAP_PENDING) {
- if (up->leap_status & PALISADE_UTC_TIME)
- pp->leap = LEAP_ADDSECOND;
- else
- pp->leap = LEAP_DELSECOND;
- }
- else if (up->leap_status)
- pp->leap = LEAP_NOWARNING;
-
- else { /* UTC flag is not set:
- * Receiver may have been reset, and lost
- * its UTC almanac data */
- pp->leap = LEAP_NOTINSYNC;
-#ifdef DEBUG
- printf("TSIP_decode: UTC Almanac unavailable: %d\n",
- mb(19));
-#endif
- refclock_report(peer, CEVNT_BADTIME);
- up->polled = -1;
- return 0;
- }
-
- pp->nsec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
-
- if ((pp->day = day_of_year(&mb(14))) < 0)
- break;
- pp->year = getint((u_char *) &mb(16));
- pp->hour = mb(11);
- pp->minute = mb(12);
- pp->second = mb(13);
-
-#ifdef DEBUG
- if (debug > 1)
-printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
- up->unit, mb(0) & 0xff, event, pp->hour, pp->minute,
- pp->second, pp->nsec, mb(15), mb(14), pp->year,
- mb(19), *Tracking_Status[st]);
-#endif
- return 1;
- break;
-
- default:
- /* Ignore Packet */
- return 0;
- } /* switch */
- }/* if 8F packets */
-
- refclock_report(peer, CEVNT_BADREPLY);
- up->polled = -1;
-#ifdef DEBUG
- printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n",
- up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff,
- event, up->rpt_cnt);
-#endif
- return 0;
-}
-
-/*
- * palisade__receive - receive data from the serial interface
- */
-
-static void
-palisade_receive (
-#ifdef PALISADE
- peer
- )
- struct peer * peer;
-#else /* ANSI */
- struct peer * peer
- )
-#endif
-{
- struct palisade_unit *up;
- struct refclockproc *pp;
-
- /*
- * Initialize pointers and read the timecode and timestamp.
- */
- pp = peer->procptr;
- up = (struct palisade_unit *)pp->unitptr;
-
- if (! TSIP_decode(peer)) return;
-
- if (up->polled <= 0)
- return; /* no poll pending, already received or timeout */
-
- up->polled = 0; /* Poll reply received */
- pp->lencode = 0; /* clear time code */
-#ifdef DEBUG
- if (debug)
- printf(
- "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
- up->unit, pp->year, pp->day, pp->hour, pp->minute,
- pp->second, pp->nsec);
-#endif
-
- /*
- * Process the sample
- * Generate timecode: YYYY DoY HH:MM:SS.microsec
- * report and process
- */
-
- (void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld",
- pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->nsec);
- pp->lencode = 24;
-
-#ifdef PALISADE
- pp->lasttime = current_time;
-#endif
- if (!refclock_process(pp
-#ifdef PALISADE
- , PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5
-#endif
- )) {
- refclock_report(peer, CEVNT_BADTIME);
-
-#ifdef DEBUG
- printf("palisade_receive: unit %d: refclock_process failed!\n",
- up->unit);
-#endif
- return;
- }
-
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-
-#ifdef DEBUG
- if (debug)
- printf("palisade_receive: unit %d: %s\n",
- up->unit, prettydate(&pp->lastrec));
-#endif
- pp->lastref = pp->lastrec;
- refclock_receive(peer
-#ifdef PALISADE
- , &pp->offset, 0, pp->dispersion,
- &pp->lastrec, &pp->lastrec, pp->leap
-#endif
- );
-}
-
-
-/*
- * palisade_poll - called by the transmit procedure
- *
- */
-static void
-palisade_poll (
-#ifdef PALISADE
- unit, peer
- )
- int unit;
- struct peer *peer;
-#else
- int unit,
- struct peer *peer
- )
-#endif
-{
- struct palisade_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct palisade_unit *)pp->unitptr;
-
- pp->polls++;
- if (up->polled > 0) /* last reply never arrived or error */
- refclock_report(peer, CEVNT_TIMEOUT);
-
- up->polled = 2; /* synchronous packet + 1 event */
-
-#ifdef DEBUG
- if (debug)
- printf("palisade_poll: unit %d: polling %s\n", unit,
- (pp->sloppyclockflag & CLK_FLAG2) ?
- "synchronous packet" : "event");
-#endif
-
- if (pp->sloppyclockflag & CLK_FLAG2)
- return; /* using synchronous packet input */
-
- if(up->type == CLK_PRAECIS) {
- if(write(peer->procptr->io.fd,"SPSTAT\r\n",8) < 0)
- msyslog(LOG_ERR, "Palisade(%d) write: %m:",unit);
- else {
- praecis_msg = 1;
- return;
- }
- }
-
- if (HW_poll(pp) < 0)
- refclock_report(peer, CEVNT_FAULT);
-}
-
-static void
-praecis_parse(struct recvbuf *rbufp, struct peer *peer)
-{
- static char buf[100];
- static int p = 0;
- struct refclockproc *pp;
-
- pp = peer->procptr;
-
- memcpy(buf+p,rbufp->recv_space.X_recv_buffer, rbufp->recv_length);
- p += rbufp->recv_length;
-
- if(buf[p-2] == '\r' && buf[p-1] == '\n') {
- buf[p-2] = '\0';
- record_clock_stats(&peer->srcadr, buf);
-
- p = 0;
- praecis_msg = 0;
-
- if (HW_poll(pp) < 0)
- refclock_report(peer, CEVNT_FAULT);
-
- }
-}
-
-static void
-palisade_io (
-#ifdef PALISADE
- rbufp
- )
- struct recvbuf *rbufp;
-#else /* ANSI */
- struct recvbuf *rbufp
- )
-#endif
-{
- /*
- * Initialize pointers and read the timecode and timestamp.
- */
- struct palisade_unit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- char * c, * d;
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct palisade_unit *)pp->unitptr;
-
- if(up->type == CLK_PRAECIS) {
- if(praecis_msg) {
- praecis_parse(rbufp,peer);
- return;
- }
- }
-
- c = (char *) &rbufp->recv_space;
- d = c + rbufp->recv_length;
-
- while (c != d) {
-
- /* Build time packet */
- switch (up->rpt_status) {
-
- case TSIP_PARSED_DLE_1:
- switch (*c)
- {
- case 0:
- case DLE:
- case ETX:
- up->rpt_status = TSIP_PARSED_EMPTY;
- break;
-
- default:
- up->rpt_status = TSIP_PARSED_DATA;
- /* save packet ID */
- up->rpt_buf[0] = *c;
- break;
- }
- break;
-
- case TSIP_PARSED_DATA:
- if (*c == DLE)
- up->rpt_status = TSIP_PARSED_DLE_2;
- else
- mb(up->rpt_cnt++) = *c;
- break;
-
- case TSIP_PARSED_DLE_2:
- if (*c == DLE) {
- up->rpt_status = TSIP_PARSED_DATA;
- mb(up->rpt_cnt++) =
- *c;
- }
- else if (*c == ETX)
- up->rpt_status = TSIP_PARSED_FULL;
- else {
- /* error: start new report packet */
- up->rpt_status = TSIP_PARSED_DLE_1;
- up->rpt_buf[0] = *c;
- }
- break;
-
- case TSIP_PARSED_FULL:
- case TSIP_PARSED_EMPTY:
- default:
- if ( *c != DLE)
- up->rpt_status = TSIP_PARSED_EMPTY;
- else
- up->rpt_status = TSIP_PARSED_DLE_1;
- break;
- }
-
- c++;
-
- if (up->rpt_status == TSIP_PARSED_DLE_1) {
- up->rpt_cnt = 0;
- if (pp->sloppyclockflag & CLK_FLAG2)
- /* stamp it */
- get_systime(&pp->lastrec);
- }
- else if (up->rpt_status == TSIP_PARSED_EMPTY)
- up->rpt_cnt = 0;
-
- else if (up->rpt_cnt > BMAX)
- up->rpt_status =TSIP_PARSED_EMPTY;
-
- if (up->rpt_status == TSIP_PARSED_FULL)
- palisade_receive(peer);
-
- } /* while chars in buffer */
-}
-
-
-/*
- * Trigger the Palisade's event input, which is driven off the RTS
- *
- * Take a system time stamp to match the GPS time stamp.
- *
- */
-long
-HW_poll (
-#ifdef PALISADE
- pp /* pointer to unit structure */
- )
- struct refclockproc * pp; /* pointer to unit structure */
-#else
- struct refclockproc * pp /* pointer to unit structure */
- )
-#endif
-{
- int x; /* state before & after RTS set */
- struct palisade_unit *up;
-
- up = (struct palisade_unit *) pp->unitptr;
-
- /* read the current status, so we put things back right */
- if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
-#ifdef DEBUG
- if (debug)
- printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno));
-#endif
- msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m",
- up->unit);
- return -1;
- }
-
- x |= TIOCM_RTS; /* turn on RTS */
-
- /* Edge trigger */
- if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) {
-#ifdef DEBUG
- if (debug)
- printf("Palisade HW_poll: unit %d: SET \n", up->unit);
-#endif
- msyslog(LOG_ERR,
- "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m",
- up->unit);
- return -1;
- }
-
- x &= ~TIOCM_RTS; /* turn off RTS */
-
- /* poll timestamp */
- get_systime(&pp->lastrec);
-
- if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
-#ifdef DEBUG
- if (debug)
- printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
-#endif
- msyslog(LOG_ERR,
- "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m",
- up->unit);
- return -1;
- }
-
- return 0;
-}
-
-#if 0 /* unused */
-/*
- * this 'casts' a character array into a float
- */
-float
-getfloat (
-#ifdef PALISADE
- bp
- )
- u_char *bp;
-#else
- u_char *bp
- )
-#endif
-{
- float sval;
-#ifdef WORDS_BIGENDIAN
- ((char *) &sval)[0] = *bp++;
- ((char *) &sval)[1] = *bp++;
- ((char *) &sval)[2] = *bp++;
- ((char *) &sval)[3] = *bp++;
-#else
- ((char *) &sval)[3] = *bp++;
- ((char *) &sval)[2] = *bp++;
- ((char *) &sval)[1] = *bp++;
- ((char *) &sval)[0] = *bp;
-#endif /* ! XNTP_BIG_ENDIAN */
- return sval;
-}
-#endif
-
-/*
- * this 'casts' a character array into a double
- */
-double
-getdbl (
-#ifdef PALISADE
- bp
- )
- u_char *bp;
-#else
- u_char *bp
- )
-#endif
-{
- double dval;
-#ifdef WORDS_BIGENDIAN
- ((char *) &dval)[0] = *bp++;
- ((char *) &dval)[1] = *bp++;
- ((char *) &dval)[2] = *bp++;
- ((char *) &dval)[3] = *bp++;
- ((char *) &dval)[4] = *bp++;
- ((char *) &dval)[5] = *bp++;
- ((char *) &dval)[6] = *bp++;
- ((char *) &dval)[7] = *bp;
-#else
- ((char *) &dval)[7] = *bp++;
- ((char *) &dval)[6] = *bp++;
- ((char *) &dval)[5] = *bp++;
- ((char *) &dval)[4] = *bp++;
- ((char *) &dval)[3] = *bp++;
- ((char *) &dval)[2] = *bp++;
- ((char *) &dval)[1] = *bp++;
- ((char *) &dval)[0] = *bp;
-#endif /* ! XNTP_BIG_ENDIAN */
- return dval;
-}
-
-/*
- * cast a 16 bit character array into a short (16 bit) int
- */
-short
-getint (
-#ifdef PALISADE
- bp
- )
- u_char *bp;
-#else
- u_char *bp
- )
-#endif
-{
-return (short) (bp[1] + (bp[0] << 8));
-}
-
-#else
-int refclock_palisade_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_palisade.h b/contrib/ntp/ntpd/refclock_palisade.h
deleted file mode 100644
index 7e1ed49..0000000
--- a/contrib/ntp/ntpd/refclock_palisade.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * This software was developed by the Software and Component Technologies
- * group of Trimble Navigation, Ltd.
- *
- * Copyright (c) 1997, 1998, 1999, 2000 Trimble Navigation Ltd.
- * 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 Trimble Navigation, Ltd.
- * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``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 TRIMBLE NAVIGATION LTD. 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.
- */
-
-/*
- * refclock_palisade - clock driver for the Trimble Palisade GPS
- * timing receiver
- *
- * For detailed information on this program, please refer to the html
- * Refclock 29 page accompanying the NTP distribution.
- *
- * for questions / bugs / comments, contact:
- * sven_dietrich@trimble.com
- *
- * Sven-Thorsten Dietrich
- * 645 North Mary Avenue
- * Post Office Box 3642
- * Sunnyvale, CA 94088-3642
- *
- */
-
-#ifndef _REFCLOCK_PALISADE_H
-#define _REFCLOCK_PALISADE_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if defined HAVE_SYS_MODEM_H
-#include <sys/modem.h>
-#define TIOCMSET MCSETA
-#define TIOCMGET MCGETA
-#define TIOCM_RTS MRTS
-#endif
-
-#ifdef HAVE_TERMIOS_H
-# ifdef TERMIOS_NEEDS__SVID3
-# define _SVID3
-# endif
-# include <termios.h>
-# ifdef TERMIOS_NEEDS__SVID3
-# undef _SVID3
-# endif
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_control.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-/*
- * GPS Definitions
- */
-#define DESCRIPTION "Trimble Palisade GPS" /* Long name */
-#define PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS\0" /* reference ID */
-#define TRMB_MINPOLL 4 /* 16 seconds */
-#define TRMB_MAXPOLL 5 /* 32 seconds */
-
-/*
- * I/O Definitions
- */
-#define DEVICE "/dev/palisade%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-
-/*
- * TSIP Report Definitions
- */
-#define LENCODE_8F0B 74 /* Length of TSIP 8F-0B Packet & header */
-#define LENCODE_NTP 22 /* Length of Palisade NTP Packet */
-
-/* Allowed Sub-Packet ID's */
-#define PACKET_8F0B 0x0B
-#define PACKET_NTP 0xAD
-
-#define DLE 0x10
-#define ETX 0x03
-
-/* parse states */
-#define TSIP_PARSED_EMPTY 0
-#define TSIP_PARSED_FULL 1
-#define TSIP_PARSED_DLE_1 2
-#define TSIP_PARSED_DATA 3
-#define TSIP_PARSED_DLE_2 4
-
-/*
- * Leap-Insert and Leap-Delete are encoded as follows:
- * PALISADE_UTC_TIME set and PALISADE_LEAP_PENDING set: INSERT leap
- */
-
-#define PALISADE_LEAP_INPROGRESS 0x08 /* This is the leap flag */
-#define PALISADE_LEAP_WARNING 0x04 /* GPS Leap Warning (see ICD-200) */
-#define PALISADE_LEAP_PENDING 0x02 /* Leap Pending (24 hours) */
-#define PALISADE_UTC_TIME 0x01 /* UTC time available */
-
-#define mb(_X_) (up->rpt_buf[(_X_ + 1)]) /* shortcut for buffer access */
-
-/* Conversion Definitions */
-#define GPS_PI (3.1415926535898)
-#define R2D (180.0/GPS_PI)
-
-/*
- * Palisade unit control structure.
- */
-struct palisade_unit {
- short unit; /* NTP refclock unit number */
- int polled; /* flag to detect noreplies */
- char leap_status; /* leap second flag */
- char rpt_status; /* TSIP Parser State */
- short rpt_cnt; /* TSIP packet length so far */
- char rpt_buf[BMAX]; /* packet assembly buffer */
- int type; /* Clock mode type */
-};
-
-/*
- * Function prototypes
- */
-
-static int palisade_start P((int, struct peer *));
-static void palisade_shutdown P((int, struct peer *));
-static void palisade_receive P((struct peer *));
-static void palisade_poll P((int, struct peer *));
-static void palisade_io P((struct recvbuf *));
-int palisade_configure P((int, struct peer *));
-int TSIP_decode P((struct peer *));
-long HW_poll P((struct refclockproc *));
-float getfloat P((u_char *));
-double getdbl P((u_char *));
-short getint P((u_char *));
-
-#endif /* PALISADE_H */
diff --git a/contrib/ntp/ntpd/refclock_parse.c b/contrib/ntp/ntpd/refclock_parse.c
deleted file mode 100644
index 52fadaa..0000000
--- a/contrib/ntp/ntpd/refclock_parse.c
+++ /dev/null
@@ -1,5386 +0,0 @@
-/*
- * /src/NTP/ntp-4/ntpd/refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A
- *
- * refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A
- *
- * generic reference clock driver for receivers
- *
- * optionally 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
- *
- * the STREAMS module is not required for operation and may be omitted
- * at the cost of reduced accuracy. As new kernel interfaces emerger this
- * restriction may be lifted in future.
- *
- * Copyright (c) 1995-1999 by Frank Kardel <kardel@acm.org>
- * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
- *
- * This software may not be sold for profit without a written consent
- * from the author.
- *
- * 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.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_PARSE)
-
-/*
- * This driver currently provides the support for
- * - Meinberg receiver DCF77 PZF 535 (TCXO version) (DCF)
- * - Meinberg receiver DCF77 PZF 535 (OCXO version) (DCF)
- * - Meinberg receiver DCF77 PZF 509 (DCF)
- * - Meinberg receiver DCF77 AM receivers (e.g. C51) (DCF)
- * - IGEL CLOCK (DCF)
- * - ELV DCF7000 (DCF)
- * - Schmid clock (DCF)
- * - Conrad DCF77 receiver module (DCF)
- * - FAU DCF77 NTP receiver (TimeBrick) (DCF)
- *
- * - Meinberg GPS166/GPS167 (GPS)
- * - Trimble (TSIP and TAIP protocol) (GPS)
- *
- * - RCC8000 MSF Receiver (MSF)
- * - WHARTON 400A Series clock (DCF)
- * - VARITEXT clock (MSF)
- */
-
-/*
- * Meinberg receivers are usually connected via a
- * 9600 baud serial line
- *
- * The Meinberg GPS receivers also have a special NTP time stamp
- * format. The firmware release is Uni-Erlangen.
- *
- * Meinberg generic receiver setup:
- * output time code every second
- * Baud rate 9600 7E2S
- *
- * Meinberg GPS16x setup:
- * output time code every second
- * Baudrate 19200 8N1
- *
- * This software supports the standard data formats used
- * in Meinberg receivers.
- *
- * Special software versions are only sensible for the
- * GPS 16x family of receivers.
- *
- * Meinberg can be reached via: http://www.meinberg.de/
- */
-
-#include "ntpd.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h" /* includes <sys/time.h> */
-#include "ntp_control.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#ifndef TM_IN_SYS_TIME
-# include <time.h>
-#endif
-
-#if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)
-# include "Bletch: Define one of {STREAM,HAVE_SYSV_TTYS,HAVE_TERMIOS}"
-#endif
-
-#ifdef STREAM
-# include <sys/stream.h>
-# include <sys/stropts.h>
-#endif
-
-#ifdef HAVE_TERMIOS
-# 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
-# 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 */
-# include "Bletch: BSD TTY not currently supported"
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif
-
-#ifdef PPS
-#ifdef HAVE_SYS_PPSCLOCK_H
-#include <sys/ppsclock.h>
-#endif
-#ifdef HAVE_TIO_SERIAL_STUFF
-#include <linux/serial.h>
-#endif
-#endif
-
-#include "ntp_io.h"
-#include "ntp_stdlib.h"
-
-#include "parse.h"
-#include "mbg_gps166.h"
-#include "trimble.h"
-#include "binio.h"
-#include "ascii.h"
-#include "ieee754io.h"
-
-static char rcsid[]="refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A";
-
-/**===========================================================================
- ** external interface to ntp mechanism
- **/
-
-static void parse_init P((void));
-static int parse_start P((int, struct peer *));
-static void parse_shutdown P((int, struct peer *));
-static void parse_poll P((int, struct peer *));
-static void parse_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
-
-#define parse_buginfo noentry
-
-struct refclock refclock_parse = {
- parse_start,
- parse_shutdown,
- parse_poll,
- parse_control,
- parse_init,
- parse_buginfo,
- NOFLAGS
-};
-
-/*
- * Definitions
- */
-#define MAXUNITS 4 /* maximum number of "PARSE" units permitted */
-#define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */
-
-#undef ABS
-#define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_))
-
-/**===========================================================================
- ** function vector for dynamically binding io handling mechanism
- **/
-
-struct parseunit; /* to keep inquiring minds happy */
-
-typedef struct bind
-{
- const char *bd_description; /* name of type of binding */
- int (*bd_init) P((struct parseunit *)); /* initialize */
- void (*bd_end) P((struct parseunit *)); /* end */
- int (*bd_setcs) P((struct parseunit *, parsectl_t *)); /* set character size */
- int (*bd_disable) P((struct parseunit *)); /* disable */
- int (*bd_enable) P((struct parseunit *)); /* enable */
- int (*bd_getfmt) P((struct parseunit *, parsectl_t *)); /* get format */
- int (*bd_setfmt) P((struct parseunit *, parsectl_t *)); /* setfmt */
- int (*bd_timecode) P((struct parseunit *, parsectl_t *)); /* get time code */
- void (*bd_receive) P((struct recvbuf *)); /* receive operation */
- int (*bd_io_input) P((struct recvbuf *)); /* input 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_GETTIMECODE(_X_, _DCT_) (*(_X_)->binding->bd_timecode)(_X_, _DCT_)
-
-/*
- * io modes
- */
-#define PARSE_F_PPSPPS 0x0001 /* use loopfilter PPS code (CIOGETEV) */
-#define PARSE_F_PPSONSECOND 0x0002 /* PPS pulses are on second */
-
-
-/**===========================================================================
- ** error message regression handling
- **
- ** there are quite a few errors that can occur in rapid succession such as
- ** noisy input data or no data at all. in order to reduce the amount of
- ** syslog messages in such case, we are using a backoff algorithm. We limit
- ** the number of error messages of a certain class to 1 per time unit. if a
- ** configurable number of messages is displayed that way, we move on to the
- ** next time unit / count for that class. a count of messages that have been
- ** suppressed is held and displayed whenever a corresponding message is
- ** displayed. the time units for a message class will also be displayed.
- ** whenever an error condition clears we reset the error message state,
- ** thus we would still generate much output on pathological conditions
- ** where the system oscillates between OK and NOT OK states. coping
- ** with that condition is currently considered too complicated.
- **/
-
-#define ERR_ALL (unsigned)~0 /* "all" errors */
-#define ERR_BADDATA (unsigned)0 /* unusable input data/conversion errors */
-#define ERR_NODATA (unsigned)1 /* no input data */
-#define ERR_BADIO (unsigned)2 /* read/write/select errors */
-#define ERR_BADSTATUS (unsigned)3 /* unsync states */
-#define ERR_BADEVENT (unsigned)4 /* non nominal events */
-#define ERR_INTERNAL (unsigned)5 /* internal error */
-#define ERR_CNT (unsigned)(ERR_INTERNAL+1)
-
-#define ERR(_X_) if (list_err(parse, (_X_)))
-
-struct errorregression
-{
- u_long err_count; /* number of repititions per class */
- u_long err_delay; /* minimum delay between messages */
-};
-
-static struct errorregression
-err_baddata[] = /* error messages for bad input data */
-{
- { 1, 0 }, /* output first message immediately */
- { 5, 60 }, /* output next five messages in 60 second intervals */
- { 3, 3600 }, /* output next 3 messages in hour intervals */
- { 0, 12*3600 } /* repeat messages only every 12 hours */
-};
-
-static struct errorregression
-err_nodata[] = /* error messages for missing input data */
-{
- { 1, 0 }, /* output first message immediately */
- { 5, 60 }, /* output next five messages in 60 second intervals */
- { 3, 3600 }, /* output next 3 messages in hour intervals */
- { 0, 12*3600 } /* repeat messages only every 12 hours */
-};
-
-static struct errorregression
-err_badstatus[] = /* unsynchronized state messages */
-{
- { 1, 0 }, /* output first message immediately */
- { 5, 60 }, /* output next five messages in 60 second intervals */
- { 3, 3600 }, /* output next 3 messages in hour intervals */
- { 0, 12*3600 } /* repeat messages only every 12 hours */
-};
-
-static struct errorregression
-err_badio[] = /* io failures (bad reads, selects, ...) */
-{
- { 1, 0 }, /* output first message immediately */
- { 5, 60 }, /* output next five messages in 60 second intervals */
- { 5, 3600 }, /* output next 3 messages in hour intervals */
- { 0, 12*3600 } /* repeat messages only every 12 hours */
-};
-
-static struct errorregression
-err_badevent[] = /* non nominal events */
-{
- { 20, 0 }, /* output first message immediately */
- { 6, 60 }, /* output next five messages in 60 second intervals */
- { 5, 3600 }, /* output next 3 messages in hour intervals */
- { 0, 12*3600 } /* repeat messages only every 12 hours */
-};
-
-static struct errorregression
-err_internal[] = /* really bad things - basically coding/OS errors */
-{
- { 0, 0 }, /* output all messages immediately */
-};
-
-static struct errorregression *
-err_tbl[] =
-{
- err_baddata,
- err_nodata,
- err_badio,
- err_badstatus,
- err_badevent,
- err_internal
-};
-
-struct errorinfo
-{
- u_long err_started; /* begin time (ntp) of error condition */
- u_long err_last; /* last time (ntp) error occurred */
- u_long err_cnt; /* number of error repititions */
- u_long err_suppressed; /* number of suppressed messages */
- struct errorregression *err_stage; /* current error stage */
-};
-
-/**===========================================================================
- ** refclock instance data
- **/
-
-struct parseunit
-{
- /*
- * NTP management
- */
- struct peer *peer; /* backlink to peer structure - refclock inactive if 0 */
- struct refclockproc *generic; /* backlink to refclockproc structure */
-
- /*
- * PARSE io
- */
- bind_t *binding; /* io handling binding */
-
- /*
- * parse state
- */
- parse_t parseio; /* io handling structure (user level parsing) */
-
- /*
- * type specific parameters
- */
- struct parse_clockinfo *parse_type; /* link to clock description */
-
- /*
- * clock state handling/reporting
- */
- u_char flags; /* flags (leap_control) */
- u_long lastchange; /* time (ntp) when last state change accured */
- u_long statetime[CEVNT_MAX+1]; /* accumulated time of clock states */
- u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */
- u_short lastformat; /* last format used */
- u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */
- u_long lastmissed; /* time (ntp) 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, receiver-specific data */
- unsigned long localstate; /* private local state */
- struct errorinfo errors[ERR_CNT]; /* error state table for suppressing excessive error messages */
- struct ctl_var *kv; /* additional pseudo variables */
- u_long laststatistic; /* time when staticstics where output */
-};
-
-
-/**===========================================================================
- ** Clockinfo section all parameter for specific clock types
- ** includes NTP parameters, TTY parameters and IO handling parameters
- **/
-
-static void poll_dpoll P((struct parseunit *));
-static void poll_poll P((struct peer *));
-static int poll_init P((struct parseunit *));
-
-typedef struct poll_info
-{
- u_long rate; /* poll rate - once every "rate" seconds - 0 off */
- const char *string; /* string to send for polling */
- u_long count; /* number of characters in string */
-} poll_info_t;
-
-#define NO_CL_FLAGS 0
-#define NO_POLL 0
-#define NO_INIT 0
-#define NO_END 0
-#define NO_EVENT 0
-#define NO_DATA 0
-#define NO_MESSAGE 0
-#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 0.0
-#define NOCLOCK_BASEDELAY 0.0
-#define NOCLOCK_DESCRIPTION 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 ""
-#define NOCLOCK_TYPE CTL_SST_TS_UNSPEC
-#define NOCLOCK_SAMPLES 0
-#define NOCLOCK_KEEP 0
-
-#define DCF_TYPE CTL_SST_TS_LF
-#define GPS_TYPE CTL_SST_TS_UHF
-
-/*
- * receiver specific constants
- */
-#define MBG_SPEED (B9600)
-#define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL)
-#define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)
-#define MBG_OFLAG 0
-#define MBG_LFLAG 0
-#define MBG_FLAGS PARSE_F_PPSONSECOND
-
-/*
- * Meinberg DCF77 receivers
- */
-#define DCFUA31_ROOTDELAY 0.0 /* 0 */
-#define DCFUA31_BASEDELAY 0.010 /* 10.7421875ms: 10 ms (+/- 3 ms) */
-#define DCFUA31_DESCRIPTION "Meinberg DCF77 C51 or compatible"
-#define DCFUA31_MAXUNSYNC 60*30 /* only trust clock for 1/2 hour */
-#define DCFUA31_SPEED MBG_SPEED
-#define DCFUA31_CFLAG MBG_CFLAG
-#define DCFUA31_IFLAG MBG_IFLAG
-#define DCFUA31_OFLAG MBG_OFLAG
-#define DCFUA31_LFLAG MBG_LFLAG
-#define DCFUA31_SAMPLES 5
-#define DCFUA31_KEEP 3
-#define DCFUA31_FORMAT "Meinberg Standard"
-
-/*
- * Meinberg DCF PZF535/TCXO (FM/PZF) receiver
- */
-#define DCFPZF535_ROOTDELAY 0.0
-#define DCFPZF535_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
-#define DCFPZF535_DESCRIPTION "Meinberg DCF PZF 535/509 / 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_SPEED MBG_SPEED
-#define DCFPZF535_CFLAG MBG_CFLAG
-#define DCFPZF535_IFLAG MBG_IFLAG
-#define DCFPZF535_OFLAG MBG_OFLAG
-#define DCFPZF535_LFLAG MBG_LFLAG
-#define DCFPZF535_SAMPLES 5
-#define DCFPZF535_KEEP 3
-#define DCFPZF535_FORMAT "Meinberg Standard"
-
-/*
- * Meinberg DCF PZF535/OCXO receiver
- */
-#define DCFPZF535OCXO_ROOTDELAY 0.0
-#define DCFPZF535OCXO_BASEDELAY 0.001968 /* 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
-#define DCFPZF535OCXO_DESCRIPTION "Meinberg DCF PZF 535/509 / 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_SPEED MBG_SPEED
-#define DCFPZF535OCXO_CFLAG MBG_CFLAG
-#define DCFPZF535OCXO_IFLAG MBG_IFLAG
-#define DCFPZF535OCXO_OFLAG MBG_OFLAG
-#define DCFPZF535OCXO_LFLAG MBG_LFLAG
-#define DCFPZF535OCXO_SAMPLES 5
-#define DCFPZF535OCXO_KEEP 3
-#define DCFPZF535OCXO_FORMAT "Meinberg Standard"
-
-/*
- * Meinberg GPS16X receiver
- */
-static void gps16x_message P((struct parseunit *, parsetime_t *));
-static int gps16x_poll_init P((struct parseunit *));
-
-#define GPS16X_ROOTDELAY 0.0 /* nothing here */
-#define GPS16X_BASEDELAY 0.001968 /* XXX to be fixed ! 1.968ms +- 104us (oscilloscope) - relative to start (end of STX) */
-#define GPS16X_DESCRIPTION "Meinberg GPS16x receiver"
-#define GPS16X_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 GPS16X_SPEED B19200
-#define GPS16X_CFLAG (CS8|CREAD|CLOCAL|HUPCL)
-#define GPS16X_IFLAG (IGNBRK|IGNPAR)
-#define GPS16X_OFLAG MBG_OFLAG
-#define GPS16X_LFLAG MBG_LFLAG
-#define GPS16X_POLLRATE 6
-#define GPS16X_POLLCMD ""
-#define GPS16X_CMDSIZE 0
-
-static poll_info_t gps16x_pollinfo = { GPS16X_POLLRATE, GPS16X_POLLCMD, GPS16X_CMDSIZE };
-
-#define GPS16X_INIT gps16x_poll_init
-#define GPS16X_POLL 0
-#define GPS16X_END 0
-#define GPS16X_DATA ((void *)(&gps16x_pollinfo))
-#define GPS16X_MESSAGE gps16x_message
-#define GPS16X_ID GPS_ID
-#define GPS16X_FORMAT "Meinberg GPS Extended"
-#define GPS16X_SAMPLES 5
-#define GPS16X_KEEP 3
-
-/*
- * ELV DCF7000 Wallclock-Receiver/Switching Clock (Kit)
- *
- * This is really not the hottest clock - but before you have nothing ...
- */
-#define DCF7000_ROOTDELAY 0.0 /* 0 */
-#define DCF7000_BASEDELAY 0.405 /* slow blow */
-#define DCF7000_DESCRIPTION "ELV DCF7000"
-#define DCF7000_MAXUNSYNC (60*5) /* sorry - but it just was not build as a clock */
-#define DCF7000_SPEED (B9600)
-#define DCF7000_CFLAG (CS8|CREAD|PARENB|PARODD|CLOCAL|HUPCL)
-#define DCF7000_IFLAG (IGNBRK)
-#define DCF7000_OFLAG 0
-#define DCF7000_LFLAG 0
-#define DCF7000_SAMPLES 5
-#define DCF7000_KEEP 3
-#define DCF7000_FORMAT "ELV DCF7000"
-
-/*
- * 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 0
-#define WSDCF_DATA ((void *)(&wsdcf_pollinfo))
-#define WSDCF_ROOTDELAY 0.0 /* 0 */
-#define WSDCF_BASEDELAY 0.010 /* ~ 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_SPEED (B1200)
-#define WSDCF_CFLAG (CS8|CREAD|CLOCAL)
-#define WSDCF_IFLAG 0
-#define WSDCF_OFLAG 0
-#define WSDCF_LFLAG 0
-#define WSDCF_SAMPLES 5
-#define WSDCF_KEEP 3
-
-/*
- * RAW DCF77 - input of DCF marks via RS232 - many variants
- */
-#define RAWDCF_FLAGS 0
-#define RAWDCF_ROOTDELAY 0.0 /* 0 */
-#define RAWDCF_BASEDELAY 0.258
-#define RAWDCF_FORMAT "RAW DCF77 Timecode"
-#define RAWDCF_MAXUNSYNC (0) /* sorry - its a true receiver - no signal - no time */
-#define RAWDCF_SPEED (B50)
-#ifdef NO_PARENB_IGNPAR /* Was: defined(SYS_IRIX4) || defined(SYS_IRIX5) */
-/* somehow doesn't grok PARENB & IGNPAR (mj) */
-# define RAWDCF_CFLAG (CS8|CREAD|CLOCAL)
-#else
-# define RAWDCF_CFLAG (CS8|CREAD|CLOCAL|PARENB)
-#endif
-#ifdef RAWDCF_NO_IGNPAR /* Was: defined(SYS_LINUX) && defined(CLOCK_RAWDCF) */
-# define RAWDCF_IFLAG 0
-#else
-# define RAWDCF_IFLAG (IGNPAR)
-#endif
-#define RAWDCF_OFLAG 0
-#define RAWDCF_LFLAG 0
-#define RAWDCF_SAMPLES 20
-#define RAWDCF_KEEP 12
-#define RAWDCF_INIT 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 0.292 /* Conrad receiver @ 50 Baud on a Sun */
-#define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)"
-
-/*
- * TimeBrick receiver
- */
-#define TIMEBRICK_BASEDELAY 0.210 /* TimeBrick @ 50 Baud on a Sun */
-#define TIMEBRICK_DESCRIPTION "RAW DCF77 CODE (TimeBrick)"
-
-/*
- * IGEL:clock receiver
- */
-#define IGELCLOCK_BASEDELAY 0.258 /* IGEL:clock receiver */
-#define IGELCLOCK_DESCRIPTION "RAW DCF77 CODE (IGEL:clock)"
-#define IGELCLOCK_SPEED (B1200)
-#define IGELCLOCK_CFLAG (CS8|CREAD|HUPCL|CLOCAL)
-
-/*
- * RAWDCF receivers that need to be powered from DTR
- * (like Expert mouse clock)
- */
-static int rawdcf_init_1 P((struct parseunit *));
-#define RAWDCFDTRSET_DESCRIPTION "RAW DCF77 CODE (DTR SET/RTS CLR)"
-#define RAWDCFDTRSET_INIT rawdcf_init_1
-
-/*
- * RAWDCF receivers that need to be powered from
- * DTR CLR and RTS SET
- */
-static int rawdcf_init_2 P((struct parseunit *));
-#define RAWDCFDTRCLRRTSSET_DESCRIPTION "RAW DCF77 CODE (DTR CLR/RTS SET)"
-#define RAWDCFDTRCLRRTSSET_INIT rawdcf_init_2
-
-/*
- * Trimble GPS receivers (TAIP and TSIP protocols)
- */
-#ifndef TRIM_POLLRATE
-#define TRIM_POLLRATE 0 /* only true direct polling */
-#endif
-
-#define TRIM_TAIPPOLLCMD ">SRM;FR_FLAG=F;EC_FLAG=F<>QTM<"
-#define TRIM_TAIPCMDSIZE (sizeof(TRIM_TAIPPOLLCMD)-1)
-
-static poll_info_t trimbletaip_pollinfo = { TRIM_POLLRATE, TRIM_TAIPPOLLCMD, TRIM_TAIPCMDSIZE };
-static int trimbletaip_init P((struct parseunit *));
-static void trimbletaip_event P((struct parseunit *, int));
-
-/* 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 *));
-static void trimbletsip_end P((struct parseunit *));
-static void trimbletsip_message P((struct parseunit *, parsetime_t *));
-static void trimbletsip_event P((struct parseunit *, int));
-
-#define TRIMBLETSIP_IDLE_TIME (300) /* 5 minutes silence at most */
-
-#define TRIMBLETAIP_SPEED (B4800)
-#define TRIMBLETAIP_CFLAG (CS8|CREAD|CLOCAL)
-#define TRIMBLETAIP_IFLAG (BRKINT|IGNPAR|ISTRIP|ICRNL|IXON)
-#define TRIMBLETAIP_OFLAG (OPOST|ONLCR)
-#define TRIMBLETAIP_LFLAG (0)
-
-#define TRIMBLETSIP_SPEED (B9600)
-#define TRIMBLETSIP_CFLAG (CS8|CLOCAL|CREAD|PARENB|PARODD)
-#define TRIMBLETSIP_IFLAG (IGNBRK)
-#define TRIMBLETSIP_OFLAG (0)
-#define TRIMBLETSIP_LFLAG (ICANON)
-
-#define TRIMBLETSIP_SAMPLES 5
-#define TRIMBLETSIP_KEEP 3
-#define TRIMBLETAIP_SAMPLES 5
-#define TRIMBLETAIP_KEEP 3
-
-#define TRIMBLETAIP_FLAGS (PARSE_F_PPSONSECOND)
-#define TRIMBLETSIP_FLAGS (TRIMBLETAIP_FLAGS)
-
-#define TRIMBLETAIP_POLL poll_dpoll
-#define TRIMBLETSIP_POLL poll_dpoll
-
-#define TRIMBLETAIP_INIT trimbletaip_init
-#define TRIMBLETSIP_INIT trimbletsip_init
-
-#define TRIMBLETAIP_EVENT trimbletaip_event
-
-#define TRIMBLETSIP_EVENT trimbletsip_event
-#define TRIMBLETSIP_MESSAGE trimbletsip_message
-
-#define TRIMBLETAIP_END 0
-#define TRIMBLETSIP_END trimbletsip_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 "Trimble TAIP"
-#define TRIMBLETSIP_FORMAT "Trimble TSIP"
-
-#define TRIMBLETAIP_ROOTDELAY 0x0
-#define TRIMBLETSIP_ROOTDELAY 0x0
-
-#define TRIMBLETAIP_BASEDELAY 0.0
-#define TRIMBLETSIP_BASEDELAY 0.020 /* 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 '<'
-
-/*
- * RadioCode Clocks RCC 800 receiver
- */
-#define RCC_POLLRATE 0 /* only true direct polling */
-#define RCC_POLLCMD "\r"
-#define RCC_CMDSIZE 1
-
-static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE };
-#define RCC8000_FLAGS 0
-#define RCC8000_POLL poll_dpoll
-#define RCC8000_INIT poll_init
-#define RCC8000_END 0
-#define RCC8000_DATA ((void *)(&rcc8000_pollinfo))
-#define RCC8000_ROOTDELAY 0.0
-#define RCC8000_BASEDELAY 0.0
-#define RCC8000_ID "MSF"
-#define RCC8000_DESCRIPTION "RCC 8000 MSF Receiver"
-#define RCC8000_FORMAT "Radiocode RCC8000"
-#define RCC8000_MAXUNSYNC (60*60) /* should be ok for an hour */
-#define RCC8000_SPEED (B2400)
-#define RCC8000_CFLAG (CS8|CREAD|CLOCAL)
-#define RCC8000_IFLAG (IGNBRK|IGNPAR)
-#define RCC8000_OFLAG 0
-#define RCC8000_LFLAG 0
-#define RCC8000_SAMPLES 5
-#define RCC8000_KEEP 3
-
-/*
- * Hopf Radio clock 6021 Format
- *
- */
-#define HOPF6021_ROOTDELAY 0.0
-#define HOPF6021_BASEDELAY 0.0
-#define HOPF6021_DESCRIPTION "HOPF 6021"
-#define HOPF6021_FORMAT "hopf Funkuhr 6021"
-#define HOPF6021_MAXUNSYNC (60*60) /* should be ok for an hour */
-#define HOPF6021_SPEED (B9600)
-#define HOPF6021_CFLAG (CS8|CREAD|CLOCAL)
-#define HOPF6021_IFLAG (IGNBRK|ISTRIP)
-#define HOPF6021_OFLAG 0
-#define HOPF6021_LFLAG 0
-#define HOPF6021_FLAGS 0
-#define HOPF6021_SAMPLES 5
-#define HOPF6021_KEEP 3
-
-/*
- * Diem's Computime Radio Clock Receiver
- */
-#define COMPUTIME_FLAGS 0
-#define COMPUTIME_ROOTDELAY 0.0
-#define COMPUTIME_BASEDELAY 0.0
-#define COMPUTIME_ID DCF_ID
-#define COMPUTIME_DESCRIPTION "Diem's Computime receiver"
-#define COMPUTIME_FORMAT "Diem's Computime Radio Clock"
-#define COMPUTIME_TYPE DCF_TYPE
-#define COMPUTIME_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
-#define COMPUTIME_SPEED (B9600)
-#define COMPUTIME_CFLAG (CSTOPB|CS7|CREAD|CLOCAL)
-#define COMPUTIME_IFLAG (IGNBRK|IGNPAR|ISTRIP)
-#define COMPUTIME_OFLAG 0
-#define COMPUTIME_LFLAG 0
-#define COMPUTIME_SAMPLES 5
-#define COMPUTIME_KEEP 3
-
-/*
- * Varitext Radio Clock Receiver
- */
-#define VARITEXT_FLAGS 0
-#define VARITEXT_ROOTDELAY 0.0
-#define VARITEXT_BASEDELAY 0.0
-#define VARITEXT_ID "MSF"
-#define VARITEXT_DESCRIPTION "Varitext receiver"
-#define VARITEXT_FORMAT "Varitext Radio Clock"
-#define VARITEXT_TYPE DCF_TYPE
-#define VARITEXT_MAXUNSYNC (60*60) /* only trust clock for 1 hour */
-#define VARITEXT_SPEED (B9600)
-#define VARITEXT_CFLAG (CS7|CREAD|CLOCAL|PARENB|PARODD)
-#define VARITEXT_IFLAG (IGNPAR|IGNBRK|INPCK) /*|ISTRIP)*/
-#define VARITEXT_OFLAG 0
-#define VARITEXT_LFLAG 0
-#define VARITEXT_SAMPLES 32
-#define VARITEXT_KEEP 20
-
-static struct parse_clockinfo
-{
- u_long cl_flags; /* operation flags (io modes) */
- void (*cl_poll) P((struct parseunit *)); /* active poll routine */
- int (*cl_init) P((struct parseunit *)); /* active poll init routine */
- void (*cl_event) P((struct parseunit *, int)); /* special event handling (e.g. reset clock) */
- void (*cl_end) P((struct parseunit *)); /* active poll end routine */
- void (*cl_message) P((struct parseunit *, parsetime_t *)); /* process a lower layer message */
- void *cl_data; /* local data area for "poll" mechanism */
- double cl_rootdelay; /* rootdelay */
- double cl_basedelay; /* current offset by which the RS232
- time code is delayed from the actual time */
- const char *cl_id; /* ID code */
- const char *cl_description; /* device name */
- const char *cl_format; /* fixed format */
- u_char cl_type; /* clock type (ntp control) */
- u_long cl_maxunsync; /* time to trust oscillator after losing synch */
- u_long cl_speed; /* terminal input & output baudrate */
- u_long cl_cflag; /* terminal control flags */
- u_long cl_iflag; /* terminal input flags */
- u_long cl_oflag; /* terminal output flags */
- u_long cl_lflag; /* terminal local flags */
- u_long cl_samples; /* samples for median filter */
- u_long cl_keep; /* samples for median filter to keep */
-} parse_clockinfo[] =
-{
- { /* mode 0 */
- MBG_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- DCFPZF535_ROOTDELAY,
- DCFPZF535_BASEDELAY,
- DCF_P_ID,
- DCFPZF535_DESCRIPTION,
- DCFPZF535_FORMAT,
- DCF_TYPE,
- DCFPZF535_MAXUNSYNC,
- DCFPZF535_SPEED,
- DCFPZF535_CFLAG,
- DCFPZF535_IFLAG,
- DCFPZF535_OFLAG,
- DCFPZF535_LFLAG,
- DCFPZF535_SAMPLES,
- DCFPZF535_KEEP
- },
- { /* mode 1 */
- MBG_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- DCFPZF535OCXO_ROOTDELAY,
- DCFPZF535OCXO_BASEDELAY,
- DCF_P_ID,
- DCFPZF535OCXO_DESCRIPTION,
- DCFPZF535OCXO_FORMAT,
- DCF_TYPE,
- DCFPZF535OCXO_MAXUNSYNC,
- DCFPZF535OCXO_SPEED,
- DCFPZF535OCXO_CFLAG,
- DCFPZF535OCXO_IFLAG,
- DCFPZF535OCXO_OFLAG,
- DCFPZF535OCXO_LFLAG,
- DCFPZF535OCXO_SAMPLES,
- DCFPZF535OCXO_KEEP
- },
- { /* mode 2 */
- MBG_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- DCFUA31_ROOTDELAY,
- DCFUA31_BASEDELAY,
- DCF_A_ID,
- DCFUA31_DESCRIPTION,
- DCFUA31_FORMAT,
- DCF_TYPE,
- DCFUA31_MAXUNSYNC,
- DCFUA31_SPEED,
- DCFUA31_CFLAG,
- DCFUA31_IFLAG,
- DCFUA31_OFLAG,
- DCFUA31_LFLAG,
- DCFUA31_SAMPLES,
- DCFUA31_KEEP
- },
- { /* mode 3 */
- MBG_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- DCF7000_ROOTDELAY,
- DCF7000_BASEDELAY,
- DCF_A_ID,
- DCF7000_DESCRIPTION,
- DCF7000_FORMAT,
- DCF_TYPE,
- DCF7000_MAXUNSYNC,
- DCF7000_SPEED,
- DCF7000_CFLAG,
- DCF7000_IFLAG,
- DCF7000_OFLAG,
- DCF7000_LFLAG,
- DCF7000_SAMPLES,
- DCF7000_KEEP
- },
- { /* mode 4 */
- NO_CL_FLAGS,
- WSDCF_POLL,
- WSDCF_INIT,
- NO_EVENT,
- WSDCF_END,
- NO_MESSAGE,
- WSDCF_DATA,
- WSDCF_ROOTDELAY,
- WSDCF_BASEDELAY,
- DCF_A_ID,
- WSDCF_DESCRIPTION,
- WSDCF_FORMAT,
- DCF_TYPE,
- WSDCF_MAXUNSYNC,
- WSDCF_SPEED,
- WSDCF_CFLAG,
- WSDCF_IFLAG,
- WSDCF_OFLAG,
- WSDCF_LFLAG,
- WSDCF_SAMPLES,
- WSDCF_KEEP
- },
- { /* mode 5 */
- RAWDCF_FLAGS,
- NO_POLL,
- RAWDCF_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- RAWDCF_ROOTDELAY,
- CONRAD_BASEDELAY,
- DCF_A_ID,
- CONRAD_DESCRIPTION,
- RAWDCF_FORMAT,
- DCF_TYPE,
- RAWDCF_MAXUNSYNC,
- RAWDCF_SPEED,
- RAWDCF_CFLAG,
- RAWDCF_IFLAG,
- RAWDCF_OFLAG,
- RAWDCF_LFLAG,
- RAWDCF_SAMPLES,
- RAWDCF_KEEP
- },
- { /* mode 6 */
- RAWDCF_FLAGS,
- NO_POLL,
- RAWDCF_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- RAWDCF_ROOTDELAY,
- TIMEBRICK_BASEDELAY,
- DCF_A_ID,
- TIMEBRICK_DESCRIPTION,
- RAWDCF_FORMAT,
- DCF_TYPE,
- RAWDCF_MAXUNSYNC,
- RAWDCF_SPEED,
- RAWDCF_CFLAG,
- RAWDCF_IFLAG,
- RAWDCF_OFLAG,
- RAWDCF_LFLAG,
- RAWDCF_SAMPLES,
- RAWDCF_KEEP
- },
- { /* mode 7 */
- MBG_FLAGS,
- GPS16X_POLL,
- GPS16X_INIT,
- NO_EVENT,
- GPS16X_END,
- GPS16X_MESSAGE,
- GPS16X_DATA,
- GPS16X_ROOTDELAY,
- GPS16X_BASEDELAY,
- GPS16X_ID,
- GPS16X_DESCRIPTION,
- GPS16X_FORMAT,
- GPS_TYPE,
- GPS16X_MAXUNSYNC,
- GPS16X_SPEED,
- GPS16X_CFLAG,
- GPS16X_IFLAG,
- GPS16X_OFLAG,
- GPS16X_LFLAG,
- GPS16X_SAMPLES,
- GPS16X_KEEP
- },
- { /* mode 8 */
- RAWDCF_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- RAWDCF_ROOTDELAY,
- IGELCLOCK_BASEDELAY,
- DCF_A_ID,
- IGELCLOCK_DESCRIPTION,
- RAWDCF_FORMAT,
- DCF_TYPE,
- RAWDCF_MAXUNSYNC,
- IGELCLOCK_SPEED,
- IGELCLOCK_CFLAG,
- RAWDCF_IFLAG,
- RAWDCF_OFLAG,
- RAWDCF_LFLAG,
- RAWDCF_SAMPLES,
- RAWDCF_KEEP
- },
- { /* mode 9 */
- TRIMBLETAIP_FLAGS,
-#if TRIM_POLLRATE /* DHD940515: Allow user config */
- NO_POLL,
-#else
- TRIMBLETAIP_POLL,
-#endif
- TRIMBLETAIP_INIT,
- TRIMBLETAIP_EVENT,
- TRIMBLETAIP_END,
- NO_MESSAGE,
- TRIMBLETAIP_DATA,
- TRIMBLETAIP_ROOTDELAY,
- TRIMBLETAIP_BASEDELAY,
- TRIMBLETAIP_ID,
- TRIMBLETAIP_DESCRIPTION,
- TRIMBLETAIP_FORMAT,
- GPS_TYPE,
- TRIMBLETAIP_MAXUNSYNC,
- TRIMBLETAIP_SPEED,
- TRIMBLETAIP_CFLAG,
- TRIMBLETAIP_IFLAG,
- TRIMBLETAIP_OFLAG,
- TRIMBLETAIP_LFLAG,
- TRIMBLETAIP_SAMPLES,
- TRIMBLETAIP_KEEP
- },
- { /* mode 10 */
- TRIMBLETSIP_FLAGS,
-#if TRIM_POLLRATE /* DHD940515: Allow user config */
- NO_POLL,
-#else
- TRIMBLETSIP_POLL,
-#endif
- TRIMBLETSIP_INIT,
- TRIMBLETSIP_EVENT,
- TRIMBLETSIP_END,
- TRIMBLETSIP_MESSAGE,
- TRIMBLETSIP_DATA,
- TRIMBLETSIP_ROOTDELAY,
- TRIMBLETSIP_BASEDELAY,
- TRIMBLETSIP_ID,
- TRIMBLETSIP_DESCRIPTION,
- TRIMBLETSIP_FORMAT,
- GPS_TYPE,
- TRIMBLETSIP_MAXUNSYNC,
- TRIMBLETSIP_SPEED,
- TRIMBLETSIP_CFLAG,
- TRIMBLETSIP_IFLAG,
- TRIMBLETSIP_OFLAG,
- TRIMBLETSIP_LFLAG,
- TRIMBLETSIP_SAMPLES,
- TRIMBLETSIP_KEEP
- },
- { /* mode 11 */
- NO_CL_FLAGS,
- RCC8000_POLL,
- RCC8000_INIT,
- NO_EVENT,
- RCC8000_END,
- NO_MESSAGE,
- RCC8000_DATA,
- RCC8000_ROOTDELAY,
- RCC8000_BASEDELAY,
- RCC8000_ID,
- RCC8000_DESCRIPTION,
- RCC8000_FORMAT,
- DCF_TYPE,
- RCC8000_MAXUNSYNC,
- RCC8000_SPEED,
- RCC8000_CFLAG,
- RCC8000_IFLAG,
- RCC8000_OFLAG,
- RCC8000_LFLAG,
- RCC8000_SAMPLES,
- RCC8000_KEEP
- },
- { /* mode 12 */
- HOPF6021_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- HOPF6021_ROOTDELAY,
- HOPF6021_BASEDELAY,
- DCF_ID,
- HOPF6021_DESCRIPTION,
- HOPF6021_FORMAT,
- DCF_TYPE,
- HOPF6021_MAXUNSYNC,
- HOPF6021_SPEED,
- HOPF6021_CFLAG,
- HOPF6021_IFLAG,
- HOPF6021_OFLAG,
- HOPF6021_LFLAG,
- HOPF6021_SAMPLES,
- HOPF6021_KEEP
- },
- { /* mode 13 */
- COMPUTIME_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- COMPUTIME_ROOTDELAY,
- COMPUTIME_BASEDELAY,
- COMPUTIME_ID,
- COMPUTIME_DESCRIPTION,
- COMPUTIME_FORMAT,
- COMPUTIME_TYPE,
- COMPUTIME_MAXUNSYNC,
- COMPUTIME_SPEED,
- COMPUTIME_CFLAG,
- COMPUTIME_IFLAG,
- COMPUTIME_OFLAG,
- COMPUTIME_LFLAG,
- COMPUTIME_SAMPLES,
- COMPUTIME_KEEP
- },
- { /* mode 14 */
- RAWDCF_FLAGS,
- NO_POLL,
- RAWDCFDTRSET_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- RAWDCF_ROOTDELAY,
- RAWDCF_BASEDELAY,
- DCF_A_ID,
- RAWDCFDTRSET_DESCRIPTION,
- RAWDCF_FORMAT,
- DCF_TYPE,
- RAWDCF_MAXUNSYNC,
- RAWDCF_SPEED,
- RAWDCF_CFLAG,
- RAWDCF_IFLAG,
- RAWDCF_OFLAG,
- RAWDCF_LFLAG,
- RAWDCF_SAMPLES,
- RAWDCF_KEEP
- },
- { /* mode 15 */
- 0, /* operation flags (io modes) */
- NO_POLL, /* active poll routine */
- NO_INIT, /* active poll init routine */
- NO_EVENT, /* special event handling (e.g. reset clock) */
- NO_END, /* active poll end routine */
- NO_MESSAGE, /* process a lower layer message */
- NO_DATA, /* local data area for "poll" mechanism */
- 0, /* rootdelay */
- 11.0 /* bits */ / 9600, /* current offset by which the RS232
- time code is delayed from the actual time */
- DCF_ID, /* ID code */
- "WHARTON 400A Series clock", /* device name */
- "WHARTON 400A Series clock Output Format 1", /* fixed format */
- /* Must match a format-name in a libparse/clk_xxx.c file */
- DCF_TYPE, /* clock type (ntp control) */
- (1*60*60), /* time to trust oscillator after losing synch */
- B9600, /* terminal input & output baudrate */
- (CS8|CREAD|PARENB|CLOCAL|HUPCL),/* terminal control flags */
- 0, /* terminal input flags */
- 0, /* terminal output flags */
- 0, /* terminal local flags */
- 5, /* samples for median filter */
- 3, /* samples for median filter to keep */
- },
- { /* mode 16 - RAWDCF RTS set, DTR clr */
- RAWDCF_FLAGS,
- NO_POLL,
- RAWDCFDTRCLRRTSSET_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- RAWDCF_ROOTDELAY,
- RAWDCF_BASEDELAY,
- DCF_A_ID,
- RAWDCFDTRCLRRTSSET_DESCRIPTION,
- RAWDCF_FORMAT,
- DCF_TYPE,
- RAWDCF_MAXUNSYNC,
- RAWDCF_SPEED,
- RAWDCF_CFLAG,
- RAWDCF_IFLAG,
- RAWDCF_OFLAG,
- RAWDCF_LFLAG,
- RAWDCF_SAMPLES,
- RAWDCF_KEEP
- },
- { /* mode 17 */
- VARITEXT_FLAGS,
- NO_POLL,
- NO_INIT,
- NO_EVENT,
- NO_END,
- NO_MESSAGE,
- NO_DATA,
- VARITEXT_ROOTDELAY,
- VARITEXT_BASEDELAY,
- VARITEXT_ID,
- VARITEXT_DESCRIPTION,
- VARITEXT_FORMAT,
- VARITEXT_TYPE,
- VARITEXT_MAXUNSYNC,
- VARITEXT_SPEED,
- VARITEXT_CFLAG,
- VARITEXT_IFLAG,
- VARITEXT_OFLAG,
- VARITEXT_LFLAG,
- VARITEXT_SAMPLES,
- VARITEXT_KEEP
- }
-};
-
-static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
-
-#define CLK_REALTYPE(x) ((int)(((x)->ttl) & 0x7F))
-#define CLK_TYPE(x) ((CLK_REALTYPE(x) >= ncltypes) ? ~0 : CLK_REALTYPE(x))
-#define CLK_UNIT(x) ((int)REFCLOCKUNIT(&(x)->srcadr))
-#define CLK_PPS(x) (((x)->ttl) & 0x80)
-
-/*
- * Other constant stuff
- */
-#define PARSEHSREFID 0x7f7f08ff /* 127.127.8.255 refid for hi strata */
-
-#define PARSESTATISTICS (60*60) /* output state statistics every hour */
-
-static struct parseunit *parseunits[MAXUNITS];
-
-static int notice = 0;
-
-#define PARSE_STATETIME(parse, i) ((parse->generic->currentstatus == 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 *));
-static void clear_err P((struct parseunit *, u_long));
-static int list_err P((struct parseunit *, u_long));
-static char * l_mktime P((u_long));
-
-/**===========================================================================
- ** implementation error message regression module
- **/
-static void
-clear_err(
- struct parseunit *parse,
- u_long lstate
- )
-{
- if (lstate == ERR_ALL)
- {
- int i;
-
- for (i = 0; i < ERR_CNT; i++)
- {
- parse->errors[i].err_stage = err_tbl[i];
- parse->errors[i].err_cnt = 0;
- parse->errors[i].err_last = 0;
- parse->errors[i].err_started = 0;
- parse->errors[i].err_suppressed = 0;
- }
- }
- else
- {
- parse->errors[lstate].err_stage = err_tbl[lstate];
- parse->errors[lstate].err_cnt = 0;
- parse->errors[lstate].err_last = 0;
- parse->errors[lstate].err_started = 0;
- parse->errors[lstate].err_suppressed = 0;
- }
-}
-
-static int
-list_err(
- struct parseunit *parse,
- u_long lstate
- )
-{
- int do_it;
- struct errorinfo *err = &parse->errors[lstate];
-
- if (err->err_started == 0)
- {
- err->err_started = current_time;
- }
-
- do_it = (current_time - err->err_last) >= err->err_stage->err_delay;
-
- if (do_it)
- err->err_cnt++;
-
- if (err->err_stage->err_count &&
- (err->err_cnt >= err->err_stage->err_count))
- {
- err->err_stage++;
- err->err_cnt = 0;
- }
-
- if (!err->err_cnt && do_it)
- msyslog(LOG_INFO, "PARSE receiver #%d: interval for following error message class is at least %s",
- CLK_UNIT(parse->peer), l_mktime(err->err_stage->err_delay));
-
- if (!do_it)
- err->err_suppressed++;
- else
- err->err_last = current_time;
-
- if (do_it && err->err_suppressed)
- {
- msyslog(LOG_INFO, "PARSE receiver #%d: %ld message%s suppressed, error condition class persists for %s",
- CLK_UNIT(parse->peer), err->err_suppressed, (err->err_suppressed == 1) ? " was" : "s where",
- l_mktime(current_time - err->err_started));
- err->err_suppressed = 0;
- }
-
- return do_it;
-}
-
-/*--------------------------------------------------
- * mkreadable - make a printable ascii string (without
- * embedded quotes so that the ntpq protocol isn't
- * fooled
- */
-#ifndef isprint
-#define isprint(_X_) (((_X_) > 0x1F) && ((_X_) < 0x7F))
-#endif
-
-static char *
-mkreadable(
- char *buffer,
- long blen,
- const char *src,
- u_long srclen,
- int hex
- )
-{
- char *b = buffer;
- 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 (!hex && /* no binary only */
- (*src != '\\') && /* no plain \ */
- (*src != '"') && /* no " */
- isprint((int)*src)) /* only printables */
- { /* they 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;
- src++;
- }
- 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;
-}
-
-
-/*--------------------------------------------------
- * mkascii - make a printable ascii string
- * assumes (unless defined better) 7-bit ASCII
- */
-static char *
-mkascii(
- char *buffer,
- long blen,
- const char *src,
- u_long srclen
- )
-{
- return mkreadable(buffer, blen, src, srclen, 0);
-}
-
-/**===========================================================================
- ** 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_end 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_timecode P((struct parseunit *, parsectl_t *));
-static void stream_receive P((struct recvbuf *));
-#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_timecode P((struct parseunit *, parsectl_t *));
-static void local_receive P((struct recvbuf *));
-static int local_input P((struct recvbuf *));
-
-static bind_t io_bindings[] =
-{
-#ifdef STREAM
- {
- "parse STREAM",
- stream_init,
- stream_end,
- stream_setcs,
- stream_disable,
- stream_enable,
- stream_getfmt,
- stream_setfmt,
- stream_timecode,
- stream_receive,
- 0,
- },
- {
- "ppsclock STREAM",
- ppsclock_init,
- local_end,
- local_setcs,
- local_nop,
- local_nop,
- local_getfmt,
- local_setfmt,
- local_timecode,
- local_receive,
- local_input,
- },
-#endif
- {
- "normal",
- local_init,
- local_end,
- local_setcs,
- local_nop,
- local_nop,
- local_getfmt,
- local_setfmt,
- local_timecode,
- local_receive,
- local_input,
- },
- {
- (char *)0,
- }
-};
-
-#ifdef STREAM
-
-#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)) \
- { \
- ERR(ERR_BADDATA) \
- msyslog(LOG_ERR,"parse: stream_receive: timestamp conversion error (buftvtots) (%s) (%ld.%06ld) ", (_Y_), (long)(&(_X_))->tv.tv_sec, (long)(&(_X_))->tv.tv_usec);\
- return; \
- } \
- else \
- { \
- (&(_X_))->fp = ts; \
- } \
- }
-
-/*--------------------------------------------------
- * ppsclock STREAM init
- */
-static int
-ppsclock_init(
- struct parseunit *parse
- )
-{
- static char m1[] = "ppsclocd";
- static char m2[] = "ppsclock";
-
- /*
- * now push the parse streams module
- * it will ensure exclusive access to the device
- */
- if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1 &&
- ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m2) == -1)
- {
- if (errno != EINVAL)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: ppsclock_init: ioctl(fd, I_PUSH, \"ppsclock\"): %m",
- CLK_UNIT(parse->peer));
- }
- return 0;
- }
- if (!local_init(parse))
- {
- (void)ioctl(parse->generic->io.fd, I_POP, (caddr_t)0);
- return 0;
- }
-
- parse->flags |= PARSE_PPSCLOCK;
- return 1;
-}
-
-/*--------------------------------------------------
- * parse STREAM init
- */
-static int
-stream_init(
- struct parseunit *parse
- )
-{
- static char m1[] = "parse";
- /*
- * now push the parse streams module
- * to test whether it is there (neat interface 8-( )
- */
- if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
- {
- if (errno != EINVAL) /* accept non-existence */
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
- }
- return 0;
- }
- else
- {
- while(ioctl(parse->generic->io.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->generic->io.fd, I_PUSH, (caddr_t)m1) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: stream_init: ioctl(fd, I_PUSH, \"parse\"): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- else
- {
- return 1;
- }
- }
-}
-
-/*--------------------------------------------------
- * parse STREAM end
- */
-static void
-stream_end(
- struct parseunit *parse
- )
-{
- while(ioctl(parse->generic->io.fd, I_POP, (caddr_t)0) == 0)
- /* empty loop */;
-}
-
-/*--------------------------------------------------
- * STREAM setcs
- */
-static int
-stream_setcs(
- 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->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: stream_setcs: ioctl(fd, I_STR, PARSEIOC_SETCS): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- return 1;
-}
-
-/*--------------------------------------------------
- * STREAM enable
- */
-static int
-stream_enable(
- 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->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: stream_enable: ioctl(fd, I_STR, PARSEIOC_ENABLE): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- parse->generic->io.clock_recv = stream_receive; /* ok - parse input in kernel */
- return 1;
-}
-
-/*--------------------------------------------------
- * STREAM disable
- */
-static int
-stream_disable(
- 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->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: stream_disable: ioctl(fd, I_STR, PARSEIOC_DISABLE): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- parse->generic->io.clock_recv = local_receive; /* ok - parse input in daemon */
- return 1;
-}
-
-/*--------------------------------------------------
- * STREAM getfmt
- */
-static int
-stream_getfmt(
- 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->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: ioctl(fd, I_STR, PARSEIOC_GETFMT): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- return 1;
-}
-
-/*--------------------------------------------------
- * STREAM setfmt
- */
-static int
-stream_setfmt(
- 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->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: stream_setfmt: ioctl(fd, I_STR, PARSEIOC_SETFMT): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- return 1;
-}
-
-
-/*--------------------------------------------------
- * STREAM timecode
- */
-static int
-stream_timecode(
- 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->generic->io.fd, I_STR, (caddr_t)&strioc) == -1)
- {
- ERR(ERR_INTERNAL)
- msyslog(LOG_ERR, "PARSE receiver #%d: stream_timecode: ioctl(fd, I_STR, PARSEIOC_TIMECODE): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- clear_err(parse, ERR_INTERNAL);
- return 1;
-}
-
-/*--------------------------------------------------
- * STREAM receive
- */
-static void
-stream_receive(
- struct recvbuf *rbufp
- )
-{
- struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
- parsetime_t parsetime;
-
- if (!parse->peer)
- return;
-
- if (rbufp->recv_length != sizeof(parsetime_t))
- {
- ERR(ERR_BADIO)
- msyslog(LOG_ERR,"PARSE receiver #%d: stream_receive: bad size (got %d expected %d)",
- CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
- parse->generic->baddata++;
- parse_event(parse, CEVNT_BADREPLY);
- return;
- }
- clear_err(parse, ERR_BADIO);
-
- memmove((caddr_t)&parsetime,
- (caddr_t)rbufp->recv_buffer,
- sizeof(parsetime_t));
-
-#ifdef DEBUG
- if (debug > 3)
- {
- printf("PARSE receiver #%d: status %06x, state %08x, time %lx.%08lx, stime %lx.%08lx, ptime %lx.%08lx\n",
- CLK_UNIT(parse->peer),
- (unsigned int)parsetime.parse_status,
- (unsigned int)parsetime.parse_state,
- (long)parsetime.parse_time.tv.tv_sec,
- (long)parsetime.parse_time.tv.tv_usec,
- (long)parsetime.parse_stime.tv.tv_sec,
- (long)parsetime.parse_stime.tv.tv_usec,
- (long)parsetime.parse_ptime.tv.tv_sec,
- (long)parsetime.parse_ptime.tv.tv_usec);
- }
-#endif
-
- /*
- * switch time stamp world - be sure to normalize small usec field
- * errors.
- */
-
- cvt_ts(parsetime.parse_stime, "parse_stime");
-
- if (PARSE_TIMECODE(parsetime.parse_state))
- {
- cvt_ts(parsetime.parse_time, "parse_time");
- }
-
- if (PARSE_PPS(parsetime.parse_state))
- cvt_ts(parsetime.parse_ptime, "parse_ptime");
-
- parse_process(parse, &parsetime);
-}
-#endif
-
-/*--------------------------------------------------
- * local init
- */
-static int
-local_init(
- struct parseunit *parse
- )
-{
- return parse_ioinit(&parse->parseio);
-}
-
-/*--------------------------------------------------
- * local end
- */
-static void
-local_end(
- struct parseunit *parse
- )
-{
- parse_ioend(&parse->parseio);
-}
-
-
-/*--------------------------------------------------
- * local nop
- */
-static int
-local_nop(
- struct parseunit *parse
- )
-{
- return 1;
-}
-
-/*--------------------------------------------------
- * local setcs
- */
-static int
-local_setcs(
- struct parseunit *parse,
- parsectl_t *tcl
- )
-{
- return parse_setcs(tcl, &parse->parseio);
-}
-
-/*--------------------------------------------------
- * local getfmt
- */
-static int
-local_getfmt(
- struct parseunit *parse,
- parsectl_t *tcl
- )
-{
- return parse_getfmt(tcl, &parse->parseio);
-}
-
-/*--------------------------------------------------
- * local setfmt
- */
-static int
-local_setfmt(
- struct parseunit *parse,
- parsectl_t *tcl
- )
-{
- return parse_setfmt(tcl, &parse->parseio);
-}
-
-/*--------------------------------------------------
- * local timecode
- */
-static int
-local_timecode(
- struct parseunit *parse,
- parsectl_t *tcl
- )
-{
- return parse_timecode(tcl, &parse->parseio);
-}
-
-
-/*--------------------------------------------------
- * local input
- */
-static int
-local_input(
- struct recvbuf *rbufp
- )
-{
- struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
- int count;
- unsigned char *s;
- timestamp_t ts;
-
- if (!parse->peer)
- return 0;
-
- /*
- * eat all characters, parsing then and feeding complete samples
- */
- count = rbufp->recv_length;
- s = (unsigned char *)rbufp->recv_buffer;
- ts.fp = rbufp->recv_time;
-
- while (count--)
- {
- if (parse_ioread(&parse->parseio, (unsigned int)(*s++), &ts))
- {
- struct recvbuf buf;
-
- /*
- * got something good to eat
- */
- if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state))
- {
-#ifdef TIOCDCDTIMESTAMP
- struct timeval dcd_time;
-
- if (ioctl(rbufp->fd, TIOCDCDTIMESTAMP, &dcd_time) != -1)
- {
- l_fp tstmp;
-
- TVTOTS(&dcd_time, &tstmp);
- tstmp.l_ui += JAN_1970;
- L_SUB(&ts.fp, &tstmp);
- if (ts.fp.l_ui == 0)
- {
-#ifdef DEBUG
- if (debug)
- {
- printf(
- "parse: local_receive: fd %d DCDTIMESTAMP %s\n",
- rbufp->fd,
- lfptoa(&tstmp, 6));
- printf(" sigio %s\n",
- lfptoa(&ts.fp, 6));
- }
-#endif
- parse->parseio.parse_dtime.parse_ptime.fp = tstmp;
- parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
- }
- }
-#else /* TIOCDCDTIMESTAMP */
-#if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
- if (parse->flags & PARSE_PPSCLOCK)
- {
- l_fp tts;
- struct ppsclockev ev;
-
-#ifdef HAVE_CIOGETEV
- if (ioctl(parse->generic->io.fd, CIOGETEV, (caddr_t)&ev) == 0)
-#endif
-#ifdef HAVE_TIOCGPPSEV
- if (ioctl(parse->generic->io.fd, TIOCGPPSEV, (caddr_t)&ev) == 0)
-#endif
- {
- if (ev.serial != parse->ppsserial)
- {
- /*
- * add PPS time stamp if available via ppsclock module
- * and not supplied already.
- */
- if (!buftvtots((const char *)&ev.tv, &tts))
- {
- ERR(ERR_BADDATA)
- msyslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
- }
- else
- {
- parse->parseio.parse_dtime.parse_ptime.fp = tts;
- parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
- }
- }
- parse->ppsserial = ev.serial;
- }
- }
-#endif
-#endif /* TIOCDCDTIMESTAMP */
- }
- if (count)
- { /* simulate receive */
- memmove((caddr_t)buf.recv_buffer,
- (caddr_t)&parse->parseio.parse_dtime,
- sizeof(parsetime_t));
- parse_iodone(&parse->parseio);
- buf.recv_length = sizeof(parsetime_t);
- buf.recv_time = rbufp->recv_time;
- buf.srcadr = rbufp->srcadr;
- buf.dstadr = rbufp->dstadr;
- buf.fd = rbufp->fd;
- buf.next = 0;
- buf.X_from_where = rbufp->X_from_where;
- rbufp->receiver(&buf);
- }
- else
- {
- memmove((caddr_t)rbufp->recv_buffer,
- (caddr_t)&parse->parseio.parse_dtime,
- sizeof(parsetime_t));
- parse_iodone(&parse->parseio);
- rbufp->recv_length = sizeof(parsetime_t);
- return 1; /* got something & in place return */
- }
- }
- }
- return 0; /* nothing to pass up */
-}
-
-/*--------------------------------------------------
- * local receive
- */
-static void
-local_receive(
- struct recvbuf *rbufp
- )
-{
- struct parseunit *parse = (struct parseunit *)((void *)rbufp->recv_srcclock);
- parsetime_t parsetime;
-
- if (!parse->peer)
- return;
-
- if (rbufp->recv_length != sizeof(parsetime_t))
- {
- ERR(ERR_BADIO)
- msyslog(LOG_ERR,"PARSE receiver #%d: local_receive: bad size (got %d expected %d)",
- CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
- parse->generic->baddata++;
- parse_event(parse, CEVNT_BADREPLY);
- return;
- }
- clear_err(parse, ERR_BADIO);
-
- memmove((caddr_t)&parsetime,
- (caddr_t)rbufp->recv_buffer,
- sizeof(parsetime_t));
-
-#ifdef DEBUG
- if (debug > 3)
- {
- printf("PARSE receiver #%d: status %06x, state %08x, time %lx.%08lx, stime %lx.%08lx, ptime %lx.%08lx\n",
- CLK_UNIT(parse->peer),
- (unsigned int)parsetime.parse_status,
- (unsigned int)parsetime.parse_state,
- (long)parsetime.parse_time.tv.tv_sec,
- (long)parsetime.parse_time.tv.tv_usec,
- (long)parsetime.parse_stime.tv.tv_sec,
- (long)parsetime.parse_stime.tv.tv_usec,
- (long)parsetime.parse_ptime.tv.tv_sec,
- (long)parsetime.parse_ptime.tv.tv_usec);
- }
-#endif
-
- parse_process(parse, &parsetime);
-}
-
-/*--------------------------------------------------
- * init_iobinding - find and initialize lower layers
- */
-static bind_t *
-init_iobinding(
- struct parseunit *parse
- )
-{
- 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(
- u_long lstate,
- char *buffer
- )
-{
- static struct bits
- {
- u_long bit;
- const 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;
- const 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 & lstate)
- {
- if (buffer[0])
- strcat(buffer, "; ");
- strcat(buffer, flagstrings[i].name);
- }
- i++;
- }
-
- if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
- {
- 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 & lstate)
- {
- 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(
- u_long lstate,
- char *buffer
- )
-{
- static struct bits
- {
- u_long bit;
- const 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" },
- { CVT_ADDITIONAL, "ADDITIONAL DATA" },
- { 0 }
- };
- int i;
-
- *buffer = '\0';
-
- i = 0;
- while (flagstrings[i].bit)
- {
- if (flagstrings[i].bit & lstate)
- {
- if (buffer[0])
- strcat(buffer, "; ");
- strcat(buffer, flagstrings[i].name);
- }
- i++;
- }
-
- return buffer;
-}
-
-/*--------------------------------------------------
- * convert a clock status flag field to a string
- */
-static const char *
-clockstatus(
- u_long lstate
- )
-{
- static char buffer[20];
- static struct status
- {
- u_long value;
- const 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" },
- { (unsigned)~0L }
- };
- int i;
-
- i = 0;
- while (flagstrings[i].value != ~0)
- {
- if (flagstrings[i].value == lstate)
- {
- return flagstrings[i].name;
- }
- i++;
- }
-
- sprintf(buffer, "unknown #%ld", (u_long)lstate);
-
- return buffer;
-}
-
-
-/*--------------------------------------------------
- * l_mktime - make representation of a relative time
- */
-static char *
-l_mktime(
- 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(
- struct parseunit *parse
- )
-{
- int i;
-
- NLOG(NLOG_CLOCKSTATIST) /* conditional if clause for conditional syslog */
- {
- msyslog(LOG_INFO, "PARSE receiver #%d: running time: %s",
- CLK_UNIT(parse->peer),
- l_mktime(current_time - parse->generic->timestarted));
-
- msyslog(LOG_INFO, "PARSE receiver #%d: current status: %s",
- CLK_UNIT(parse->peer),
- clockstatus(parse->generic->currentstatus));
-
- for (i = 0; i <= CEVNT_MAX; i++)
- {
- u_long s_time;
- u_long percent, d = current_time - parse->generic->timestarted;
-
- percent = s_time = PARSE_STATETIME(parse, i);
-
- while (((u_long)(~0) / 10000) < percent)
- {
- percent /= 10;
- d /= 10;
- }
-
- if (d)
- percent = (percent * 10000) / d;
- else
- percent = 10000;
-
- if (s_time)
- msyslog(LOG_INFO, "PARSE receiver #%d: state %18s: %13s (%3ld.%02ld%%)",
- CLK_UNIT(parse->peer),
- clockstatus((unsigned int)i),
- l_mktime(s_time),
- percent / 100, percent % 100);
- }
- }
-}
-
-/*--------------------------------------------------
- * cparse_statistics - wrapper for statistics call
- */
-static void
-cparse_statistics(
- register struct parseunit *parse
- )
-{
- if (parse->laststatistic + PARSESTATISTICS < current_time)
- parse_statistics(parse);
- parse->laststatistic = current_time;
-}
-
-/**===========================================================================
- ** ntp interface routines
- **/
-
-/*--------------------------------------------------
- * parse_init - initialize internal parse driver data
- */
-static void
-parse_init(void)
-{
- memset((caddr_t)parseunits, 0, sizeof parseunits);
-}
-
-
-/*--------------------------------------------------
- * parse_shutdown - shut down a PARSE clock
- */
-static void
-parse_shutdown(
- int unit,
- struct peer *peer
- )
-{
- struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
-
- if (parse && !parse->peer)
- {
- msyslog(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);
-
- 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.
- */
- io_closeclock(&parse->generic->io);
-
- free_varlist(parse->kv);
-
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" removed",
- CLK_UNIT(parse->peer), parse->parse_type->cl_description);
-
- parse->peer = (struct peer *)0; /* unused now */
- free(parse);
-}
-
-/*--------------------------------------------------
- * parse_start - open the PARSE devices and initialize data for processing
- */
-static int
-parse_start(
- int sysunit,
- struct peer *peer
- )
-{
- u_int unit;
- int fd232;
-#ifdef HAVE_TERMIOS
- struct termios tio; /* NEEDED FOR A LONG TIME ! */
-#endif
-#ifdef HAVE_SYSV_TTYS
- struct termio tio; /* NEEDED FOR A LONG TIME ! */
-#endif
- struct parseunit * parse;
- char parsedev[sizeof(PARSEDEVICE)+20];
- parsectl_t tmp_ctl;
- u_int type;
-
- type = CLK_TYPE(peer);
- unit = CLK_UNIT(peer);
-
- if ((type == ~0) || (parse_clockinfo[type].cl_description == (char *)0))
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: unsupported clock type %d (max %d)",
- unit, CLK_REALTYPE(peer), ncltypes-1);
- 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
-#ifdef O_NONBLOCK
- | O_NONBLOCK
-#endif
- , 0777);
-
- if (fd232 == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: open of %s failed: %m", unit, parsedev);
- return 0;
- }
-
- parse = (struct parseunit *)emalloc(sizeof(struct parseunit));
-
- memset((char *)parse, 0, sizeof(struct parseunit));
-
- parse->generic = peer->procptr; /* link up */
- parse->generic->unitptr = (caddr_t)parse; /* link down */
-
- /*
- * Set up the structures
- */
- parse->generic->timestarted = current_time;
- parse->lastchange = current_time;
-
- parse->generic->currentstatus = CEVNT_TIMEOUT; /* expect the worst */
-
- parse->flags = 0;
- parse->pollneeddata = 0;
- parse->laststatistic = current_time;
- parse->lastformat = (unsigned short)~0; /* assume no format known */
- parse->time.parse_status = (unsigned short)~0; /* be sure to mark initial status change */
- parse->lastmissed = 0; /* assume got everything */
- parse->ppsserial = 0;
- parse->localdata = (void *)0;
- parse->localstate = 0;
- parse->kv = (struct ctl_var *)0;
-
- clear_err(parse, ERR_ALL);
-
- parse->parse_type = &parse_clockinfo[type];
-
- parse->generic->fudgetime1 = parse->parse_type->cl_basedelay;
-
- parse->generic->fudgetime2 = 0.0;
-
- parse->generic->clockdesc = parse->parse_type->cl_description;
-
- 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 *)&parse->generic->refid, parse->parse_type->cl_id, 4);
- else
- parse->generic->refid = htonl(PARSEHSREFID);
-
- parse->generic->io.fd = fd232;
-
- parse->peer = peer; /* marks it also as busy */
-
- /*
- * configure terminal line
- */
- if (TTY_GETATTR(fd232, &tio) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcgetattr(%d, &tio): %m", unit, fd232);
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0;
- }
- else
- {
-#ifndef _PC_VDISABLE
- memset((char *)tio.c_cc, 0, sizeof(tio.c_cc));
-#else
- int disablec;
- errno = 0; /* pathconf can deliver -1 without changing errno ! */
-
- disablec = fpathconf(parse->generic->io.fd, _PC_VDISABLE);
- if (disablec == -1 && errno)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: fpathconf(fd, _PC_VDISABLE): %m", CLK_UNIT(parse->peer));
- memset((char *)tio.c_cc, 0, sizeof(tio.c_cc)); /* best guess */
- }
- else
- if (disablec != -1)
- memset((char *)tio.c_cc, disablec, sizeof(tio.c_cc));
-#endif
-
-#if defined (VMIN) || defined(VTIME)
- if ((parse_clockinfo[type].cl_lflag & ICANON) == 0)
- {
-#ifdef VMIN
- tio.c_cc[VMIN] = 1;
-#endif
-#ifdef VTIME
- tio.c_cc[VTIME] = 0;
-#endif
- }
-#endif
-
- tio.c_cflag = parse_clockinfo[type].cl_cflag;
- tio.c_iflag = parse_clockinfo[type].cl_iflag;
- tio.c_oflag = parse_clockinfo[type].cl_oflag;
- tio.c_lflag = parse_clockinfo[type].cl_lflag;
-
-
-#ifdef HAVE_TERMIOS
- if ((cfsetospeed(&tio, parse_clockinfo[type].cl_speed) == -1) ||
- (cfsetispeed(&tio, parse_clockinfo[type].cl_speed) == -1))
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcset{i,o}speed(&tio, speed): %m", unit);
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0;
- }
-#else
- tio.c_cflag |= parse_clockinfo[type].cl_speed;
-#endif
-
-#if defined(HAVE_TIO_SERIAL_STUFF) /* Linux hack: define PPS interface */
- {
- struct serial_struct ss;
- if (ioctl(fd232, TIOCGSERIAL, &ss) < 0 ||
- (
-#ifdef ASYNC_LOW_LATENCY
- ss.flags |= ASYNC_LOW_LATENCY,
-#endif
-#ifdef ASYNC_PPS_CD_NEG
- ss.flags |= ASYNC_PPS_CD_NEG,
-#endif
- ioctl(fd232, TIOCSSERIAL, &ss)) < 0) {
- msyslog(LOG_NOTICE, "refclock_parse: TIOCSSERIAL fd %d, %m", fd232);
- msyslog(LOG_NOTICE,
- "refclock_parse: optional PPS processing not available");
- } else {
- parse->flags |= PARSE_PPSCLOCK;
- msyslog(LOG_INFO,
- "refclock_parse: PPS detection on");
- }
- }
-#endif
-#ifdef HAVE_TIOCSPPS /* SUN PPS support */
- if (CLK_PPS(parse->peer))
- {
- int i = 1;
-
- if (ioctl(fd232, TIOCSPPS, (caddr_t)&i) == 0)
- {
- parse->flags |= PARSE_PPSCLOCK;
- }
- }
-#endif
-
- if (TTY_SETATTR(fd232, &tio) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: tcsetattr(%d, &tio): %m", unit, fd232);
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0;
- }
- }
-
- /*
- * Insert in async io device list.
- */
- parse->generic->io.srcclock = (caddr_t)parse;
- parse->generic->io.datalen = 0;
-
- if (!io_addclock(&parse->generic->io))
- {
- msyslog(LOG_ERR,
- "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0;
- }
-
- parse->binding = init_iobinding(parse);
- parse->generic->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
- parse->generic->io.io_input = parse->binding->bd_io_input; /* pick correct input routine */
-
- if (parse->binding == (bind_t *)0)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: io sub system initialisation failed.", CLK_UNIT(parse->peer));
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0; /* well, ok - special initialisation broke */
- }
-
- /*
- * 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 (tio.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))
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setcs() FAILED.", unit);
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* 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))
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_start: parse_setfmt() FAILED.", unit);
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0; /* well, ok - special initialisation broke */
- }
-
- /*
- * get rid of all IO accumulated so far
- */
-#ifdef HAVE_TERMIOS
- (void) tcflush(parse->generic->io.fd, TCIOFLUSH);
-#else
-#ifdef TCFLSH
- {
-#ifndef TCIOFLUSH
-#define TCIOFLUSH 2
-#endif
- int flshcmd = TCIOFLUSH;
-
- (void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd);
- }
-#endif
-#endif
-
- /*
- * try to do any special initializations
- */
- if (parse->parse_type->cl_init)
- {
- if (parse->parse_type->cl_init(parse))
- {
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0; /* well, ok - special initialisation broke */
- }
- }
-
- /*
- * get out Copyright information once
- */
- if (!notice)
- {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-1999, Frank Kardel");
- notice = 1;
- }
-
- /*
- * print out configuration
- */
- NLOG(NLOG_CLOCKINFO)
- {
- /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (device %s) added",
- CLK_UNIT(parse->peer),
- parse->parse_type->cl_description, parsedev);
-
- msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, %sPPS support, trust time %s, precision %d",
- CLK_UNIT(parse->peer),
- parse->peer->stratum, CLK_PPS(parse->peer) ? "" : "no ",
- l_mktime(parse->parse_type->cl_maxunsync), parse->peer->precision);
-
- msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phaseadjust %.6f s, %s IO handling",
- CLK_UNIT(parse->peer),
- parse->parse_type->cl_rootdelay,
- parse->generic->fudgetime1,
- parse->binding->bd_description);
-
- msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
- parse->parse_type->cl_format);
-#ifdef PPS
- msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS ioctl support", CLK_UNIT(parse->peer),
- (parse->flags & PARSE_PPSCLOCK) ? "" : "NO ");
-#endif
- }
-
- return 1;
-}
-
-/*--------------------------------------------------
- * parse_poll - called by the transmit procedure
- */
-static void
-parse_poll(
- int unit,
- struct peer *peer
- )
-{
- struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
-
- if (peer != parse->peer)
- {
- msyslog(LOG_ERR,
- "PARSE receiver #%d: poll: INTERNAL: peer incorrect",
- unit);
- return;
- }
-
- /*
- * Update clock stat counters
- */
- parse->generic->polls++;
-
- if (parse->pollneeddata &&
- ((current_time - parse->pollneeddata) > (1<<(max(min(parse->peer->hpoll, parse->peer->ppoll), parse->peer->minpoll)))))
- {
- /*
- * start worrying when exceeding a poll inteval
- * bad news - didn't get a response last time
- */
- parse->generic->noreply++;
- parse->lastmissed = current_time;
- parse_event(parse, CEVNT_TIMEOUT);
-
- ERR(ERR_NODATA)
- msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / cableling)", CLK_UNIT(parse->peer));
- }
-
- /*
- * we just mark that we want the next sample for the clock filter
- */
- parse->pollneeddata = current_time;
-
- if (parse->parse_type->cl_poll)
- {
- parse->parse_type->cl_poll(parse);
- }
-
- cparse_statistics(parse);
-
- return;
-}
-
-#define LEN_STATES 300 /* length of state string */
-
-/*--------------------------------------------------
- * parse_control - set fudge factors, return statistics
- */
-static void
-parse_control(
- int unit,
- struct refclockstat *in,
- struct refclockstat *out,
- struct peer *peer
- )
-{
- register struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
- parsectl_t tmpctl;
-
- static char outstatus[400]; /* status output buffer */
-
- if (out)
- {
- out->lencode = 0;
- out->p_lastcode = 0;
- out->kv_list = (struct ctl_var *)0;
- }
-
- if (!parse || !parse->peer)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: unit invalid (UNIT INACTIVE)",
- unit);
- return;
- }
-
- unit = CLK_UNIT(parse->peer);
-
- if (in)
- {
- if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
- {
- parse->flags = in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4);
- }
- }
-
- if (out)
- {
- u_long sum = 0;
- char *t, *tt, *start;
- int i;
-
- outstatus[0] = '\0';
-
- out->type = REFCLK_PARSE;
- out->haveflags |= CLK_HAVETIME2;
-
- /*
- * 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, 80, 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\"", gmprettydate(&parse->time.parse_ptime.fp));
- }
-
- 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
- {
- sprintf(tt, "%s\"", gmprettydate(&parse->time.parse_time.fp));
- t = tt + strlen(tt);
- }
-
- if (!PARSE_GETTIMECODE(parse, &tmpctl))
- {
- ERR(ERR_INTERNAL)
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_control: parse_timecode() FAILED", unit);
- }
- else
- {
- tt = add_var(&out->kv_list, 512, 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), (int)(sizeof(outstatus)- strlen(outstatus) - 1),
- tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1));
-
- parse->generic->badformat += tmpctl.parsegettc.parse_badformat;
- }
-
- tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
-
- if (!PARSE_GETFMT(parse, &tmpctl))
- {
- ERR(ERR_INTERNAL)
- msyslog(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
- */
-
- start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF);
- strcpy(tt, "refclock_states=\"");
- tt += strlen(tt);
-
- for (i = 0; i <= CEVNT_MAX; i++)
- {
- u_long s_time;
- u_long d = current_time - parse->generic->timestarted;
- u_long percent;
-
- percent = s_time = PARSE_STATETIME(parse, i);
-
- while (((u_long)(~0) / 10000) < percent)
- {
- percent /= 10;
- d /= 10;
- }
-
- if (d)
- percent = (percent * 10000) / d;
- else
- percent = 10000;
-
- if (s_time)
- {
- char item[80];
- int count;
-
- sprintf(item, "%s%s%s: %s (%d.%02d%%)",
- sum ? "; " : "",
- (parse->generic->currentstatus == i) ? "*" : "",
- clockstatus((unsigned int)i),
- l_mktime(s_time),
- (int)(percent / 100), (int)(percent % 100));
- if ((count = strlen(item)) < (LEN_STATES - 40 - (tt - start)))
- {
- strcpy(tt, item);
- tt += count;
- }
- sum += s_time;
- }
- }
-
- 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=\"%s\"", rcsid);
-
- {
- struct ctl_var *k;
-
- k = parse->kv;
- while (k && !(k->flags & EOV))
- {
- set_var(&out->kv_list, k->text, strlen(k->text)+1, k->flags);
- k++;
- }
- }
-
- out->lencode = strlen(outstatus);
- out->p_lastcode = outstatus;
- }
-}
-
-/**===========================================================================
- ** processing routines
- **/
-
-/*--------------------------------------------------
- * event handling - note that nominal events will also be posted
- */
-static void
-parse_event(
- struct parseunit *parse,
- int event
- )
-{
- if (parse->generic->currentstatus != (u_char) event)
- {
- parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange;
- parse->lastchange = current_time;
-
- parse->generic->currentstatus = (u_char)event;
-
- if (parse->parse_type->cl_event)
- parse->parse_type->cl_event(parse, event);
-
- if (event != CEVNT_NOMINAL)
- {
- parse->generic->lastevent = parse->generic->currentstatus;
- }
- else
- {
- NLOG(NLOG_CLOCKSTATUS)
- msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED",
- CLK_UNIT(parse->peer));
- }
-
- if (event == CEVNT_FAULT)
- {
- NLOG(NLOG_CLOCKEVENT) /* conditional if clause for conditional syslog */
- ERR(ERR_BADEVENT)
- msyslog(LOG_ERR,
- "clock %s fault '%s' (0x%02x)", refnumtoa(&parse->peer->srcadr), ceventstr(event),
- (u_int)event);
- }
- else
- {
- NLOG(NLOG_CLOCKEVENT) /* conditional if clause for conditional syslog */
- if (event == CEVNT_NOMINAL || list_err(parse, ERR_BADEVENT))
- msyslog(LOG_INFO,
- "clock %s event '%s' (0x%02x)", refnumtoa(&parse->peer->srcadr), ceventstr(event),
- (u_int)event);
- }
-
- report_event(EVNT_PEERCLOCK, parse->peer);
- report_event(EVNT_CLOCKEXCPT, parse->peer);
- }
-}
-
-/*--------------------------------------------------
- * process a PARSE time sample
- */
-static void
-parse_process(
- struct parseunit *parse,
- parsetime_t *parsetime
- )
-{
- l_fp off, rectime, reftime;
- double fudge;
-
- /*
- * check for changes in conversion status
- * (only one for each new status !)
- */
- if (((parsetime->parse_status & CVT_MASK) != CVT_OK) &&
- ((parsetime->parse_status & CVT_MASK) != CVT_NONE) &&
- (parse->time.parse_status != parsetime->parse_status))
- {
- char buffer[400];
-
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
- CLK_UNIT(parse->peer), 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))
- {
- ERR(ERR_INTERNAL)
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_process: parse_timecode() FAILED", CLK_UNIT(parse->peer));
- }
- else
- {
- ERR(ERR_BADDATA)
- msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / cableling)",
- CLK_UNIT(parse->peer), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1)));
- parse->generic->badformat += tmpctl.parsegettc.parse_badformat;
- }
- }
- }
-
- /*
- * 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:
- if ((parsetime->parse_status & CVT_ADDITIONAL) &&
- parse->parse_type->cl_message)
- parse->parse_type->cl_message(parse, parsetime);
- break; /* well, still waiting - timeout is handled at higher levels */
-
- case CVT_FAIL:
- parse->generic->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))
- {
- ERR(ERR_INTERNAL)
- msyslog(LOG_ERR, "PARSE receiver #%d: parse_getfmt() FAILED", CLK_UNIT(parse->peer));
- }
- else
- {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "PARSE receiver #%d: packet format \"%s\"",
- CLK_UNIT(parse->peer), 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);
-
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
- CLK_UNIT(parse->peer), 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 Meinberg DCF77 receivers the lost synchronisation
- * is 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);
- NLOG(NLOG_CLOCKSTATUS)
- ERR(ERR_BADSTATUS)
- msyslog(LOG_ERR,"PARSE receiver #%d: NOT SYNCHRONIZED",
- CLK_UNIT(parse->peer));
- }
- 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 Meinberg DCF77 clocks 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
- */
-
- if (PARSE_SYNC(parsetime->parse_state))
- {
- /*
- * currently completely synchronized - best possible state
- */
- parse->lastsync = current_time;
- clear_err(parse, ERR_BADSTATUS);
- }
- else
- {
- /*
- * we have had some problems receiving the time code
- */
- parse_event(parse, CEVNT_PROP);
- NLOG(NLOG_CLOCKSTATUS)
- ERR(ERR_BADSTATUS)
- msyslog(LOG_ERR,"PARSE receiver #%d: TIMECODE NOT CONFIRMED",
- CLK_UNIT(parse->peer));
- }
- }
-
- fudge = parse->generic->fudgetime1; /* standard RS232 Fudgefactor */
-
- if (PARSE_TIMECODE(parsetime->parse_state))
- {
- rectime = parsetime->parse_stime.fp;
- off = reftime = parsetime->parse_time.fp;
-
- L_SUB(&off, &rectime); /* prepare for PPS adjustments logic */
-
-#ifdef DEBUG
- if (debug > 3)
- printf("PARSE receiver #%d: Reftime %s, Recvtime %s - initial offset %s\n",
- CLK_UNIT(parse->peer),
- prettydate(&reftime),
- prettydate(&rectime),
- lfptoa(&off,6));
-#endif
- }
-
- if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
- {
- l_fp offset;
-
- /*
- * we have a PPS signal - much better than the RS232 stuff (we hope)
- */
- offset = parsetime->parse_ptime.fp;
-
-#ifdef DEBUG
- if (debug > 3)
- printf("PARSE receiver #%d: PPStime %s\n",
- CLK_UNIT(parse->peer),
- prettydate(&offset));
-#endif
- 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))
- {
- fudge = parse->generic->fudgetime2; /* pick PPS fudge factor */
-
- /*
- * RS232 offsets within [-0.5..0.5[ - take PPS offsets
- */
-
- if (parse->parse_type->cl_flags & PARSE_F_PPSONSECOND)
- {
- reftime = off = offset;
- if (reftime.l_uf & (unsigned)0x80000000)
- reftime.l_ui++;
- reftime.l_uf = 0;
-
-
- /*
- * 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
- */
- reftime = off = parsetime->parse_time.fp;
-
- L_SUB(&off, &offset); /* true offset */
- }
- }
- /*
- * take RS232 offset when PPS when out of bounds
- */
- }
- else
- {
- fudge = parse->generic->fudgetime2; /* pick PPS fudge factor */
- /*
- * Well, no time code to guide us - assume on second pulse
- * and pray, that we are within [-0.5..0.5[
- */
- off = offset;
- reftime = offset;
- if (reftime.l_uf & (unsigned)0x80000000)
- reftime.l_ui++;
- reftime.l_uf = 0;
- /*
- * 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 ...
- */
- if ((parsetime->parse_status & CVT_ADDITIONAL) &&
- parse->parse_type->cl_message)
- parse->parse_type->cl_message(parse, parsetime);
- return;
- }
- }
-
-#ifdef DEBUG
- if (debug > 3)
- printf("PARSE receiver #%d: Reftime %s, Recvtime %s - final offset %s\n",
- CLK_UNIT(parse->peer),
- prettydate(&reftime),
- prettydate(&rectime),
- lfptoa(&off,6));
-#endif
-
-
- rectime = reftime;
- L_SUB(&rectime, &off); /* just to keep the ntp interface happy */
-
-#ifdef DEBUG
- if (debug > 3)
- printf("PARSE receiver #%d: calculated Reftime %s, Recvtime %s\n",
- CLK_UNIT(parse->peer),
- prettydate(&reftime),
- prettydate(&rectime));
-#endif
-
- if ((parsetime->parse_status & CVT_ADDITIONAL) &&
- parse->parse_type->cl_message)
- parse->parse_type->cl_message(parse, parsetime);
-
- if (PARSE_SYNC(parsetime->parse_state))
- {
- /*
- * log OK status
- */
- parse_event(parse, CEVNT_NOMINAL);
- }
-
- clear_err(parse, ERR_BADIO);
- clear_err(parse, ERR_BADDATA);
- clear_err(parse, ERR_NODATA);
- clear_err(parse, ERR_INTERNAL);
-
-#ifdef DEBUG
- if (debug > 2)
- {
- printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
- CLK_UNIT(parse->peer),
- prettydate(&reftime),
- prettydate(&rectime),
- fudge);
- }
-#endif
-
- refclock_process_offset(parse->generic, reftime, rectime, fudge);
- if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
- {
- (void) pps_sample(&parse->time.parse_ptime.fp);
- }
-
-
- /*
- * 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))
- {
- parse->generic->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).
- */
- parse->generic->leap = (parse->flags & PARSE_LEAP_DELETE) ? LEAP_DELSECOND : LEAP_ADDSECOND;
- }
- else
- if (PARSE_LEAPDEL(parsetime->parse_state))
- {
- parse->generic->leap = LEAP_DELSECOND;
- }
- else
- {
- parse->generic->leap = LEAP_NOWARNING;
- }
- }
-
- /*
- * ready, unless the machine wants a sample
- */
- if (!parse->pollneeddata)
- return;
-
- parse->pollneeddata = 0;
-
- refclock_receive(parse->peer);
-}
-
-/**===========================================================================
- ** special code for special clocks
- **/
-
-static void
-mk_utcinfo(
- char *t,
- int wnt,
- int wnlsf,
- int dn,
- int dtls,
- int dtlsf
- )
-{
- l_fp leapdate;
-
- sprintf(t, "current correction %d sec", dtls);
- t += strlen(t);
-
- if (wnlsf < 990)
- wnlsf += 1024;
-
- if (wnt < 990)
- wnt += 1024;
-
- gpstolfp((unsigned short)wnlsf, (unsigned short)dn, 0, &leapdate);
-
- if ((dtlsf != dtls) &&
- ((wnlsf - wnt) < 52))
- {
- sprintf(t, ", next correction %d sec on %s, new GPS-UTC offset %d",
- dtlsf - dtls, gmprettydate(&leapdate), dtlsf);
- }
- else
- {
- sprintf(t, ", last correction on %s",
- gmprettydate(&leapdate));
- }
-}
-
-#ifdef CLOCK_MEINBERG
-/**===========================================================================
- ** Meinberg GPS166/GPS167 support
- **/
-
-/*------------------------------------------------------------
- * gps16x_message - process GPS16x messages
- */
-static void
-gps16x_message(
- struct parseunit *parse,
- parsetime_t *parsetime
- )
-{
- if (parse->time.parse_msglen && parsetime->parse_msg[0] == SOH)
- {
- GPS_MSG_HDR header;
- unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1;
-
-#ifdef DEBUG
- if (debug > 2)
- {
- char msgbuffer[600];
-
- mkreadable(msgbuffer, sizeof(msgbuffer), (char *)parsetime->parse_msg, parsetime->parse_msglen, 1);
- printf("PARSE receiver #%d: received message (%d bytes) >%s<\n",
- CLK_UNIT(parse->peer),
- parsetime->parse_msglen,
- msgbuffer);
- }
-#endif
- get_mbg_header(&bufp, &header);
- if (header.gps_hdr_csum == mbg_csum(parsetime->parse_msg + 1, 6) &&
- (header.gps_len == 0 ||
- (header.gps_len < sizeof(parsetime->parse_msg) &&
- header.gps_data_csum == mbg_csum(bufp, header.gps_len))))
- {
- /*
- * clean message
- */
- switch (header.gps_cmd)
- {
- case GPS_SW_REV:
- {
- char buffer[64];
- SW_REV gps_sw_rev;
-
- get_mbg_sw_rev(&bufp, &gps_sw_rev);
- sprintf(buffer, "meinberg_gps_version=\"%x.%02x%s%s\"",
- (gps_sw_rev.code >> 8) & 0xFF,
- gps_sw_rev.code & 0xFF,
- gps_sw_rev.name[0] ? " " : "",
- gps_sw_rev.name);
- set_var(&parse->kv, buffer, 64, RO|DEF);
- }
- break;
-
- case GPS_STAT:
- {
- static struct state
- {
- unsigned short flag; /* status flag */
- unsigned const char *string; /* bit name */
- } states[] =
- {
- { TM_ANT_DISCONN, (const unsigned char *)"ANTENNA FAULTY" },
- { TM_SYN_FLAG, (const unsigned char *)"NO SYNC SIGNAL" },
- { TM_NO_SYNC, (const unsigned char *)"NO SYNC POWERUP" },
- { TM_NO_POS, (const unsigned char *)"NO POSITION" },
- { 0, (const unsigned char *)"" }
- };
- unsigned short status;
- struct state *s = states;
- char buffer[512];
- char *p, *b;
-
- status = get_lsb_short(&bufp);
- sprintf(buffer, "meinberg_gps_status=\"[0x%04x] ", status);
-
- if (status)
- {
- p = b = buffer + strlen(buffer);
- while (s->flag)
- {
- if (status & s->flag)
- {
- if (p != b)
- {
- *p++ = ',';
- *p++ = ' ';
- }
-
- strcat(p, (const char *)s->string);
- }
- s++;
- }
-
- *p++ = '"';
- *p = '\0';
- }
- else
- {
- strcat(buffer, "<OK>\"");
- }
-
- set_var(&parse->kv, buffer, 64, RO|DEF);
- }
- break;
-
- case GPS_POS_XYZ:
- {
- XYZ xyz;
- char buffer[256];
-
- get_mbg_xyz(&bufp, xyz);
- sprintf(buffer, "gps_position(XYZ)=\"%s m, %s m, %s m\"",
- mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1),
- mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1),
- mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1));
-
- set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
- }
- break;
-
- case GPS_POS_LLA:
- {
- LLA lla;
- char buffer[256];
-
- get_mbg_lla(&bufp, lla);
-
- sprintf(buffer, "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
- mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4),
- mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4),
- mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1));
-
- set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
- }
- break;
-
- case GPS_TZDL:
- break;
-
- case GPS_PORT_PARM:
- break;
-
- case GPS_SYNTH:
- break;
-
- case GPS_ANT_INFO:
- {
- ANT_INFO antinfo;
- u_char buffer[512];
- u_char *p;
-
- get_mbg_antinfo(&bufp, &antinfo);
- sprintf(buffer, "meinberg_antenna_status=\"");
- p = buffer + strlen(buffer);
-
- switch (antinfo.status)
- {
- case ANT_INVALID:
- strcat(p, "<OK>");
- p += strlen(p);
- break;
-
- case ANT_DISCONN:
- strcat(p, "DISCONNECTED since ");
- NLOG(NLOG_CLOCKSTATUS)
- ERR(ERR_BADSTATUS)
- msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s",
- CLK_UNIT(parse->peer), p);
-
- p += strlen(p);
- mbg_tm_str(&p, &antinfo.tm_disconn);
- *p = '\0';
- break;
-
- case ANT_RECONN:
- strcat(p, "RECONNECTED on ");
- p += strlen(p);
- mbg_tm_str(&p, &antinfo.tm_reconn);
- sprintf(p, ", reconnect clockoffset %c%ld.%07ld s, disconnect time ",
- (antinfo.delta_t < 0) ? '-' : '+',
- ABS(antinfo.delta_t) / 10000,
- ABS(antinfo.delta_t) % 10000);
- p += strlen(p);
- mbg_tm_str(&p, &antinfo.tm_disconn);
- *p = '\0';
- break;
-
- default:
- sprintf(p, "bad status 0x%04x", antinfo.status);
- p += strlen(p);
- break;
- }
-
- *p++ = '"';
- *p = '\0';
-
- set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
- }
- break;
-
- case GPS_UCAP:
- break;
-
- case GPS_CFGH:
- {
- CFGH cfgh;
- u_char buffer[512];
- u_char *p;
-
- get_mbg_cfgh(&bufp, &cfgh);
- if (cfgh.valid)
- {
- int i;
-
- p = buffer;
- strcpy(buffer, "gps_tot_51=\"");
- p += strlen(p);
- mbg_tgps_str(&p, &cfgh.tot_51);
- *p++ = '"';
- *p = '\0';
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
-
- p = buffer;
- strcpy(buffer, "gps_tot_63=\"");
- p += strlen(p);
- mbg_tgps_str(&p, &cfgh.tot_63);
- *p++ = '"';
- *p = '\0';
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
-
- p = buffer;
- strcpy(buffer, "gps_t0a=\"");
- p += strlen(p);
- mbg_tgps_str(&p, &cfgh.t0a);
- *p++ = '"';
- *p = '\0';
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
-
- for (i = MIN_SVNO; i <= MAX_SVNO; i++)
- {
- p = buffer;
- sprintf(p, "gps_cfg[%d]=\"[0x%x] ", i, cfgh.cfg[i]);
- p += strlen(p);
- switch (cfgh.cfg[i] & 0x7)
- {
- case 0:
- strcpy(p, "BLOCK I");
- break;
- case 1:
- strcpy(p, "BLOCK II");
- break;
- default:
- sprintf(p, "bad CFG");
- break;
- }
- strcat(p, "\"");
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
-
- p = buffer;
- sprintf(p, "gps_health[%d]=\"[0x%x] ", i, cfgh.health[i]);
- p += strlen(p);
- switch ((cfgh.health[i] >> 5) & 0x7 )
- {
- case 0:
- strcpy(p, "OK;");
- break;
- case 1:
- strcpy(p, "PARITY;");
- break;
- case 2:
- strcpy(p, "TLM/HOW;");
- break;
- case 3:
- strcpy(p, "Z-COUNT;");
- break;
- case 4:
- strcpy(p, "SUBFRAME 1,2,3;");
- break;
- case 5:
- strcpy(p, "SUBFRAME 4,5;");
- break;
- case 6:
- strcpy(p, "UPLOAD BAD;");
- break;
- case 7:
- strcpy(p, "DATA BAD;");
- break;
- }
-
- p += strlen(p);
-
- switch (cfgh.health[i] & 0x1F)
- {
- case 0:
- strcpy(p, "SIGNAL OK");
- break;
- case 0x1C:
- strcpy(p, "SV TEMP OUT");
- break;
- case 0x1D:
- strcpy(p, "SV WILL BE TEMP OUT");
- break;
- case 0x1E:
- break;
- case 0x1F:
- strcpy(p, "MULTIPLE ERRS");
- break;
- default:
- strcpy(p, "TRANSMISSION PROBLEMS");
- break;
- }
-
- strcat(p, "\"");
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
- }
- }
- }
- break;
-
- case GPS_ALM:
- break;
-
- case GPS_EPH:
- break;
-
- case GPS_UTC:
- {
- UTC utc;
- char buffer[512];
- char *p;
-
- p = buffer;
-
- get_mbg_utc(&bufp, &utc);
-
- if (utc.valid)
- {
- strcpy(p, "gps_utc_correction=\"");
- p += strlen(p);
- mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf);
- strcat(p, "\"");
- }
- else
- {
- strcpy(p, "gps_utc_correction=\"<NO UTC DATA>\"");
- }
- set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
- }
- break;
-
- case GPS_IONO:
- break;
-
- case GPS_ASCII_MSG:
- {
- ASCII_MSG gps_ascii_msg;
- char buffer[128];
-
- get_mbg_ascii_msg(&bufp, &gps_ascii_msg);
-
- if (gps_ascii_msg.valid)
- {
- char buffer1[128];
- mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0);
-
- sprintf(buffer, "gps_message=\"%s\"", buffer1);
- }
- else
- strcpy(buffer, "gps_message=<NONE>");
-
- set_var(&parse->kv, buffer, 128, RO|DEF);
- }
-
- break;
-
- default:
- break;
- }
- }
- else
- {
- msyslog(LOG_DEBUG, "PARSE receiver #%d: gps16x_message: message checksum error: hdr_csum = 0x%x (expected 0x%lx), data_len = %d, data_csum = 0x%x (expected 0x%lx)",
- CLK_UNIT(parse->peer),
- header.gps_hdr_csum, mbg_csum(parsetime->parse_msg + 1, 6),
- header.gps_len,
- header.gps_data_csum, mbg_csum(bufp, (unsigned)((header.gps_len < sizeof(parsetime->parse_msg)) ? header.gps_len : 0)));
- }
- }
-
- return;
-}
-
-/*------------------------------------------------------------
- * gps16x_poll - query the reciver peridically
- */
-static void
-gps16x_poll(
- struct peer *peer
- )
-{
- struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
-
- static GPS_MSG_HDR sequence[] =
- {
- { GPS_SW_REV, 0, 0, 0 },
- { GPS_STAT, 0, 0, 0 },
- { GPS_UTC, 0, 0, 0 },
- { GPS_ASCII_MSG, 0, 0, 0 },
- { GPS_ANT_INFO, 0, 0, 0 },
- { GPS_CFGH, 0, 0, 0 },
- { GPS_POS_XYZ, 0, 0, 0 },
- { GPS_POS_LLA, 0, 0, 0 },
- { (unsigned short)~0, 0, 0, 0 }
- };
-
- int rtc;
- unsigned char cmd_buffer[64];
- unsigned char *outp = cmd_buffer;
- GPS_MSG_HDR *header;
-
- if (((poll_info_t *)parse->parse_type->cl_data)->rate)
- {
- parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
- }
-
- if (sequence[parse->localstate].gps_cmd == (unsigned short)~0)
- parse->localstate = 0;
-
- header = sequence + parse->localstate++;
-
- *outp++ = SOH; /* start command */
-
- put_mbg_header(&outp, header);
- outp = cmd_buffer + 1;
-
- header->gps_hdr_csum = (short)mbg_csum(outp, 6);
- put_mbg_header(&outp, header);
-
-#ifdef DEBUG
- if (debug > 2)
- {
- char buffer[128];
-
- mkreadable(buffer, sizeof(buffer), (char *)cmd_buffer, (unsigned)(outp - cmd_buffer), 1);
- printf("PARSE receiver #%d: transmitted message #%ld (%d bytes) >%s<\n",
- CLK_UNIT(parse->peer),
- parse->localstate - 1,
- (int)(outp - cmd_buffer),
- buffer);
- }
-#endif
-
- rtc = write(parse->generic->io.fd, cmd_buffer, (unsigned long)(outp - cmd_buffer));
-
- if (rtc < 0)
- {
- ERR(ERR_BADIO)
- msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
- }
- else
- if (rtc != outp - cmd_buffer)
- {
- ERR(ERR_BADIO)
- msyslog(LOG_ERR, "PARSE receiver #%d: gps16x_poll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, (int)(outp - cmd_buffer));
- }
-
- clear_err(parse, ERR_BADIO);
- return;
-}
-
-/*--------------------------------------------------
- * init routine - setup timer
- */
-static int
-gps16x_poll_init(
- struct parseunit *parse
- )
-{
- if (((poll_info_t *)parse->parse_type->cl_data)->rate)
- {
- parse->peer->action = gps16x_poll;
- gps16x_poll(parse->peer);
- }
-
- return 0;
-}
-
-#else
-static void
-gps16x_message(
- struct parseunit *parse,
- parsetime_t *parsetime
- )
-{}
-static int
-gps16x_poll_init(
- struct parseunit *parse
- )
-{
- return 1;
-}
-#endif /* CLOCK_MEINBERG */
-
-/**===========================================================================
- ** clock polling support
- **/
-
-/*--------------------------------------------------
- * direct poll routine
- */
-static void
-poll_dpoll(
- struct parseunit *parse
- )
-{
- int rtc;
- const char *ps = ((poll_info_t *)parse->parse_type->cl_data)->string;
- int ct = ((poll_info_t *)parse->parse_type->cl_data)->count;
-
- rtc = write(parse->generic->io.fd, ps, (unsigned long)ct);
- if (rtc < 0)
- {
- ERR(ERR_BADIO)
- msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
- }
- else
- if (rtc != ct)
- {
- ERR(ERR_BADIO)
- msyslog(LOG_ERR, "PARSE receiver #%d: poll_dpoll: failed to send cmd incomplete (%d of %d bytes sent)", CLK_UNIT(parse->peer), rtc, ct);
- }
- clear_err(parse, ERR_BADIO);
-}
-
-/*--------------------------------------------------
- * periodic poll routine
- */
-static void
-poll_poll(
- struct peer *peer
- )
-{
- struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
-
- if (parse->parse_type->cl_poll)
- parse->parse_type->cl_poll(parse);
-
- if (((poll_info_t *)parse->parse_type->cl_data)->rate)
- {
- parse->peer->nextaction = current_time + ((poll_info_t *)parse->parse_type->cl_data)->rate;
- }
-}
-
-/*--------------------------------------------------
- * init routine - setup timer
- */
-static int
-poll_init(
- struct parseunit *parse
- )
-{
- if (((poll_info_t *)parse->parse_type->cl_data)->rate)
- {
- parse->peer->action = poll_poll;
- poll_poll(parse->peer);
- }
-
- return 0;
-}
-
-/**===========================================================================
- ** Trimble support
- **/
-
-/*-------------------------------------------------------------
- * trimble TAIP init routine - setup EOL and then do poll_init.
- */
-static int
-trimbletaip_init(
- struct parseunit *parse
- )
-{
-#ifdef HAVE_TERMIOS
- struct termios tio;
-#endif
-#ifdef HAVE_SYSV_TTYS
- struct termio tio;
-#endif
- /*
- * configure terminal line for trimble receiver
- */
- if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcgetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- else
- {
- tio.c_cc[VEOL] = TRIMBLETAIP_EOL;
-
- if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_init: tcsetattr(fd, &tio): %m", CLK_UNIT(parse->peer));
- return 0;
- }
- }
- return poll_init(parse);
-}
-
-/*--------------------------------------------------
- * trimble TAIP event routine - reset receiver upon data format trouble
- */
-static const char *taipinit[] = {
- ">FPV00000000<",
- ">SRM;ID_FLAG=F;CS_FLAG=T;EC_FLAG=F;FR_FLAG=T;CR_FLAG=F<",
- ">FTM00020001<",
- (char *)0
-};
-
-static void
-trimbletaip_event(
- struct parseunit *parse,
- int event
- )
-{
- switch (event)
- {
- case CEVNT_BADREPLY: /* reset on garbled input */
- case CEVNT_TIMEOUT: /* reset on no input */
- {
- const char **iv;
-
- iv = taipinit;
- while (*iv)
- {
- int rtc = write(parse->generic->io.fd, *iv, strlen(*iv));
- if (rtc < 0)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
- return;
- }
- else
- {
- if (rtc != strlen(*iv))
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: failed to send cmd incomplete (%d of %d bytes sent)",
- CLK_UNIT(parse->peer), rtc, (int)strlen(*iv));
- return;
- }
- }
- iv++;
- }
-
- NLOG(NLOG_CLOCKINFO)
- ERR(ERR_BADIO)
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletaip_event: RECEIVER INITIALIZED",
- CLK_UNIT(parse->peer));
- }
- break;
-
- default: /* ignore */
- break;
- }
-}
-
-/*
- * 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 ntpd 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 !
- *
- * CURRENT LIMITATION: float implementation. This runs only on systems
- * with IEEE754 floats as native floats
- */
-
-typedef struct trimble
-{
- u_long last_msg; /* last message received */
- u_char qtracking; /* query tracking status */
- u_long ctrack; /* current tracking set */
- u_long ltrack; /* last tracking set */
-} trimble_t;
-
-union uval {
- u_char bd[8];
- int iv;
- float fv;
- double dv;
-};
-
-struct txbuf
-{
- short idx; /* index to first unused byte */
- u_char *txt; /* pointer to actual data buffer */
-};
-
-void sendcmd P((struct txbuf *buf, int c));
-void sendbyte P((struct txbuf *buf, int b));
-void sendetx P((struct txbuf *buf, struct parseunit *parse));
-void sendint P((struct txbuf *buf, int a));
-void sendflt P((struct txbuf *buf, double a));
-
-void
-sendcmd(
- struct txbuf *buf,
- int c
- )
-{
- buf->txt[0] = DLE;
- buf->txt[1] = (u_char)c;
- buf->idx = 2;
-}
-
-void
-sendbyte(
- struct txbuf *buf,
- int b
- )
-{
- if (b == DLE)
- buf->txt[buf->idx++] = DLE;
- buf->txt[buf->idx++] = (u_char)b;
-}
-
-void
-sendetx(
- struct txbuf *buf,
- struct parseunit *parse
- )
-{
- buf->txt[buf->idx++] = DLE;
- buf->txt[buf->idx++] = ETX;
-
- if (write(parse->generic->io.fd, buf->txt, (unsigned long)buf->idx) != buf->idx)
- {
- ERR(ERR_BADIO)
- msyslog(LOG_ERR, "PARSE receiver #%d: sendetx: failed to send cmd to clock: %m", CLK_UNIT(parse->peer));
- }
- else
- {
-#ifdef DEBUG
- if (debug > 2)
- {
- char buffer[256];
-
- mkreadable(buffer, sizeof(buffer), (char *)buf->txt, (unsigned)buf->idx, 1);
- printf("PARSE receiver #%d: transmitted message (%d bytes) >%s<\n",
- CLK_UNIT(parse->peer),
- buf->idx, buffer);
- }
-#endif
- clear_err(parse, ERR_BADIO);
- }
-}
-
-void
-sendint(
- struct txbuf *buf,
- int a
- )
-{
- /* send 16bit int, msbyte first */
- sendbyte(buf, (u_char)((a>>8) & 0xff));
- sendbyte(buf, (u_char)(a & 0xff));
-}
-
-void
-sendflt(
- struct txbuf *buf,
- double a
- )
-{
- int i;
- union uval uval;
-
- uval.fv = a;
-#ifdef WORDS_BIGENDIAN
- for (i=0; i<=3; i++)
-#else
- for (i=3; i>=0; i--)
-#endif
- sendbyte(buf, uval.bd[i]);
-}
-
-#define TRIM_POS_OPT 0x13 /* output position with high precision */
-#define TRIM_TIME_OPT 0x03 /* use UTC time stamps, on second */
-
-/*--------------------------------------------------
- * trimble TSIP setup routine
- */
-static int
-trimbletsip_setup(
- struct parseunit *parse,
- const char *reason
- )
-{
- u_char buffer[256];
- struct txbuf buf;
-
- buf.txt = buffer;
-
- sendcmd(&buf, CMD_CVERSION); /* request software versions */
- sendetx(&buf, parse);
-
- sendcmd(&buf, CMD_COPERPARAM); /* 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, CMD_CMODESEL); /* fix mode select */
- sendbyte(&buf, 0); /* automatic */
- sendetx(&buf, parse);
-
- sendcmd(&buf, CMD_CMESSAGE); /* request system message */
- sendetx(&buf, parse);
-
- sendcmd(&buf, CMD_CSUPER); /* superpacket fix */
- sendbyte(&buf, 0x2); /* binary mode */
- sendetx(&buf, parse);
-
- sendcmd(&buf, CMD_CIOOPTIONS); /* set I/O options */
- sendbyte(&buf, TRIM_POS_OPT); /* position output */
- sendbyte(&buf, 0x00); /* no velocity output */
- sendbyte(&buf, TRIM_TIME_OPT); /* UTC, compute on seconds */
- sendbyte(&buf, 0x00); /* no raw measurements */
- sendetx(&buf, parse);
-
- sendcmd(&buf, CMD_CUTCPARAM); /* request UTC correction data */
- sendetx(&buf, parse);
-
- NLOG(NLOG_CLOCKINFO)
- ERR(ERR_BADIO)
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_setup: RECEIVER RE-INITIALIZED (%s)", CLK_UNIT(parse->peer), reason);
-
- return 0;
-}
-
-/*--------------------------------------------------
- * TRIMBLE TSIP check routine
- */
-static void
-trimble_check(
- struct peer *peer
- )
-{
- struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
- trimble_t *t = parse->localdata;
- u_char buffer[256];
- struct txbuf buf;
- buf.txt = buffer;
-
- if (t)
- {
- if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME)
- (void)trimbletsip_setup(parse, "message timeout");
- }
- poll_poll(parse->peer); /* emit query string and re-arm timer */
-
- if (t->qtracking)
- {
- u_long oldsats = t->ltrack & ~t->ctrack;
-
- t->qtracking = 0;
- t->ltrack = t->ctrack;
-
- if (oldsats)
- {
- int i;
-
- for (i = 0; oldsats; i++)
- if (oldsats & (1 << i))
- {
- sendcmd(&buf, CMD_CSTATTRACK);
- sendbyte(&buf, i+1); /* old sat */
- sendetx(&buf, parse);
- }
- oldsats &= ~(1 << i);
- }
-
- sendcmd(&buf, CMD_CSTATTRACK);
- sendbyte(&buf, 0x00); /* current tracking set */
- sendetx(&buf, parse);
- }
-}
-
-/*--------------------------------------------------
- * TRIMBLE TSIP end routine
- */
-static void
-trimbletsip_end(
- struct parseunit *parse
- )
-{ trimble_t *t = parse->localdata;
-
- if (t)
- {
- free(t);
- parse->localdata = (void *)0;
- }
- parse->peer->nextaction = 0;
- parse->peer->action = (void (*) P((struct peer *)))0;
-}
-
-/*--------------------------------------------------
- * TRIMBLE TSIP init routine
- */
-static int
-trimbletsip_init(
- struct parseunit *parse
- )
-{
-#if defined(VEOL) || defined(VEOL2)
-#ifdef HAVE_TERMIOS
- struct termios tio; /* NEEDED FOR A LONG TIME ! */
-#endif
-#ifdef HAVE_SYSV_TTYS
- struct termio tio; /* NEEDED FOR A LONG TIME ! */
-#endif
- /*
- * allocate local data area
- */
- if (!parse->localdata)
- {
- trimble_t *t;
-
- t = (trimble_t *)(parse->localdata = emalloc(sizeof(trimble_t)));
-
- if (t)
- {
- memset((char *)t, 0, sizeof(trimble_t));
- t->last_msg = current_time;
- }
- }
-
- parse->peer->action = trimble_check;
- parse->peer->nextaction = current_time;
-
- /*
- * configure terminal line for ICANON mode with VEOL characters
- */
- if (TTY_GETATTR(parse->generic->io.fd, &tio) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcgetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
- return 0;
- }
- else
- {
- if ((parse_clockinfo[CLK_TYPE(parse->peer)].cl_lflag & ICANON))
- {
-#ifdef VEOL
- tio.c_cc[VEOL] = ETX;
-#endif
-#ifdef VEOL2
- tio.c_cc[VEOL2] = DLE;
-#endif
- }
-
- if (TTY_SETATTR(parse->generic->io.fd, &tio) == -1)
- {
- msyslog(LOG_ERR, "PARSE receiver #%d: trimbletsip_init: tcsetattr(%d, &tio): %m", CLK_UNIT(parse->peer), parse->generic->io.fd);
- return 0;
- }
- }
-#endif
- return trimbletsip_setup(parse, "initial startup");
-}
-
-/*------------------------------------------------------------
- * trimbletsip_event - handle Trimble events
- * simple evente handler - attempt to re-initialize receiver
- */
-static void
-trimbletsip_event(
- struct parseunit *parse,
- int event
- )
-{
- switch (event)
- {
- case CEVNT_BADREPLY: /* reset on garbled input */
- case CEVNT_TIMEOUT: /* reset on no input */
- (void)trimbletsip_setup(parse, "event BAD_REPLY/TIMEOUT");
- break;
-
- default: /* ignore */
- break;
- }
-}
-
-/*
- * getflt, 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(
- u_char *bp
- )
-{
- union uval uval;
-
-#ifdef WORDS_BIGENDIAN
- uval.bd[0] = *bp++;
- uval.bd[1] = *bp++;
- uval.bd[2] = *bp++;
- uval.bd[3] = *bp;
-#else /* ! WORDS_BIGENDIAN */
- uval.bd[3] = *bp++;
- uval.bd[2] = *bp++;
- uval.bd[1] = *bp++;
- uval.bd[0] = *bp;
-#endif /* ! WORDS_BIGENDIAN */
- return uval.fv;
-}
-
-static double
-getdbl(
- u_char *bp
- )
-{
- union uval uval;
-
-#ifdef WORDS_BIGENDIAN
- 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;
-#else /* ! WORDS_BIGENDIAN */
- uval.bd[7] = *bp++;
- uval.bd[6] = *bp++;
- uval.bd[5] = *bp++;
- uval.bd[4] = *bp++;
- uval.bd[3] = *bp++;
- uval.bd[2] = *bp++;
- uval.bd[1] = *bp++;
- uval.bd[0] = *bp;
-#endif /* ! WORDS_BIGENDIAN */
- return uval.dv;
-}
-
-static int
-getshort(
- unsigned char *p
- )
-{
- return get_msb_short(&p);
-}
-
-/*--------------------------------------------------
- * trimbletsip_message - process trimble messages
- */
-#define RTOD (180.0 / 3.1415926535898)
-#define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */
-
-static void
-trimbletsip_message(
- struct parseunit *parse,
- parsetime_t *parsetime
- )
-{
- unsigned char *buffer = parsetime->parse_msg;
- unsigned int size = parsetime->parse_msglen;
-
- if ((size < 4) ||
- (buffer[0] != DLE) ||
- (buffer[size-1] != ETX) ||
- (buffer[size-2] != DLE))
- {
-#ifdef DEBUG
- if (debug > 2) {
- int i;
-
- printf("TRIMBLE 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;
- }
- else
- {
- int var_flag;
- trimble_t *tr = parse->localdata;
- unsigned int cmd = buffer[1];
- char pbuffer[200];
- char *t = pbuffer;
- cmd_info_t *s;
-
-#ifdef DEBUG
- if (debug > 3) {
- int i;
-
- printf("TRIMBLE packet 0x%02x, size %d:\n ", cmd, size);
- for (i = 0; i < size; i++) {
- printf ("%2.2x, ", buffer[i]&0xff);
- if (i%16 == 15) printf("\n\t");
- }
- printf("\n");
- }
-#endif
-
- if (tr)
- tr->last_msg = current_time;
-
- s = trimble_convert(cmd, trimble_rcmds);
-
- if (s)
- {
- sprintf(t, "%s=\"", s->varname);
- }
- else
- {
- printf("TRIMBLE unknown command 0x%02x\n", cmd);
- return;
- }
-
- var_flag = s->varmode;
-
- t += strlen(t);
-
- switch(cmd)
- {
- case CMD_RCURTIME:
- sprintf(t, "%f, %d, %f",
- getflt((unsigned char *)&mb(0)), getshort((unsigned char *)&mb(4)),
- getflt((unsigned char *)&mb(6)));
- break;
-
- case CMD_RBEST4:
- strcpy(t, "mode: ");
- t += strlen(t);
- switch (mb(0) & 0xF)
- {
- default:
- sprintf(t, "0x%x", mb(0) & 0x7);
- break;
-
- case 1:
- strcat(t, "0D");
- break;
-
- case 3:
- strcat(t, "2D");
- break;
-
- case 4:
- strcat(t, "3D");
- break;
- }
- t += strlen(t);
- if (mb(0) & 0x10)
- strcpy(t, "-MANUAL, ");
- else
- strcpy(t, "-AUTO, ");
- t += strlen(t);
-
- sprintf(t, "satellites %02d %02d %02d %02d, PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f",
- mb(1), mb(2), mb(3), mb(4),
- getflt((unsigned char *)&mb(5)),
- getflt((unsigned char *)&mb(9)),
- getflt((unsigned char *)&mb(13)),
- getflt((unsigned char *)&mb(17)));
-
- break;
-
- case CMD_RVERSION:
- sprintf(t, "%d.%d (%d/%d/%d)",
- mb(0)&0xff, mb(1)&0xff, 1900+(mb(4)&0xff), mb(2)&0xff, mb(3)&0xff);
- break;
-
- case CMD_RRECVHEALTH:
- {
- static const char *msgs[] =
- {
- "Battery backup failed",
- "Signal processor error",
- "Alignment error, channel or chip 1",
- "Alignment error, channel or chip 2",
- "Antenna feed line fault",
- "Excessive ref freq. error",
- "<BIT 6>",
- "<BIT 7>"
- };
-
- int i, bits;
-
- switch (mb(0) & 0xFF)
- {
- default:
- sprintf(t, "illegal value 0x%02x", mb(0) & 0xFF);
- break;
- case 0x00:
- strcpy(t, "doing position fixes");
- break;
- case 0x01:
- strcpy(t, "no GPS time yet");
- break;
- case 0x03:
- strcpy(t, "PDOP too high");
- break;
- case 0x08:
- strcpy(t, "no usable satellites");
- break;
- case 0x09:
- strcpy(t, "only ONE usable satellite");
- break;
- case 0x0A:
- strcpy(t, "only TWO usable satellites");
- break;
- case 0x0B:
- strcpy(t, "only THREE usable satellites");
- break;
- case 0x0C:
- strcpy(t, "the chosen satellite is unusable");
- break;
- }
-
- t += strlen(t);
-
- bits = mb(1) & 0xFF;
-
- for (i = 0; i < 8; i++)
- if (bits & (0x1<<i))
- {
- sprintf(t, ", %s", msgs[i]);
- t += strlen(t);
- }
- }
- break;
-
- case CMD_RMESSAGE:
- mkreadable(t, (int)(sizeof(pbuffer) - (t - pbuffer)), (char *)&mb(0), (unsigned)(size - 2 - (&mb(0) - buffer)), 0);
- break;
-
- case CMD_RMACHSTAT:
- {
- static const char *msgs[] =
- {
- "Synthesizer Fault",
- "Battery Powered Time Clock Fault",
- "A-to-D Converter Fault",
- "The almanac stored in the receiver is not complete and current",
- "<BIT 4>",
- "<BIT 5",
- "<BIT 6>",
- "<BIT 7>"
- };
-
- int i, bits;
-
- sprintf(t, "machine id 0x%02x", mb(0) & 0xFF);
- t += strlen(t);
-
- bits = mb(1) & 0xFF;
-
- for (i = 0; i < 8; i++)
- if (bits & (0x1<<i))
- {
- sprintf(t, ", %s", msgs[i]);
- t += strlen(t);
- }
-
- sprintf(t, ", Superpackets %ssupported", (mb(2) & 0xFF) ? "" :"un" );
- }
- break;
-
- case CMD_ROPERPARAM:
- sprintf(t, "%2x %.1f %.1f %.1f %.1f",
- mb(0), getflt((unsigned char *)&mb(1)), getflt((unsigned char *)&mb(5)),
- getflt((unsigned char *)&mb(9)), getflt((unsigned char *)&mb(13)));
- break;
-
- case CMD_RUTCPARAM:
- {
- float t0t = getflt((unsigned char *)&mb(14));
- short wnt = getshort((unsigned char *)&mb(18));
- short dtls = getshort((unsigned char *)&mb(12));
- short wnlsf = getshort((unsigned char *)&mb(20));
- short dn = getshort((unsigned char *)&mb(22));
- short dtlsf = getshort((unsigned char *)&mb(24));
-
- if ((int)t0t != 0)
- {
- mk_utcinfo(t, wnt, wnlsf, dn, dtls, dtlsf);
- }
- else
- {
- strcpy(t, "<NO UTC DATA>");
- }
- }
- break;
-
- case CMD_RSAT1BIAS:
- sprintf(t, "%.1fm %.2fm/s at %.1fs",
- getflt(&mb(0)), getflt(&mb(4)), getflt(&mb(8)));
- break;
-
- case CMD_RIOOPTIONS:
- {
- sprintf(t, "%02x %02x %02x %02x",
- mb(0), mb(1), mb(2), mb(3));
- if (mb(0) != TRIM_POS_OPT ||
- mb(2) != TRIM_TIME_OPT)
- {
- (void)trimbletsip_setup(parse, "bad io options");
- }
- }
- break;
-
- case CMD_RSPOSXYZ:
- {
- double x = getflt((unsigned char *)&mb(0));
- double y = getflt((unsigned char *)&mb(4));
- double z = getflt((unsigned char *)&mb(8));
- double f = getflt((unsigned char *)&mb(12));
-
- if (f > 0.0)
- sprintf(t, "x= %.1fm, y= %.1fm, z= %.1fm, time_of_fix= %f sec",
- x, y, z,
- f);
- else
- return;
- }
- break;
-
- case CMD_RSLLAPOS:
- {
- double lat = getflt((unsigned char *)&mb(0));
- double lng = getflt((unsigned char *)&mb(4));
- double f = getflt((unsigned char *)&mb(12));
-
- if (f > 0.0)
- sprintf(t, "lat %f %c, long %f %c, alt %.2fm",
- ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
- ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
- getflt((unsigned char *)&mb(8)));
- else
- return;
- }
- break;
-
- case CMD_RDOUBLEXYZ:
- {
- double x = getdbl((unsigned char *)&mb(0));
- double y = getdbl((unsigned char *)&mb(8));
- double z = getdbl((unsigned char *)&mb(16));
- sprintf(t, "x= %.1fm, y= %.1fm, z= %.1fm",
- x, y, z);
- }
- break;
-
- case CMD_RDOUBLELLA:
- {
- double lat = getdbl((unsigned char *)&mb(0));
- double lng = getdbl((unsigned char *)&mb(8));
- sprintf(t, "lat %f %c, lon %f %c, alt %.2fm",
- ((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
- ((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
- getdbl((unsigned char *)&mb(16)));
- }
- break;
-
- case CMD_RALLINVIEW:
- {
- int i, sats;
-
- strcpy(t, "mode: ");
- t += strlen(t);
- switch (mb(0) & 0x7)
- {
- default:
- sprintf(t, "0x%x", mb(0) & 0x7);
- break;
-
- case 3:
- strcat(t, "2D");
- break;
-
- case 4:
- strcat(t, "3D");
- break;
- }
- t += strlen(t);
- if (mb(0) & 0x8)
- strcpy(t, "-MANUAL, ");
- else
- strcpy(t, "-AUTO, ");
- t += strlen(t);
-
- sats = (mb(0)>>4) & 0xF;
-
- sprintf(t, "PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f, %d satellite%s in view: ",
- getflt((unsigned char *)&mb(1)),
- getflt((unsigned char *)&mb(5)),
- getflt((unsigned char *)&mb(9)),
- getflt((unsigned char *)&mb(13)),
- sats, (sats == 1) ? "" : "s");
- t += strlen(t);
-
- for (i=0; i < sats; i++)
- {
- sprintf(t, "%s%02d", i ? ", " : "", mb(17+i));
- t += strlen(t);
- if (tr)
- tr->ctrack |= (1 << (mb(17+i)-1));
- }
-
- if (tr)
- { /* mark for tracking status query */
- tr->qtracking = 1;
- }
- }
- break;
-
- case CMD_RSTATTRACK:
- {
- sprintf(t-2, "[%02d]=\"", mb(0)); /* add index to var name */
- t += strlen(t);
-
- if (getflt((unsigned char *)&mb(4)) < 0.0)
- {
- strcpy(t, "<NO MEASUREMENTS>");
- var_flag &= ~DEF;
- }
- else
- {
- sprintf(t, "ch=%d, acq=%s, eph=%d, signal_level= %5.2f, elevation= %5.2f, azimuth= %6.2f",
- (mb(1) & 0xFF)>>3,
- mb(2) ? ((mb(2) == 1) ? "ACQ" : "SRCH") : "NEVER",
- mb(3),
- getflt((unsigned char *)&mb(4)),
- getflt((unsigned char *)&mb(12)) * RTOD,
- getflt((unsigned char *)&mb(16)) * RTOD);
- t += strlen(t);
- if (mb(20))
- {
- var_flag &= ~DEF;
- strcpy(t, ", OLD");
- }
- t += strlen(t);
- if (mb(22))
- {
- if (mb(22) == 1)
- strcpy(t, ", BAD PARITY");
- else
- if (mb(22) == 2)
- strcpy(t, ", BAD EPH HEALTH");
- }
- t += strlen(t);
- if (mb(23))
- strcpy(t, ", collecting data");
- }
- }
- break;
-
- default:
- strcpy(t, "<UNDECODED>");
- break;
- }
- strcat(t,"\"");
- set_var(&parse->kv, pbuffer, sizeof(pbuffer), var_flag);
- }
-}
-
-
-/**============================================================
- ** RAWDCF support
- **/
-
-/*--------------------------------------------------
- * rawdcf_init_1 - set up modem lines for RAWDCF receivers
- * SET DTR line
- */
-#if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
-static int
-rawdcf_init_1(
- struct parseunit *parse
- )
-{
- /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
- /*
- * You can use the RS232 to supply the power for a DCF77 receiver.
- * Here a voltage between the DTR and the RTS line is used. Unfortunately
- * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
- */
- int sl232;
-
- if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
- return 0;
- }
-
-#ifdef TIOCM_DTR
- sl232 = (sl232 & ~TIOCM_RTS) | TIOCM_DTR; /* turn on DTR, clear RTS for power supply */
-#else
- sl232 = (sl232 & ~CIOCM_RTS) | CIOCM_DTR; /* turn on DTR, clear RTS for power supply */
-#endif
-
- if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
- }
- return 0;
-}
-#else
-static int
-rawdcfdtr_init_1(
- struct parseunit *parse
- )
-{
- msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: OS interface incapable of setting DTR to power DCF modules", CLK_UNIT(parse->peer));
- return 0;
-}
-#endif /* DTR initialisation type */
-
-/*--------------------------------------------------
- * rawdcf_init_2 - set up modem lines for RAWDCF receivers
- * CLR DTR line, SET RTS line
- */
-#if defined(TIOCMSET) && (defined(TIOCM_RTS) || defined(CIOCM_RTS))
-static int
-rawdcf_init_2(
- struct parseunit *parse
- )
-{
- /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
- /*
- * You can use the RS232 to supply the power for a DCF77 receiver.
- * Here a voltage between the DTR and the RTS line is used. Unfortunately
- * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
- */
- int sl232;
-
- if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
- return 0;
- }
-
-#ifdef TIOCM_RTS
- sl232 = (sl232 & ~TIOCM_DTR) | TIOCM_RTS; /* turn on RTS, clear DTR for power supply */
-#else
- sl232 = (sl232 & ~CIOCM_DTR) | CIOCM_RTS; /* turn on RTS, clear DTR for power supply */
-#endif
-
- if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
- {
- msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
- }
- return 0;
-}
-#else
-static int
-rawdcf_init_2(
- struct parseunit *parse
- )
-{
- msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: OS interface incapable of setting RTS to power DCF modules", CLK_UNIT(parse->peer));
- return 0;
-}
-#endif /* DTR initialisation type */
-
-#else /* defined(REFCLOCK) && defined(PARSE) */
-int refclock_parse_bs;
-#endif /* defined(REFCLOCK) && defined(PARSE) */
-
-/*
- * History:
- *
- * refclock_parse.c,v
- * Revision 4.36 1999/11/28 17:18:20 kardel
- * disabled burst mode
- *
- * Revision 4.35 1999/11/28 09:14:14 kardel
- * RECON_4_0_98F
- *
- * Revision 4.34 1999/05/14 06:08:05 kardel
- * store current_time in a suitable container (u_long)
- *
- * Revision 4.33 1999/05/13 21:48:38 kardel
- * double the no response timeout interval
- *
- * Revision 4.32 1999/05/13 20:09:13 kardel
- * complain only about missing polls after a full poll interval
- *
- * Revision 4.31 1999/05/13 19:59:32 kardel
- * add clock type 16 for RTS set DTR clr in RAWDCF
- *
- * Revision 4.30 1999/02/28 20:36:43 kardel
- * fixed printf fmt
- *
- * Revision 4.29 1999/02/28 19:58:23 kardel
- * updated copyright information
- *
- * Revision 4.28 1999/02/28 19:01:50 kardel
- * improved debug out on sent Meinberg messages
- *
- * Revision 4.27 1999/02/28 18:05:55 kardel
- * no linux/ppsclock.h stuff
- *
- * Revision 4.26 1999/02/28 15:27:27 kardel
- * wharton clock integration
- *
- * Revision 4.25 1999/02/28 14:04:46 kardel
- * added missing double quotes to UTC information string
- *
- * Revision 4.24 1999/02/28 12:06:50 kardel
- * (parse_control): using gmprettydate instead of prettydate()
- * (mk_utcinfo): new function for formatting GPS derived UTC information
- * (gps16x_message): changed to use mk_utcinfo()
- * (trimbletsip_message): changed to use mk_utcinfo()
- * ignoring position information in unsynchronized mode
- * (parse_start): augument linux support for optional ASYNC_LOW_LATENCY
- *
- * Revision 4.23 1999/02/23 19:47:53 kardel
- * fixed #endifs
- * (stream_receive): fixed formats
- *
- * Revision 4.22 1999/02/22 06:21:02 kardel
- * use new autoconfig symbols
- *
- * Revision 4.21 1999/02/21 12:18:13 kardel
- * 4.91f reconcilation
- *
- * Revision 4.20 1999/02/21 10:53:36 kardel
- * initial Linux PPSkit version
- *
- * Revision 4.19 1999/02/07 09:10:45 kardel
- * clarify STREAMS mitigation rules in comment
- *
- * Revision 4.18 1998/12/20 23:45:34 kardel
- * fix types and warnings
- *
- * Revision 4.17 1998/11/15 21:24:51 kardel
- * cannot access mbg_ routines when CLOCK_MEINBERG
- * is not defined
- *
- * Revision 4.16 1998/11/15 20:28:17 kardel
- * Release 4.0.73e13 reconcilation
- *
- * Revision 4.15 1998/08/22 21:56:08 kardel
- * fixed IO handling for non-STREAM IO
- *
- * Revision 4.14 1998/08/16 19:00:48 kardel
- * (gps16x_message): reduced UTC parameter information (dropped A0,A1)
- * made uval a local variable (killed one of the last globals)
- * (sendetx): added logging of messages when in debug mode
- * (trimble_check): added periodic checks to facilitate re-initialization
- * (trimbletsip_init): made use of EOL character if in non-kernel operation
- * (trimbletsip_message): extended message interpretation
- * (getdbl): fixed data conversion
- *
- * Revision 4.13 1998/08/09 22:29:13 kardel
- * Trimble TSIP support
- *
- * Revision 4.12 1998/07/11 10:05:34 kardel
- * Release 4.0.73d reconcilation
- *
- * Revision 4.11 1998/06/14 21:09:42 kardel
- * Sun acc cleanup
- *
- * Revision 4.10 1998/06/13 12:36:45 kardel
- * signed/unsigned, name clashes
- *
- * Revision 4.9 1998/06/12 15:30:00 kardel
- * prototype fixes
- *
- * Revision 4.8 1998/06/12 11:19:42 kardel
- * added direct input processing routine for refclocks in
- * order to avaiod that single character io gobbles up all
- * receive buffers and drops input data. (Problem started
- * with fast machines so a character a buffer was possible
- * one of the few cases where faster machines break existing
- * allocation algorithms)
- *
- * Revision 4.7 1998/06/06 18:35:20 kardel
- * (parse_start): added BURST mode initialisation
- *
- * Revision 4.6 1998/05/27 06:12:46 kardel
- * RAWDCF_BASEDELAY default added
- * old comment removed
- * casts for ioctl()
- *
- * Revision 4.5 1998/05/25 22:05:09 kardel
- * RAWDCF_SETDTR option removed
- * clock type 14 attempts to set DTR for
- * power supply of RAWDCF receivers
- *
- * Revision 4.4 1998/05/24 16:20:47 kardel
- * updated comments referencing Meinberg clocks
- * added RAWDCF clock with DTR set option as type 14
- *
- * Revision 4.3 1998/05/24 10:48:33 kardel
- * calibrated CONRAD RAWDCF default fudge factor
- *
- * Revision 4.2 1998/05/24 09:59:35 kardel
- * corrected version information (ntpq support)
- *
- * Revision 4.1 1998/05/24 09:52:31 kardel
- * use fixed format only (new IO model)
- * output debug to stdout instead of msyslog()
- * don't include >"< in ASCII output in order not to confuse
- * ntpq parsing
- *
- * Revision 4.0 1998/04/10 19:52:11 kardel
- * Start 4.0 release version numbering
- *
- * Revision 1.2 1998/04/10 19:28:04 kardel
- * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
- * derived from 3.105.1.2 from V3 tree
- *
- * Revision information 3.1 - 3.105 from log deleted 1998/04/10 kardel
- *
- */
diff --git a/contrib/ntp/ntpd/refclock_pcf.c b/contrib/ntp/ntpd/refclock_pcf.c
deleted file mode 100644
index d4e9fd1..0000000
--- a/contrib/ntp/ntpd/refclock_pcf.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * refclock_pcf - clock driver for the Conrad parallel port radio clock
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_PCF)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-/*
- * This driver supports the parallel port radio clock sold by Conrad
- * Electronic under order numbers 967602 and 642002.
- *
- * It requires that the local timezone be CET/CEST and that the pcfclock
- * device driver be installed. A device driver for Linux is available at
- * http://home.pages.de/~voegele/pcf.html. Information about a FreeBSD
- * driver is available at http://schumann.cx/pcfclock/.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/pcfclocks/%d"
-#define OLDDEVICE "/dev/pcfclock%d"
-#define PRECISION (-1) /* precision assumed (about 0.5 s) */
-#define REFID "PCF"
-#define DESCRIPTION "Conrad parallel port radio clock"
-
-#define LENPCF 18 /* timecode length */
-
-/*
- * Function prototypes
- */
-static int pcf_start P((int, struct peer *));
-static void pcf_shutdown P((int, struct peer *));
-static void pcf_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_pcf = {
- pcf_start, /* start up driver */
- pcf_shutdown, /* shut down driver */
- pcf_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-
-
-/*
- * pcf_start - open the device and initialize data for processing
- */
-static int
-pcf_start(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- int fd;
- char device[128];
-
- /*
- * Open device file for reading.
- */
- (void)sprintf(device, DEVICE, unit);
- fd = open(device, O_RDONLY);
- if (fd == -1) {
- (void)sprintf(device, OLDDEVICE, unit);
- fd = open(device, O_RDONLY);
- }
-#ifdef DEBUG
- if (debug)
- printf ("starting PCF with device %s\n",device);
-#endif
- if (fd == -1) {
- return (0);
- }
-
- pp = peer->procptr;
- pp->io.clock_recv = noentry;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- /* one transmission takes 172.5 milliseconds since the radio clock
- transmits 69 bits with a period of 2.5 milliseconds per bit */
- pp->fudgetime1 = 0.1725;
- memcpy((char *)&pp->refid, REFID, 4);
-
- return (1);
-}
-
-
-/*
- * pcf_shutdown - shut down the clock
- */
-static void
-pcf_shutdown(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
- (void)close(pp->io.fd);
-}
-
-
-/*
- * pcf_poll - called by the transmit procedure
- */
-static void
-pcf_poll(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- char buf[LENPCF];
- struct tm tm, *tp;
- time_t t;
-
- pp = peer->procptr;
-
- buf[0] = 0;
- if (read(pp->io.fd, buf, sizeof(buf)) < sizeof(buf) || buf[0] != 9) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
-
- tm.tm_mday = buf[11] * 10 + buf[10];
- tm.tm_mon = buf[13] * 10 + buf[12] - 1;
- tm.tm_year = buf[15] * 10 + buf[14];
- tm.tm_hour = buf[7] * 10 + buf[6];
- tm.tm_min = buf[5] * 10 + buf[4];
- tm.tm_sec = buf[3] * 10 + buf[2];
- tm.tm_isdst = (buf[8] & 1) ? 1 : (buf[8] & 2) ? 0 : -1;
-
- /*
- * Y2K convert the 2-digit year
- */
- if (tm.tm_year < 99)
- tm.tm_year += 100;
-
- t = mktime(&tm);
- if (t == (time_t) -1) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
-#if defined(__GLIBC__) && defined(_BSD_SOURCE)
- if ((tm.tm_isdst > 0 && tm.tm_gmtoff != 7200)
- || (tm.tm_isdst == 0 && tm.tm_gmtoff != 3600)
- || tm.tm_isdst < 0) {
-#ifdef DEBUG
- if (debug)
- printf ("local time zone not set to CET/CEST\n");
-#endif
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-#endif
-
- pp->lencode = strftime(pp->a_lastcode, BMAX, "%Y %m %d %H %M %S", &tm);
-
-#if defined(_REENTRANT) || defined(_THREAD_SAFE)
- tp = gmtime_r(&t, &tm);
-#else
- tp = gmtime(&t);
-#endif
- if (!tp) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
-
- get_systime(&pp->lastrec);
- pp->polls++;
- pp->year = tp->tm_year + 1900;
- pp->day = tp->tm_yday + 1;
- pp->hour = tp->tm_hour;
- pp->minute = tp->tm_min;
- pp->second = tp->tm_sec;
- pp->nsec = buf[16] * 31250000;
- if (buf[17] & 1)
- pp->nsec += 500000000;
-
-#ifdef DEBUG
- if (debug)
- printf ("pcf%d: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n",
- unit, pp->year, tp->tm_mon + 1, tp->tm_mday, pp->hour,
- pp->minute, pp->second);
-#endif
-
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- if ((buf[1] & 1) && !(pp->sloppyclockflag & CLK_FLAG2))
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-}
-#else
-int refclock_pcf_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_pst.c b/contrib/ntp/ntpd/refclock_pst.c
deleted file mode 100644
index 2443b2c..0000000
--- a/contrib/ntp/ntpd/refclock_pst.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * refclock_pst - clock driver for PSTI/Traconex WWV/WWVH receivers
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_PST)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * 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 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 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.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/wwv%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 */
-#define PST_PHI (10e-6) /* max clock oscillator offset */
-#define LENPST 46 /* min timecode length */
-
-/*
- * Unit control structure
- */
-struct pstunit {
- int tcswitch; /* timecode switch */
- char *lastptr; /* pointer to timecode data */
-};
-
-/*
- * Function prototypes
- */
-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_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_pst = {
- 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_start - open the devices and initialize data for processing
- */
-static int
-pst_start(
- int unit,
- struct peer *peer
- )
-{
- register struct pstunit *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 pstunit *)emalloc(sizeof(struct pstunit)))) {
- (void) close(fd);
- return (0);
- }
- 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);
- }
- pp->unitptr = (caddr_t)up;
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, WWVREFID, 4);
- peer->burst = MAXSTAGE;
- return (1);
-}
-
-
-/*
- * pst_shutdown - shut down the clock
- */
-static void
-pst_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct pstunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct pstunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * pst_receive - receive data from the serial interface
- */
-static void
-pst_receive(
- struct recvbuf *rbufp
- )
-{
- 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 */
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct pstunit *)pp->unitptr;
- up->lastptr += refclock_gtlin(rbufp, up->lastptr, pp->a_lastcode
- + BMAX - 2 - up->lastptr, &trtmp);
- *up->lastptr++ = ' ';
- *up->lastptr = '\0';
-
- /*
- * Note we get a buffer and timestamp for each <cr>, but only
- * the first timestamp is retained.
- */
- if (up->tcswitch == 0)
- pp->lastrec = trtmp;
- up->tcswitch++;
- pp->lencode = up->lastptr - pp->a_lastcode;
- if (up->tcswitch < 3)
- return;
-
- /*
- * 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 < LENPST) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Timecode format:
- * "ahh:mm:ss.fffs yy/dd/mm/ddd frdzycchhSSFTttttuuxx"
- */
- if (sscanf(pp->a_lastcode,
- "%c%2d:%2d:%2d.%3ld%c %9s%3d%13s%4ld",
- &ampmchar, &pp->hour, &pp->minute, &pp->second, &pp->nsec,
- &daychar, junque, &pp->day, info, &ltemp) != 10) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
- pp->nsec *= 1000000;
-
- /*
- * 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.
- */
- if (info[9] != '8')
- pp->leap = LEAP_NOTINSYNC;
- if (info[12] == 'H')
- memcpy((char *)&pp->refid, WWVHREFID, 4);
- else
- memcpy((char *)&pp->refid, WWVREFID, 4);
- if (peer->stratum <= 1)
- peer->refid = pp->refid;
- if (ltemp == 0)
- pp->lastref = pp->lastrec;
- pp->disp = PST_PHI * ltemp * 60;
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if (!refclock_process(pp))
- refclock_report(peer, CEVNT_BADTIME);
-
-}
-
-
-/*
- * pst_poll - called by the transmit procedure
- */
-static void
-pst_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct pstunit *up;
- struct refclockproc *pp;
-
- /*
- * Time to poll the clock. The PSTI/Traconex clock responds to a
- * "QTQDQMT" by returning a timecode in the format 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 the clock
- * becomes unreachable, declare a timeout and keep going.
- */
- pp = peer->procptr;
- up = (struct pstunit *)pp->unitptr;
- up->tcswitch = 0;
- up->lastptr = pp->a_lastcode;
- if (write(pp->io.fd, "QTQDQMT", 6) != 6)
- refclock_report(peer, CEVNT_FAULT);
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("pst: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
- peer->burst = MAXSTAGE;
- pp->polls++;
-}
-
-#else
-int refclock_pst_int;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_ptbacts.c b/contrib/ntp/ntpd/refclock_ptbacts.c
deleted file mode 100644
index 09d7bf4..0000000
--- a/contrib/ntp/ntpd/refclock_ptbacts.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * crude hack to avoid hard links in distribution
- * and keep only one ACTS type source for different
- * ACTS refclocks
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_PTBACTS)
-# define KEEPPTBACTS
-# include "refclock_acts.c"
-#else /* not (REFCLOCK && CLOCK_PTBACTS) */
-int refclock_ptbacts_bs;
-#endif /* not (REFCLOCK && CLOCK_PTBACTS) */
diff --git a/contrib/ntp/ntpd/refclock_ripencc.c b/contrib/ntp/ntpd/refclock_ripencc.c
deleted file mode 100644
index 6337f63..0000000
--- a/contrib/ntp/ntpd/refclock_ripencc.c
+++ /dev/null
@@ -1,4870 +0,0 @@
-/*
- * $Id: refclock_ripencc.c,v 1.13 2002/06/18 14:20:55 marks Exp marks $
- *
- * Copyright (c) 2002 RIPE NCC
- *
- * All Rights Reserved
- *
- * 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 appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of the author not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
- * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
- * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- *
- *
- * This driver was developed for use with the RIPE NCC TTM project.
- *
- *
- * The initial driver was developed by Daniel Karrenberg <dfk@ripe.net>
- * using the code made available by Trimble. This was for xntpd-3.x.x
- *
- * Rewrite of the driver for ntpd-4.x.x by Mark Santcroos <marks@ripe.net>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#if defined(REFCLOCK) && defined(CLOCK_RIPENCC)
-
-#include "ntp_stdlib.h"
-#include "ntpd.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_io.h"
-
-#ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-#else /* HAVE_TIMEPPS_H */
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif /* HAVE_SYS_TIMEPPS_H */
-#endif /* HAVE_TIMEPPS_H */
-
-/*
- * Definitions
- */
-
-/* we are on little endian */
-#define BYTESWAP
-
-/*
- * DEBUG statements: uncomment if necessary
- */
-/* #define DEBUG_NCC */ /* general debug statements */
-/* #define DEBUG_PPS */ /* debug pps */
-/* #define DEBUG_RAW */ /* print raw packets */
-
-#define TRIMBLE_OUTPUT_FUNC
-#define TSIP_VERNUM "7.12a"
-
-#ifndef FALSE
-#define FALSE (0)
-#define TRUE (!FALSE)
-#endif /* FALSE */
-
-#define GPS_PI (3.1415926535898)
-#define GPS_C (299792458.)
-#define D2R (GPS_PI/180.0)
-#define R2D (180.0/GPS_PI)
-#define WEEK (604800.)
-#define MAXCHAN (8)
-
-/* control characters for TSIP packets */
-#define DLE (0x10)
-#define ETX (0x03)
-
-#define MAX_RPTBUF (256)
-
-/* values of TSIPPKT.status */
-#define TSIP_PARSED_EMPTY 0
-#define TSIP_PARSED_FULL 1
-#define TSIP_PARSED_DLE_1 2
-#define TSIP_PARSED_DATA 3
-#define TSIP_PARSED_DLE_2 4
-
-#define UTCF_UTC_AVAIL (unsigned char) (1) /* UTC available */
-#define UTCF_LEAP_SCHD (unsigned char) (1<<4) /* Leap scheduled */
-#define UTCF_LEAP_PNDG (unsigned char) (1<<5) /* Leap pending, will occur at end of day */
-
-#define DEVICE "/dev/gps%d" /* name of radio device */
-#define PRECISION (-9) /* precision assumed (about 2 ms) */
-#define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS\0" /* reference id */
-#define REFID_LEN 4
-#define DESCRIPTION "RIPE NCC GPS (Palisade)" /* Description */
-#define SPEED232 B9600 /* 9600 baud */
-
-#define NSAMPLES 3 /* stages of median filter */
-
-/* Structures */
-
-/* TSIP packets have the following structure, whether report or command. */
-typedef struct {
- short
- counter, /* counter */
- len; /* size of buf; < MAX_RPTBUF unsigned chars */
- unsigned char
- status, /* TSIP packet format/parse status */
- code, /* TSIP code */
- buf[MAX_RPTBUF];/* report or command string */
-} TSIPPKT;
-
-/* TSIP binary data structures */
-typedef struct {
- unsigned char
- t_oa_raw, SV_health;
- float
- e, t_oa, i_0, OMEGADOT, sqrt_A,
- OMEGA_0, omega, M_0, a_f0, a_f1,
- Axis, n, OMEGA_n, ODOT_n, t_zc;
- short
- weeknum, wn_oa;
-} ALM_INFO;
-
-typedef struct { /* Almanac health page (25) parameters */
- unsigned char
- WN_a, SV_health[32], t_oa;
-} ALH_PARMS;
-
-typedef struct { /* Universal Coordinated Time (UTC) parms */
- double
- A_0;
- float
- A_1;
- short
- delta_t_LS;
- float
- t_ot;
- short
- WN_t, WN_LSF, DN, delta_t_LSF;
-} UTC_INFO;
-
-typedef struct { /* Ionospheric info (float) */
- float
- alpha_0, alpha_1, alpha_2, alpha_3,
- beta_0, beta_1, beta_2, beta_3;
-} ION_INFO;
-
-typedef struct { /* Subframe 1 info (float) */
- short
- weeknum;
- unsigned char
- codeL2, L2Pdata, SVacc_raw, SV_health;
- short
- IODC;
- float
- T_GD, t_oc, a_f2, a_f1, a_f0, SVacc;
-} EPHEM_CLOCK;
-
-typedef struct { /* Ephemeris info (float) */
- unsigned char
- IODE, fit_interval;
- float
- C_rs, delta_n;
- double
- M_0;
- float
- C_uc;
- double
- e;
- float
- C_us;
- double
- sqrt_A;
- float
- t_oe, C_ic;
- double
- OMEGA_0;
- float
- C_is;
- double
- i_0;
- float
- C_rc;
- double
- omega;
- float
- OMEGADOT, IDOT;
- double
- Axis, n, r1me2, OMEGA_n, ODOT_n;
-} EPHEM_ORBIT;
-
-typedef struct { /* Navigation data structure */
- short
- sv_number; /* SV number (0 = no entry) */
- float
- t_ephem; /* time of ephemeris collection */
- EPHEM_CLOCK
- ephclk; /* subframe 1 data */
- EPHEM_ORBIT
- ephorb; /* ephemeris data */
-} NAV_INFO;
-
-typedef struct {
- unsigned char
- bSubcode,
- operating_mode,
- dgps_mode,
- dyn_code,
- trackmode;
- float
- elev_mask,
- cno_mask,
- dop_mask,
- dop_switch;
- unsigned char
- dgps_age_limit;
-} TSIP_RCVR_CFG;
-
-
-#ifdef TRIMBLE_OUTPUT_FUNC
-static char
- *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
- old_baudnum[] = {0, 1, 4, 5, 6, 8, 9, 11, 28, 12},
- *st_baud_text_app [] = {"", "", " 300", " 600", " 1200", " 2400",
- " 4800", " 9600", "19200", "38400"},
- *old_parity_text[] = {"EVEN", "ODD", "", "", "NONE"},
- *parity_text [] = {"NONE", "ODD", "EVEN"},
- *old_input_ch[] = { "TSIP", "RTCM (6 of 8 bits)"},
- *old_output_ch[] = { "TSIP", "No output", "", "", "", "NMEA 0183"},
- *protocols_in_text[] = { "", "TSIP", "", ""},
- *protocols_out_text[] = { "", "TSIP", "NMEA"},
- *rcvr_port_text [] = { "Port A ", "Port B ", "Current Port"},
- *dyn_text [] = {"Unchanged", "Land", "Sea", "Air", "Static"},
- *NavModeText0xBB[] = {"automatic", "time only (0-D)", "", "2-D",
- "3-D", "", "", "OverDetermined Time"},
- *PPSTimeBaseText[] = {"GPS", "UTC", "USER"},
- *PPSPolarityText[] = {"Positive", "Negative"},
- *MaskText[] = { "Almanac ", "Ephemeris", "UTC ", "Iono ",
- "GPS Msg ", "Alm Hlth ", "Time Fix ", "SV Select",
- "Ext Event", "Pos Fix ", "Raw Meas "};
-
-#endif /* TRIMBLE_OUTPUT_FUNC */
-
-/*
- * Unit control structure
- */
-struct ripencc_unit {
- int unit; /* unit number */
- int pollcnt; /* poll message counter */
- int polled; /* Hand in a sample? */
- char leapdelta; /* delta of next leap event */
- unsigned char utcflags; /* delta of next leap event */
- l_fp tstamp; /* timestamp of last poll */
-
- struct timespec ts; /* last timestamp */
- pps_params_t pps_params; /* pps parameters */
- pps_info_t pps_info; /* last pps data */
- pps_handle_t handle; /* pps handlebars */
-
-};
-
-
-/******************* PROTOYPES *****************/
-
-/* prototypes for report parsing primitives */
-short rpt_0x3D (TSIPPKT *rpt, unsigned char *tx_baud_index,
- unsigned char *rx_baud_index, unsigned char *char_format_index,
- unsigned char *stop_bits, unsigned char *tx_mode_index,
- unsigned char *rx_mode_index);
-short rpt_0x40 (TSIPPKT *rpt, unsigned char *sv_prn, short *week_num,
- float *t_zc, float *eccentricity, float *t_oa, float *i_0,
- float *OMEGA_dot, float *sqrt_A, float *OMEGA_0, float *omega,
- float *M_0);
-short rpt_0x41 (TSIPPKT *rpt, float *time_of_week, float *UTC_offset,
- short *week_num);
-short rpt_0x42 (TSIPPKT *rpt, float ECEF_pos[3], float *time_of_fix);
-short rpt_0x43 (TSIPPKT *rpt, float ECEF_vel[3], float *freq_offset,
- float *time_of_fix);
-short rpt_0x45 (TSIPPKT *rpt, unsigned char *major_nav_version,
- unsigned char *minor_nav_version, unsigned char *nav_day,
- unsigned char *nav_month, unsigned char *nav_year,
- unsigned char *major_dsp_version, unsigned char *minor_dsp_version,
- unsigned char *dsp_day, unsigned char *dsp_month,
- unsigned char *dsp_year);
-short rpt_0x46 (TSIPPKT *rpt, unsigned char *status1, unsigned char *status2);
-short rpt_0x47 (TSIPPKT *rpt, unsigned char *nsvs, unsigned char *sv_prn,
- float *snr);
-short rpt_0x48 (TSIPPKT *rpt, unsigned char *message);
-short rpt_0x49 (TSIPPKT *rpt, unsigned char *sv_health);
-short rpt_0x4A (TSIPPKT *rpt, float *lat, float *lon, float *alt,
- float *clock_bias, float *time_of_fix);
-short rpt_0x4A_2 (TSIPPKT *rpt, float *alt, float *dummy,
- unsigned char *alt_flag);
-short rpt_0x4B (TSIPPKT *rpt, unsigned char *machine_id,
- unsigned char *status3, unsigned char *status4);
-short rpt_0x4C (TSIPPKT *rpt, unsigned char *dyn_code, float *el_mask,
- float *snr_mask, float *dop_mask, float *dop_switch);
-short rpt_0x4D (TSIPPKT *rpt, float *osc_offset);
-short rpt_0x4E (TSIPPKT *rpt, unsigned char *response);
-short rpt_0x4F (TSIPPKT *rpt, double *a0, float *a1, float *time_of_data,
- short *dt_ls, short *wn_t, short *wn_lsf, short *dn, short *dt_lsf);
-short rpt_0x54 (TSIPPKT *rpt, float *clock_bias, float *freq_offset,
- float *time_of_fix);
-short rpt_0x55 (TSIPPKT *rpt, unsigned char *pos_code, unsigned char *vel_code,
- unsigned char *time_code, unsigned char *aux_code);
-short rpt_0x56 (TSIPPKT *rpt, float vel_ENU[3], float *freq_offset,
- float *time_of_fix);
-short rpt_0x57 (TSIPPKT *rpt, unsigned char *source_code,
- unsigned char *diag_code, short *week_num, float *time_of_fix);
-short rpt_0x58 (TSIPPKT *rpt, unsigned char *op_code, unsigned char *data_type,
- unsigned char *sv_prn, unsigned char *data_length,
- unsigned char *data_packet);
-short rpt_0x59 (TSIPPKT *rpt, unsigned char *code_type,
- unsigned char status_code[32]);
-short rpt_0x5A (TSIPPKT *rpt, unsigned char *sv_prn, float *sample_length,
- float *signal_level, float *code_phase, float *Doppler,
- double *time_of_fix);
-short rpt_0x5B (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *sv_health,
- unsigned char *sv_iode, unsigned char *fit_interval_flag,
- float *time_of_collection, float *time_of_eph, float *sv_accy);
-short rpt_0x5C (TSIPPKT *rpt, unsigned char *sv_prn, unsigned char *slot,
- unsigned char *chan, unsigned char *acq_flag, unsigned char *eph_flag,
- float *signal_level, float *time_of_last_msmt, float *elev,
- float *azim, unsigned char *old_msmt_flag,
- unsigned char *integer_msec_flag, unsigned char *bad_data_flag,
- unsigned char *data_collect_flag);
-short rpt_0x6D (TSIPPKT *rpt, unsigned char *manual_mode, unsigned char *nsvs,
- unsigned char *ndim, unsigned char sv_prn[], float *pdop,
- float *hdop, float *vdop, float *tdop);
-short rpt_0x82 (TSIPPKT *rpt, unsigned char *diff_mode);
-short rpt_0x83 (TSIPPKT *rpt, double ECEF_pos[3], double *clock_bias,
- float *time_of_fix);
-short rpt_0x84 (TSIPPKT *rpt, double *lat, double *lon, double *alt,
- double *clock_bias, float *time_of_fix);
-short rpt_Paly0xBB(TSIPPKT *rpt, TSIP_RCVR_CFG *TsipxBB);
-short rpt_0xBC (TSIPPKT *rpt, unsigned char *port_num,
- unsigned char *in_baud, unsigned char *out_baud,
- unsigned char *data_bits, unsigned char *parity,
- unsigned char *stop_bits, unsigned char *flow_control,
- unsigned char *protocols_in, unsigned char *protocols_out,
- unsigned char *reserved);
-
-/* prototypes for superpacket parsers */
-
-short rpt_0x8F0B (TSIPPKT *rpt, unsigned short *event, double *tow,
- unsigned char *date, unsigned char *month, short *year,
- unsigned char *dim_mode, short *utc_offset, double *bias, double *drift,
- float *bias_unc, float *dr_unc, double *lat, double *lon, double *alt,
- char sv_id[8]);
-short rpt_0x8F14 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
-short rpt_0x8F15 (TSIPPKT *rpt, short *datum_idx, double datum_coeffs[5]);
-short rpt_0x8F20 (TSIPPKT *rpt, unsigned char *info, double *lat,
- double *lon, double *alt, double vel_enu[], double *time_of_fix,
- short *week_num, unsigned char *nsvs, unsigned char sv_prn[],
- short sv_IODC[], short *datum_index);
-short rpt_0x8F41 (TSIPPKT *rpt, unsigned char *bSearchRange,
- unsigned char *bBoardOptions, unsigned long *iiSerialNumber,
- unsigned char *bBuildYear, unsigned char *bBuildMonth,
- unsigned char *bBuildDay, unsigned char *bBuildHour,
- float *fOscOffset, unsigned short *iTestCodeId);
-short rpt_0x8F42 (TSIPPKT *rpt, unsigned char *bProdOptionsPre,
- unsigned char *bProdNumberExt, unsigned short *iCaseSerialNumberPre,
- unsigned long *iiCaseSerialNumber, unsigned long *iiProdNumber,
- unsigned short *iPremiumOptions, unsigned short *iMachineID,
- unsigned short *iKey);
-short rpt_0x8F45 (TSIPPKT *rpt, unsigned char *bSegMask);
-short rpt_0x8F4A_16 (TSIPPKT *rpt, unsigned char *pps_enabled,
- unsigned char *pps_timebase, unsigned char *pos_polarity,
- double *pps_offset, float *bias_unc_threshold);
-short rpt_0x8F4B (TSIPPKT *rpt, unsigned long *decorr_max);
-short rpt_0x8F4D (TSIPPKT *rpt, unsigned long *event_mask);
-short rpt_0x8FA5 (TSIPPKT *rpt, unsigned char *spktmask);
-short rpt_0x8FAD (TSIPPKT *rpt, unsigned short *COUNT, double *FracSec,
- unsigned char *Hour, unsigned char *Minute, unsigned char *Second,
- unsigned char *Day, unsigned char *Month, unsigned short *Year,
- unsigned char *Status, unsigned char *Flags);
-
-/**/
-/* prototypes for command-encode primitives with suffix convention: */
-/* c = clear, s = set, q = query, e = enable, d = disable */
-void cmd_0x1F (TSIPPKT *cmd);
-void cmd_0x26 (TSIPPKT *cmd);
-void cmd_0x2F (TSIPPKT *cmd);
-void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
- unsigned char time_code, unsigned char opts_code);
-void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn);
-void cmd_0x3Ds (TSIPPKT *cmd, unsigned char baud_out, unsigned char baud_inp,
- unsigned char char_code, unsigned char stopbitcode,
- unsigned char output_mode, unsigned char input_mode);
-void cmd_0xBBq (TSIPPKT *cmd, unsigned char subcode) ;
-
-/* prototypes 8E commands */
-void cmd_0x8E0Bq (TSIPPKT *cmd);
-void cmd_0x8E41q (TSIPPKT *cmd);
-void cmd_0x8E42q (TSIPPKT *cmd);
-void cmd_0x8E4Aq (TSIPPKT *cmd);
-void cmd_0x8E4As (TSIPPKT *cmd, unsigned char PPSOnOff, unsigned char TimeBase,
- unsigned char Polarity, double PPSOffset, float Uncertainty);
-void cmd_0x8E4Bq (TSIPPKT *cmd);
-void cmd_0x8E4Ds (TSIPPKT *cmd, unsigned long AutoOutputMask);
-void cmd_0x8EADq (TSIPPKT *cmd);
-
-/* header/source border XXXXXXXXXXXXXXXXXXXXXXXXXX */
-
-/* Trimble parse functions */
-static int parse0x8FAD P((TSIPPKT *, struct peer *));
-static int parse0x8F0B P((TSIPPKT *, struct peer *));
-#ifdef TRIMBLE_OUTPUT_FUNC
-static int parseany P((TSIPPKT *, struct peer *));
-static void TranslateTSIPReportToText P((TSIPPKT *, char *));
-#endif /* TRIMBLE_OUTPUT_FUNC */
-static int parse0x5C P((TSIPPKT *, struct peer *));
-static int parse0x4F P((TSIPPKT *, struct peer *));
-static void tsip_input_proc P((TSIPPKT *, int));
-
-/* Trimble helper functions */
-static void bPutFloat P((float *, unsigned char *));
-static void bPutDouble P((double *, unsigned char *));
-static void bPutULong P((unsigned long *, unsigned char *));
-static int print_msg_table_header P((int rptcode, char *HdrStr, int force));
-static char * show_time P((float time_of_week));
-
-/* RIPE NCC functions */
-static void ripencc_control P((int, struct refclockstat *, struct
- refclockstat *, struct peer *));
-static int ripencc_ppsapi P((struct peer *, int, int));
-static int ripencc_get_pps_ts P((struct ripencc_unit *, l_fp *));
-static int ripencc_start P((int, struct peer *));
-static void ripencc_shutdown P((int, struct peer *));
-static void ripencc_poll P((int, struct peer *));
-static void ripencc_send P((struct peer *, TSIPPKT spt));
-static void ripencc_receive P((struct recvbuf *));
-
-/* fill in reflock structure for our clock */
-struct refclock refclock_ripencc = {
- ripencc_start, /* start up driver */
- ripencc_shutdown, /* shut down driver */
- ripencc_poll, /* transmit poll message */
- ripencc_control, /* control function */
- noentry, /* initialize driver */
- noentry, /* debug info */
- NOFLAGS /* clock flags */
-};
-
-/*
- * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
- * leap.
- */
-static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-
-/*
- * ripencc_start - open the GPS devices and initialize data for processing
- */
-static int
-ripencc_start(int unit, struct peer *peer)
-{
- register struct ripencc_unit *up;
- struct refclockproc *pp;
- char device[40];
- int fd;
- struct termios tio;
- TSIPPKT spt;
-
- /*
- * Open serial port
- */
- (void)snprintf(device, sizeof(device), DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_RAW)))
- return (0);
-
- /* from refclock_palisade.c */
- if (tcgetattr(fd, &tio) < 0) {
- msyslog(LOG_ERR, "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
- return (0);
- }
-
- /*
- * set flags
- */
- tio.c_cflag |= (PARENB|PARODD);
- tio.c_iflag &= ~ICRNL;
- if (tcsetattr(fd, TCSANOW, &tio) == -1) {
- msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
- return (0);
- }
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct ripencc_unit *)
- emalloc(sizeof(struct ripencc_unit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct ripencc_unit));
- pp = peer->procptr;
- pp->io.clock_recv = ripencc_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, REFID_LEN);
- up->pollcnt = 2;
- up->unit = unit;
- up->leapdelta = 0;
- up->utcflags = 0;
-
- /*
- * Initialize the Clock
- */
-
- /* query software versions */
- cmd_0x1F(&spt);
- ripencc_send(peer, spt);
-
- /* query receiver health */
- cmd_0x26(&spt);
- ripencc_send(peer, spt);
-
- /* query serial numbers */
- cmd_0x8E42q(&spt);
- ripencc_send(peer, spt);
-
- /* query manuf params */
- cmd_0x8E41q(&spt);
- ripencc_send(peer, spt);
-
- /* i/o opts */ /* trimble manual page A30 */
- cmd_0x35s(&spt,
- 0x1C, /* position */
- 0x00, /* velocity */
- 0x05, /* timing */
- 0x0a); /* auxilary */
- ripencc_send(peer, spt);
-
- /* turn off port A */
- cmd_0x3Ds (&spt,
- 0x0B, /* baud_out */
- 0x0B, /* baud_inp */
- 0x07, /* char_code */
- 0x07, /* stopbitcode */
- 0x01, /* output_mode */
- 0x00); /* input_mode */
- ripencc_send(peer, spt);
-
- /* set i/o options */
- cmd_0x8E4As (&spt,
- 0x01, /* PPS on */
- 0x01, /* Timebase UTC */
- 0x00, /* polarity positive */
- 0., /* 100 ft. cable XXX make flag */
- 1e-6 * GPS_C); /* turn of biasuncert. > (1us) */
- ripencc_send(peer,spt);
-
- /* all outomatic packet output off */
- cmd_0x8E4Ds(&spt,
- 0x00000000); /* AutoOutputMask */
- ripencc_send(peer, spt);
-
- cmd_0xBBq (&spt,
- 0x00); /* query primary configuration */
- ripencc_send(peer,spt);
-
-
- /* query PPS parameters */
- cmd_0x8E4Aq (&spt); /* query PPS params */
- ripencc_send(peer,spt);
-
- /* query survey limit */
- cmd_0x8E4Bq (&spt); /* query survey limit */
- ripencc_send(peer,spt);
-
-#ifdef DEBUG_NCC
- if (debug)
- printf("ripencc_start: success\n");
-#endif /* DEBUG_NCC */
-
- /*
- * Start the PPSAPI interface if it is there. Default to use
- * the assert edge and do not enable the kernel hardpps.
- */
- if (time_pps_create(fd, &up->handle) < 0) {
- up->handle = 0;
- msyslog(LOG_ERR, "refclock_ripencc: time_pps_create failed: %m");
- return (1);
- }
-
- return(ripencc_ppsapi(peer, 0, 0));
-}
-
-/*
- * ripencc_control - fudge control
- */
-static void
-ripencc_control(
- int unit, /* unit (not used) */
- struct refclockstat *in, /* input parameters (not used) */
- struct refclockstat *out, /* output parameters (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-
-#ifdef DEBUG_NCC
- msyslog(LOG_INFO,"%s()",__FUNCTION__);
-#endif /* DEBUG_NCC */
-
- pp = peer->procptr;
- ripencc_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
- pp->sloppyclockflag & CLK_FLAG3);
-}
-
-
-/*
- * Initialize PPSAPI
- */
-int
-ripencc_ppsapi(
- struct peer *peer, /* peer structure pointer */
- int enb_clear, /* clear enable */
- int enb_hardpps /* hardpps enable */
- )
-{
- struct refclockproc *pp;
- struct ripencc_unit *up;
- int capability;
-
- pp = peer->procptr;
- up = (struct ripencc_unit *)pp->unitptr;
- if (time_pps_getcap(up->handle, &capability) < 0) {
- msyslog(LOG_ERR,
- "refclock_ripencc: time_pps_getcap failed: %m");
- return (0);
- }
- memset(&up->pps_params, 0, sizeof(pps_params_t));
- if (enb_clear)
- up->pps_params.mode = capability & PPS_CAPTURECLEAR;
- else
- up->pps_params.mode = capability & PPS_CAPTUREASSERT;
- if (!up->pps_params.mode) {
- msyslog(LOG_ERR,
- "refclock_ripencc: invalid capture edge %d",
- !enb_clear);
- return (0);
- }
- up->pps_params.mode |= PPS_TSFMT_TSPEC;
- if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
- msyslog(LOG_ERR,
- "refclock_ripencc: time_pps_setparams failed: %m");
- return (0);
- }
- if (enb_hardpps) {
- if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
- up->pps_params.mode & ~PPS_TSFMT_TSPEC,
- PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR,
- "refclock_ripencc: time_pps_kcbind failed: %m");
- return (0);
- }
- pps_enable = 1;
- }
- peer->precision = PPS_PRECISION;
-
-#if DEBUG_NCC
- if (debug) {
- time_pps_getparams(up->handle, &up->pps_params);
- printf(
- "refclock_ripencc: capability 0x%x version %d mode 0x%x kern %d\n",
- capability, up->pps_params.api_version,
- up->pps_params.mode, enb_hardpps);
- }
-#endif /* DEBUG_NCC */
-
- return (1);
-}
-
-/*
- * This function is called every 64 seconds from ripencc_receive
- * It will fetch the pps time
- *
- * Return 0 on failure and 1 on success.
- */
-static int
-ripencc_get_pps_ts(
- struct ripencc_unit *up,
- l_fp *tsptr
- )
-{
- pps_info_t pps_info;
- struct timespec timeout, ts;
- double dtemp;
- l_fp tstmp;
-
-#ifdef DEBUG_PPS
- msyslog(LOG_INFO,"ripencc_get_pps_ts\n");
-#endif /* DEBUG_PPS */
-
-
- /*
- * Convert the timespec nanoseconds field to ntp l_fp units.
- */
- if (up->handle == 0)
- return (0);
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
- if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
- &timeout) < 0)
- return (0);
- if (up->pps_params.mode & PPS_CAPTUREASSERT) {
- if (pps_info.assert_sequence ==
- up->pps_info.assert_sequence)
- return (0);
- ts = up->pps_info.assert_timestamp;
- } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
- if (pps_info.clear_sequence ==
- up->pps_info.clear_sequence)
- return (0);
- ts = up->pps_info.clear_timestamp;
- } else {
- return (0);
- }
- if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
- return (0);
- up->ts = ts;
-
- tstmp.l_ui = ts.tv_sec + JAN_1970;
- dtemp = ts.tv_nsec * FRAC / 1e9;
- tstmp.l_uf = (u_int32)dtemp;
-
-#ifdef DEBUG_PPS
- msyslog(LOG_INFO,"ts.tv_sec: %d\n",(int)ts.tv_sec);
- msyslog(LOG_INFO,"ts.tv_nsec: %ld\n",ts.tv_nsec);
-#endif /* DEBUG_PPS */
-
- *tsptr = tstmp;
- return (1);
-}
-
-/*
- * ripencc_shutdown - shut down a GPS clock
- */
-static void
-ripencc_shutdown(int unit, struct peer *peer)
-{
- register struct ripencc_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct ripencc_unit *)pp->unitptr;
-
- if (up->handle != 0)
- time_pps_destroy(up->handle);
-
- io_closeclock(&pp->io);
-
- free(up);
-}
-
-/*
- * ripencc_poll - called by the transmit procedure
- */
-static void
-ripencc_poll(int unit, struct peer *peer)
-{
- register struct ripencc_unit *up;
- struct refclockproc *pp;
- TSIPPKT spt;
-
-#ifdef DEBUG_NCC
- if (debug)
- fprintf(stderr, "ripencc_poll(%d)\n", unit);
-#endif /* DEBUG_NCC */
- pp = peer->procptr;
- up = (struct ripencc_unit *)pp->unitptr;
- if (up->pollcnt == 0)
- refclock_report(peer, CEVNT_TIMEOUT);
- else
- up->pollcnt--;
-
- pp->polls++;
- up->polled = 1;
-
- /* poll for UTC superpacket */
- cmd_0x8EADq (&spt);
- ripencc_send(peer,spt);
-}
-
-/*
- * ripencc_send - send message to clock
- * use the structures being created by the trimble functions!
- * makes the code more readable/clean
- */
-static void
-ripencc_send(struct peer *peer, TSIPPKT spt)
-{
- unsigned char *ip, *op;
- unsigned char obuf[512];
-
-#ifdef DEBUG_RAW
- {
- register struct ripencc_unit *up;
- register struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct ripencc_unit *)pp->unitptr;
- if (debug)
- printf("ripencc_send(%d, %02X)\n", up->unit, cmd);
- }
-#endif /* DEBUG_RAW */
-
- ip = spt.buf;
- op = obuf;
-
- *op++ = 0x10;
- *op++ = spt.code;
-
- while (spt.len--) {
- if (op-obuf > sizeof(obuf)-5) {
- msyslog(LOG_ERR, "ripencc_send obuf overflow!");
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
-
- if (*ip == 0x10) /* byte stuffing */
- *op++ = 0x10;
- *op++ = *ip++;
- }
-
- *op++ = 0x10;
- *op++ = 0x03;
-
-#ifdef DEBUG_RAW
- if (debug) { /* print raw packet */
- unsigned char *cp;
- int i;
-
- printf("ripencc_send: len %d\n", op-obuf);
- for (i=1, cp=obuf; cp<op; i++, cp++) {
- printf(" %02X", *cp);
- if (i%10 == 0)
- printf("\n");
- }
- printf("\n");
- }
-#endif /* DEBUG_RAW */
-
- if (write(peer->procptr->io.fd, obuf, op-obuf) == -1) {
- refclock_report(peer, CEVNT_FAULT);
- }
-}
-
-/*
- * ripencc_receive()
- *
- * called when a packet is received on the serial port
- * takes care of further processing
- *
- */
-static void
-ripencc_receive(struct recvbuf *rbufp)
-{
- register struct ripencc_unit *up;
- register struct refclockproc *pp;
- struct peer *peer;
- static TSIPPKT rpt; /* structure for current incoming TSIP report */
- TSIPPKT spt; /* send packet */
- int ns_since_pps;
- int i;
- char *cp;
- /* Use these variables to hold data until we decide its worth keeping */
- char rd_lastcode[BMAX];
- l_fp rd_tmp;
- u_short rd_lencode;
-
- /* msyslog(LOG_INFO, "%s",__FUNCTION__); */
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct ripencc_unit *)pp->unitptr;
- rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
-
-#ifdef DEBUG_RAW
- if (debug)
- fprintf(stderr, "ripencc_receive(%d)\n", up->unit);
-#endif /* DEBUG_RAW */
-
-#ifdef DEBUG_RAW
- if (debug) { /* print raw packet */
- int i;
- unsigned char *cp;
-
- printf("ripencc_receive: len %d\n", rbufp->recv_length);
- for (i=1, cp=(char*)&rbufp->recv_space; i <= rbufp->recv_length; i++, cp++) {
- printf(" %02X", *cp);
- if (i%10 == 0)
- printf("\n");
- }
- printf("\n");
- }
-#endif /* DEBUG_RAW */
-
- cp = (char*) &rbufp->recv_space;
- i=rbufp->recv_length;
-
- while (i--) { /* loop over received chars */
-
- tsip_input_proc(&rpt, (unsigned char) *cp++);
-
- if (rpt.status != TSIP_PARSED_FULL)
- continue;
-
- switch (rpt.code) {
-
- case 0x8F: /* superpacket */
-
- switch (rpt.buf[0]) {
-
- case 0xAD: /* UTC Time */
- /*
- * When polling on port B the timecode
- * is the time of the previous PPS.
- * If we completed receiving the packet
- * less than 150ms after the turn of the second,
- * it may have the code of the previous second.
- * We do not trust that and simply poll again
- * without even parsing it.
- *
- * More elegant would be to re-schedule the poll,
- * but I do not know (yet) how to do that cleanly.
- *
- */
- /* BLA ns_since_pps = ncc_tstmp(rbufp, &trtmp); */
-/* if (up->polled && ns_since_pps > -1 && ns_since_pps < 150) { */
-
- ns_since_pps=200;
- if (up->polled && ns_since_pps < 150) {
- msyslog(LOG_INFO, "%s(): up->polled",__FUNCTION__);
- ripencc_poll(up->unit, peer);
- break;
- }
-
- /*
- * Parse primary utc time packet
- * and fill refclock structure
- * from results.
- */
- if (parse0x8FAD(&rpt, peer) < 0) {
- msyslog(LOG_INFO, "%s(): parse0x8FAD < 0",__FUNCTION__);
- refclock_report(peer, CEVNT_BADREPLY);
- break;
- }
- /*
- * If the PPSAPI is working, rather use its
- * timestamps.
- * assume that the PPS occurs on the second
- * so blow any msec
- */
- if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
- pp->lastrec = up->tstamp = rd_tmp;
- pp->nsec = 0;
- }
- else
- msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__);
-
-
- if (!up->polled) {
- msyslog(LOG_INFO, "%s(): unrequested packet\n",__FUNCTION__);
- /* unrequested packet */
- break;
- }
-
- /* we have been polled ! */
- up->polled = 0;
- up->pollcnt = 2;
-
- /* poll for next packet */
- cmd_0x8E0Bq(&spt);
- ripencc_send(peer,spt);
-
- if (ns_since_pps < 0) { /* no PPS */
- msyslog(LOG_INFO, "%s(): ns_since_pps < 0",__FUNCTION__);
- refclock_report(peer, CEVNT_BADTIME);
- break;
- }
-
- /*
- * Process the new sample in the median filter and determine the
- * reference clock offset and dispersion.
- */
- if (!refclock_process(pp)) {
- msyslog(LOG_INFO, "%s(): !refclock_process",__FUNCTION__);
- refclock_report(peer, CEVNT_BADTIME);
- break;
- }
-
- refclock_receive(peer);
- break;
-
- case 0x0B: /* comprehensive time packet */
- parse0x8F0B(&rpt, peer);
- break;
-
- default: /* other superpackets */
-#ifdef DEBUG_NCC
- msyslog(LOG_INFO, "%s(): calling parseany",__FUNCTION__);
-#endif /* DEBUG_NCC */
-#ifdef TRIMBLE_OUTPUT_FUNC
- parseany(&rpt, peer);
-#endif /* TRIMBLE_OUTPUT_FUNC */
- break;
- }
- break;
-
- case 0x4F: /* UTC parameters, for leap info */
- parse0x4F(&rpt, peer);
- break;
-
- case 0x5C: /* sat tracking data */
- parse0x5C(&rpt, peer);
- break;
-
- default: /* other packets */
-#ifdef TRIMBLE_OUTPUT_FUNC
- parseany(&rpt, peer);
-#endif /* TRIMBLE_OUTPUT_FUNC */
- break;
- }
- rpt.status = TSIP_PARSED_EMPTY;
- }
-}
-
-/*
- * All trimble functions that are directly referenced from driver code
- * (so not from parseany)
- */
-
-void cmd_0x1F (TSIPPKT *cmd)
-/* request software versions */
-{
- cmd->len = 0;
- cmd->code = 0x1F;
-}
-
-void cmd_0x26 (TSIPPKT *cmd)
-/* request receiver health */
-{
- cmd->len = 0;
- cmd->code = 0x26;
-}
-
-
-
-
-void cmd_0x2F (TSIPPKT *cmd)
-/* request UTC params */
-{
- cmd->len = 0;
- cmd->code = 0x2F;
-}
-
-void cmd_0x35s (TSIPPKT *cmd, unsigned char pos_code, unsigned char vel_code,
- unsigned char time_code, unsigned char opts_code)
-/* set serial I/O options */
-{
- cmd->buf[0] = pos_code;
- cmd->buf[1] = vel_code;
- cmd->buf[2] = time_code;
- cmd->buf[3] = opts_code;
- cmd->len = 4;
- cmd->code = 0x35;
-}
-void cmd_0x3C (TSIPPKT *cmd, unsigned char sv_prn)
-/* request tracking status */
-{
- cmd->buf[0] = sv_prn;
- cmd->len = 1;
- cmd->code = 0x3C;
-}
-
-
-void cmd_0x3Ds (TSIPPKT *cmd,
- unsigned char baud_out, unsigned char baud_inp,
- unsigned char char_code, unsigned char stopbitcode,
- unsigned char output_mode, unsigned char input_mode)
-/* set Channel A configuration for dual-port operation */
-{
- cmd->buf[0] = baud_out; /* XMT baud rate */
- cmd->buf[1] = baud_inp; /* RCV baud rate */
- cmd->buf[2] = char_code; /* parity and #bits per byte */
- cmd->buf[3] = stopbitcode; /* number of stop bits code */
- cmd->buf[4] = output_mode; /* Ch. A transmission mode */
- cmd->buf[5] = input_mode; /* Ch. A reception mode */
- cmd->len = 6;
- cmd->code = 0x3D;
-}
-
-
-/* query primary configuration */
-void cmd_0xBBq (TSIPPKT *cmd,
- unsigned char subcode)
-{
-
- cmd->len = 1;
- cmd->code = 0xBB;
- cmd->buf[0] = subcode;
-}
-
-
-/**** Superpackets ****/
-void cmd_0x8E0Bq (TSIPPKT *cmd)
-/* 8E-0B to query 8F-0B controls */
-{
-
- cmd->len = 1;
- cmd->code = 0x8E;
- cmd->buf[0] = 0x0B;
-}
-
-
-void cmd_0x8E41q (TSIPPKT *cmd)
-/* 8F-41 to query board serial number */
-{
-
- cmd->len = 1;
- cmd->code = 0x8E;
- cmd->buf[0] = 0x41;
-}
-
-
-void cmd_0x8E42q (TSIPPKT *cmd)
-/* 8F-42 to query product serial number */
-{
-
- cmd->len = 1;
- cmd->code = 0x8E;
- cmd->buf[0] = 0x42;
-}
-void cmd_0x8E4Aq (TSIPPKT *cmd)
-/* 8F-4A to query PPS parameters */
-{
- cmd->len = 1;
- cmd->code = 0x8E;
- cmd->buf[0] = 0x4A;
-}
-
-
-/* set i/o options */
-void cmd_0x8E4As (TSIPPKT *cmd,
- unsigned char PPSOnOff,
- unsigned char TimeBase,
- unsigned char Polarity,
- double PPSOffset,
- float Uncertainty)
-{
- cmd->len = 16;
- cmd->code = 0x8E;
- cmd->buf[0] = 0x4A;
- cmd->buf[1] = PPSOnOff;
- cmd->buf[2] = TimeBase;
- cmd->buf[3] = Polarity;
- bPutDouble (&PPSOffset, &cmd->buf[4]);
- bPutFloat (&Uncertainty, &cmd->buf[12]);
-}
-void cmd_0x8E4Bq (TSIPPKT *cmd)
-/* 8F-4B query survey limit */
-{
- cmd->len = 1;
- cmd->code = 0x8E;
- cmd->buf[0] = 0x4B;
-}
-
-
-/* poll for UTC superpacket */
-void cmd_0x8EADq (TSIPPKT *cmd)
-/* 8E-AD to query 8F-AD controls */
-{
- cmd->len = 1;
- cmd->code = 0x8E;
- cmd->buf[0] = 0xAD;
-}
-
-/* all outomatic packet output off */
-void cmd_0x8E4Ds (TSIPPKT *cmd,
- unsigned long AutoOutputMask)
-{
- cmd->len = 5;
- cmd->code = 0x8E;
- cmd->buf[0] = 0x4D;
- bPutULong (&AutoOutputMask, &cmd->buf[1]);
-}
-
-
-
-
-/* for DOS machines, reverse order of bytes as they come through the
- * serial port. */
-#ifdef BYTESWAP
-static short bGetShort (unsigned char *bp)
-{
- short outval;
- unsigned char *optr;
-
- optr = (unsigned char*)&outval + 1;
- *optr-- = *bp++;
- *optr = *bp;
- return outval;
-}
-
-#ifdef TRIMBLE_OUTPUT_FUNC
-static unsigned short bGetUShort (unsigned char *bp)
-{
- unsigned short outval;
- unsigned char *optr;
-
- optr = (unsigned char*)&outval + 1;
- *optr-- = *bp++;
- *optr = *bp;
- return outval;
-}
-
-static long bGetLong (unsigned char *bp)
-{
- long outval;
- unsigned char *optr;
-
- optr = (unsigned char*)&outval + 3;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
- return outval;
-}
-
-static unsigned long bGetULong (unsigned char *bp)
-{
- unsigned long outval;
- unsigned char *optr;
-
- optr = (unsigned char*)&outval + 3;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
- return outval;
-}
-#endif /* TRIMBLE_OUTPUT_FUNC */
-
-static float bGetSingle (unsigned char *bp)
-{
- float outval;
- unsigned char *optr;
-
- optr = (unsigned char*)&outval + 3;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
- return outval;
-}
-
-static double bGetDouble (unsigned char *bp)
-{
- double outval;
- unsigned char *optr;
-
- optr = (unsigned char*)&outval + 7;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr-- = *bp++;
- *optr = *bp;
- return outval;
-}
-
-#else /* not BYTESWAP */
-
-#define bGetShort(bp) (*(short*)(bp))
-#define bGetLong(bp) (*(long*)(bp))
-#define bGetULong(bp) (*(unsigned long*)(bp))
-#define bGetSingle(bp) (*(float*)(bp))
-#define bGetDouble(bp) (*(double*)(bp))
-
-#endif /* BYTESWAP */
-/*
- * Byte-reversal is necessary for little-endian (Intel-based) machines.
- * TSIP streams are Big-endian (Motorola-based).
- */
-#ifdef BYTESWAP
-
-void
-bPutFloat (float *in, unsigned char *out)
-{
- unsigned char *inptr;
-
- inptr = (unsigned char*)in + 3;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out = *inptr;
-}
-
-static void
-bPutULong (unsigned long *in, unsigned char *out)
-{
- unsigned char *inptr;
-
- inptr = (unsigned char*)in + 3;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out = *inptr;
-}
-
-static void
-bPutDouble (double *in, unsigned char *out)
-{
- unsigned char *inptr;
-
- inptr = (unsigned char*)in + 7;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out++ = *inptr--;
- *out = *inptr;
-}
-
-#else /* not BYTESWAP */
-
-void bPutShort (short a, unsigned char *cmdbuf) {*(short*) cmdbuf = a;}
-void bPutULong (long a, unsigned char *cmdbuf) {*(long*) cmdbuf = a;}
-void bPutFloat (float a, unsigned char *cmdbuf) {*(float*) cmdbuf = a;}
-void bPutDouble (double a, unsigned char *cmdbuf){*(double*) cmdbuf = a;}
-
-#endif /* BYTESWAP */
-
-/*
- * Parse primary utc time packet
- * and fill refclock structure
- * from results.
- *
- * 0 = success
- * -1 = errors
- */
-
-static int
-parse0x8FAD(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
-{
- register struct refclockproc *pp;
- register struct ripencc_unit *up;
-
- unsigned day, month, year; /* data derived from received timecode */
- unsigned hour, minute, second;
- unsigned char trackstat, utcflags;
-
- static char logbuf[1024]; /* logging string buffer */
- int i;
- unsigned char *buf;
-
- buf = rpt->buf;
- pp = peer->procptr;
-
- if (rpt->len != 22)
- return (-1);
-
- if (bGetShort(&buf[1]) != 0) {
-#ifdef DEBUG_NCC
- if (debug)
- printf("parse0x8FAD: event count != 0\n");
-#endif /* DEBUG_NCC */
- return(-1);
- }
-
-
- if (bGetDouble(&buf[3]) != 0.0) {
-#ifdef DEBUG_NCC
- if (debug)
- printf("parse0x8FAD: fracsecs != 0\n");
-#endif /* DEBUG_NCC */
- return(-1);
- }
-
- hour = (unsigned int) buf[11];
- minute = (unsigned int) buf[12];
- second = (unsigned int) buf[13];
- day = (unsigned int) buf[14];
- month = (unsigned int) buf[15];
- year = bGetShort(&buf[16]);
- trackstat = buf[18];
- utcflags = buf[19];
-
-
- sprintf(logbuf, "U1 %d.%d.%d %02d:%02d:%02d %d %02x",
- day, month, year, hour, minute, second, trackstat, utcflags);
-
-#ifdef DEBUG_NCC
- if (debug)
- puts(logbuf);
-#endif /* DEBUG_NCC */
-
- record_clock_stats(&peer->srcadr, logbuf);
-
- if (!utcflags & UTCF_UTC_AVAIL)
- return(-1);
-
- /* poll for UTC parameters once and then if UTC flag changed */
- up = (struct ripencc_unit *) pp->unitptr;
- if (utcflags != up->utcflags) {
- TSIPPKT spt; /* local structure for send packet */
- cmd_0x2F (&spt); /* request UTC params */
- ripencc_send(peer,spt);
- up->utcflags = utcflags;
- }
-
- /*
- * If we hit the leap second, we choose to skip this sample
- * rather than rely on other code to be perfectly correct.
- * No offense, just defense ;-).
- */
- if (second == 60)
- return(-1);
-
- /* now check and convert the time we received */
-
- pp->year = year;
- if (month < 1 || month > 12 || day < 1 || day > 31)
- return(-1);
-
- if (pp->year % 4) {
- if (day > day1tab[month - 1])
- return(-1);
- for (i = 0; i < month - 1; i++)
- day += day1tab[i];
- } else {
- if (day > day2tab[month - 1])
- return(-1);
- for (i = 0; i < month - 1; i++)
- day += day2tab[i];
- }
- pp->day = day;
- pp->hour = hour;
- pp->minute = minute;
- pp-> second = second;
- pp->nsec = 0;
-
- if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0)
- pp-> leap = (up->leapdelta > 0 ? LEAP_ADDSECOND : LEAP_DELSECOND);
- else
- pp-> leap = LEAP_NOWARNING;
-
- return (0);
-}
-
-/*
- * Parse comprehensive time packet
- *
- * 0 = success
- * -1 = errors
- */
-
-int parse0x8F0B(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
-{
- register struct refclockproc *pp;
-
- unsigned day, month, year; /* data derived from received timecode */
- unsigned hour, minute, second;
- unsigned utcoff;
- unsigned char mode;
- double bias, rate;
- float biasunc, rateunc;
- double lat, lon, alt;
- short lat_deg, lon_deg;
- float lat_min, lon_min;
- unsigned char north_south, east_west;
- char sv[9];
-
- static char logbuf[1024]; /* logging string buffer */
- unsigned char b;
- int i;
- unsigned char *buf;
- double tow;
-
- buf = rpt->buf;
- pp = peer->procptr;
-
- if (rpt->len != 74)
- return (-1);
-
- if (bGetShort(&buf[1]) != 0)
- return(-1);;
-
- tow = bGetDouble(&buf[3]);
-
- if (tow == -1.0) {
- return(-1);
- }
- else if ((tow >= 604800.0) || (tow < 0.0)) {
- return(-1);
- }
- else
- {
- if (tow < 604799.9) tow = tow + .00000001;
- second = (unsigned int) fmod(tow, 60.);
- minute = (unsigned int) fmod(tow/60., 60.);
- hour = (unsigned int )fmod(tow / 3600., 24.);
- }
-
-
- day = (unsigned int) buf[11];
- month = (unsigned int) buf[12];
- year = bGetShort(&buf[13]);
- mode = buf[15];
- utcoff = bGetShort(&buf[16]);
- bias = bGetDouble(&buf[18]) / GPS_C * 1e9; /* ns */
- rate = bGetDouble(&buf[26]) / GPS_C * 1e9; /* ppb */
- biasunc = bGetSingle(&buf[34]) / GPS_C * 1e9; /* ns */
- rateunc = bGetSingle(&buf[38]) / GPS_C * 1e9; /* ppb */
- lat = bGetDouble(&buf[42]) * R2D;
- lon = bGetDouble(&buf[50]) * R2D;
- alt = bGetDouble(&buf[58]);
-
- if (lat < 0.0) {
- north_south = 'S';
- lat = -lat;
- }
- else {
- north_south = 'N';
- }
- lat_deg = (short)lat;
- lat_min = (lat - lat_deg) * 60.0;
-
- if (lon < 0.0) {
- east_west = 'W';
- lon = -lon;
- }
- else {
- east_west = 'E';
- }
-
- lon_deg = (short)lon;
- lon_min = (lon - lon_deg) * 60.0;
-
- for (i=0; i<8; i++) {
- sv[i] = buf[i + 66];
- if (sv[i]) {
- TSIPPKT spt; /* local structure for sendpacket */
- b = (unsigned char) (sv[i]<0 ? -sv[i] : sv[i]);
- /* request tracking status */
- cmd_0x3C (&spt, b);
- ripencc_send(peer,spt);
- }
- }
-
-
- sprintf(logbuf, "C1 %02d%02d%04d %02d%02d%02d %d %7.0f %.1f %.0f %.1f %d %02d%09.6f %c %02d%09.6f %c %.0f %d %d %d %d %d %d %d %d",
- day, month, year, hour, minute, second, mode, bias, biasunc, rate, rateunc, utcoff,
- lat_deg, lat_min, north_south, lon_deg, lon_min, east_west, alt,
- sv[0], sv[1], sv[2], sv[3], sv[4], sv[5], sv[6], sv[7]);
-
-#ifdef DEBUG_NCC
- if (debug)
- puts(logbuf);
-#endif /* DEBUG_NCC */
-
- record_clock_stats(&peer->srcadr, logbuf);
-
- return (0);
-}
-
-#ifdef TRIMBLE_OUTPUT_FUNC
-/*
- * Parse any packet using Trimble machinery
- */
-int parseany(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
-{
- static char logbuf[1024]; /* logging string buffer */
-
- TranslateTSIPReportToText (rpt, logbuf); /* anything else */
-#ifdef DEBUG_NCC
- if (debug)
- puts(&logbuf[1]);
-#endif /* DEBUG_NCC */
- record_clock_stats(&peer->srcadr, &logbuf[1]);
- return(0);
-}
-#endif /* TRIMBLE_OUTPUT_FUNC */
-
-
-/*
- * Parse UTC Parameter Packet
- *
- * See the IDE for documentation!
- *
- * 0 = success
- * -1 = errors
- */
-
-int parse0x4F(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
-{
- register struct ripencc_unit *up;
-
- double a0;
- float a1, tot;
- int dt_ls, wn_t, wn_lsf, dn, dt_lsf;
-
- static char logbuf[1024]; /* logging string buffer */
- unsigned char *buf;
-
- buf = rpt->buf;
-
- if (rpt->len != 26)
- return (-1);
- a0 = bGetDouble (buf);
- a1 = bGetSingle (&buf[8]);
- dt_ls = bGetShort (&buf[12]);
- tot = bGetSingle (&buf[14]);
- wn_t = bGetShort (&buf[18]);
- wn_lsf = bGetShort (&buf[20]);
- dn = bGetShort (&buf[22]);
- dt_lsf = bGetShort (&buf[24]);
-
- sprintf(logbuf, "L1 %d %d %d %g %g %g %d %d %d",
- dt_lsf - dt_ls, dt_ls, dt_lsf, a0, a1, tot, wn_t, wn_lsf, dn);
-
-#ifdef DEBUG_NCC
- if (debug)
- puts(logbuf);
-#endif /* DEBUG_NCC */
-
- record_clock_stats(&peer->srcadr, logbuf);
-
- up = (struct ripencc_unit *) peer->procptr->unitptr;
- up->leapdelta = dt_lsf - dt_ls;
-
- return (0);
-}
-
-/*
- * Parse Tracking Status packet
- *
- * 0 = success
- * -1 = errors
- */
-
-int parse0x5C(rpt, peer)
- TSIPPKT *rpt;
- struct peer *peer;
-{
- unsigned char prn, channel, aqflag, ephstat;
- float snr, azinuth, elevation;
-
- static char logbuf[1024]; /* logging string buffer */
- unsigned char *buf;
-
- buf = rpt->buf;
-
- if (rpt->len != 24)
- return(-1);
-
- prn = buf[0];
- channel = (unsigned char)(buf[1] >> 3);
- if (channel == 0x10)
- channel = 2;
- else
- channel++;
- aqflag = buf[2];
- ephstat = buf[3];
- snr = bGetSingle(&buf[4]);
- elevation = bGetSingle(&buf[12]) * R2D;
- azinuth = bGetSingle(&buf[16]) * R2D;
-
- sprintf(logbuf, "S1 %02d %d %d %02x %4.1f %5.1f %4.1f",
- prn, channel, aqflag, ephstat, snr, azinuth, elevation);
-
-#ifdef DEBUG_NCC
- if (debug)
- puts(logbuf);
-#endif /* DEBUG_NCC */
-
- record_clock_stats(&peer->srcadr, logbuf);
-
- return (0);
-}
-
-/******* Code below is from Trimble Tsipchat *************/
-
-/*
- * *************************************************************************
- *
- * Trimble Navigation, Ltd.
- * OEM Products Development Group
- * P.O. Box 3642
- * 645 North Mary Avenue
- * Sunnyvale, California 94088-3642
- *
- * Corporate Headquarter:
- * Telephone: (408) 481-8000
- * Fax: (408) 481-6005
- *
- * Technical Support Center:
- * Telephone: (800) 767-4822 (U.S. and Canada)
- * (408) 481-6940 (outside U.S. and Canada)
- * Fax: (408) 481-6020
- * BBS: (408) 481-7800
- * e-mail: trimble_support@trimble.com
- * ftp://ftp.trimble.com/pub/sct/embedded/bin
- *
- * *************************************************************************
- *
- * ------- BYTE-SWAPPING -------
- * TSIP is big-endian (Motorola) protocol. To use on little-endian (Intel)
- * systems, the bytes of all multi-byte types (shorts, floats, doubles, etc.)
- * must be reversed. This is controlled by the MACRO BYTESWAP; if defined, it
- * assumes little-endian protocol.
- * --------------------------------
- *
- * T_PARSER.C and T_PARSER.H contains primitive functions that interpret
- * reports received from the receiver. A second source file pair,
- * T_FORMAT.C and T_FORMAT.H, contin the matching TSIP command formatters.
- *
- * The module is in very portable, basic C language. It can be used as is, or
- * with minimal changes if a TSIP communications application is needed separate
- * from TSIPCHAT. The construction of most argument lists avoid the use of
- * structures, but the developer is encouraged to reconstruct them using such
- * definitions to meet project requirements. Declarations of T_PARSER.C
- * functions are included in T_PARSER.H to provide prototyping definitions.
- *
- * There are two types of functions: a serial input processing routine,
- * tsip_input_proc()
- * which assembles incoming bytes into a TSIPPKT structure, and the
- * report parsers, rpt_0x??().
- *
- * 1) The function tsip_input_proc() accumulates bytes from the receiver,
- * strips control bytes (DLE), and checks if the report end sequence (DLE ETX)
- * has been received. rpt.status is defined as TSIP_PARSED_FULL (== 1)
- * if a complete packet is available.
- *
- * 2) The functions rpt_0x??() are report string interpreters patterned after
- * the document called "Trimble Standard Interface Protocol". It should be
- * noted that if the report buffer is sent into the receiver with the wrong
- * length (byte count), the rpt_0x??() returns the Boolean equivalence for
- * TRUE.
- *
- * *************************************************************************
- *
- */
-
-
-/**/
-static void tsip_input_proc (
- TSIPPKT *rpt,
- int inbyte)
-/* reads bytes until serial buffer is empty or a complete report
- * has been received; end of report is signified by DLE ETX.
- */
-{
- unsigned char newbyte;
-
- if (inbyte < 0 || inbyte > 0xFF) return;
-
- newbyte = (unsigned char)(inbyte);
- switch (rpt->status)
- {
- case TSIP_PARSED_DLE_1:
- switch (newbyte)
- {
- case 0:
- case ETX:
- /* illegal TSIP IDs */
- rpt->len = 0;
- rpt->status = TSIP_PARSED_EMPTY;
- break;
- case DLE:
- /* try normal message start again */
- rpt->len = 0;
- rpt->status = TSIP_PARSED_DLE_1;
- break;
- default:
- /* legal TSIP ID; start message */
- rpt->code = newbyte;
- rpt->len = 0;
- rpt->status = TSIP_PARSED_DATA;
- break;
- }
- break;
- case TSIP_PARSED_DATA:
- switch (newbyte) {
- case DLE:
- /* expect DLE or ETX next */
- rpt->status = TSIP_PARSED_DLE_2;
- break;
- default:
- /* normal data byte */
- rpt->buf[rpt->len] = newbyte;
- rpt->len++;
- /* no change in rpt->status */
- break;
- }
- break;
- case TSIP_PARSED_DLE_2:
- switch (newbyte) {
- case DLE:
- /* normal data byte */
- rpt->buf[rpt->len] = newbyte;
- rpt->len++;
- rpt->status = TSIP_PARSED_DATA;
- break;
- case ETX:
- /* end of message; return TRUE here. */
- rpt->status = TSIP_PARSED_FULL;
- break;
- default:
- /* error: treat as TSIP_PARSED_DLE_1; start new report packet */
- rpt->code = newbyte;
- rpt->len = 0;
- rpt->status = TSIP_PARSED_DATA;
- }
- break;
- case TSIP_PARSED_FULL:
- case TSIP_PARSED_EMPTY:
- default:
- switch (newbyte) {
- case DLE:
- /* normal message start */
- rpt->len = 0;
- rpt->status = TSIP_PARSED_DLE_1;
- break;
- default:
- /* error: ignore newbyte */
- rpt->len = 0;
- rpt->status = TSIP_PARSED_EMPTY;
- }
- break;
- }
- if (rpt->len > MAX_RPTBUF) {
- /* error: start new report packet */
- rpt->status = TSIP_PARSED_EMPTY;
- rpt->len = 0;
- }
-}
-
-#ifdef TRIMBLE_OUTPUT_FUNC
-
-/**/
-short rpt_0x3D (TSIPPKT *rpt,
- unsigned char *tx_baud_index,
- unsigned char *rx_baud_index,
- unsigned char *char_format_index,
- unsigned char *stop_bits,
- unsigned char *tx_mode_index,
- unsigned char *rx_mode_index)
-/* Channel A configuration for dual port operation */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 6) return TRUE;
- *tx_baud_index = buf[0];
- *rx_baud_index = buf[1];
- *char_format_index = buf[2];
- *stop_bits = (unsigned char)((buf[3] == 0x07) ? 1 : 2);
- *tx_mode_index = buf[4];
- *rx_mode_index = buf[5];
- return FALSE;
-}
-
-/**/
-short rpt_0x40 (TSIPPKT *rpt,
- unsigned char *sv_prn,
- short *week_num,
- float *t_zc,
- float *eccentricity,
- float *t_oa,
- float *i_0,
- float *OMEGA_dot,
- float *sqrt_A,
- float *OMEGA_0,
- float *omega,
- float *M_0)
-/* almanac data for specified satellite */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 39) return TRUE;
- *sv_prn = buf[0];
- *t_zc = bGetSingle (&buf[1]);
- *week_num = bGetShort (&buf[5]);
- *eccentricity = bGetSingle (&buf[7]);
- *t_oa = bGetSingle (&buf[11]);
- *i_0 = bGetSingle (&buf[15]);
- *OMEGA_dot = bGetSingle (&buf[19]);
- *sqrt_A = bGetSingle (&buf[23]);
- *OMEGA_0 = bGetSingle (&buf[27]);
- *omega = bGetSingle (&buf[31]);
- *M_0 = bGetSingle (&buf[35]);
- return FALSE;
-}
-
-short rpt_0x41 (TSIPPKT *rpt,
- float *time_of_week,
- float *UTC_offset,
- short *week_num)
-/* GPS time */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 10) return TRUE;
- *time_of_week = bGetSingle (buf);
- *week_num = bGetShort (&buf[4]);
- *UTC_offset = bGetSingle (&buf[6]);
- return FALSE;
-}
-
-short rpt_0x42 (TSIPPKT *rpt,
- float pos_ECEF[3],
- float *time_of_fix)
-/* position in ECEF, single precision */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 16) return TRUE;
- pos_ECEF[0] = bGetSingle (buf);
- pos_ECEF[1]= bGetSingle (&buf[4]);
- pos_ECEF[2]= bGetSingle (&buf[8]);
- *time_of_fix = bGetSingle (&buf[12]);
- return FALSE;
-}
-
-short rpt_0x43 (TSIPPKT *rpt,
- float ECEF_vel[3],
- float *freq_offset,
- float *time_of_fix)
-/* velocity in ECEF, single precision */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 20) return TRUE;
- ECEF_vel[0] = bGetSingle (buf);
- ECEF_vel[1] = bGetSingle (&buf[4]);
- ECEF_vel[2] = bGetSingle (&buf[8]);
- *freq_offset = bGetSingle (&buf[12]);
- *time_of_fix = bGetSingle (&buf[16]);
- return FALSE;
-}
-
-short rpt_0x45 (TSIPPKT *rpt,
- unsigned char *major_nav_version,
- unsigned char *minor_nav_version,
- unsigned char *nav_day,
- unsigned char *nav_month,
- unsigned char *nav_year,
- unsigned char *major_dsp_version,
- unsigned char *minor_dsp_version,
- unsigned char *dsp_day,
- unsigned char *dsp_month,
- unsigned char *dsp_year)
-/* software versions */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 10) return TRUE;
- *major_nav_version = buf[0];
- *minor_nav_version = buf[1];
- *nav_day = buf[2];
- *nav_month = buf[3];
- *nav_year = buf[4];
- *major_dsp_version = buf[5];
- *minor_dsp_version = buf[6];
- *dsp_day = buf[7];
- *dsp_month = buf[8];
- *dsp_year = buf[9];
- return FALSE;
-}
-
-short rpt_0x46 (TSIPPKT *rpt,
- unsigned char *status1,
- unsigned char *status2)
-/* receiver health and status */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 2) return TRUE;
- *status1 = buf[0];
- *status2 = buf[1];
- return FALSE;
-}
-
-short rpt_0x47 (TSIPPKT *rpt,
- unsigned char *nsvs, unsigned char *sv_prn,
- float *snr)
-/* signal levels for all satellites tracked */
-{
- short isv;
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 1 + 5*buf[0]) return TRUE;
- *nsvs = buf[0];
- for (isv = 0; isv < (*nsvs); isv++) {
- sv_prn[isv] = buf[5*isv + 1];
- snr[isv] = bGetSingle (&buf[5*isv + 2]);
- }
- return FALSE;
-}
-
-short rpt_0x48 (TSIPPKT *rpt,
- unsigned char *message)
-/* GPS system message */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 22) return TRUE;
- memcpy (message, buf, 22);
- message[22] = 0;
- return FALSE;
-}
-
-short rpt_0x49 (TSIPPKT *rpt,
- unsigned char *sv_health)
-/* health for all satellites from almanac health page */
-{
- short i;
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 32) return TRUE;
- for (i = 0; i < 32; i++) sv_health [i]= buf[i];
- return FALSE;
-}
-
-short rpt_0x4A (TSIPPKT *rpt,
- float *lat,
- float *lon,
- float *alt,
- float *clock_bias,
- float *time_of_fix)
-/* position in lat-lon-alt, single precision */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 20) return TRUE;
- *lat = bGetSingle (buf);
- *lon = bGetSingle (&buf[4]);
- *alt = bGetSingle (&buf[8]);
- *clock_bias = bGetSingle (&buf[12]);
- *time_of_fix = bGetSingle (&buf[16]);
- return FALSE;
-}
-
-short rpt_0x4A_2 (TSIPPKT *rpt,
- float *alt, float *dummy , unsigned char *alt_flag)
-/* reference altitude parameters */
-{
- unsigned char *buf;
-
- buf = rpt->buf;
-
- if (rpt->len != 9) return TRUE;
- *alt = bGetSingle (buf);
- *dummy = bGetSingle (&buf[4]);
- *alt_flag = buf[8];
- return FALSE;
-}
-
-short rpt_0x4B (TSIPPKT *rpt,
- unsigned char *machine_id,
- unsigned char *status3,
- unsigned char *status4)
-/* machine ID code, status */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 3) return TRUE;
- *machine_id = buf[0];
- *status3 = buf[1];
- *status4 = buf[2];
- return FALSE;
-}
-
-short rpt_0x4C (TSIPPKT *rpt,
- unsigned char *dyn_code,
- float *el_mask,
- float *snr_mask,
- float *dop_mask,
- float *dop_switch)
-/* operating parameters and masks */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 17) return TRUE;
- *dyn_code = buf[0];
- *el_mask = bGetSingle (&buf[1]);
- *snr_mask = bGetSingle (&buf[5]);
- *dop_mask = bGetSingle (&buf[9]);
- *dop_switch = bGetSingle (&buf[13]);
- return FALSE;
-}
-
-short rpt_0x4D (TSIPPKT *rpt,
- float *osc_offset)
-/* oscillator offset */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 4) return TRUE;
- *osc_offset = bGetSingle (buf);
- return FALSE;
-}
-
-short rpt_0x4E (TSIPPKT *rpt,
- unsigned char *response)
-/* yes/no response to command to set GPS time */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 1) return TRUE;
- *response = buf[0];
- return FALSE;
-}
-
-short rpt_0x4F (TSIPPKT *rpt,
- double *a0,
- float *a1,
- float *time_of_data,
- short *dt_ls,
- short *wn_t,
- short *wn_lsf,
- short *dn,
- short *dt_lsf)
-/* UTC data */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 26) return TRUE;
- *a0 = bGetDouble (buf);
- *a1 = bGetSingle (&buf[8]);
- *dt_ls = bGetShort (&buf[12]);
- *time_of_data = bGetSingle (&buf[14]);
- *wn_t = bGetShort (&buf[18]);
- *wn_lsf = bGetShort (&buf[20]);
- *dn = bGetShort (&buf[22]);
- *dt_lsf = bGetShort (&buf[24]);
- return FALSE;
-}
-
-/**/
-short rpt_0x54 (TSIPPKT *rpt,
- float *clock_bias,
- float *freq_offset,
- float *time_of_fix)
-/* clock offset and frequency offset in 1-SV (0-D) mode */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 12) return TRUE;
- *clock_bias = bGetSingle (buf);
- *freq_offset = bGetSingle (&buf[4]);
- *time_of_fix = bGetSingle (&buf[8]);
- return FALSE;
-}
-
-short rpt_0x55 (TSIPPKT *rpt,
- unsigned char *pos_code,
- unsigned char *vel_code,
- unsigned char *time_code,
- unsigned char *aux_code)
-/* I/O serial options */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 4) return TRUE;
- *pos_code = buf[0];
- *vel_code = buf[1];
- *time_code = buf[2];
- *aux_code = buf[3];
- return FALSE;
-}
-
-short rpt_0x56 (TSIPPKT *rpt,
- float vel_ENU[3], float *freq_offset, float *time_of_fix)
-/* velocity in east-north-up coordinates */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 20) return TRUE;
- /* east */
- vel_ENU[0] = bGetSingle (buf);
- /* north */
- vel_ENU[1] = bGetSingle (&buf[4]);
- /* up */
- vel_ENU[2] = bGetSingle (&buf[8]);
- *freq_offset = bGetSingle (&buf[12]);
- *time_of_fix = bGetSingle (&buf[16]);
- return FALSE;
-}
-
-short rpt_0x57 (TSIPPKT *rpt,
- unsigned char *source_code, unsigned char *diag_code,
- short *week_num,
- float *time_of_fix)
-/* info about last computed fix */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 8) return TRUE;
- *source_code = buf[0];
- *diag_code = buf[1];
- *time_of_fix = bGetSingle (&buf[2]);
- *week_num = bGetShort (&buf[6]);
- return FALSE;
-}
-
-short rpt_0x58 (TSIPPKT *rpt,
- unsigned char *op_code, unsigned char *data_type, unsigned char *sv_prn,
- unsigned char *data_length, unsigned char *data_packet)
-/* GPS system data or acknowledgment of GPS system data load */
-{
- unsigned char *buf, *buf4;
- short dl;
- ALM_INFO* alminfo;
- ION_INFO* ioninfo;
- UTC_INFO* utcinfo;
- NAV_INFO* navinfo;
-
- buf = rpt->buf;
-
- if (buf[0] == 2) {
- if (rpt->len < 4) return TRUE;
- if (rpt->len != 4+buf[3]) return TRUE;
- }
- else if (rpt->len != 3) {
- return TRUE;
- }
- *op_code = buf[0];
- *data_type = buf[1];
- *sv_prn = buf[2];
- if (*op_code == 2) {
- dl = buf[3];
- *data_length = (unsigned char)dl;
- buf4 = &buf[4];
- switch (*data_type) {
- case 2:
- /* Almanac */
- if (*data_length != sizeof (ALM_INFO)) return TRUE;
- alminfo = (ALM_INFO*)data_packet;
- alminfo->t_oa_raw = buf4[0];
- alminfo->SV_health = buf4[1];
- alminfo->e = bGetSingle(&buf4[2]);
- alminfo->t_oa = bGetSingle(&buf4[6]);
- alminfo->i_0 = bGetSingle(&buf4[10]);
- alminfo->OMEGADOT = bGetSingle(&buf4[14]);
- alminfo->sqrt_A = bGetSingle(&buf4[18]);
- alminfo->OMEGA_0 = bGetSingle(&buf4[22]);
- alminfo->omega = bGetSingle(&buf4[26]);
- alminfo->M_0 = bGetSingle(&buf4[30]);
- alminfo->a_f0 = bGetSingle(&buf4[34]);
- alminfo->a_f1 = bGetSingle(&buf4[38]);
- alminfo->Axis = bGetSingle(&buf4[42]);
- alminfo->n = bGetSingle(&buf4[46]);
- alminfo->OMEGA_n = bGetSingle(&buf4[50]);
- alminfo->ODOT_n = bGetSingle(&buf4[54]);
- alminfo->t_zc = bGetSingle(&buf4[58]);
- alminfo->weeknum = bGetShort(&buf4[62]);
- alminfo->wn_oa = bGetShort(&buf4[64]);
- break;
-
- case 3:
- /* Almanac health page */
- if (*data_length != sizeof (ALH_PARMS) + 3) return TRUE;
-
- /* this record is returned raw */
- memcpy (data_packet, buf4, dl);
- break;
-
- case 4:
- /* Ionosphere */
- if (*data_length != sizeof (ION_INFO) + 8) return TRUE;
- ioninfo = (ION_INFO*)data_packet;
- ioninfo->alpha_0 = bGetSingle (&buf4[8]);
- ioninfo->alpha_1 = bGetSingle (&buf4[12]);
- ioninfo->alpha_2 = bGetSingle (&buf4[16]);
- ioninfo->alpha_3 = bGetSingle (&buf4[20]);
- ioninfo->beta_0 = bGetSingle (&buf4[24]);
- ioninfo->beta_1 = bGetSingle (&buf4[28]);
- ioninfo->beta_2 = bGetSingle (&buf4[32]);
- ioninfo->beta_3 = bGetSingle (&buf4[36]);
- break;
-
- case 5:
- /* UTC */
- if (*data_length != sizeof (UTC_INFO) + 13) return TRUE;
- utcinfo = (UTC_INFO*)data_packet;
- utcinfo->A_0 = bGetDouble (&buf4[13]);
- utcinfo->A_1 = bGetSingle (&buf4[21]);
- utcinfo->delta_t_LS = bGetShort (&buf4[25]);
- utcinfo->t_ot = bGetSingle(&buf4[27]);
- utcinfo->WN_t = bGetShort (&buf4[31]);
- utcinfo->WN_LSF = bGetShort (&buf4[33]);
- utcinfo->DN = bGetShort (&buf4[35]);
- utcinfo->delta_t_LSF = bGetShort (&buf4[37]);
- break;
-
- case 6:
- /* Ephemeris */
- if (*data_length != sizeof (NAV_INFO) - 1) return TRUE;
-
- navinfo = (NAV_INFO*)data_packet;
-
- navinfo->sv_number = buf4[0];
- navinfo->t_ephem = bGetSingle (&buf4[1]);
- navinfo->ephclk.weeknum = bGetShort (&buf4[5]);
-
- navinfo->ephclk.codeL2 = buf4[7];
- navinfo->ephclk.L2Pdata = buf4[8];
- navinfo->ephclk.SVacc_raw = buf4[9];
- navinfo->ephclk.SV_health = buf4[10];
- navinfo->ephclk.IODC = bGetShort (&buf4[11]);
- navinfo->ephclk.T_GD = bGetSingle (&buf4[13]);
- navinfo->ephclk.t_oc = bGetSingle (&buf4[17]);
- navinfo->ephclk.a_f2 = bGetSingle (&buf4[21]);
- navinfo->ephclk.a_f1 = bGetSingle (&buf4[25]);
- navinfo->ephclk.a_f0 = bGetSingle (&buf4[29]);
- navinfo->ephclk.SVacc = bGetSingle (&buf4[33]);
-
- navinfo->ephorb.IODE = buf4[37];
- navinfo->ephorb.fit_interval = buf4[38];
- navinfo->ephorb.C_rs = bGetSingle (&buf4[39]);
- navinfo->ephorb.delta_n = bGetSingle (&buf4[43]);
- navinfo->ephorb.M_0 = bGetDouble (&buf4[47]);
- navinfo->ephorb.C_uc = bGetSingle (&buf4[55]);
- navinfo->ephorb.e = bGetDouble (&buf4[59]);
- navinfo->ephorb.C_us = bGetSingle (&buf4[67]);
- navinfo->ephorb.sqrt_A = bGetDouble (&buf4[71]);
- navinfo->ephorb.t_oe = bGetSingle (&buf4[79]);
- navinfo->ephorb.C_ic = bGetSingle (&buf4[83]);
- navinfo->ephorb.OMEGA_0 = bGetDouble (&buf4[87]);
- navinfo->ephorb.C_is = bGetSingle (&buf4[95]);
- navinfo->ephorb.i_0 = bGetDouble (&buf4[99]);
- navinfo->ephorb.C_rc = bGetSingle (&buf4[107]);
- navinfo->ephorb.omega = bGetDouble (&buf4[111]);
- navinfo->ephorb.OMEGADOT=bGetSingle (&buf4[119]);
- navinfo->ephorb.IDOT = bGetSingle (&buf4[123]);
- navinfo->ephorb.Axis = bGetDouble (&buf4[127]);
- navinfo->ephorb.n = bGetDouble (&buf4[135]);
- navinfo->ephorb.r1me2 = bGetDouble (&buf4[143]);
- navinfo->ephorb.OMEGA_n=bGetDouble (&buf4[151]);
- navinfo->ephorb.ODOT_n = bGetDouble (&buf4[159]);
- break;
- }
- }
- return FALSE;
-}
-
-short rpt_0x59 (TSIPPKT *rpt,
- unsigned char *code_type,
- unsigned char status_code[32])
-/* satellite enable/disable or health heed/ignore list */
-{
- short iprn;
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 33) return TRUE;
- *code_type = buf[0];
- for (iprn = 0; iprn < 32; iprn++)
- status_code[iprn] = buf[iprn + 1];
- return FALSE;
-}
-
-short rpt_0x5A (TSIPPKT *rpt,
- unsigned char *sv_prn,
- float *sample_length,
- float *signal_level,
- float *code_phase,
- float *Doppler,
- double *time_of_fix)
-/* raw measurement data - code phase/Doppler */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 25) return TRUE;
- *sv_prn = buf[0];
- *sample_length = bGetSingle (&buf[1]);
- *signal_level = bGetSingle (&buf[5]);
- *code_phase = bGetSingle (&buf[9]);
- *Doppler = bGetSingle (&buf[13]);
- *time_of_fix = bGetDouble (&buf[17]);
- return FALSE;
-}
-
-short rpt_0x5B (TSIPPKT *rpt,
- unsigned char *sv_prn,
- unsigned char *sv_health,
- unsigned char *sv_iode,
- unsigned char *fit_interval_flag,
- float *time_of_collection,
- float *time_of_eph,
- float *sv_accy)
-/* satellite ephorb status */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 16) return TRUE;
- *sv_prn = buf[0];
- *time_of_collection = bGetSingle (&buf[1]);
- *sv_health = buf[5];
- *sv_iode = buf[6];
- *time_of_eph = bGetSingle (&buf[7]);
- *fit_interval_flag = buf[11];
- *sv_accy = bGetSingle (&buf[12]);
- return FALSE;
-}
-
-short rpt_0x5C (TSIPPKT *rpt,
- unsigned char *sv_prn,
- unsigned char *slot,
- unsigned char *chan,
- unsigned char *acq_flag,
- unsigned char *eph_flag,
- float *signal_level,
- float *time_of_last_msmt,
- float *elev,
- float *azim,
- unsigned char *old_msmt_flag,
- unsigned char *integer_msec_flag,
- unsigned char *bad_data_flag,
- unsigned char *data_collect_flag)
-/* satellite tracking status */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 24) return TRUE;
- *sv_prn = buf[0];
- *slot = (unsigned char)((buf[1] & 0x07) + 1);
- *chan = (unsigned char)(buf[1] >> 3);
- if (*chan == 0x10) *chan = 2;
- else (*chan)++;
- *acq_flag = buf[2];
- *eph_flag = buf[3];
- *signal_level = bGetSingle (&buf[4]);
- *time_of_last_msmt = bGetSingle (&buf[8]);
- *elev = bGetSingle (&buf[12]);
- *azim = bGetSingle (&buf[16]);
- *old_msmt_flag = buf[20];
- *integer_msec_flag = buf[21];
- *bad_data_flag = buf[22];
- *data_collect_flag = buf[23];
- return FALSE;
-}
-
-/**/
-short rpt_0x6D (TSIPPKT *rpt,
- unsigned char *manual_mode,
- unsigned char *nsvs,
- unsigned char *ndim,
- unsigned char sv_prn[],
- float *pdop,
- float *hdop,
- float *vdop,
- float *tdop)
-/* over-determined satellite selection for position fixes, PDOP, fix mode */
-{
- short islot;
- unsigned char *buf;
- buf = rpt->buf;
-
- *nsvs = (unsigned char)((buf[0] & 0xF0) >> 4);
- if ((*nsvs)>8) return TRUE;
- if (rpt->len != 17 + (*nsvs) ) return TRUE;
-
- *manual_mode = (unsigned char)(buf[0] & 0x08);
- *ndim = (unsigned char)((buf[0] & 0x07));
- *pdop = bGetSingle (&buf[1]);
- *hdop = bGetSingle (&buf[5]);
- *vdop = bGetSingle (&buf[9]);
- *tdop = bGetSingle (&buf[13]);
- for (islot = 0; islot < (*nsvs); islot++)
- sv_prn[islot] = buf[islot + 17];
- return FALSE;
-}
-
-/**/
-short rpt_0x82 (TSIPPKT *rpt,
- unsigned char *diff_mode)
-/* differential fix mode */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 1) return TRUE;
- *diff_mode = buf[0];
- return FALSE;
-}
-
-short rpt_0x83 (TSIPPKT *rpt,
- double ECEF_pos[3],
- double *clock_bias,
- float *time_of_fix)
-/* position, ECEF double precision */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 36) return TRUE;
- ECEF_pos[0] = bGetDouble (buf);
- ECEF_pos[1] = bGetDouble (&buf[8]);
- ECEF_pos[2] = bGetDouble (&buf[16]);
- *clock_bias = bGetDouble (&buf[24]);
- *time_of_fix = bGetSingle (&buf[32]);
- return FALSE;
-}
-
-short rpt_0x84 (TSIPPKT *rpt,
- double *lat,
- double *lon,
- double *alt,
- double *clock_bias,
- float *time_of_fix)
-/* position, lat-lon-alt double precision */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 36) return TRUE;
- *lat = bGetDouble (buf);
- *lon = bGetDouble (&buf[8]);
- *alt = bGetDouble (&buf[16]);
- *clock_bias = bGetDouble (&buf[24]);
- *time_of_fix = bGetSingle (&buf[32]);
- return FALSE;
-}
-
-short rpt_Paly0xBB(TSIPPKT *rpt,
- TSIP_RCVR_CFG *TsipxBB)
-{
-
- unsigned char *buf;
- buf = rpt->buf;
-
- /* Palisade is inconsistent with other TSIP, which has a kength of 40 */
- /* if (rpt->len != 40) return TRUE; */
- if (rpt->len != 43) return TRUE;
-
- TsipxBB->bSubcode = buf[0];
- TsipxBB->operating_mode = buf[1] ;
- TsipxBB->dyn_code = buf[3] ;
- TsipxBB->elev_mask = bGetSingle (&buf[5]);
- TsipxBB->cno_mask = bGetSingle (&buf[9]);
- TsipxBB->dop_mask = bGetSingle (&buf[13]);
- TsipxBB->dop_switch = bGetSingle (&buf[17]);
- return FALSE;
-}
-
-short rpt_0xBC (TSIPPKT *rpt,
- unsigned char *port_num,
- unsigned char *in_baud,
- unsigned char *out_baud,
- unsigned char *data_bits,
- unsigned char *parity,
- unsigned char *stop_bits,
- unsigned char *flow_control,
- unsigned char *protocols_in,
- unsigned char *protocols_out,
- unsigned char *reserved)
-/* Receiver serial port configuration */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 10) return TRUE;
- *port_num = buf[0];
- *in_baud = buf[1];
- *out_baud = buf[2];
- *data_bits = buf[3];
- *parity = buf[4];
- *stop_bits = buf[5];
- *flow_control = buf[6];
- *protocols_in = buf[7];
- *protocols_out = buf[8];
- *reserved = buf[9];
-
- return FALSE;
-}
-
-/**** Superpackets ****/
-
-short rpt_0x8F0B(TSIPPKT *rpt,
- unsigned short *event,
- double *tow,
- unsigned char *date,
- unsigned char *month,
- short *year,
- unsigned char *dim_mode,
- short *utc_offset,
- double *bias,
- double *drift,
- float *bias_unc,
- float *dr_unc,
- double *lat,
- double *lon,
- double *alt,
- char sv_id[8])
-{
- short local_index;
- unsigned char *buf;
-
- buf = rpt->buf;
- if (rpt->len != 74) return TRUE;
- *event = bGetShort(&buf[1]);
- *tow = bGetDouble(&buf[3]);
- *date = buf[11];
- *month = buf[12];
- *year = bGetShort(&buf[13]);
- *dim_mode = buf[15];
- *utc_offset = bGetShort(&buf[16]);
- *bias = bGetDouble(&buf[18]);
- *drift = bGetDouble(&buf[26]);
- *bias_unc = bGetSingle(&buf[34]);
- *dr_unc = bGetSingle(&buf[38]);
- *lat = bGetDouble(&buf[42]);
- *lon = bGetDouble(&buf[50]);
- *alt = bGetDouble(&buf[58]);
-
- for (local_index=0; local_index<8; local_index++) sv_id[local_index] = buf[local_index + 66];
- return FALSE;
-}
-
-short rpt_0x8F14 (TSIPPKT *rpt,
- short *datum_idx,
- double datum_coeffs[5])
-/* datum index and coefficients */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 43) return TRUE;
- *datum_idx = bGetShort(&buf[1]);
- datum_coeffs[0] = bGetDouble (&buf[3]);
- datum_coeffs[1] = bGetDouble (&buf[11]);
- datum_coeffs[2] = bGetDouble (&buf[19]);
- datum_coeffs[3] = bGetDouble (&buf[27]);
- datum_coeffs[4] = bGetDouble (&buf[35]);
- return FALSE;
-}
-
-
-short rpt_0x8F15 (TSIPPKT *rpt,
- short *datum_idx,
- double datum_coeffs[5])
-/* datum index and coefficients */
-{
- unsigned char *buf;
- buf = rpt->buf;
-
- if (rpt->len != 43) return TRUE;
- *datum_idx = bGetShort(&buf[1]);
- datum_coeffs[0] = bGetDouble (&buf[3]);
- datum_coeffs[1] = bGetDouble (&buf[11]);
- datum_coeffs[2] = bGetDouble (&buf[19]);
- datum_coeffs[3] = bGetDouble (&buf[27]);
- datum_coeffs[4] = bGetDouble (&buf[35]);
- return FALSE;
-}
-
-
-#define MAX_LONG (2147483648.) /* 2**31 */
-
-short rpt_0x8F20 (TSIPPKT *rpt,
- unsigned char *info,
- double *lat,
- double *lon,
- double *alt,
- double vel_enu[],
- double *time_of_fix,
- short *week_num,
- unsigned char *nsvs,
- unsigned char sv_prn[],
- short sv_IODC[],
- short *datum_index)
-{
- short
- isv;
- unsigned char
- *buf, prnx, iode;
- unsigned long
- ulongtemp;
- long
- longtemp;
- double
- vel_scale;
-
- buf = rpt->buf;
-
- if (rpt->len != 56) return TRUE;
-
- vel_scale = (buf[24]&1)? 0.020 : 0.005;
- vel_enu[0] = bGetShort (buf+2)*vel_scale;
- vel_enu[1] = bGetShort (buf+4)*vel_scale;
- vel_enu[2] = bGetShort (buf+6)*vel_scale;
-
- *time_of_fix = bGetULong (buf+8)*.001;
-
- longtemp = bGetLong (buf+12);
- *lat = longtemp*(GPS_PI/MAX_LONG);
-
- ulongtemp = bGetULong (buf+16);
- *lon = ulongtemp*(GPS_PI/MAX_LONG);
- if (*lon > GPS_PI) *lon -= 2.0*GPS_PI;
-
- *alt = bGetLong (buf+20)*.001;
- /* 25 blank; 29 = UTC */
- (*datum_index) = (short)((short)buf[26]-1);
- *info = buf[27];
- *nsvs = buf[28];
- *week_num = bGetShort (&buf[30]);
- for (isv = 0; isv < 8; isv++) {
- prnx = buf[32+2*isv];
- sv_prn[isv] = (unsigned char)(prnx&0x3F);
- iode = buf[33+2*isv];
- sv_IODC[isv] = (short)(iode | ((prnx>>6)<<8));
- }
- return FALSE;
-}
-
-short rpt_0x8F41 (TSIPPKT *rpt,
- unsigned char *bSearchRange,
- unsigned char *bBoardOptions,
- unsigned long *iiSerialNumber,
- unsigned char *bBuildYear,
- unsigned char *bBuildMonth,
- unsigned char *bBuildDay,
- unsigned char *bBuildHour,
- float *fOscOffset,
- unsigned short *iTestCodeId)
-{
- if(rpt->len != 17) return FALSE;
- *bSearchRange = rpt->buf[1];
- *bBoardOptions = rpt->buf[2];
- *iiSerialNumber = bGetLong(&rpt->buf[3]);
- *bBuildYear = rpt->buf[7];
- *bBuildMonth = rpt->buf[8];
- *bBuildDay = rpt->buf[9];
- *bBuildHour = rpt->buf[10];
- *fOscOffset = bGetSingle(&rpt->buf[11]);
- *iTestCodeId = bGetShort(&rpt->buf[15]);
-/* Tsipx8E41Data = *Tsipx8E41; */
- return TRUE;
-}
-
-short rpt_0x8F42 (TSIPPKT *rpt,
- unsigned char *bProdOptionsPre,
- unsigned char *bProdNumberExt,
- unsigned short *iCaseSerialNumberPre,
- unsigned long *iiCaseSerialNumber,
- unsigned long *iiProdNumber,
- unsigned short *iPremiumOptions,
- unsigned short *iMachineID,
- unsigned short *iKey)
-{
- if(rpt->len != 19) return FALSE;
- *bProdOptionsPre = rpt->buf[1];
- *bProdNumberExt = rpt->buf[2];
- *iCaseSerialNumberPre = bGetShort(&rpt->buf[3]);
- *iiCaseSerialNumber = bGetLong(&rpt->buf[5]);
- *iiProdNumber = bGetLong(&rpt->buf[9]);
- *iPremiumOptions = bGetShort(&rpt->buf[13]);
- *iMachineID = bGetShort(&rpt->buf[15]);
- *iKey = bGetShort(&rpt->buf[17]);
- return TRUE;
-}
-
-short rpt_0x8F45(TSIPPKT *rpt,
- unsigned char *bSegMask)
-{
- if(rpt->len != 2) return FALSE;
- *bSegMask = rpt->buf[1];
- return TRUE;
-}
-
-short rpt_0x8F4A_16(TSIPPKT *rpt,
- unsigned char *pps_enabled,
- unsigned char *pps_timebase,
- unsigned char *pos_polarity,
- double *pps_offset,
- float *bias_unc_threshold)
-/* Stinger PPS definition */
-{
- unsigned char
- *buf;
-
- buf = rpt->buf;
- if (rpt->len != 16) return TRUE;
- *pps_enabled = buf[1];
- *pps_timebase = buf[2];
- *pos_polarity = buf[3];
- *pps_offset = bGetDouble(&buf[4]);
- *bias_unc_threshold = bGetSingle(&buf[12]);
- return FALSE;
-}
-
-short rpt_0x8F4B(TSIPPKT *rpt,
- unsigned long *decorr_max)
-{
- unsigned char
- *buf;
-
- buf = rpt->buf;
- if (rpt->len != 5) return TRUE;
- *decorr_max = bGetLong(&buf[1]);
- return FALSE;
-}
-
-short rpt_0x8F4D(TSIPPKT *rpt,
- unsigned long *event_mask)
-{
- unsigned char
- *buf;
-
- buf = rpt->buf;
- if (rpt->len != 5) return TRUE;
- *event_mask = bGetULong (&buf[1]);
- return FALSE;
-}
-
-short rpt_0x8FA5(TSIPPKT *rpt,
- unsigned char *spktmask)
-{
- unsigned char
- *buf;
-
- buf = rpt->buf;
- if (rpt->len != 5) return TRUE;
- spktmask[0] = buf[1];
- spktmask[1] = buf[2];
- spktmask[2] = buf[3];
- spktmask[3] = buf[4];
- return FALSE;
-}
-
-short rpt_0x8FAD (TSIPPKT *rpt,
- unsigned short *COUNT,
- double *FracSec,
- unsigned char *Hour,
- unsigned char *Minute,
- unsigned char *Second,
- unsigned char *Day,
- unsigned char *Month,
- unsigned short *Year,
- unsigned char *Status,
- unsigned char *Flags)
-{
-
- if (rpt->len != 22) return TRUE;
-
- *COUNT = bGetUShort(&rpt->buf[1]);
- *FracSec = bGetDouble(&rpt->buf[3]);
- *Hour = rpt->buf[11];
- *Minute = rpt->buf[12];
- *Second = rpt->buf[13];
- *Day = rpt->buf[14];
- *Month = rpt->buf[15];
- *Year = bGetUShort(&rpt->buf[16]);
- *Status = rpt->buf[18];
- *Flags = rpt->buf[19];
- return FALSE;
-}
-
-
-/*
- * *************************************************************************
- *
- * Trimble Navigation, Ltd.
- * OEM Products Development Group
- * P.O. Box 3642
- * 645 North Mary Avenue
- * Sunnyvale, California 94088-3642
- *
- * Corporate Headquarter:
- * Telephone: (408) 481-8000
- * Fax: (408) 481-6005
- *
- * Technical Support Center:
- * Telephone: (800) 767-4822 (U.S. and Canada)
- * (408) 481-6940 (outside U.S. and Canada)
- * Fax: (408) 481-6020
- * BBS: (408) 481-7800
- * e-mail: trimble_support@trimble.com
- * ftp://ftp.trimble.com/pub/sct/embedded/bin
- *
- * *************************************************************************
- *
- * T_REPORT.C consists of a primary function TranslateTSIPReportToText()
- * called by main().
- *
- * This function takes a character buffer that has been received as a report
- * from a TSIP device and interprets it. The character buffer has been
- * assembled using tsip_input_proc() in T_PARSER.C.
- *
- * A large case statement directs processing to one of many mid-level
- * functions. The mid-level functions specific to the current report
- * code passes the report buffer to the appropriate report decoder
- * rpt_0x?? () in T_PARSER.C, which converts the byte stream in rpt.buf
- * to data values approporaite for use.
- *
- * *************************************************************************
- *
- */
-
-
-#define GOOD_PARSE 0
-#define BADID_PARSE 1
-#define BADLEN_PARSE 2
-#define BADDATA_PARSE 3
-
-#define B_TSIP 0x02
-#define B_NMEA 0x04
-
-
-/* pbuf is the pointer to the current location of the text output */
-static char
- *pbuf;
-
-/* keep track of whether the message has been successfully parsed */
-static short
- parsed;
-
-
-/* convert time of week into day-hour-minute-second and print */
-char* show_time (float time_of_week)
-{
- short days, hours, minutes;
- float seconds;
- double tow = 0;
- static char timestring [80];
-
- if (time_of_week == -1.0)
- {
- sprintf(timestring, " <No time yet> ");
- }
- else if ((time_of_week >= 604800.0) || (time_of_week < 0.0))
- {
- sprintf(timestring, " <Bad time> ");
- }
- else
- {
- if (time_of_week < 604799.9)
- tow = time_of_week + .00000001;
- seconds = (float)fmod(tow, 60.);
- minutes = (short) fmod(tow/60., 60.);
- hours = (short)fmod(tow / 3600., 24.);
- days = (short)(tow / 86400.0);
- sprintf(timestring, " %s %02d:%02d:%05.2f ",
- dayname[days], hours, minutes, seconds);
- }
- return timestring;
-}
-
-/**/
-/* 0x3D */
-static void rpt_chan_A_config (TSIPPKT *rpt)
-{
- unsigned char
- tx_baud_index, rx_baud_index,
- char_format_index, stop_bits,
- tx_mode_index, rx_mode_index,
- databits, parity;
- int
- i, nbaud;
-
- /* unload rptbuf */
- if (rpt_0x3D (rpt,
- &tx_baud_index, &rx_baud_index, &char_format_index,
- &stop_bits, &tx_mode_index, &rx_mode_index)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nChannel A Configuration");
-
- nbaud = sizeof(old_baudnum);
-
- for (i = 0; i < nbaud; ++i) if (tx_baud_index == old_baudnum[i]) break;
- pbuf += sprintf(pbuf, "\n Transmit speed: %s at %s",
- old_output_ch[tx_mode_index], st_baud_text_app[i]);
-
- for (i = 0; i < nbaud; ++i) if (rx_baud_index == old_baudnum[i]) break;
- pbuf += sprintf(pbuf, "\n Receive speed: %s at %s",
- old_input_ch[rx_mode_index], st_baud_text_app[i]);
-
- databits = (unsigned char)((char_format_index & 0x03) + 5);
-
- parity = (unsigned char)(char_format_index >> 2);
- if (parity > 4) parity = 2;
-
- pbuf += sprintf(pbuf, "\n Character format (bits/char, parity, stop bits): %d-%s-%d",
- databits, old_parity_text[parity], stop_bits);
-}
-
-/**/
-/* 0x40 */
-static void rpt_almanac_data_page (TSIPPKT *rpt)
-{
- unsigned char
- sv_prn;
- short
- week_num;
- float
- t_zc,
- eccentricity,
- t_oa,
- i_0,
- OMEGA_dot,
- sqrt_A,
- OMEGA_0,
- omega,
- M_0;
-
- /* unload rptbuf */
- if (rpt_0x40 (rpt,
- &sv_prn, &week_num, &t_zc, &eccentricity, &t_oa,
- &i_0, &OMEGA_dot, &sqrt_A, &OMEGA_0, &omega, &M_0)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nAlmanac for SV %02d", sv_prn);
- pbuf += sprintf(pbuf, "\n Captured:%15.0f %s",
- t_zc, show_time (t_zc));
- pbuf += sprintf(pbuf, "\n week:%15d", week_num);
- pbuf += sprintf(pbuf, "\n Eccentricity:%15g", eccentricity);
- pbuf += sprintf(pbuf, "\n T_oa:%15.0f %s",
- t_oa, show_time (t_oa));
- pbuf += sprintf(pbuf, "\n i 0:%15g", i_0);
- pbuf += sprintf(pbuf, "\n OMEGA dot:%15g", OMEGA_dot);
- pbuf += sprintf(pbuf, "\n sqrt A:%15g", sqrt_A);
- pbuf += sprintf(pbuf, "\n OMEGA 0:%15g", OMEGA_0);
- pbuf += sprintf(pbuf, "\n omega:%15g", omega);
- pbuf += sprintf(pbuf, "\n M 0:%15g", M_0);
-}
-
-/* 0x41 */
-static void rpt_GPS_time (TSIPPKT *rpt)
-{
- float
- time_of_week, UTC_offset;
- short
- week_num;
-
- /* unload rptbuf */
- if (rpt_0x41 (rpt, &time_of_week, &UTC_offset, &week_num)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nGPS time:%s GPS week: %d UTC offset %.1f",
- show_time(time_of_week), week_num, UTC_offset);
-
-}
-
-/* 0x42 */
-static void rpt_single_ECEF_position (TSIPPKT *rpt)
-{
- float
- ECEF_pos[3], time_of_fix;
-
- /* unload rptbuf */
- if (rpt_0x42 (rpt, ECEF_pos, &time_of_fix)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nSXYZ: %15.0f %15.0f %15.0f %s",
- ECEF_pos[0], ECEF_pos[1], ECEF_pos[2],
- show_time(time_of_fix));
-}
-
-/* 0x43 */
-static void rpt_single_ECEF_velocity (TSIPPKT *rpt)
-{
-
- float
- ECEF_vel[3], freq_offset, time_of_fix;
-
- /* unload rptbuf */
- if (rpt_0x43 (rpt, ECEF_vel, &freq_offset, &time_of_fix)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nVelECEF: %11.3f %11.3f %11.3f %12.3f%s",
- ECEF_vel[0], ECEF_vel[1], ECEF_vel[2], freq_offset,
- show_time(time_of_fix));
-}
-
-/* 0x45 */
-static void rpt_SW_version (TSIPPKT *rpt) {
- unsigned char
- major_nav_version, minor_nav_version,
- nav_day, nav_month, nav_year,
- major_dsp_version, minor_dsp_version,
- dsp_day, dsp_month, dsp_year;
-
- /* unload rptbuf */
- if (rpt_0x45 (rpt,
- &major_nav_version, &minor_nav_version,
- &nav_day, &nav_month, &nav_year,
- &major_dsp_version, &minor_dsp_version,
- &dsp_day, &dsp_month, &dsp_year)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf,
-"\nFW Versions: Nav Proc %2d.%02d %2d/%2d/%2d Sig Proc %2d.%02d %2d/%2d/%2d",
- major_nav_version, minor_nav_version, nav_day, nav_month, nav_year,
- major_dsp_version, minor_dsp_version, dsp_day, dsp_month, dsp_year);
-}
-
-/* 0x46 */
-static void rpt_rcvr_health (TSIPPKT *rpt)
-{
- unsigned char
- status1, status2;
- static char
- *sc_text[] = {
- "Doing position fixes",
- "Don't have GPS time yet",
- "Waiting for almanac collection",
- "DOP too high ",
- "No satellites available",
- "Only 1 satellite available",
- "Only 2 satellites available",
- "Only 3 satellites available",
- "No satellites usable ",
- "Only 1 satellite usable",
- "Only 2 satellites usable",
- "Only 3 satellites usable",
- "Chosen satellite unusable"};
-
-
- /* unload rptbuf */
- if (rpt_0x46 (rpt, &status1, &status2))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nRcvr status1: %s (%02Xh); ",
- sc_text[rpt->buf[0]], status1);
-
- pbuf += sprintf(pbuf, "status2: %s, %s (%02Xh)",
- (status2 & 0x01)?"No BBRAM":"BBRAM OK",
- (status2 & 0x10)?"No Ant":"Ant OK",
- status2);
-}
-
-/* 0x47 */
-static void rpt_SNR_all_SVs (TSIPPKT *rpt)
-{
- unsigned char
- nsvs, sv_prn[12];
- short
- isv;
- float
- snr[12];
-
- /* unload rptbuf */
- if (rpt_0x47 (rpt, &nsvs, sv_prn, snr))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nSNR for satellites: %d", nsvs);
- for (isv = 0; isv < nsvs; isv++)
- {
- pbuf += sprintf(pbuf, "\n SV %02d %6.2f",
- sv_prn[isv], snr[isv]);
- }
-}
-
-/* 0x48 */
-static void rpt_GPS_system_message (TSIPPKT *rpt)
-{
- unsigned char
- message[23];
-
- /* unload rptbuf */
- if (rpt_0x48 (rpt, message))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nGPS message: %s", message);
-}
-
-/* 0x49 */
-static void rpt_almanac_health_page (TSIPPKT *rpt)
-{
- short
- iprn;
- unsigned char
- sv_health [32];
-
- /* unload rptbuf */
- if (rpt_0x49 (rpt, sv_health))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nAlmanac health page:");
- for (iprn = 0; iprn < 32; iprn++)
- {
- if (!(iprn%5)) *pbuf++ = '\n';
- pbuf += sprintf(pbuf, " SV%02d %2X",
- (iprn+1) , sv_health[iprn]);
- }
-}
-
-/* 0x4A */
-static void rpt_single_lla_position (TSIPPKT *rpt) {
- short
- lat_deg, lon_deg;
- float
- lat, lon,
- alt, clock_bias, time_of_fix;
- double lat_min, lon_min;
- unsigned char
- north_south, east_west;
-
- if (rpt_0x4A (rpt,
- &lat, &lon, &alt, &clock_bias, &time_of_fix))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- /* convert from radians to degrees */
- lat *= (float)R2D;
- north_south = 'N';
- if (lat < 0.0)
- {
- north_south = 'S';
- lat = -lat;
- }
- lat_deg = (short)lat;
- lat_min = (lat - lat_deg) * 60.0;
-
- lon *= (float)R2D;
- east_west = 'E';
- if (lon < 0.0)
- {
- east_west = 'W';
- lon = -lon;
- }
- lon_deg = (short)lon;
- lon_min = (lon - lon_deg) * 60.0;
-
- pbuf += sprintf(pbuf, "\nSLLA: %4d: %06.3f %c%5d:%06.3f %c%10.2f %12.2f%s",
- lat_deg, lat_min, north_south,
- lon_deg, lon_min, east_west,
- alt, clock_bias,
- show_time(time_of_fix));
-}
-
-/* 0x4A */
-static void rpt_ref_alt (TSIPPKT *rpt) {
-
- float
- alt, dummy;
- unsigned char
- alt_flag;
-
- if (rpt_0x4A_2 (rpt,
- &alt, &dummy, &alt_flag))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nReference Alt: %.1f m; %s",
- alt, alt_flag?"ON":"OFF");
-}
-
-/* 0x4B */
-static void rpt_rcvr_id_and_status (TSIPPKT *rpt)
-{
-
- unsigned char
- machine_id, status3, status4;
-
- /* unload rptbuf */
- if (rpt_0x4B (rpt, &machine_id, &status3, &status4))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nRcvr Machine ID: %d; Status3 = %s, %s (%02Xh)",
- machine_id,
- (status3 & 0x02)?"No RTC":"RTC OK",
- (status3 & 0x08)?"No Alm":"Alm OK",
- status3);
-}
-
-/* 0x4C */
-static void rpt_operating_parameters (TSIPPKT *rpt)
-{
- unsigned char
- dyn_code;
- float
- el_mask, snr_mask, dop_mask, dop_switch;
-
- /* unload rptbuf */
- if (rpt_0x4C (rpt, &dyn_code, &el_mask,
- &snr_mask, &dop_mask, &dop_switch))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nOperating Parameters:");
- pbuf += sprintf(pbuf, "\n Dynamics code = %d %s",
- dyn_code, dyn_text[dyn_code]);
- pbuf += sprintf(pbuf, "\n Elevation mask = %.2fø", el_mask * R2D);
- pbuf += sprintf(pbuf, "\n SNR mask = %.2f", snr_mask);
- pbuf += sprintf(pbuf, "\n DOP mask = %.2f", dop_mask);
- pbuf += sprintf(pbuf, "\n DOP switch = %.2f", dop_switch);
-}
-
-/* 0x4D */
-static void rpt_oscillator_offset (TSIPPKT *rpt)
-{
- float
- osc_offset;
-
- /* unload rptbuf */
- if (rpt_0x4D (rpt, &osc_offset))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nOscillator offset: %.2f Hz = %.3f PPM",
- osc_offset, osc_offset/1575.42);
-}
-
-/* 0x4E */
-static void rpt_GPS_time_set_response (TSIPPKT *rpt)
-{
-
- unsigned char
- response;
-
- /* unload rptbuf */
- if (rpt_0x4E (rpt, &response))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- switch (response)
- {
- case 'Y':
- pbuf += sprintf(pbuf, "\nTime set accepted");
- break;
-
- case 'N':
- pbuf += sprintf(pbuf, "\nTime set rejected or not required");
- break;
-
- default:
- parsed = BADDATA_PARSE;
- }
-}
-
-/* 0x4F */
-static void rpt_UTC_offset (TSIPPKT *rpt)
-{
- double
- a0;
- float
- a1, time_of_data;
- short
- dt_ls, wn_t, wn_lsf, dn, dt_lsf;
-
- /* unload rptbuf */
- if (rpt_0x4F (rpt, &a0, &a1, &time_of_data,
- &dt_ls, &wn_t, &wn_lsf, &dn, &dt_lsf)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nUTC Correction Data");
- pbuf += sprintf(pbuf, "\n A_0 = %g ", a0);
- pbuf += sprintf(pbuf, "\n A_1 = %g ", a1);
- pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", dt_ls);
- pbuf += sprintf(pbuf, "\n t_ot = %.0f ", time_of_data);
- pbuf += sprintf(pbuf, "\n WN_t = %d ", wn_t );
- pbuf += sprintf(pbuf, "\n WN_LSF = %d ", wn_lsf );
- pbuf += sprintf(pbuf, "\n DN = %d ", dn );
- pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", dt_lsf );
-}
-
-/**/
-/* 0x54 */
-static void rpt_1SV_bias (TSIPPKT *rpt)
-{
- float
- clock_bias, freq_offset, time_of_fix;
-
- /* unload rptbuf */
- if (rpt_0x54 (rpt, &clock_bias, &freq_offset, &time_of_fix)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf (pbuf, "\nTime Fix Clock Bias: %6.2f m Freq Bias: %6.2f m/s%s",
- clock_bias, freq_offset, show_time (time_of_fix));
-}
-
-/* 0x55 */
-static void rpt_io_opt (TSIPPKT *rpt)
-{
- unsigned char
- pos_code, vel_code, time_code, aux_code;
-
- /* unload rptbuf */
- if (rpt_0x55 (rpt,
- &pos_code, &vel_code, &time_code, &aux_code)) {
- parsed = BADLEN_PARSE;
- return;
- }
- /* rptbuf unloaded */
-
- pbuf += sprintf(pbuf, "\nI/O Options: %2X %2X %2X %2X",
- pos_code, vel_code, time_code, aux_code);
-
- if (pos_code & 0x01) {
- pbuf += sprintf(pbuf, "\n ECEF XYZ position output");
- }
-
- if (pos_code & 0x02) {
- pbuf += sprintf(pbuf, "\n LLA position output");
- }
-
- pbuf += sprintf(pbuf, (pos_code & 0x04)?
- "\n MSL altitude output (Geoid height) ":
- "\n WGS-84 altitude output");
-
- pbuf += sprintf(pbuf, (pos_code & 0x08)?
- "\n MSL altitude input":
- "\n WGS-84 altitude input");
-
- pbuf += sprintf(pbuf, (pos_code & 0x10)?
- "\n Double precision":
- "\n Single precision");
-
- if (pos_code & 0x20) {
- pbuf += sprintf(pbuf, "\n All Enabled Superpackets");
- }
-
- if (vel_code & 0x01) {
- pbuf += sprintf(pbuf, "\n ECEF XYZ velocity output");
- }
-
- if (vel_code & 0x02) {
- pbuf += sprintf(pbuf, "\n ENU velocity output");
- }
-
- pbuf += sprintf(pbuf, (time_code & 0x01)?
- "\n Time tags in UTC":
- "\n Time tags in GPS time");
-
- if (time_code & 0x02) {
- pbuf += sprintf(pbuf, "\n Fixes delayed to integer seconds");
- }
-
- if (time_code & 0x04) {
- pbuf += sprintf(pbuf, "\n Fixes sent only on request");
- }
-
- if (time_code & 0x08) {
- pbuf += sprintf(pbuf, "\n Synchronized measurements");
- }
-
- if (time_code & 0x10) {
- pbuf += sprintf(pbuf, "\n Minimize measurement propagation");
- }
-
- pbuf += sprintf(pbuf, (time_code & 0x20) ?
- "\n PPS output at all times" :
- "\n PPS output during fixes");
-
- if (aux_code & 0x01) {
- pbuf += sprintf(pbuf, "\n Raw measurement output");
- }
-
- if (aux_code & 0x02) {
- pbuf += sprintf(pbuf, "\n Code-phase smoothed before output");
- }
-
- if (aux_code & 0x04) {
- pbuf += sprintf(pbuf, "\n Additional fix status");
- }
-
- pbuf += sprintf(pbuf, (aux_code & 0x08)?
- "\n Signal Strength Output as dBHz" :
- "\n Signal Strength Output as AMU");
-}
-
-/* 0x56 */
-static void rpt_ENU_velocity (TSIPPKT *rpt)
-{
- float
- vel_ENU[3], freq_offset, time_of_fix;
-
- /* unload rptbuf */
- if (rpt_0x56 (rpt, vel_ENU, &freq_offset, &time_of_fix)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nVel ENU: %11.3f %11.3f %11.3f %12.3f%s",
- vel_ENU[0], vel_ENU[1], vel_ENU[2], freq_offset,
- show_time (time_of_fix));
-}
-
-/* 0x57 */
-static void rpt_last_fix_info (TSIPPKT *rpt)
-{
- unsigned char
- source_code, diag_code;
- short
- week_num;
- float
- time_of_fix;
-
- /* unload rptbuf */
- if (rpt_0x57 (rpt, &source_code, &diag_code, &week_num, &time_of_fix)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\n source code %d; diag code: %2Xh",
- source_code, diag_code);
- pbuf += sprintf(pbuf, "\n Time of last fix:%s", show_time(time_of_fix));
- pbuf += sprintf(pbuf, "\n Week of last fix: %d", week_num);
-}
-
-/* 0x58 */
-static void rpt_GPS_system_data (TSIPPKT *rpt)
-{
- unsigned char
- iprn,
- op_code, data_type, sv_prn,
- data_length, data_packet[250];
- ALM_INFO
- *almanac;
- ALH_PARMS
- *almh;
- UTC_INFO
- *utc;
- ION_INFO
- *ionosphere;
- EPHEM_CLOCK
- *cdata;
- EPHEM_ORBIT
- *edata;
- NAV_INFO
- *nav_data;
- unsigned char
- curr_t_oa;
- unsigned short
- curr_wn_oa;
- static char
- *datname[] =
- {"", "", "Almanac Orbit",
- "Health Page & Ref Time", "Ionosphere", "UTC ",
- "Ephemeris"};
-
- /* unload rptbuf */
- if (rpt_0x58 (rpt, &op_code, &data_type, &sv_prn,
- &data_length, data_packet))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nSystem data [%d]: %s SV%02d",
- data_type, datname[data_type], sv_prn);
- switch (op_code)
- {
- case 1:
- pbuf += sprintf(pbuf, " Acknowledgment");
- break;
- case 2:
- pbuf += sprintf(pbuf, " length = %d bytes", data_length);
- switch (data_type) {
- case 2:
- /* Almanac */
- if (sv_prn == 0 || sv_prn > 32) {
- pbuf += sprintf(pbuf, " Binary PRN invalid");
- return;
- }
- almanac = (ALM_INFO*)data_packet;
- pbuf += sprintf(pbuf, "\n t_oa_raw = % -12d SV_hlth = % -12d ",
- almanac->t_oa_raw , almanac->SV_health );
- pbuf += sprintf(pbuf, "\n e = % -12g t_oa = % -12g ",
- almanac->e , almanac->t_oa );
- pbuf += sprintf(pbuf, "\n i_0 = % -12g OMEGADOT = % -12g ",
- almanac->i_0 , almanac->OMEGADOT );
- pbuf += sprintf(pbuf, "\n sqrt_A = % -12g OMEGA_0 = % -12g ",
- almanac->sqrt_A , almanac->OMEGA_0 );
- pbuf += sprintf(pbuf, "\n omega = % -12g M_0 = % -12g ",
- almanac->omega , almanac->M_0 );
- pbuf += sprintf(pbuf, "\n a_f0 = % -12g a_f1 = % -12g ",
- almanac->a_f0 , almanac->a_f1 );
- pbuf += sprintf(pbuf, "\n Axis = % -12g n = % -12g ",
- almanac->Axis , almanac->n );
- pbuf += sprintf(pbuf, "\n OMEGA_n = % -12g ODOT_n = % -12g ",
- almanac->OMEGA_n , almanac->ODOT_n );
- pbuf += sprintf(pbuf, "\n t_zc = % -12g weeknum = % -12d ",
- almanac->t_zc , almanac->weeknum );
- pbuf += sprintf(pbuf, "\n wn_oa = % -12d", almanac->wn_oa );
- break;
-
- case 3:
- /* Almanac health page */
- almh = (ALH_PARMS*)data_packet;
- pbuf += sprintf(pbuf, "\n t_oa = %d, wn_oa&0xFF = %d ",
- almh->t_oa, almh->WN_a);
- pbuf += sprintf(pbuf, "\nAlmanac health page:");
- for (iprn = 0; iprn < 32; iprn++) {
- if (!(iprn%5)) *pbuf++ = '\n';
- pbuf += sprintf(pbuf, " SV%02d %2X",
- (iprn+1) , almh->SV_health[iprn]);
- }
- curr_t_oa = data_packet[34];
- curr_wn_oa = (unsigned short)((data_packet[35]<<8) + data_packet[36]);
- pbuf += sprintf(pbuf, "\n current t_oa = %d, wn_oa = %d ",
- curr_t_oa, curr_wn_oa);
- break;
-
- case 4:
- /* Ionosphere */
- ionosphere = (ION_INFO*)data_packet;
- pbuf += sprintf(pbuf, "\n alpha_0 = % -12g alpha_1 = % -12g ",
- ionosphere->alpha_0, ionosphere->alpha_1);
- pbuf += sprintf(pbuf, "\n alpha_2 = % -12g alpha_3 = % -12g ",
- ionosphere->alpha_2, ionosphere->alpha_3);
- pbuf += sprintf(pbuf, "\n beta_0 = % -12g beta_1 = % -12g ",
- ionosphere->beta_0, ionosphere->beta_1);
- pbuf += sprintf(pbuf, "\n beta_2 = % -12g beta_3 = % -12g ",
- ionosphere->beta_2, ionosphere->beta_3);
- break;
-
- case 5:
- /* UTC */
- utc = (UTC_INFO*)data_packet;
- pbuf += sprintf(pbuf, "\n A_0 = %g ", utc->A_0);
- pbuf += sprintf(pbuf, "\n A_1 = %g ", utc->A_1);
- pbuf += sprintf(pbuf, "\n delta_t_LS = %d ", utc->delta_t_LS);
- pbuf += sprintf(pbuf, "\n t_ot = %.0f ", utc->t_ot );
- pbuf += sprintf(pbuf, "\n WN_t = %d ", utc->WN_t );
- pbuf += sprintf(pbuf, "\n WN_LSF = %d ", utc->WN_LSF );
- pbuf += sprintf(pbuf, "\n DN = %d ", utc->DN );
- pbuf += sprintf(pbuf, "\n delta_t_LSF = %d ", utc->delta_t_LSF );
- break;
-
- case 6: /* Ephemeris */
- if (sv_prn == 0 || sv_prn > 32) {
- pbuf += sprintf(pbuf, " Binary PRN invalid");
- return;
- }
- nav_data = (NAV_INFO*)data_packet;
-
- pbuf += sprintf(pbuf, "\n SV_PRN = % -12d . t_ephem = % -12g . ",
- nav_data->sv_number , nav_data->t_ephem );
- cdata = &(nav_data->ephclk);
- pbuf += sprintf(pbuf,
- "\n weeknum = % -12d . codeL2 = % -12d . L2Pdata = % -12d",
- cdata->weeknum , cdata->codeL2 , cdata->L2Pdata );
- pbuf += sprintf(pbuf,
- "\n SVacc_raw = % -12d .SV_health = % -12d . IODC = % -12d",
- cdata->SVacc_raw, cdata->SV_health, cdata->IODC );
- pbuf += sprintf(pbuf,
- "\n T_GD = % -12g . t_oc = % -12g . a_f2 = % -12g",
- cdata->T_GD, cdata->t_oc, cdata->a_f2 );
- pbuf += sprintf(pbuf,
- "\n a_f1 = % -12g . a_f0 = % -12g . SVacc = % -12g",
- cdata->a_f1, cdata->a_f0, cdata->SVacc );
- edata = &(nav_data->ephorb);
- pbuf += sprintf(pbuf,
- "\n IODE = % -12d .fit_intvl = % -12d . C_rs = % -12g",
- edata->IODE, edata->fit_interval, edata->C_rs );
- pbuf += sprintf(pbuf,
- "\n delta_n = % -12g . M_0 = % -12g . C_uc = % -12g",
- edata->delta_n, edata->M_0, edata->C_uc );
- pbuf += sprintf(pbuf,
- "\n ecc = % -12g . C_us = % -12g . sqrt_A = % -12g",
- edata->e, edata->C_us, edata->sqrt_A );
- pbuf += sprintf(pbuf,
- "\n t_oe = % -12g . C_ic = % -12g . OMEGA_0 = % -12g",
- edata->t_oe, edata->C_ic, edata->OMEGA_0 );
- pbuf += sprintf(pbuf,
- "\n C_is = % -12g . i_0 = % -12g . C_rc = % -12g",
- edata->C_is, edata->i_0, edata->C_rc );
- pbuf += sprintf(pbuf,
- "\n omega = % -12g . OMEGADOT = % -12g . IDOT = % -12g",
- edata->omega, edata->OMEGADOT, edata->IDOT );
- pbuf += sprintf(pbuf,
- "\n Axis = % -12g . n = % -12g . r1me2 = % -12g",
- edata->Axis, edata->n, edata->r1me2 );
- pbuf += sprintf(pbuf,
- "\n OMEGA_n = % -12g . ODOT_n = % -12g",
- edata->OMEGA_n, edata->ODOT_n );
- break;
- }
- }
-}
-
-
-/* 0x59: */
-static void rpt_SVs_enabled (TSIPPKT *rpt)
-{
- unsigned char
- numsvs,
- code_type,
- status_code[32];
- short
- iprn;
-
- /* unload rptbuf */
- if (rpt_0x59 (rpt, &code_type, status_code))
- {
- parsed = BADLEN_PARSE;
- return;
- }
- switch (code_type)
- {
- case 3: pbuf += sprintf(pbuf, "\nSVs Disabled:\n"); break;
- case 6: pbuf += sprintf(pbuf, "\nSVs with Health Ignored:\n"); break;
- default: return;
- }
- numsvs = 0;
- for (iprn=0; iprn<32; iprn++)
- {
- if (status_code[iprn])
- {
- pbuf += sprintf(pbuf, " %02d", iprn+1);
- numsvs++;
- }
- }
- if (numsvs == 0) pbuf += sprintf(pbuf, "None");
-}
-
-
-/* 0x5A */
-static void rpt_raw_msmt (TSIPPKT *rpt)
-{
- unsigned char
- sv_prn;
- float
- sample_length, signal_level, code_phase, Doppler;
- double
- time_of_fix;
-
- /* unload rptbuf */
- if (rpt_0x5A (rpt, &sv_prn, &sample_length, &signal_level,
- &code_phase, &Doppler, &time_of_fix))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\n %02d %5.0f %7.1f %10.2f %10.2f %12.3f %s",
- sv_prn, sample_length, signal_level, code_phase, Doppler, time_of_fix,
- show_time ((float)time_of_fix));
-}
-
-/* 0x5B */
-static void rpt_SV_ephemeris_status (TSIPPKT *rpt)
-{
- unsigned char
- sv_prn, sv_health, sv_iode, fit_interval_flag;
- float
- time_of_collection, time_of_eph, sv_accy;
-
- /* unload rptbuf */
- if (rpt_0x5B (rpt, &sv_prn, &sv_health, &sv_iode, &fit_interval_flag,
- &time_of_collection, &time_of_eph, &sv_accy))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\n SV%02d %s %2Xh %2Xh ",
- sv_prn, show_time (time_of_collection), sv_health, sv_iode);
- /* note: cannot use show_time twice in same call */
- pbuf += sprintf(pbuf, "%s %1d %4.1f",
- show_time (time_of_eph), fit_interval_flag, sv_accy);
-}
-
-/* 0x5C */
-static void rpt_SV_tracking_status (TSIPPKT *rpt)
-{
- unsigned char
- sv_prn, chan, slot, acq_flag, eph_flag,
- old_msmt_flag, integer_msec_flag, bad_data_flag,
- data_collect_flag;
- float
- signal_level, time_of_last_msmt,
- elev, azim;
-
- /* unload rptbuf */
- if (rpt_0x5C (rpt,
- &sv_prn, &slot, &chan, &acq_flag, &eph_flag,
- &signal_level, &time_of_last_msmt, &elev, &azim,
- &old_msmt_flag, &integer_msec_flag, &bad_data_flag,
- &data_collect_flag))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf,
-"\n SV%2d %1d %1d %1d %4.1f %s %5.1f %5.1f",
- sv_prn, chan,
- acq_flag, eph_flag, signal_level,
- show_time(time_of_last_msmt),
- elev*R2D, azim*R2D);
-}
-
-/**/
-/* 0x6D */
-static void rpt_allSV_selection (TSIPPKT *rpt)
-{
- unsigned char
- manual_mode, nsvs, sv_prn[8], ndim;
- short
- islot;
- float
- pdop, hdop, vdop, tdop;
-
- /* unload rptbuf */
- if (rpt_0x6D (rpt,
- &manual_mode, &nsvs, &ndim, sv_prn,
- &pdop, &hdop, &vdop, &tdop))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- switch (ndim)
- {
- case 0:
- pbuf += sprintf(pbuf, "\nMode: Searching, %d-SV:", nsvs);
- break;
- case 1:
- pbuf += sprintf(pbuf, "\nMode: One-SV Timing:");
- break;
- case 3: case 4:
- pbuf += sprintf(pbuf, "\nMode: %c-%dD, %d-SV:",
- manual_mode ? 'M' : 'A', ndim - 1, nsvs);
- break;
- case 5:
- pbuf += sprintf(pbuf, "\nMode: Timing, %d-SV:", nsvs);
- break;
- default:
- pbuf += sprintf(pbuf, "\nMode: Unknown = %d:", ndim);
- break;
- }
-
- for (islot = 0; islot < nsvs; islot++)
- {
- if (sv_prn[islot]) pbuf += sprintf(pbuf, " %02d", sv_prn[islot]);
- }
- if (ndim == 3 || ndim == 4)
- {
- pbuf += sprintf(pbuf, "; DOPs: P %.1f H %.1f V %.1f T %.1f",
- pdop, hdop, vdop, tdop);
- }
-}
-
-/**/
-/* 0x82 */
-static void rpt_DGPS_position_mode (TSIPPKT *rpt)
-{
- unsigned char
- diff_mode;
-
- /* unload rptbuf */
- if (rpt_0x82 (rpt, &diff_mode)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nFix is%s DGPS-corrected (%s mode) (%d)",
- (diff_mode&1) ? "" : " not",
- (diff_mode&2) ? "auto" : "manual",
- diff_mode);
-}
-
-/* 0x83 */
-static void rpt_double_ECEF_position (TSIPPKT *rpt)
-{
-
- double
- ECEF_pos[3], clock_bias;
- float
- time_of_fix;
-
- /* unload rptbuf */
- if (rpt_0x83 (rpt, ECEF_pos, &clock_bias, &time_of_fix))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nDXYZ:%12.2f %13.2f %13.2f %12.2f%s",
- ECEF_pos[0], ECEF_pos[1], ECEF_pos[2], clock_bias,
- show_time(time_of_fix));
-}
-
-/* 0x84 */
-static void rpt_double_lla_position (TSIPPKT *rpt)
-{
- short
- lat_deg, lon_deg;
- double
- lat, lon, lat_min, lon_min,
- alt, clock_bias;
- float
- time_of_fix;
- unsigned char
- north_south, east_west;
-
- /* unload rptbuf */
- if (rpt_0x84 (rpt,
- &lat, &lon, &alt, &clock_bias, &time_of_fix))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- lat *= R2D;
- lon *= R2D;
- if (lat < 0.0) {
- north_south = 'S';
- lat = -lat;
- } else {
- north_south = 'N';
- }
- lat_deg = (short)lat;
- lat_min = (lat - lat_deg) * 60.0;
-
- if (lon < 0.0) {
- east_west = 'W';
- lon = -lon;
- } else {
- east_west = 'E';
- }
- lon_deg = (short)lon;
- lon_min = (lon - lon_deg) * 60.0;
- pbuf += sprintf(pbuf, "\nDLLA: %2d:%08.5f %c; %3d:%08.5f %c; %10.2f %12.2f%s",
- lat_deg, lat_min, north_south,
- lon_deg, lon_min, east_west,
- alt, clock_bias,
- show_time(time_of_fix));
-}
-
-/* 0xBB */
-static void rpt_complete_rcvr_config (TSIPPKT *rpt)
-{
- TSIP_RCVR_CFG TsipxBB ;
- /* unload rptbuf */
- if (rpt_Paly0xBB (rpt, &TsipxBB))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\n operating mode: %s",
- NavModeText0xBB[TsipxBB.operating_mode]);
- pbuf += sprintf(pbuf, "\n dynamics: %s",
- dyn_text[TsipxBB.dyn_code]);
- pbuf += sprintf(pbuf, "\n elev angle mask: %g deg",
- TsipxBB.elev_mask * R2D);
- pbuf += sprintf(pbuf, "\n SNR mask: %g AMU",
- TsipxBB.cno_mask);
- pbuf += sprintf(pbuf, "\n DOP mask: %g",
- TsipxBB.dop_mask);
- pbuf += sprintf(pbuf, "\n DOP switch: %g",
- TsipxBB.dop_switch);
- return ;
-}
-
-/* 0xBC */
-static void rpt_rcvr_serial_port_config (TSIPPKT *rpt)
-{
- unsigned char
- port_num, in_baud, out_baud, data_bits, parity, stop_bits, flow_control,
- protocols_in, protocols_out, reserved;
- unsigned char known;
-
- /* unload rptbuf */
- if (rpt_0xBC (rpt, &port_num, &in_baud, &out_baud, &data_bits, &parity,
- &stop_bits, &flow_control, &protocols_in, &protocols_out, &reserved)) {
- parsed = BADLEN_PARSE;
- return;
- }
- /* rptbuf unloaded */
-
- pbuf += sprintf(pbuf, "\n RECEIVER serial port %s config:",
- rcvr_port_text[port_num]);
-
- pbuf += sprintf(pbuf, "\n I/O Baud %s/%s, %d - %s - %d",
- st_baud_text_app[in_baud],
- st_baud_text_app[out_baud],
- data_bits+5,
- parity_text[parity],
- stop_bits=1);
- pbuf += sprintf(pbuf, "\n Input protocols: ");
- known = FALSE;
- if (protocols_in&B_TSIP)
- {
- pbuf += sprintf(pbuf, "%s ", protocols_in_text[1]);
- known = TRUE;
- }
- if (known == FALSE) pbuf += sprintf(pbuf, "No known");
-
- pbuf += sprintf(pbuf, "\n Output protocols: ");
- known = FALSE;
- if (protocols_out&B_TSIP)
- {
- pbuf += sprintf(pbuf, "%s ", protocols_out_text[1]);
- known = TRUE;
- }
- if (protocols_out&B_NMEA)
- {
- pbuf += sprintf(pbuf, "%s ", protocols_out_text[2]);
- known = TRUE;
- }
- if (known == FALSE) pbuf += sprintf(pbuf, "No known");
- reserved = reserved;
-
- }
-
-/* 0x8F */
-/* 8F0B */
-static void rpt_8F0B(TSIPPKT *rpt)
-{
- const char
- *oprtng_dim[7] = {
- "horizontal (2-D)",
- "full position (3-D)",
- "single satellite (0-D)",
- "automatic",
- "N/A",
- "N/A",
- "overdetermined clock"};
- char
- sv_id[8];
- unsigned char
- month,
- date,
- dim_mode,
- north_south,
- east_west;
- unsigned short
- event;
- short
- utc_offset,
- year,
- local_index;
- short
- lat_deg,
- lon_deg;
- float
- bias_unc,
- dr_unc;
- double
- tow,
- bias,
- drift,
- lat,
- lon,
- alt,
- lat_min,
- lon_min;
- int
- numfix,
- numnotfix;
-
- if (rpt_0x8F0B(rpt,
- &event,
- &tow,
- &date,
- &month,
- &year,
- &dim_mode,
- &utc_offset,
- &bias,
- &drift,
- &bias_unc,
- &dr_unc,
- &lat,
- &lon,
- &alt,
- sv_id))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- if (event == 0)
- {
- pbuf += sprintf(pbuf, "\nNew partial+full meas");
- }
- else
- {
- pbuf += sprintf(pbuf, "\nEvent count: %5d", event);
- }
-
- pbuf += sprintf(pbuf, "\nGPS time : %s %2d/%2d/%2d (DMY)",
- show_time(tow), date, month, year);
- pbuf += sprintf(pbuf, "\nMode : %s", oprtng_dim[dim_mode]);
- pbuf += sprintf(pbuf, "\nUTC offset: %2d", utc_offset);
- pbuf += sprintf(pbuf, "\nClock Bias: %6.2f m", bias);
- pbuf += sprintf(pbuf, "\nFreq bias : %6.2f m/s", drift);
- pbuf += sprintf(pbuf, "\nBias unc : %6.2f m", bias_unc);
- pbuf += sprintf(pbuf, "\nFreq unc : %6.2f m/s", dr_unc);
-
- lat *= R2D; /* convert from radians to degrees */
- lon *= R2D;
- if (lat < 0.0)
- {
- north_south = 'S';
- lat = -lat;
- }
- else
- {
- north_south = 'N';
- }
-
- lat_deg = (short)lat;
- lat_min = (lat - lat_deg) * 60.0;
- if (lon < 0.0)
- {
- east_west = 'W';
- lon = -lon;
- }
- else
- {
- east_west = 'E';
- }
-
- lon_deg = (short)lon;
- lon_min = (lon - lon_deg) * 60.0;
- pbuf += sprintf(pbuf, "\nPosition :");
- pbuf += sprintf(pbuf, " %4d %6.3f %c", lat_deg, lat_min, north_south);
- pbuf += sprintf(pbuf, " %5d %6.3f %c", lon_deg, lon_min, east_west);
- pbuf += sprintf(pbuf, " %10.2f", alt);
-
- numfix = numnotfix = 0;
- for (local_index=0; local_index<8; local_index++)
- {
- if (sv_id[local_index] < 0) numnotfix++;
- if (sv_id[local_index] > 0) numfix++;
- }
- if (numfix > 0)
- {
- pbuf += sprintf(pbuf, "\nSVs used in fix : ");
- for (local_index=0; local_index<8; local_index++)
- {
- if (sv_id[local_index] > 0)
- {
- pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
- }
- }
- }
- if (numnotfix > 0)
- {
- pbuf += sprintf(pbuf, "\nOther SVs tracked: ");
- for (local_index=0; local_index<8; local_index++)
- {
- if (sv_id[local_index] < 0)
- {
- pbuf += sprintf(pbuf, "%2d ", sv_id[local_index]);
- }
- }
- }
-}
-
-/* 0x8F14 */
-static void rpt_8F14 (TSIPPKT *rpt)
-/* Datum parameters */
-{
- double
- datum_coeffs[5];
- short
- datum_idx;
-
- /* unload rptbuf */
- if (rpt_0x8F14 (rpt, &datum_idx, datum_coeffs))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- if (datum_idx == -1)
- {
- pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
- pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
- pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
- pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
- pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
- pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
- }
- else if (datum_idx == 0)
- {
- pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
- }
- else
- {
- pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
- }
-}
-
-/* 0x8F15 */
-static void rpt_8F15 (TSIPPKT *rpt)
-/* Datum parameters */
-{
- double
- datum_coeffs[5];
- short
- datum_idx;
-
- /* unload rptbuf */
- if (rpt_0x8F15 (rpt, &datum_idx, datum_coeffs)) {
- parsed = BADLEN_PARSE;
- return;
- }
-
- if (datum_idx == -1)
- {
- pbuf += sprintf(pbuf, "\nUser-Entered Datum:");
- pbuf += sprintf(pbuf, "\n dx = %6.1f", datum_coeffs[0]);
- pbuf += sprintf(pbuf, "\n dy = %6.1f", datum_coeffs[1]);
- pbuf += sprintf(pbuf, "\n dz = %6.1f", datum_coeffs[2]);
- pbuf += sprintf(pbuf, "\n a-axis = %10.3f", datum_coeffs[3]);
- pbuf += sprintf(pbuf, "\n e-squared = %16.14f", datum_coeffs[4]);
- }
- else if (datum_idx == 0)
- {
- pbuf += sprintf(pbuf, "\nWGS-84 datum, Index 0 ");
- }
- else
- {
- pbuf += sprintf(pbuf, "\nStandard Datum, Index %3d ", datum_idx);
- }
-}
-
-/* 0x8F20 */
-#define INFO_DGPS 0x02
-#define INFO_2D 0x04
-#define INFO_ALTSET 0x08
-#define INFO_FILTERED 0x10
-static void rpt_8F20 (TSIPPKT *rpt)
-{
- unsigned char
- info, nsvs, sv_prn[32];
- short
- week_num, datum_index, sv_IODC[32];
- double
- lat, lon, alt, time_of_fix;
- double
- londeg, latdeg, vel[3];
- short
- isv;
- char
- datum_string[20];
-
- /* unload rptbuf */
- if (rpt_0x8F20 (rpt,
- &info, &lat, &lon, &alt, vel,
- &time_of_fix,
- &week_num, &nsvs, sv_prn, sv_IODC, &datum_index))
- {
- parsed = BADLEN_PARSE;
- return;
- }
- pbuf += sprintf(pbuf,
- "\nFix at: %04d:%3s:%02d:%02d:%06.3f GPS (=UTC+%2ds) FixType: %s%s%s",
- week_num,
- dayname[(short)(time_of_fix/86400.0)],
- (short)fmod(time_of_fix/3600., 24.),
- (short)fmod(time_of_fix/60., 60.),
- fmod(time_of_fix, 60.),
- (char)rpt->buf[29], /* UTC offset */
- (info & INFO_DGPS)?"Diff":"",
- (info & INFO_2D)?"2D":"3D",
- (info & INFO_FILTERED)?"-Filtrd":"");
-
- if (datum_index > 0)
- {
- sprintf(datum_string, "Datum%3d", datum_index);
- }
- else if (datum_index)
- {
- sprintf(datum_string, "Unknown ");
- }
- else
- {
- sprintf(datum_string, "WGS-84");
- }
-
- /* convert from radians to degrees */
- latdeg = R2D * fabs(lat);
- londeg = R2D * fabs(lon);
- pbuf += sprintf(pbuf,
- "\n Pos: %4d:%09.6f %c %5d:%09.6f %c %10.2f m HAE (%s)",
- (short)latdeg, fmod (latdeg, 1.)*60.0,
- (lat<0.0)?'S':'N',
- (short)londeg, fmod (londeg, 1.)*60.0,
- (lon<0.0)?'W':'E',
- alt,
- datum_string);
- pbuf += sprintf(pbuf,
- "\n Vel: %9.3f E %9.3f N %9.3f U (m/sec)",
- vel[0], vel[1], vel[2]);
-
- pbuf += sprintf(pbuf,
- "\n SVs: ");
- for (isv = 0; isv < nsvs; isv++) {
- pbuf += sprintf(pbuf, " %02d", sv_prn[isv]);
- }
- pbuf += sprintf(pbuf, " (IODEs:");
- for (isv = 0; isv < nsvs; isv++) {
- pbuf += sprintf(pbuf, " %02X", sv_IODC[isv]&0xFF);
- }
- pbuf += sprintf(pbuf, ")");
-}
-
-/* 0x8F41 */
-static void rpt_8F41(TSIPPKT *rpt)
-{
- unsigned char
- bSearchRange,
- bBoardOptions,
- bBuildYear,
- bBuildMonth,
- bBuildDay,
- bBuildHour;
- float
- fOscOffset;
- unsigned short
- iTestCodeId;
- unsigned long
- iiSerialNumber;
-
- if (!rpt_0x8F41(rpt,
- &bSearchRange,
- &bBoardOptions,
- &iiSerialNumber,
- &bBuildYear,
- &bBuildMonth,
- &bBuildDay,
- &bBuildHour,
- &fOscOffset,
- &iTestCodeId))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\n search range: %d",
- bSearchRange);
- pbuf += sprintf(pbuf, "\n board options: %d",
- bBoardOptions);
- pbuf += sprintf(pbuf, "\n board serial #: %ld",
- iiSerialNumber);
- pbuf += sprintf(pbuf, "\n build date/hour: %02d/%02d/%02d %02d:00",
- bBuildDay, bBuildMonth, bBuildYear, bBuildHour);
- pbuf += sprintf(pbuf, "\n osc offset: %.3f PPM (%.0f Hz)",
- fOscOffset/1575.42, fOscOffset);
- pbuf += sprintf(pbuf, "\n test code: %d",
- iTestCodeId);
-}
-
-/* 0x8F42 */
-static void rpt_8F42(TSIPPKT *rpt)
-{
- unsigned char
- bProdOptionsPre,
- bProdNumberExt;
- unsigned short
- iCaseSerialNumberPre,
- iPremiumOptions,
- iMachineID,
- iKey;
- unsigned long
- iiCaseSerialNumber,
- iiProdNumber;
-
- if (!rpt_0x8F42(rpt,
- &bProdOptionsPre,
- &bProdNumberExt,
- &iCaseSerialNumberPre,
- &iiCaseSerialNumber,
- &iiProdNumber,
- &iPremiumOptions,
- &iMachineID,
- &iKey))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nProduct ID 8F42");
- pbuf += sprintf(pbuf, "\n extension: %d", bProdNumberExt);
- pbuf += sprintf(pbuf, "\n case serial # prefix: %d", iCaseSerialNumberPre);
- pbuf += sprintf(pbuf, "\n case serial #: %ld", iiCaseSerialNumber);
- pbuf += sprintf(pbuf, "\n prod. #: %ld", iiProdNumber);
- pbuf += sprintf(pbuf, "\n premium options: %Xh", iPremiumOptions);
- pbuf += sprintf(pbuf, "\n machine ID: %d", iMachineID);
- pbuf += sprintf(pbuf, "\n key: %Xh", iKey);
-}
-
-/* 0x8F45 */
-static void rpt_8F45(TSIPPKT *rpt)
-{
- unsigned char bSegMask;
-
- if (!rpt_0x8F45(rpt,
- &bSegMask))
- {
- parsed = BADLEN_PARSE;
- return;
- }
- pbuf += sprintf(pbuf, "\nCleared Segment Mask: %Xh", bSegMask);
-}
-
-static void rpt_8F4A(TSIPPKT *rpt)
-/* Stinger PPS def */
-{
- unsigned char
- pps_enabled,
- pps_timebase,
- pps_polarity;
- float
- bias_unc_threshold;
- double
- pps_offset;
-
- if (rpt_0x8F4A_16 (rpt,
- &pps_enabled,
- &pps_timebase,
- &pps_polarity,
- &pps_offset,
- &bias_unc_threshold))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nPPS is %s", pps_enabled?"enabled":"disabled");
- pbuf += sprintf(pbuf, "\n timebase: %s", PPSTimeBaseText[pps_timebase]);
- pbuf += sprintf(pbuf, "\n polarity: %s", PPSPolarityText[pps_polarity]);
- pbuf += sprintf(pbuf, "\n offset: %.1f ns, ", pps_offset*1.e9);
- pbuf += sprintf(pbuf, "\n biasunc: %.1f ns", bias_unc_threshold/GPS_C*1.e9);
-}
-
-static void rpt_8F4B(TSIPPKT *rpt)
-/* fast-SA decorrolation time for self-survey */
-{
- unsigned long
- decorr_max;
-
- if (rpt_0x8F4B(rpt, &decorr_max))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf,
- "\nMax # of position fixes for self-survey : %ld",
- decorr_max);
-}
-
-static void rpt_8F4D(TSIPPKT *rpt)
-{
- static char
- *linestart;
- unsigned long
- OutputMask;
- static unsigned long
- MaskBit[] = {
- 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
- 0x00000100L, 0x00000800L, 0x00001000L,
- 0x40000000L, 0x80000000L};
- int
- ichoice,
- numchoices;
-
- if (rpt_0x8F4D(rpt, &OutputMask))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nAuto-Report Mask: %02X %02X %02X %02X",
- (unsigned char)(OutputMask>>24),
- (unsigned char)(OutputMask>>16),
- (unsigned char)(OutputMask>>8),
- (unsigned char)OutputMask);
-
- numchoices = sizeof(MaskText)/sizeof(char*);
- pbuf += sprintf(pbuf, "\nAuto-Reports scheduled for Output:");
- linestart = pbuf;
- for (ichoice=0; ichoice<numchoices; ichoice++)
- {
- if (OutputMask&MaskBit[ichoice])
- {
- pbuf += sprintf(pbuf, "%s %s",
- (pbuf==linestart)?"\n ":",",
- MaskText[ichoice]);
- if (pbuf-linestart > 60) linestart = pbuf;
- }
- }
-
- pbuf += sprintf(pbuf, "\nAuto-Reports NOT scheduled for Output:");
- linestart = pbuf;
- for (ichoice=0; ichoice<numchoices; ichoice++)
- {
- if (OutputMask&MaskBit[ichoice]) continue;
- pbuf += sprintf(pbuf, "%s %s",
- (pbuf==linestart)?"\n ":",",
- MaskText[ichoice]);
- if (pbuf-linestart > 60) linestart = pbuf;
- }
-}
-
-static void rpt_8FA5(TSIPPKT *rpt)
-{
- unsigned char
- spktmask[4];
-
- if (rpt_0x8FA5(rpt, spktmask))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\nSuperpacket auto-output mask: %02X %02X %02X %02X",
- spktmask[0], spktmask[1], spktmask[2], spktmask[3]);
-
- if (spktmask[0]&0x01) pbuf+= sprintf (pbuf, "\n PPS 8F-0B");
- if (spktmask[0]&0x02) pbuf+= sprintf (pbuf, "\n Event 8F-0B");
- if (spktmask[0]&0x10) pbuf+= sprintf (pbuf, "\n PPS 8F-AD");
- if (spktmask[0]&0x20) pbuf+= sprintf (pbuf, "\n Event 8F-AD");
- if (spktmask[2]&0x01) pbuf+= sprintf (pbuf, "\n ppos Fix 8F-20");
-}
-
-static void rpt_8FAD (TSIPPKT *rpt)
-{
- unsigned short
- Count,
- Year;
- double
- FracSec;
- unsigned char
- Hour,
- Minute,
- Second,
- Day,
- Month,
- Status,
- Flags;
- static char* Status8FADText[] = {
- "CODE_DOING_FIXES",
- "CODE_GOOD_1_SV",
- "CODE_APPX_1SV",
- "CODE_NEED_TIME",
- "CODE_NEED_INITIALIZATION",
- "CODE_PDOP_HIGH",
- "CODE_BAD_1SV",
- "CODE_0SVS",
- "CODE_1SV",
- "CODE_2SVS",
- "CODE_3SVS",
- "CODE_NO_INTEGRITY",
- "CODE_DCORR_GEN",
- "CODE_OVERDET_CLK",
- "Invalid Status"},
- *LeapStatusText[] = {
- " UTC Avail", " ", " ", " ",
- " Scheduled", " Pending", " Warning", " In Progress"};
- int i;
-
- if (rpt_0x8FAD (rpt,
- &Count,
- &FracSec,
- &Hour,
- &Minute,
- &Second,
- &Day,
- &Month,
- &Year,
- &Status,
- &Flags))
- {
- parsed = BADLEN_PARSE;
- return;
- }
-
- pbuf += sprintf(pbuf, "\n8FAD Count: %d Status: %s",
- Count, Status8FADText[Status]);
-
- pbuf += sprintf(pbuf, "\n Leap Flags:");
- if (Flags)
- {
- for (i=0; i<8; i++)
- {
- if (Flags&(1<<i)) pbuf += sprintf(pbuf, LeapStatusText[i]);
- }
- }
- else
- {
- pbuf += sprintf(pbuf, " UTC info not available");
- }
-
- pbuf += sprintf(pbuf, "\n %02d/%02d/%04d (DMY) %02d:%02d:%02d.%09ld UTC",
- Day, Month, Year, Hour, Minute, Second, (long)(FracSec*1.e9));
-}
-
-
-int print_msg_table_header (int rptcode, char *HdrStr, int force)
-{
- /* force header is to help auto-output function */
- /* last_rptcode is to determine whether to print a header */
- /* for the first occurrence of a series of reports */
- static int
- last_rptcode = 0;
- int
- numchars;
-
- numchars = 0;
- if (force || rptcode!=last_rptcode)
- {
- /* supply a header in console output */
- switch (rptcode)
- {
- case 0x5A:
- numchars = sprintf(HdrStr, "\nRaw Measurement Data");
- numchars += sprintf(HdrStr+numchars,
- "\n SV Sample SNR Code Phase Doppler Seconds Time of Meas");
- break;
-
- case 0x5B:
- numchars = sprintf(HdrStr, "\nEphemeris Status");
- numchars += sprintf(HdrStr+numchars,
- "\n SV Time collected Health IODE t oe Fit URA");
- break;
-
- case 0x5C:
- numchars = sprintf(HdrStr, "\nTracking Info");
- numchars += sprintf(HdrStr+numchars,
- "\n SV C Acq Eph SNR Time of Meas Elev Azim ");
- break;
-
- }
- }
- last_rptcode = rptcode;
- return (short)numchars;
-}
-
-static void unknown_rpt (TSIPPKT *rpt)
-{
- int i;
-
- /* app-specific rpt packets */
- if (parsed == BADLEN_PARSE)
- {
- pbuf += sprintf(pbuf, "\nTSIP report packet ID %2Xh, length %d: Bad length",
- rpt->code, rpt->len);
- }
- if (parsed == BADID_PARSE)
- {
- pbuf += sprintf(pbuf,
- "\nTSIP report packet ID %2Xh, length %d: translation not supported",
- rpt->code, rpt->len);
- }
-
- if (parsed == BADDATA_PARSE)
- {
- pbuf += sprintf(pbuf,
- "\nTSIP report packet ID %2Xh, length %d: data content incorrect",
- rpt->code, rpt->len);
- }
-
- for (i = 0; i < rpt->len; i++) {
- if ((i % 20) == 0) *pbuf++ = '\n';
- pbuf += sprintf(pbuf, " %02X", rpt->buf[i]);
- }
-}
-/**/
-/*
-** main subroutine, called from ProcessInputBytesWhileWaitingForKBHit()
-*/
-void TranslateTSIPReportToText (TSIPPKT *rpt, char *TextOutputBuffer)
-{
-
- /* pbuf is the pointer to the current location of the text output */
- pbuf = TextOutputBuffer;
-
- /* keep track of whether the message has been successfully parsed */
- parsed = GOOD_PARSE;
-
- /* print a header if this is the first of a series of messages */
- pbuf += print_msg_table_header (rpt->code, pbuf, FALSE);
-
- /* process incoming TSIP report according to code */
- switch (rpt->code)
- {
- case 0x3D: rpt_chan_A_config (rpt); break;
- case 0x40: rpt_almanac_data_page (rpt); break;
- case 0x41: rpt_GPS_time (rpt); break;
- case 0x42: rpt_single_ECEF_position (rpt); break;
- case 0x43: rpt_single_ECEF_velocity (rpt); break;
- case 0x45: rpt_SW_version (rpt); break;
- case 0x46: rpt_rcvr_health (rpt); break;
- case 0x47: rpt_SNR_all_SVs (rpt); break;
- case 0x48: rpt_GPS_system_message (rpt); break;
- case 0x49: rpt_almanac_health_page (rpt); break;
- case 0x4A: switch (rpt->len) {
- /*
- ** special case (=slip-up) in the TSIP protocol;
- ** parsing method depends on length
- */
- case 20: rpt_single_lla_position (rpt); break;
- case 9: rpt_ref_alt (rpt); break;
- } break;
- case 0x4B: rpt_rcvr_id_and_status (rpt);break;
- case 0x4C: rpt_operating_parameters (rpt); break;
- case 0x4D: rpt_oscillator_offset (rpt); break;
- case 0x4E: rpt_GPS_time_set_response (rpt); break;
- case 0x4F: rpt_UTC_offset (rpt); break;
- case 0x54: rpt_1SV_bias (rpt); break;
- case 0x55: rpt_io_opt (rpt); break;
- case 0x56: rpt_ENU_velocity (rpt); break;
- case 0x57: rpt_last_fix_info (rpt); break;
- case 0x58: rpt_GPS_system_data (rpt); break;
- case 0x59: rpt_SVs_enabled (rpt); break;
- case 0x5A: rpt_raw_msmt (rpt); break;
- case 0x5B: rpt_SV_ephemeris_status (rpt); break;
- case 0x5C: rpt_SV_tracking_status (rpt); break;
- case 0x6D: rpt_allSV_selection (rpt); break;
- case 0x82: rpt_DGPS_position_mode (rpt); break;
- case 0x83: rpt_double_ECEF_position (rpt); break;
- case 0x84: rpt_double_lla_position (rpt); break;
- case 0xBB: rpt_complete_rcvr_config (rpt); break;
- case 0xBC: rpt_rcvr_serial_port_config (rpt); break;
-
- case 0x8F: switch (rpt->buf[0])
- {
- /* superpackets; parsed according to subcodes */
- case 0x0B: rpt_8F0B(rpt); break;
- case 0x14: rpt_8F14(rpt); break;
- case 0x15: rpt_8F15(rpt); break;
- case 0x20: rpt_8F20(rpt); break;
- case 0x41: rpt_8F41(rpt); break;
- case 0x42: rpt_8F42(rpt); break;
- case 0x45: rpt_8F45(rpt); break;
- case 0x4A: rpt_8F4A(rpt); break;
- case 0x4B: rpt_8F4B(rpt); break;
- case 0x4D: rpt_8F4D(rpt); break;
- case 0xA5: rpt_8FA5(rpt); break;
- case 0xAD: rpt_8FAD(rpt); break;
- default: parsed = BADID_PARSE; break;
- }
- break;
-
- default: parsed = BADID_PARSE; break;
- }
-
- if (parsed != GOOD_PARSE)
- {
- /*
- **The message has TSIP structure (DLEs, etc.)
- ** but could not be parsed by above routines
- */
- unknown_rpt (rpt);
- }
-
- /* close TextOutputBuffer */
- pbuf = '\0';
-}
-
-#endif /* TRIMBLE_OUTPUT_FUNC */
-
-#else /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
-int refclock_ripencc_bs;
-#endif /* defined(REFCLOCK) && defined(CLOCK_RIPENCC) */
-
diff --git a/contrib/ntp/ntpd/refclock_shm.c b/contrib/ntp/ntpd/refclock_shm.c
deleted file mode 100644
index 4ab0ede..0000000
--- a/contrib/ntp/ntpd/refclock_shm.c
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * refclock_shm - clock driver for utc via shared memory
- * - under construction -
- * To add new modes: Extend or union the shmTime-struct. Do not
- * extend/shrink size, because otherwise existing implementations
- * will specify wrong size of shared memory-segment
- * PB 18.3.97
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_SHM)
-
-#include "ntpd.h"
-#undef fileno
-#include "ntp_io.h"
-#undef fileno
-#include "ntp_refclock.h"
-#undef fileno
-#include "ntp_unixtime.h"
-#undef fileno
-#include "ntp_stdlib.h"
-
-#undef fileno
-#include <ctype.h>
-#undef fileno
-
-#ifndef SYS_WINNT
-# include <sys/ipc.h>
-# include <sys/shm.h>
-# include <assert.h>
-# include <unistd.h>
-# include <stdio.h>
-#endif
-
-/*
- * This driver supports a reference clock attached thru shared memory
- */
-
-/*
- * SHM interface definitions
- */
-#define PRECISION (-1) /* precision assumed (0.5 s) */
-#define REFID "SHM" /* reference ID */
-#define DESCRIPTION "SHM/Shared memory interface"
-
-#define NSAMPLES 3 /* stages of median filter */
-
-/*
- * Function prototypes
- */
-static int shm_start (int, struct peer *);
-static void shm_shutdown (int, struct peer *);
-static void shm_poll (int unit, struct peer *);
-
-/*
- * Transfer vector
- */
-struct refclock refclock_shm = {
- shm_start, /* start up driver */
- shm_shutdown, /* shut down driver */
- shm_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* initialize driver (not used) */
- noentry, /* not used */
- NOFLAGS /* not used */
-};
-struct shmTime {
- int mode; /* 0 - if valid set
- * use values,
- * clear valid
- * 1 - if valid set
- * if count before and after read of values is equal,
- * use values
- * clear valid
- */
- int count;
- time_t clockTimeStampSec;
- int clockTimeStampUSec;
- time_t receiveTimeStampSec;
- int receiveTimeStampUSec;
- int leap;
- int precision;
- int nsamples;
- int valid;
- int dummy[10];
-};
-
-struct shmTime *getShmTime(int);
-
-struct shmTime *getShmTime (int unit) {
-#ifndef SYS_WINNT
- int shmid=0;
-
- assert (unit<10); /* MAXUNIT is 4, so should never happen */
- shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
- IPC_CREAT|(unit<2?0700:0777));
- if (shmid==-1) { /*error */
- msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
- return 0;
- }
- else { /* no error */
- struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
- if ((int)(long)p==-1) { /* error */
- msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
- return 0;
- }
- return p;
- }
-#else
- char buf[10];
- LPSECURITY_ATTRIBUTES psec=0;
- HANDLE shmid=0;
- SECURITY_DESCRIPTOR sd;
- SECURITY_ATTRIBUTES sa;
- sprintf (buf,"NTP%d",unit);
- if (unit>=2) { /* world access */
- if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
- msyslog(LOG_ERR,"SHM InitializeSecurityDescriptor (unit %d): %m",unit);
- return 0;
- }
- if (!SetSecurityDescriptorDacl(&sd,1,0,0)) {
- msyslog(LOG_ERR,"SHM SetSecurityDescriptorDacl (unit %d): %m",unit);
- return 0;
- }
- sa.nLength=sizeof (SECURITY_ATTRIBUTES);
- sa.lpSecurityDescriptor=&sd;
- sa.bInheritHandle=0;
- psec=&sa;
- }
- shmid=CreateFileMapping ((HANDLE)0xffffffff, psec, PAGE_READWRITE,
- 0, sizeof (struct shmTime),buf);
- if (!shmid) { /*error*/
- char buf[1000];
- FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
- 0, GetLastError (), 0, buf, sizeof (buf), 0);
- msyslog(LOG_ERR,"SHM CreateFileMapping (unit %d): %s",unit,buf);
- return 0;
- }
- else {
- struct shmTime *p=(struct shmTime *) MapViewOfFile (shmid,
- FILE_MAP_WRITE, 0, 0, sizeof (struct shmTime));
- if (p==0) { /*error*/
- char buf[1000];
- FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,
- 0, GetLastError (), 0, buf, sizeof (buf), 0);
- msyslog(LOG_ERR,"SHM MapViewOfFile (unit %d): %s",unit,buf);
- return 0;
- }
- return p;
- }
-#endif
-}
-/*
- * shm_start - attach to shared memory
- */
-static int
-shm_start(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- pp = peer->procptr;
- pp->io.clock_recv = noentry;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = -1;
- pp->unitptr = (caddr_t)getShmTime(unit);
-
- /*
- * Initialize miscellaneous peer variables
- */
- memcpy((char *)&pp->refid, REFID, 4);
- if (pp->unitptr!=0) {
- ((struct shmTime*)pp->unitptr)->precision=PRECISION;
- peer->precision = ((struct shmTime*)pp->unitptr)->precision;
- ((struct shmTime*)pp->unitptr)->valid=0;
- ((struct shmTime*)pp->unitptr)->nsamples=NSAMPLES;
- pp->clockdesc = DESCRIPTION;
- return (1);
- }
- else {
- return 0;
- }
-}
-
-
-/*
- * shm_shutdown - shut down the clock
- */
-static void
-shm_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct shmTime *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct shmTime *)pp->unitptr;
-#ifndef SYS_WINNT
- /* HMS: shmdt()wants char* or const void * */
- (void) shmdt (up);
-#else
- UnmapViewOfFile (up);
-#endif
-}
-
-
-/*
- * shm_poll - called by the transmit procedure
- */
-static void
-shm_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct shmTime *up;
- struct refclockproc *pp;
-
- /*
- * This is the main routine. It snatches the time from the shm
- * board and tacks on a local timestamp.
- */
- pp = peer->procptr;
- up = (struct shmTime*)pp->unitptr;
- if (up==0) { /* try to map again - this may succeed if meanwhile some-
- body has ipcrm'ed the old (unaccessible) shared mem
- segment */
- pp->unitptr = (caddr_t)getShmTime(unit);
- up = (struct shmTime*)pp->unitptr;
- }
- if (up==0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- if (up->valid) {
- struct timeval tvr;
- struct timeval tvt;
- struct tm *t;
- int ok=1;
- switch (up->mode) {
- case 0: {
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
- }
- break;
- case 1: {
- int cnt=up->count;
- tvr.tv_sec=up->receiveTimeStampSec;
- tvr.tv_usec=up->receiveTimeStampUSec;
- tvt.tv_sec=up->clockTimeStampSec;
- tvt.tv_usec=up->clockTimeStampUSec;
- ok=(cnt==up->count);
- }
- break;
- default:
- msyslog (LOG_ERR, "SHM: bad mode found in shared memory: %d",up->mode);
- }
- up->valid=0;
- if (ok) {
- TVTOTS(&tvr,&pp->lastrec);
- pp->lastrec.l_ui += JAN_1970;
- /* pp->lasttime = current_time; */
- pp->polls++;
- t=gmtime (&tvt.tv_sec);
- pp->day=t->tm_yday+1;
- pp->hour=t->tm_hour;
- pp->minute=t->tm_min;
- pp->second=t->tm_sec;
- pp->nsec=tvt.tv_usec * 1000;
- peer->precision=up->precision;
- pp->leap=up->leap;
- }
- else {
- refclock_report(peer, CEVNT_FAULT);
- msyslog (LOG_NOTICE, "SHM: access clash in shared memory");
- return;
- }
- }
- else {
- refclock_report(peer, CEVNT_TIMEOUT);
- /*
- msyslog (LOG_NOTICE, "SHM: no new value found in shared memory");
- */
- return;
- }
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-}
-
-#else
-int refclock_shm_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_tpro.c b/contrib/ntp/ntpd/refclock_tpro.c
deleted file mode 100644
index 3c42568..0000000
--- a/contrib/ntp/ntpd/refclock_tpro.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * refclock_tpro - clock driver for the KSI/Odetics TPRO-S IRIG-B reader
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_TPRO)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "sys/tpro.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * This driver supports the KSI/Odetecs TPRO-S IRIG-B reader and TPRO-
- * SAT GPS receiver for the Sun Microsystems SBus. It requires that the
- * tpro.o device driver be installed and loaded.
- */
-
-/*
- * TPRO interface definitions
- */
-#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 */
-
-/*
- * Unit control structure
- */
-struct tprounit {
- struct tproval tprodata; /* data returned from tpro read */
-};
-
-/*
- * Function prototypes
- */
-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 *));
-
-/*
- * Transfer vector
- */
-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_start - open the TPRO device and initialize data for processing
- */
-static int
-tpro_start(
- int unit,
- struct peer *peer
- )
-{
- register struct tprounit *up;
- struct refclockproc *pp;
- char device[20];
- int fd;
-
- /*
- * Open TPRO device
- */
- (void)sprintf(device, DEVICE, unit);
- fd = open(device, O_RDONLY | O_NDELAY, 0777);
- if (fd == -1) {
- msyslog(LOG_ERR, "tpro_start: open of %s: %m", device);
- return (0);
- }
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct tprounit *) emalloc(sizeof(struct tprounit)))) {
- (void) close(fd);
- return (0);
- }
- 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;
- pp->unitptr = (caddr_t)up;
-
- /*
- * Initialize miscellaneous peer variables
- */
- peer->precision = PRECISION;
- peer->burst = NSTAGE;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- return (1);
-}
-
-
-/*
- * tpro_shutdown - shut down the clock
- */
-static void
-tpro_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct tprounit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct tprounit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * tpro_poll - called by the transmit procedure
- */
-static void
-tpro_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct tprounit *up;
- struct refclockproc *pp;
- struct tproval *tp;
-
- /*
- * 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;
-
- tp = &up->tprodata;
- if (read(pp->io.fd, (char *)tp, sizeof(struct tproval)) < 0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- get_systime(&pp->lastrec);
- pp->polls++;
-
- /*
- * 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. All format error checking is
- * done by the sprintf() and sscanf() routines.
- *
- * Note that the refclockproc usec member has now become nsec.
- * We could either multiply the read-in usec value by 1000 or
- * we could pad the written string appropriately and read the
- * resulting value in already scaled.
- */
- sprintf(pp->a_lastcode,
- "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
- 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);
- pp->lencode = strlen(pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("tpro: time %s timecode %d %s\n",
- ulfptoa(&pp->lastrec, 6), pp->lencode,
- pp->a_lastcode);
-#endif
- if (sscanf(pp->a_lastcode, "%3d %2d:%2d:%2d.%6ld", &pp->day,
- &pp->hour, &pp->minute, &pp->second, &pp->nsec)
- != 5) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->nsec *= 1000; /* Convert usec to nsec */
- if (!tp->status & 0x3)
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- refclock_receive(peer);
- pp->lastref = pp->lastrec;
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- refclock_receive(peer);
- peer->burst = NSTAGE;
-}
-
-#else
-int refclock_tpro_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_trak.c b/contrib/ntp/ntpd/refclock_trak.c
deleted file mode 100644
index 3a4a54e..0000000
--- a/contrib/ntp/ntpd/refclock_trak.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * refclock_trak - clock driver for the TRAK 8810 GPS Station Clock
- *
- * Tomoaki TSURUOKA <tsuruoka@nc.fukuoka-u.ac.jp>
- * original version Dec, 1993
- * revised version Sep, 1994 for ntp3.4e or later
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_TRAK) && defined(PPS)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-#include "ntp_unixtime.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#ifdef HAVE_SYS_TERMIOS_H
-# include <sys/termios.h>
-#endif
-#ifdef HAVE_SYS_PPSCLOCK_H
-# include <sys/ppsclock.h>
-#endif
-
-/*
- * This driver supports the TRAK 8810/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 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.
- *
- * 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.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/trak%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS\0" /* reference ID */
-#define DESCRIPTION "TRACK 8810/8820 Station Clock" /* WRU */
-
-#define LENTRAK 24 /* timecode length */
-#define C_CTO "RQTS\r" /* start continuous time output */
-
-/*
- * Unit control structure
- */
-struct trakunit {
- int polled; /* poll message flag */
- l_fp tstamp; /* timestamp of last poll */
-};
-
-/*
- * Function prototypes
- */
-static int trak_start P((int, struct peer *));
-static void trak_shutdown P((int, struct peer *));
-static void trak_receive P((struct recvbuf *));
-static void trak_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-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_start - open the devices and initialize data for processing
- */
-static int
-trak_start(
- int unit,
- struct peer *peer
- )
-{
- register struct trakunit *up;
- struct refclockproc *pp;
- int fd;
- char device[20];
-
- /*
- * Open serial port. The LDISC_ACTS line discipline inserts a
- * timestamp following the "*" on-time character of the
- * timecode.
- */
- (void)sprintf(device, DEVICE, unit);
- if (
-#ifdef PPS
- !(fd = refclock_open(device, SPEED232, LDISC_CLK))
-#else
- !(fd = refclock_open(device, SPEED232, 0))
-#endif /* PPS */
- )
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct trakunit *)
- emalloc(sizeof(struct trakunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct trakunit));
- 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);
- }
- pp->unitptr = (caddr_t)up;
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- up->polled = 0;
-
- /*
- * Start continuous time output. If something breaks, fold the
- * tent and go home.
- */
- 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);
-}
-
-
-/*
- * trak_shutdown - shut down the clock
- */
-static void
-trak_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct trakunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct trakunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * trak_receive - receive data from the serial interface
- */
-static void
-trak_receive(
- struct recvbuf *rbufp
- )
-{
- register struct trakunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- l_fp trtmp;
- char *dpt, *dpend;
- char qchar;
-#ifdef PPS
- struct ppsclockev ppsev;
- int request;
-#ifdef HAVE_CIOGETEV
- request = CIOGETEV;
-#endif
-#ifdef HAVE_TIOCGPPSEV
- request = TIOCGPPSEV;
-#endif
-#endif /* PPS */
-
- /*
- * Initialize pointers and read the timecode and timestamp. We
- * then chuck out everything, including runts, except one
- * message each poll interval.
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct trakunit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
- &pp->lastrec);
-
- /*
- * 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->a_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;
- ++dpt;
- }
- }
- }
- if (up->polled == 0) return;
- up->polled = 0;
-#ifndef PPS
- get_systime(&up->tstamp);
-#endif
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("trak: timecode %d %s\n", pp->lencode,
- pp->a_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 < LENTRAK) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Timecode format: "*RQTS U,ddd:hh:mm:ss.0,q"
- */
- if (sscanf(pp->a_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;
- }
-
- /*
- * Decode quality and leap characters. If unsynchronized, set
- * the leap bits accordingly and exit.
- */
- if (qchar == '0') {
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
-#ifdef PPS
- if(ioctl(fdpps,request,(caddr_t) &ppsev) >=0) {
- ppsev.tv.tv_sec += (u_int32) JAN_1970;
- TVTOTS(&ppsev.tv,&up->tstamp);
- }
-#endif /* PPS */
- /* record the last ppsclock event time stamp */
- pp->lastrec = up->tstamp;
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
-}
-
-
-/*
- * trak_poll - called by the transmit procedure
- */
-static void
-trak_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct trakunit *up;
- struct refclockproc *pp;
-
- /*
- * We don't really do anything here, except arm the receiving
- * side to capture a sample and check for timeouts.
- */
- pp = peer->procptr;
- up = (struct trakunit *)pp->unitptr;
- if (up->polled)
- refclock_report(peer, CEVNT_TIMEOUT);
- pp->polls++;
- up->polled = 1;
-}
-
-#else
-int refclock_trak_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_true.c b/contrib/ntp/ntpd/refclock_true.c
deleted file mode 100644
index dd355d9..0000000
--- a/contrib/ntp/ntpd/refclock_true.c
+++ /dev/null
@@ -1,873 +0,0 @@
-/*
- * refclock_true - clock driver for the Kinemetrics Truetime receivers
- * 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
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_TRUETIME)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/* This should be an atom clock but those are very hard to build.
- *
- * The PCL720 from P C Labs has an Intel 8253 lookalike, as well as a bunch
- * of TTL input and output pins, all brought out to the back panel. If you
- * wire a PPS signal (such as the TTL PPS coming out of a GOES or other
- * Kinemetrics/Truetime clock) to the 8253's GATE0, and then also wire the
- * 8253's OUT0 to the PCL720's INPUT3.BIT0, then we can read CTR0 to get the
- * number of uSecs since the last PPS upward swing, mediated by reading OUT0
- * to find out if the counter has wrapped around (this happens if more than
- * 65535us (65ms) elapses between the PPS event and our being called.)
- */
-#ifdef CLOCK_PPS720
-# undef min /* XXX */
-# undef max /* XXX */
-# include <machine/inline.h>
-# include <sys/pcl720.h>
-# include <sys/i8253.h>
-# define PCL720_IOB 0x2a0 /* XXX */
-# define PCL720_CTR 0 /* XXX */
-#endif
-
-/*
- * Support for Kinemetrics Truetime Receivers
- * GOES
- * GPS/TM-TMD
- * XL-DC (a 151-602-210, reported by the driver as a GPS/TM-TMD)
- * GPS-800 TCU (an 805-957 with the RS232 Talker/Listener module)
- * OM-DC: getting stale ("OMEGA")
- *
- * 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 (this is stripped before we see it)
- * Q - Quality indication (see below)
- * C - Carriage return
- * L - Line feed
- *
- * Quality codes indicate possible error of
- * 468-DC GOES Receiver:
- * GPS-TM/TMD Receiver: (default quality codes for XL-DC)
- * ? +/- 1 milliseconds # +/- 100 microseconds
- * * +/- 10 microseconds . +/- 1 microsecond
- * space less than 1 microsecond
- * OM-DC OMEGA Receiver: (default quality codes for OMEGA)
- * WARNING OMEGA navigation system is no longer existent
- * > >+- 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 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 (GOES only.)
- *
- * Notes on the 468-DC receiver:
- *
- * Since the old east/west satellite locations are only historical, 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 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 = "TRUE", see below)
- * flag1 - will silence the clock side of ntpd, just reading the clock
- * without trying to write to it. (default = 0)
- * flag2 - generate a debug file /tmp/true%d.
- * flag3 - enable ppsclock streams module
- * flag4 - use the PCL-720 (BSD/OS only)
- */
-
-
-/*
- * Definitions
- */
-#define DEVICE "/dev/true%d"
-#define SPEED232 B9600 /* 9600 baud */
-
-/*
- * Radio interface parameters
- */
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#define REFID "TRUE" /* reference id */
-#define DESCRIPTION "Kinemetrics/TrueTime Receiver"
-
-/*
- * Tags which station (satellite) we see
- */
-#define GOES_WEST 0 /* Default to WEST satellite and apply time1 */
-#define GOES_EAST 1 /* until you discover otherwise */
-
-/*
- * used by the state machine
- */
-enum true_event {e_Init, e_Huh, e_F18, e_F50, e_F51, e_Satellite,
- e_Poll, e_Location, e_TS, e_Max};
-const char *events[] = {"Init", "Huh", "F18", "F50", "F51", "Satellite",
- "Poll", "Location", "TS"};
-#define eventStr(x) (((int)x<(int)e_Max) ? events[(int)x] : "?")
-
-enum true_state {s_Base, s_InqTM, s_InqTCU, s_InqOmega, s_InqGOES,
- s_Init, s_F18, s_F50, s_Start, s_Auto, s_Max};
-const char *states[] = {"Base", "InqTM", "InqTCU", "InqOmega", "InqGOES",
- "Init", "F18", "F50", "Start", "Auto"};
-#define stateStr(x) (((int)x<(int)s_Max) ? states[(int)x] : "?")
-
-enum true_type {t_unknown, t_goes, t_tm, t_tcu, t_omega, t_Max};
-const char *types[] = {"unknown", "goes", "tm", "tcu", "omega"};
-#define typeStr(x) (((int)x<(int)t_Max) ? types[(int)x] : "?")
-
-/*
- * unit control structure
- */
-struct true_unit {
- unsigned int pollcnt; /* poll message counter */
- unsigned int station; /* which station we are on */
- unsigned int polled; /* Hand in a time sample? */
- enum true_state state; /* state machine */
- enum true_type type; /* what kind of clock is it? */
- int unit; /* save an extra copy of this */
- FILE *debug; /* debug logging file */
-#ifdef CLOCK_PPS720
- int pcl720init; /* init flag for PCL 720 */
-#endif
-};
-
-/*
- * Function prototypes
- */
-static int true_start P((int, struct peer *));
-static void true_shutdown P((int, struct peer *));
-static void true_receive P((struct recvbuf *));
-static void true_poll P((int, struct peer *));
-static void true_send P((struct peer *, const char *));
-static void true_doevent P((struct peer *, enum true_event));
-
-#ifdef CLOCK_PPS720
-static u_long true_sample720 P((void));
-#endif
-
-/*
- * Transfer vector
- */
-struct refclock refclock_true = {
- true_start, /* start up driver */
- true_shutdown, /* shut down driver */
- true_poll, /* transmit poll message */
- noentry, /* not used (old true_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old true_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-#if !defined(__STDC__)
-# define true_debug (void)
-#else
-static void
-true_debug(struct peer *peer, const char *fmt, ...)
-{
- va_list ap;
- int want_debugging, now_debugging;
- struct refclockproc *pp;
- struct true_unit *up;
-
- va_start(ap, fmt);
- pp = peer->procptr;
- up = (struct true_unit *)pp->unitptr;
-
- want_debugging = (pp->sloppyclockflag & CLK_FLAG2) != 0;
- now_debugging = (up->debug != NULL);
- if (want_debugging != now_debugging)
- {
- if (want_debugging) {
- char filename[40];
- int fd;
-
- snprintf(filename, sizeof(filename), "/tmp/true%d.debug", up->unit);
- fd = open(filename, O_CREAT | O_WRONLY | O_EXCL, 0600);
- if (fd >= 0 && (up->debug = fdopen(fd, "r+"))) {
-#ifdef HAVE_SETVBUF
- static char buf[BUFSIZ];
- setvbuf(up->debug, buf, _IOLBF, BUFSIZ);
-#else
- setlinebuf(up->debug);
-#endif
- }
- } else {
- fclose(up->debug);
- up->debug = NULL;
- }
- }
-
- if (up->debug) {
- fprintf(up->debug, "true%d: ", up->unit);
- vfprintf(up->debug, fmt, ap);
- }
-}
-#endif /*STDC*/
-
-/*
- * true_start - open the devices and initialize data for processing
- */
-static int
-true_start(
- int unit,
- struct peer *peer
- )
-{
- register struct true_unit *up;
- struct refclockproc *pp;
- char device[40];
- int fd;
-
- /*
- * Open serial port
- */
- (void)snprintf(device, sizeof(device), DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
- return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct true_unit *)
- emalloc(sizeof(struct true_unit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct true_unit));
- pp = peer->procptr;
- pp->io.clock_recv = true_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;
- up->type = t_unknown;
- up->state = s_Base;
- true_doevent(peer, e_Init);
- return (1);
-}
-
-/*
- * true_shutdown - shut down the clock
- */
-static void
-true_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct true_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct true_unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * true_receive - receive data from the serial interface on a clock
- */
-static void
-true_receive(
- struct recvbuf *rbufp
- )
-{
- register struct true_unit *up;
- struct refclockproc *pp;
- struct peer *peer;
- u_short new_station;
- char synced;
- int i;
- int lat, lon, off; /* GOES Satellite position */
- /* Use these variable to hold data until we decide its worth keeping */
- char rd_lastcode[BMAX];
- l_fp rd_tmp;
- u_short rd_lencode;
-
- /*
- * Get the clock this applies to and pointers to the data.
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct true_unit *)pp->unitptr;
-
- /*
- * Read clock output. Automatically handles STREAMS, CLKLDISC.
- */
- rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
- rd_lastcode[rd_lencode] = '\0';
-
- /*
- * There is a case where <cr><lf> generates 2 timestamps.
- */
- if (rd_lencode == 0)
- return;
- pp->lencode = rd_lencode;
- strcpy(pp->a_lastcode, rd_lastcode);
- pp->lastrec = rd_tmp;
- true_debug(peer, "receive(%s) [%d]\n", pp->a_lastcode, pp->lencode);
-
- up->pollcnt = 2;
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-
- /*
- * 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.
- */
-
- /*
- * Clock misunderstood our last command?
- */
- if (pp->a_lastcode[0] == '?' ||
- strcmp(pp->a_lastcode, "ERROR 05 NO SUCH FUNCTION") == 0) {
- true_doevent(peer, e_Huh);
- return;
- }
-
- /*
- * Timecode: "nnnnn+nnn-nnn"
- * (from GOES clock when asked about satellite position)
- */
- if ((pp->a_lastcode[5] == '+' || pp->a_lastcode[5] == '-') &&
- (pp->a_lastcode[9] == '+' || pp->a_lastcode[9] == '-') &&
- sscanf(pp->a_lastcode, "%5d%*c%3d%*c%3d", &lon, &lat, &off) == 3
- ) {
- const char *label = "Botch!";
-
- /*
- * This is less than perfect. Call the (satellite)
- * either EAST or WEST and adjust slop accodingly
- * Perfectionists would recalculate the exact delay
- * and adjust accordingly...
- */
- if (lon > 7000 && lon < 14000) {
- if (lon < 10000) {
- new_station = GOES_EAST;
- label = "EAST";
- } else {
- new_station = GOES_WEST;
- label = "WEST";
- }
-
- if (new_station != up->station) {
- double dtemp;
-
- dtemp = pp->fudgetime1;
- pp->fudgetime1 = pp->fudgetime2;
- pp->fudgetime2 = dtemp;
- up->station = new_station;
- }
- }
- else {
- /*refclock_report(peer, CEVNT_BADREPLY);*/
- label = "UNKNOWN";
- }
- true_debug(peer, "GOES: station %s\n", label);
- true_doevent(peer, e_Satellite);
- return;
- }
-
- /*
- * Timecode: "Fnn"
- * (from TM/TMD clock when it wants to tell us what it's up to.)
- */
- if (sscanf(pp->a_lastcode, "F%2d", &i) == 1 && i > 0 && i < 80) {
- switch (i) {
- case 50:
- true_doevent(peer, e_F50);
- break;
- case 51:
- true_doevent(peer, e_F51);
- break;
- default:
- true_debug(peer, "got F%02d - ignoring\n", i);
- break;
- }
- return;
- }
-
- /*
- * Timecode: " TRUETIME Mk III" or " TRUETIME XL"
- * (from a TM/TMD/XL clock during initialization.)
- */
- if (strcmp(pp->a_lastcode, " TRUETIME Mk III") == 0 ||
- strncmp(pp->a_lastcode, " TRUETIME XL", 12) == 0) {
- true_doevent(peer, e_F18);
- NLOG(NLOG_CLOCKSTATUS) {
- msyslog(LOG_INFO, "TM/TMD/XL: %s", pp->a_lastcode);
- }
- return;
- }
-
- /*
- * Timecode: "N03726428W12209421+000033"
- * 1 2
- * 0123456789012345678901234
- * (from a TCU during initialization)
- */
- if ((pp->a_lastcode[0] == 'N' || pp->a_lastcode[0] == 'S') &&
- (pp->a_lastcode[9] == 'W' || pp->a_lastcode[9] == 'E') &&
- pp->a_lastcode[18] == '+') {
- true_doevent(peer, e_Location);
- NLOG(NLOG_CLOCKSTATUS) {
- msyslog(LOG_INFO, "TCU-800: %s", pp->a_lastcode);
- }
- return;
- }
- /*
- * Timecode: "ddd:hh:mm:ssQ"
- * (from all clocks supported by this driver.)
- */
- if (pp->a_lastcode[3] == ':' &&
- pp->a_lastcode[6] == ':' &&
- pp->a_lastcode[9] == ':' &&
- sscanf(pp->a_lastcode, "%3d:%2d:%2d:%2d%c",
- &pp->day, &pp->hour, &pp->minute,
- &pp->second, &synced) == 5) {
-
- /*
- * Adjust the synchronize indicator according to timecode
- * say were OK, and then say not if we really are not OK
- */
- if (synced == '>' || synced == '#' || synced == '?')
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
-
- true_doevent(peer, e_TS);
-
-#ifdef CLOCK_PPS720
- /* If it's taken more than 65ms to get here, we'll lose. */
- if ((pp->sloppyclockflag & CLK_FLAG4) && up->pcl720init) {
- l_fp off;
-
-#ifdef CLOCK_ATOM
- /*
- * find out what time it really is. Include
- * the count from the PCL720
- */
- if (!clocktime(pp->day, pp->hour, pp->minute,
- pp->second, GMT, pp->lastrec.l_ui,
- &pp->yearstart, &off.l_ui)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- off.l_uf = 0;
-#endif
-
- pp->usec = true_sample720();
-#ifdef CLOCK_ATOM
- TVUTOTSF(pp->usec, off.l_uf);
-#endif
-
- /*
- * Stomp all over the timestamp that was pulled out
- * of the input stream. It's irrelevant since we've
- * adjusted the input time to reflect now (via pp->usec)
- * rather than when the data was collected.
- */
- get_systime(&pp->lastrec);
-#ifdef CLOCK_ATOM
- /*
- * Create a true offset for feeding to pps_sample()
- */
- L_SUB(&off, &pp->lastrec);
-
- pps_sample(peer, &off);
-#endif
- true_debug(peer, "true_sample720: %luus\n", pp->usec);
- }
-#endif
-
- /*
- * 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;
-
- true_doevent(peer, e_Poll);
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- /*
- * If clock is good we send a NOMINAL message so that
- * any previous BAD messages are nullified
- */
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- refclock_report(peer, CEVNT_NOMINAL);
-
- /*
- * We have succedded in answering the poll.
- * Turn off the flag and return
- */
- up->polled = 0;
-
- return;
- }
-
- /*
- * No match to known timecodes, report failure and return
- */
- refclock_report(peer, CEVNT_BADREPLY);
- return;
-}
-
-
-/*
- * true_send - time to send the clock a signal to cough up a time sample
- */
-static void
-true_send(
- struct peer *peer,
- const char *cmd
- )
-{
- struct refclockproc *pp;
-
- pp = peer->procptr;
- if (!(pp->sloppyclockflag & CLK_FLAG1)) {
- register int len = strlen(cmd);
-
- true_debug(peer, "Send '%s'\n", cmd);
- if (write(pp->io.fd, cmd, (unsigned)len) != len)
- refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
- }
-}
-
-
-/*
- * state machine for initializing and controlling a clock
- */
-static void
-true_doevent(
- struct peer *peer,
- enum true_event event
- )
-{
- struct true_unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct true_unit *)pp->unitptr;
- if (event != e_TS) {
- NLOG(NLOG_CLOCKSTATUS) {
- msyslog(LOG_INFO, "TRUE: clock %s, state %s, event %s",
- typeStr(up->type),
- stateStr(up->state),
- eventStr(event));
- }
- }
- true_debug(peer, "clock %s, state %s, event %s\n",
- typeStr(up->type), stateStr(up->state), eventStr(event));
- switch (up->type) {
- case t_goes:
- switch (event) {
- case e_Init: /* FALLTHROUGH */
- case e_Satellite:
- /*
- * Switch back to on-second time codes and return.
- */
- true_send(peer, "C");
- up->state = s_Start;
- break;
- case e_Poll:
- /*
- * After each poll, check the station (satellite).
- */
- true_send(peer, "P");
- /* No state change needed. */
- break;
- default:
- break;
- }
- /* FALLTHROUGH */
- case t_omega:
- switch (event) {
- case e_Init:
- true_send(peer, "C");
- up->state = s_Start;
- break;
- case e_TS:
- if (up->state != s_Start && up->state != s_Auto) {
- true_send(peer, "\03\r");
- break;
- }
- up->state = s_Auto;
- break;
- default:
- break;
- }
- break;
- case t_tm:
- switch (event) {
- case e_Init:
- true_send(peer, "F18\r");
- up->state = s_Init;
- break;
- case e_F18:
- true_send(peer, "F50\r");
- up->state = s_F18;
- break;
- case e_F50:
- true_send(peer, "F51\r");
- up->state = s_F50;
- break;
- case e_F51:
- true_send(peer, "F08\r");
- up->state = s_Start;
- break;
- case e_TS:
- if (up->state != s_Start && up->state != s_Auto) {
- true_send(peer, "\03\r");
- break;
- }
- up->state = s_Auto;
- break;
- default:
- break;
- }
- break;
- case t_tcu:
- switch (event) {
- case e_Init:
- true_send(peer, "MD3\r"); /* GPS Synch'd Gen. */
- true_send(peer, "TSU\r"); /* UTC, not GPS. */
- true_send(peer, "AU\r"); /* Auto Timestamps. */
- up->state = s_Start;
- break;
- case e_TS:
- if (up->state != s_Start && up->state != s_Auto) {
- true_send(peer, "\03\r");
- break;
- }
- up->state = s_Auto;
- break;
- default:
- break;
- }
- break;
- case t_unknown:
- switch (up->state) {
- case s_Base:
- if (event != e_Init)
- abort();
- true_send(peer, "P\r");
- up->state = s_InqGOES;
- break;
- case s_InqGOES:
- switch (event) {
- case e_Satellite:
- up->type = t_goes;
- true_doevent(peer, e_Init);
- break;
- case e_Init: /*FALLTHROUGH*/
- case e_Huh: /*FALLTHROUGH*/
- case e_TS:
- up->state = s_InqOmega;
- true_send(peer, "C\r");
- break;
- default:
- abort();
- }
- break;
- case s_InqOmega:
- switch (event) {
- case e_TS:
- up->type = t_omega;
- up->state = s_Auto; /* Inq side-effect. */
- break;
- case e_Init: /*FALLTHROUGH*/
- case e_Huh:
- up->state = s_InqTM;
- true_send(peer, "F18\r");
- break;
- default:
- abort();
- }
- break;
- case s_InqTM:
- switch (event) {
- case e_F18:
- up->type = t_tm;
- true_doevent(peer, e_Init);
- break;
- case e_Init: /*FALLTHROUGH*/
- case e_Huh:
- true_send(peer, "PO\r");
- up->state = s_InqTCU;
- break;
- default:
- abort();
- }
- break;
- case s_InqTCU:
- switch (event) {
- case e_Location:
- up->type = t_tcu;
- true_doevent(peer, e_Init);
- break;
- case e_Init: /*FALLTHROUGH*/
- case e_Huh:
- up->state = s_Base;
- sleep(1); /* XXX */
- break;
- default:
- abort();
- }
- break;
- /*
- * An expedient hack to prevent lint complaints,
- * these don't actually need to be used here...
- */
- case s_Init:
- case s_F18:
- case s_F50:
- case s_Start:
- case s_Auto:
- case s_Max:
- msyslog(LOG_INFO, "TRUE: state %s is unexpected!", stateStr(up->state));
- }
- break;
- default:
- abort();
- /* NOTREACHED */
- }
-
-#ifdef CLOCK_PPS720
- if ((pp->sloppyclockflag & CLK_FLAG4) && !up->pcl720init) {
- /* Make counter trigger on gate0, count down from 65535. */
- pcl720_load(PCL720_IOB, PCL720_CTR, i8253_oneshot, 65535);
- /*
- * (These constants are OK since
- * they represent hardware maximums.)
- */
- NLOG(NLOG_CLOCKINFO) {
- msyslog(LOG_NOTICE, "PCL-720 initialized");
- }
- up->pcl720init++;
- }
-#endif
-
-
-}
-
-/*
- * true_poll - called by the transmit procedure
- */
-static void
-true_poll(
- int unit,
- struct peer *peer
- )
-{
- struct true_unit *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.
- */
- pp = peer->procptr;
- up = (struct true_unit *)pp->unitptr;
- if (up->pollcnt > 0)
- up->pollcnt--;
- else {
- true_doevent(peer, e_Init);
- refclock_report(peer, CEVNT_TIMEOUT);
- }
-
- /*
- * polled every 64 seconds. Ask true_receive to hand in a
- * timestamp.
- */
- up->polled = 1;
- pp->polls++;
-}
-
-#ifdef CLOCK_PPS720
-/*
- * true_sample720 - sample the PCL-720
- */
-static u_long
-true_sample720(void)
-{
- unsigned long f;
-
- /* We wire the PCL-720's 8253.OUT0 to bit 0 of connector 3.
- * If it is not being held low now, we did not get called
- * within 65535us.
- */
- if (inb(pcl720_data_16_23(PCL720_IOB)) & 0x01) {
- NLOG(NLOG_CLOCKINFO) {
- msyslog(LOG_NOTICE, "PCL-720 out of synch");
- }
- return (0);
- }
- f = (65536 - pcl720_read(PCL720_IOB, PCL720_CTR));
-#ifdef PPS720_DEBUG
- msyslog(LOG_DEBUG, "PCL-720: %luus", f);
-#endif
- return (f);
-}
-#endif
-
-#else
-int refclock_true_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_tt560.c b/contrib/ntp/ntpd/refclock_tt560.c
deleted file mode 100644
index f3d7bc1..0000000
--- a/contrib/ntp/ntpd/refclock_tt560.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * refclock_tt560 - clock driver for the TrueTime 560 IRIG-B decoder
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_TT560)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "sys/tt560_api.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * This driver supports the TrueTime 560 IRIG-B decoder for the PCI bus.
- */
-
-/*
- * TT560 interface definitions
- */
-#define DEVICE "/dev/tt560%d" /* device name and unit */
-#define PRECISION (-20) /* precision assumed (1 us) */
-#define REFID "IRIG" /* reference ID */
-#define DESCRIPTION "TrueTime 560 IRIG-B PCI Decoder"
-
-/*
- * Unit control structure
- */
-struct tt560unit {
- tt_mem_space_t *tt_mem; /* mapped address of PCI board */
- time_freeze_reg_t tt560rawt; /* data returned from PCI board */
-};
-
-typedef union byteswap_u
-{
- unsigned int long_word;
- unsigned char byte[4];
-} byteswap_t;
-
-/*
- * Function prototypes
- */
-static int tt560_start P((int, struct peer *));
-static void tt560_shutdown P((int, struct peer *));
-static void tt560_poll P((int unit, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_tt560 = {
- tt560_start, /* clock_start */
- tt560_shutdown, /* clock_shutdown */
- tt560_poll, /* clock_poll */
- noentry, /* clock_control (not used) */
- noentry, /* clock_init (not used) */
- noentry, /* clock_buginfo (not used) */
- NOFLAGS /* clock_flags (not used) */
-};
-
-
-/*
- * tt560_start - open the TT560 device and initialize data for processing
- */
-static int
-tt560_start(
- int unit,
- struct peer *peer
- )
-{
- register struct tt560unit *up;
- struct refclockproc *pp;
- char device[20];
- int fd;
- caddr_t membase;
-
- /*
- * Open TT560 device
- */
- (void)sprintf(device, DEVICE, unit);
- fd = open(device, O_RDWR);
- if (fd == -1) {
- msyslog(LOG_ERR, "tt560_start: open of %s: %m", device);
- return (0);
- }
-
- /*
- * Map the device registers into user space.
- */
- membase = mmap ((caddr_t) 0, TTIME_MEMORY_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, fd, (off_t)0);
-
- if (membase == (caddr_t) -1) {
- msyslog(LOG_ERR, "tt560_start: mapping of %s: %m", device);
- (void) close(fd);
- return (0);
- }
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct tt560unit *) emalloc(sizeof(struct tt560unit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct tt560unit));
- up->tt_mem = (tt_mem_space_t *)membase;
- pp = peer->procptr;
- pp->io.clock_recv = noentry;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- pp->unitptr = (caddr_t)up;
-
- /*
- * Initialize miscellaneous peer variables
- */
- peer->precision = PRECISION;
- peer->burst = NSTAGE;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- return (1);
-}
-
-
-/*
- * tt560_shutdown - shut down the clock
- */
-static void
-tt560_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct tt560unit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct tt560unit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * tt560_poll - called by the transmit procedure
- */
-static void
-tt560_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct tt560unit *up;
- struct refclockproc *pp;
- time_freeze_reg_t *tp;
- tt_mem_space_t *mp;
-
- int i;
- unsigned int *p_time_t, *tt_mem_t;
-
- /*
- * This is the main routine. It snatches the time from the TT560
- * board and tacks on a local timestamp.
- */
- pp = peer->procptr;
- up = (struct tt560unit *)pp->unitptr;
- mp = up->tt_mem;
- tp = &up->tt560rawt;
-
- p_time_t = (unsigned int *)tp;
- tt_mem_t = (unsigned int *)&mp->time_freeze_reg;
-
- *tt_mem_t = 0; /* update the time freeze register */
- /* and copy time stamp to memory */
- for (i=0; i < TIME_FREEZE_REG_LEN; i++) {
- *p_time_t = byte_swap(*tt_mem_t);
- p_time_t++;
- tt_mem_t++;
- }
-
- get_systime(&pp->lastrec);
- pp->polls++;
-
- /*
- * 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. All format error checking is
- * done by the sprintf() and sscanf() routines.
- */
- sprintf(pp->a_lastcode,
- "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
- tp->hun_day, tp->tens_day, tp->unit_day,
- tp->tens_hour, tp->unit_hour,
- tp->tens_min, tp->unit_min,
- tp->tens_sec, tp->unit_sec,
- tp->hun_ms, tp->tens_ms, tp->unit_ms,
- tp->hun_us, tp->tens_us, tp->unit_us,
- tp->status);
- pp->lencode = strlen(pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("tt560: time %s timecode %d %s\n",
- ulfptoa(&pp->lastrec, 6), pp->lencode,
- pp->a_lastcode);
-#endif
- if (sscanf(pp->a_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 & 0x6) != 0x6)
- pp->leap = LEAP_NOTINSYNC;
- else
- pp->leap = LEAP_NOWARNING;
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- refclock_receive(peer);
- peer->burst = NSTAGE;
-}
-
-/******************************************************************
- *
- * byte_swap
- *
- * Inputs: 32 bit integer
- *
- * Output: byte swapped 32 bit integer.
- *
- * This routine is used to compensate for the byte alignment
- * differences between big-endian and little-endian integers.
- *
- ******************************************************************/
-static unsigned int
-byte_swap(unsigned int input_num)
-{
- byteswap_t byte_swap;
- unsigned char temp;
-
- byte_swap.long_word = input_num;
-
- temp = byte_swap.byte[3];
- byte_swap.byte[3] = byte_swap.byte[0];
- byte_swap.byte[0] = temp;
-
- temp = byte_swap.byte[2];
- byte_swap.byte[2] = byte_swap.byte[1];
- byte_swap.byte[1] = temp;
-
- return (byte_swap.long_word);
-}
-
-#else
-int refclock_tt560_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_ulink.c b/contrib/ntp/ntpd/refclock_ulink.c
deleted file mode 100644
index 1f5e78a..0000000
--- a/contrib/ntp/ntpd/refclock_ulink.c
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * refclock_ulink - clock driver for Ultralink WWVB receiver
- *
- */
-
-/***********************************************************************
- * *
- * Copyright (c) David L. Mills 1992-1998 *
- * *
- * 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. *
- **********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_ULINK)
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-/*
- * This driver supports ultralink Model 320,330,331,332 WWVB radios
- *
- * this driver was based on the refclock_wwvb.c driver
- * in the ntp distribution.
- *
- * Fudge Factors
- *
- * fudge flag1 0 don't poll clock
- * 1 send poll character
- *
- * revision history:
- * 99/9/09 j.c.lang original edit's
- * 99/9/11 j.c.lang changed timecode parse to
- * match what the radio actually
- * sends.
- * 99/10/11 j.c.lang added support for continous
- * time code mode (dipsw2)
- * 99/11/26 j.c.lang added support for 320 decoder
- * (taken from Dave Strout's
- * Model 320 driver)
- * 99/11/29 j.c.lang added fudge flag 1 to control
- * clock polling
- * 99/12/15 j.c.lang fixed 320 quality flag
- * 01/02/21 s.l.smith fixed 33x quality flag
- * added more debugging stuff
- * updated 33x time code explanation
- *
- * Questions, bugs, ideas send to:
- * Joseph C. Lang
- * tcnojl1@earthlink.net
- *
- * Dave Strout
- * dstrout@linuxfoundry.com
- *
- *
- * on the Ultralink model 33X decoder Dip switch 2 controls
- * polled or continous timecode
- * set fudge flag1 if using polled (needed for model 320)
- * dont set fudge flag1 if dip switch 2 is set on model 33x decoder
-*/
-
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/wwvb%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-10) /* precision assumed (about 10 ms) */
-#define REFID "WWVB" /* reference ID */
-#define DESCRIPTION "Ultralink WWVB Receiver" /* WRU */
-
-#define LEN33X 32 /* timecode length Model 325 & 33X */
-#define LEN320 24 /* timecode length Model 320 */
-
-/*
- * unit control structure
- */
-struct ulinkunit {
- u_char tcswitch; /* timecode switch */
- l_fp laststamp; /* last receive timestamp */
-};
-
-/*
- * Function prototypes
- */
-static int ulink_start P((int, struct peer *));
-static void ulink_shutdown P((int, struct peer *));
-static void ulink_receive P((struct recvbuf *));
-static void ulink_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_ulink = {
- ulink_start, /* start up driver */
- ulink_shutdown, /* shut down driver */
- ulink_poll, /* transmit poll message */
- noentry, /* not used */
- noentry, /* not used */
- noentry, /* not used */
- NOFLAGS
-};
-
-
-/*
- * ulink_start - open the devices and initialize data for processing
- */
-static int
-ulink_start(
- int unit,
- struct peer *peer
- )
-{
- register struct ulinkunit *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 ulinkunit *)
- emalloc(sizeof(struct ulinkunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct ulinkunit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = ulink_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);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- peer->burst = NSTAGE;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- return (1);
-}
-
-
-/*
- * ulink_shutdown - shut down the clock
- */
-static void
-ulink_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct ulinkunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct ulinkunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * ulink_receive - receive data from the serial interface
- */
-static void
-ulink_receive(
- struct recvbuf *rbufp
- )
-{
- struct ulinkunit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- l_fp trtmp; /* arrival timestamp */
- int quality; /* quality indicator */
- int temp; /* int temp */
- char syncchar; /* synchronization indicator */
- char leapchar; /* leap indicator */
- char modechar; /* model 320 mode flag */
- char char_quality[2]; /* temp quality flag */
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct ulinkunit *)pp->unitptr;
- temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
-
- /*
- * Note we get a buffer and timestamp for both a <cr> and <lf>,
- * but only the <cr> timestamp is retained.
- */
- if (temp == 0) {
- if (up->tcswitch == 0) {
- up->tcswitch = 1;
- up->laststamp = trtmp;
- } else
- up->tcswitch = 0;
- return;
- }
- pp->lencode = temp;
- pp->lastrec = up->laststamp;
- up->laststamp = trtmp;
- up->tcswitch = 1;
-#ifdef DEBUG
- if (debug)
- printf("ulink: timecode %d %s\n", pp->lencode,
- pp->a_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.
- */
- syncchar = leapchar = modechar = ' ';
- switch (pp->lencode ) {
- case LEN33X:
- /*
- * Model 33X decoder:
- * Timecode format from January 29, 2001 datasheet is:
- * <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5
- * S WWVB decoder sync indicator. S for in-sync(?)
- * or N for noisy signal.
- * 9+ RF signal level in S-units, 0-9 followed by
- * a space (0x20). The space turns to '+' if the
- * level is over 9.
- * D Data bit 0, 1, 2 (position mark), or
- * 3 (unknown).
- * space Space character (0x20)
- * 00 Hours since last good WWVB frame sync. Will
- * be 00-23 hrs, or '1d' to '7d'. Will be 'Lk'
- * if currently in sync.
- * space Space character (0x20)
- * YYYY Current year, 1990-2089
- * + Leap year indicator. '+' if a leap year,
- * a space (0x20) if not.
- * DDD Day of year, 001 - 366.
- * UTC Timezone (always 'UTC').
- * S Daylight savings indicator
- * S - standard time (STD) in effect
- * O - during STD to DST day 0000-2400
- * D - daylight savings time (DST) in effect
- * I - during DST to STD day 0000-2400
- * space Space character (0x20)
- * HH Hours 00-23
- * : This is the REAL in sync indicator (: = insync)
- * MM Minutes 00-59
- * : : = in sync ? = NOT in sync
- * SS Seconds 00-59
- * L Leap second flag. Changes from space (0x20)
- * to '+' or '-' during month preceding leap
- * second adjustment.
- * +5 UT1 correction (sign + digit ))
- */
-
- if (sscanf(pp->a_lastcode,
- "%*4c %2c %4d%*c%3d%*4c %2d%c%2d:%2d%c%*2c",
- char_quality, &pp->year, &pp->day,
- &pp->hour, &syncchar, &pp->minute, &pp->second,
- &leapchar) == 8) {
-
- if (char_quality[0] == 'L') {
- quality = 0;
- } else if (char_quality[0] == '0') {
- quality = (char_quality[1] & 0x0f);
- } else {
- quality = 99;
- }
-
-/*
-#ifdef DEBUG
- if (debug) {
- printf("ulink: char_quality %c %c\n",
- char_quality[0], char_quality[1]);
- printf("ulink: quality %d\n", quality);
- printf("ulink: syncchar %x\n", syncchar);
- printf("ulink: leapchar %x\n", leapchar);
- }
-#endif
-*/
-
- break;
- }
-
- case LEN320:
- /*
- * Model 320 Decoder
- * The timecode format is:
- *
- * <cr><lf>SQRYYYYDDD+HH:MM:SS.mmLT<cr>
- *
- * where:
- *
- * S = 'S' -- sync'd in last hour,
- * '0'-'9' - hours x 10 since last update,
- * '?' -- not in sync
- * Q = Number of correlating time-frames, from 0 to 5
- * R = 'R' -- reception in progress,
- * 'N' -- Noisy reception,
- * ' ' -- standby mode
- * YYYY = year from 1990 to 2089
- * DDD = current day from 1 to 366
- * + = '+' if current year is a leap year, else ' '
- * HH = UTC hour 0 to 23
- * MM = Minutes of current hour from 0 to 59
- * SS = Seconds of current minute from 0 to 59
- * mm = 10's milliseconds of the current second from 00 to 99
- * L = Leap second pending at end of month
- * 'I' = insert, 'D'= delete
- * T = DST <-> STD transition indicators
- *
- */
- if (sscanf(pp->a_lastcode, "%c%1d%c%4d%3d%*c%2d:%2d:%2d.%2ld%c",
- &syncchar, &quality, &modechar, &pp->year, &pp->day,
- &pp->hour, &pp->minute, &pp->second,
- &pp->nsec, &leapchar) == 10) {
- pp->nsec *= 10000000; /* M320 returns 10's of msecs */
- if (leapchar == 'I' ) leapchar = '+';
- if (leapchar == 'D' ) leapchar = '-';
- if (syncchar != '?' ) syncchar = ':';
-
- break;
- }
-
- default:
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
-
- /*
- * Decode quality indicator
- * For the 325 & 33x series, the lower the number the "better"
- * the time is. I used the dispersion as the measure of time
- * quality. The quality indicator in the 320 is the number of
- * correlating time frames (the more the better)
- */
-
- /*
- * The spec sheet for the 325 & 33x series states the clock will
- * maintain +/-0.002 seconds accuracy when locked to WWVB. This
- * is indicated by 'Lk' in the quality portion of the incoming
- * string. When not in lock, a drift of +/-0.015 seconds should
- * be allowed for.
- * With the quality indicator decoding scheme above, the 'Lk'
- * condition will produce a quality value of 0. If the quality
- * indicator starts with '0' then the second character is the
- * number of hours since we were last locked. If the first
- * character is anything other than 'L' or '0' then we have been
- * out of lock for more than 9 hours so we assume the worst and
- * force a quality value that selects the 'default' maximum
- * dispersion. The dispersion values below are what came with the
- * driver. They're not unreasonable so they've not been changed.
- */
-
- if (pp->lencode == LEN33X) {
- switch (quality) {
- case 0 :
- pp->disp=.002;
- break;
- case 1 :
- pp->disp=.02;
- break;
- case 2 :
- pp->disp=.04;
- break;
- case 3 :
- pp->disp=.08;
- break;
- default:
- pp->disp=MAXDISPERSE;
- break;
- }
- } else {
- switch (quality) {
- case 5 :
- pp->disp=.002;
- break;
- case 4 :
- pp->disp=.02;
- break;
- case 3 :
- pp->disp=.04;
- break;
- case 2 :
- pp->disp=.08;
- break;
- case 1 :
- pp->disp=.16;
- break;
- default:
- pp->disp=MAXDISPERSE;
- break;
- }
-
- }
-
- /*
- * Decode synchronization, and leap characters. If
- * unsynchronized, set the leap bits accordingly and exit.
- * Otherwise, set the leap bits according to the leap character.
- */
-
- if (syncchar != ':')
- pp->leap = LEAP_NOTINSYNC;
- else if (leapchar == '+')
- pp->leap = LEAP_ADDSECOND;
- else if (leapchar == '-')
- pp->leap = LEAP_DELSECOND;
- else
- pp->leap = LEAP_NOWARNING;
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- }
-
-}
-
-
-/*
- * ulink_poll - called by the transmit procedure
- */
-static void
-ulink_poll(
- int unit,
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- char pollchar;
-
- pp = peer->procptr;
- pollchar = 'T';
- if (pp->sloppyclockflag & CLK_FLAG1) {
- if (write(pp->io.fd, &pollchar, 1) != 1)
- refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
- }
- else
- pp->polls++;
-
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- peer->burst = NSTAGE;
-
-}
-
-#else
-int refclock_ulink_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_usno.c b/contrib/ntp/ntpd/refclock_usno.c
deleted file mode 100644
index 057eef9..0000000
--- a/contrib/ntp/ntpd/refclock_usno.c
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * refclock_usno - clock driver for the Naval Observatory dialup
- * Michael Shields <shields@tembel.org> 1995/02/25
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_USNO)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-#include "ntp_control.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
-/*
- * This driver supports the Naval Observatory dialup at +1 202 653 0351.
- * It is a hacked-up version of the ACTS driver.
- *
- * This driver does not support the `phone' configuration because that
- * is needlessly global; it would clash with the ACTS driver.
- *
- * The Naval Observatory does not support the echo-delay measurement scheme.
- *
- * However, this driver *does* support UUCP port locking, allowing the
- * line to be shared with other processes when not actually dialing
- * for time.
- */
-
-/*
- * Interface definitions
- */
-
-#define DEVICE "/dev/cua%d" /* device name and unit */
-#define LOCKFILE "/var/lock/LCK..cua%d"
-/* #define LOCKFILE "/usr/spool/uucp/LCK..cua%d" */
-
-#define PHONE "atdt 202 653 0351"
-/* #define PHONE "atdt 1 202 653 0351" */
-
-#define SPEED232 B1200 /* uart speed (1200 cowardly baud) */
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#define REFID "USNO" /* reference ID */
-#define DESCRIPTION "Naval Observatory dialup"
-
-#define MODE_AUTO 0 /* automatic mode */
-#define MODE_BACKUP 1 /* backup mode */
-#define MODE_MANUAL 2 /* manual mode */
-
-#define MSGCNT 10 /* we need this many time messages */
-#define SMAX 80 /* max token string length */
-#define LENCODE 20 /* length of valid timecode string */
-#define USNO_MINPOLL 10 /* log2 min poll interval (1024 s) */
-#define USNO_MAXPOLL 14 /* log2 max poll interval (16384 s) */
-#define MAXOUTAGE 3600 /* max before USNO 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 (MSGCNT+16) /* timecode timeout (s) */
-
-/*
- * Unit control structure
- */
-struct usnounit {
- int pollcnt; /* poll message counter */
-
- int state; /* the first one was Delaware */
- int run; /* call program run switch */
- int msgcnt; /* count of time messages received */
- long redial; /* interval to next automatic call */
- int unit; /* unit number (= port) */
-};
-
-/*
- * Function prototypes
- */
-static int usno_start P((int, struct peer *));
-static void usno_shutdown P((int, struct peer *));
-static void usno_poll P((int, struct peer *));
-static void usno_disc P((struct peer *));
-#if 0
-static void usno_timeout P((struct peer *));
-static void usno_receive P((struct recvbuf *));
-static int usno_write P((struct peer *, const char *));
-#endif /* 0 */
-
-/*
- * Transfer vector
- */
-struct refclock refclock_usno = {
- usno_start, /* start up driver */
- usno_shutdown, /* shut down driver */
- usno_poll, /* transmit poll message */
- noentry, /* not used (usno_control) */
- noentry, /* not used (usno_init) */
- noentry, /* not used (usno_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-/*
- * usno_start - open the devices and initialize data for processing
- */
-static int
-usno_start(
- int unit,
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
-
- /*
- * Initialize miscellaneous variables
- */
- pp = peer->procptr;
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- peer->minpoll = USNO_MINPOLL;
- peer->maxpoll = USNO_MAXPOLL;
- peer->sstclktype = CTL_SST_TS_TELEPHONE;
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct usnounit *)
- emalloc(sizeof(struct usnounit))))
- return (0);
- memset((char *)up, 0, sizeof(struct usnounit));
- up->unit = unit;
- pp->unitptr = (caddr_t)up;
-
- /*
- * Set up the driver timeout
- */
- peer->nextdate = current_time + WAIT;
- return (1);
-}
-
-
-/*
- * usno_shutdown - shut down the clock
- */
-static void
-usno_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
-
-#ifdef DEBUG
- if (debug)
- printf("usno: clock %s shutting down\n", ntoa(&peer->srcadr));
-#endif
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
- usno_disc(peer);
- free(up);
-}
-
-
-#if 0
-/*
- * usno_receive - receive data from the serial interface
- */
-static void
-usno_receive(
- struct recvbuf *rbufp
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
- struct peer *peer;
- char str[SMAX];
- u_long mjd; /* Modified Julian Day */
- static int day, hour, minute, second;
-
- /*
- * 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 usnounit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
- &pp->lastrec);
- if (pp->lencode == 0) {
- if (strcmp(pp->a_lastcode, "OK") == 0)
- pp->lencode = 2;
- return;
- }
-#ifdef DEBUG
- if (debug)
- printf("usno: timecode %d %s\n", pp->lencode,
- pp->a_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 about to dial. Just drop it.
- */
- return;
-
- case 2:
-
- /*
- * State 2. 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
- * 3.
- */
- (void)strncpy(str, strtok(pp->a_lastcode, " "), SMAX);
- if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") ==
- 0 || strcmp(str, "NO") == 0) {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO modem status %s",
- ntoa(&peer->srcadr), pp->a_lastcode);
- usno_disc(peer);
- } else if (strcmp(str, "CONNECT") == 0) {
- peer->nextdate = current_time + CONNECT;
- up->msgcnt = 0;
- up->state++;
- } else {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_WARNING,
- "clock %s USNO unknown modem status %s",
- ntoa(&peer->srcadr), pp->a_lastcode);
- }
- return;
-
- case 3:
-
- /*
- * State 3. The call has been answered and we are
- * waiting for the first message. If this doesn't
- * happen within the timecode timeout, hang up the
- * phone. We probably got a wrong number or they are
- * down.
- */
- peer->nextdate = current_time + TIMECODE;
- up->state++;
- return;
-
- case 4:
-
- /*
- * State 4. We are reading a timecode. It's an actual
- * timecode, or it's the `*' OTM.
- *
- * jjjjj nnn hhmmss UTC
- */
- if (pp->lencode == LENCODE) {
- if (sscanf(pp->a_lastcode, "%5ld %3d %2d%2d%2d UTC",
- &mjd, &day, &hour, &minute, &second) != 5) {
-#ifdef DEBUG
- if (debug)
- printf("usno: bad timecode format\n");
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- } else
- up->msgcnt++;
- return;
- } else if (pp->lencode != 1 || !up->msgcnt)
- return;
- /* else, OTM; drop out of switch */
- }
-
- pp->leap = LEAP_NOWARNING;
- pp->day = day;
- pp->hour = hour;
- pp->minute = minute;
- pp->second = second;
-
- /*
- * 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 (!refclock_process(pp)) {
-#ifdef DEBUG
- if (debug)
- printf("usno: time rejected\n");
-#endif
- 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.
- */
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- pp->sloppyclockflag &= ~CLK_FLAG1;
- up->pollcnt = 0;
- up->state = 0;
- usno_disc(peer);
-}
-#endif /* 0 */
-
-
-/*
- * usno_poll - called by the transmit routine
- */
-static void
-usno_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct usnounit *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. If not, the enable flag can be set using
- * ntpdc. If this is the sustem peer, then follow the system
- * poll interval.
- */
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
- if (up->run) {
- pp->sloppyclockflag |= CLK_FLAG1;
- if (peer == sys_peer)
- peer->hpoll = sys_poll;
- else
- peer->hpoll = peer->minpoll;
- }
-}
-
-
-#if 0
-/*
- * usno_timeout - called by the timer interrupt
- */
-static void
-usno_timeout(
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
- int fd;
- char device[20];
- char lockfile[128], pidbuf[8];
- 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 usnounit *)pp->unitptr;
- if (up->state) {
- if (up->state != 1) {
- usno_disc(peer);
- return;
- }
- /*
- * Call, and start the answer timeout. We think it
- * strange if the OK status has not been received from
- * the modem, but plow ahead anyway.
- *
- * This code is *here* because we had to stick in a brief
- * delay to let the modem settle down after raising DTR,
- * and for the OK to be received. State machines are
- * contorted.
- */
- if (strcmp(pp->a_lastcode, "OK") != 0)
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s USNO no modem status",
- ntoa(&peer->srcadr));
- (void)usno_write(peer, PHONE);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s USNO calling %s\n",
- ntoa(&peer->srcadr), PHONE);
- up->state = 2;
- up->pollcnt++;
- pp->polls++;
- peer->nextdate = current_time + ANSWER;
- return;
- }
- switch (peer->ttl) {
-
- /*
- * In manual mode the calling program is activated
- * by the ntpdc 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 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 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;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO backup started ",
- ntoa(&peer->srcadr));
- }
- } else if (up->run && sys_peer->sstclktype != CTL_SST_TS_TELEPHONE) {
- peer->hpoll = peer->minpoll;
- up->run = 0;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO backup stopped",
- ntoa(&peer->srcadr));
- }
- break;
-
- default:
- msyslog(LOG_ERR,
- "clock %s USNO invalid mode", ntoa(&peer->srcadr));
-
- }
-
- /*
- * The fudge flag1 is used as an enable/disable; if set either
- * by the code or via ntpdc, the calling program is
- * started; if reset, the phones stop ringing.
- */
- if (!(pp->sloppyclockflag & CLK_FLAG1)) {
- up->pollcnt = 0;
- peer->nextdate = current_time + IDLE;
- return;
- }
-
- /*
- * Lock the port.
- */
- (void)sprintf(lockfile, LOCKFILE, up->unit);
- fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL, 0644);
- if (fd < 0) {
- msyslog(LOG_ERR, "clock %s USNO port busy",
- ntoa(&peer->srcadr));
- return;
- }
- sprintf(pidbuf, "%d\n", (int) getpid());
- write(fd, pidbuf, strlen(pidbuf));
- close(fd);
-
- /*
- * 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, up->unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS))) {
- unlink(lockfile);
- return;
- }
- if (ioctl(fd, TIOCMBIC, (char *)&dtr) < 0)
- msyslog(LOG_WARNING, "usno_timeout: clock %s: couldn't clear DTR: %m",
- ntoa(&peer->srcadr));
-
- pp->io.clock_recv = usno_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
- (void) close(fd);
- unlink(lockfile);
- free(up);
- return;
- }
-
- /*
- * Initialize modem and kill DTR. We skedaddle if this comes
- * bum.
- */
- if (!usno_write(peer, MODEM_SETUP)) {
- msyslog(LOG_ERR, "clock %s USNO couldn't write",
- ntoa(&peer->srcadr));
- io_closeclock(&pp->io);
- unlink(lockfile);
- free(up);
- return;
- }
-
- /*
- * Initiate a call to the Observatory. If we wind up here in
- * other than state 0, a successful call could not be completed
- * within minpoll seconds.
- */
- if (up->pollcnt) {
- refclock_report(peer, CEVNT_TIMEOUT);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO calling program terminated",
- ntoa(&peer->srcadr));
- pp->sloppyclockflag &= ~CLK_FLAG1;
- up->pollcnt = 0;
-#ifdef DEBUG
- if (debug)
- printf("usno: calling program terminated\n");
-#endif
- usno_disc(peer);
- return;
- }
-
- /*
- * Raise DTR, and let the modem settle. Then we'll dial.
- */
- if (ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr) < -1)
- msyslog(LOG_INFO, "usno_timeout: clock %s: couldn't set DTR: %m",
- ntoa(&peer->srcadr));
- up->state = 1;
- peer->nextdate = current_time + WAIT;
-}
-#endif /* 0 */
-
-
-/*
- * usno_disc - disconnect the call and wait for the ruckus to cool
- */
-static void
-usno_disc(
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
- int dtr = TIOCM_DTR;
- char lockfile[128];
-
- /*
- * 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 the modem is hammering away full tilt.
- */
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
-
- if (ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr) < 0)
- msyslog(LOG_INFO, "usno_disc: clock %s: couldn't clear DTR: %m",
- ntoa(&peer->srcadr));
-
- if (up->state > 0) {
- up->state = 0;
- msyslog(LOG_NOTICE, "clock %s USNO call failed %d",
- ntoa(&peer->srcadr), up->state);
-#ifdef DEBUG
- if (debug)
- printf("usno: call failed %d\n", up->state);
-#endif
- }
-
- io_closeclock(&pp->io);
- sprintf(lockfile, LOCKFILE, up->unit);
- unlink(lockfile);
-
- peer->nextdate = current_time + WAIT;
-}
-
-
-#if 0
-/*
- * usno_write - write a message to the serial port
- */
-static int
-usno_write(
- struct peer *peer,
- const char *str
- )
-{
- register struct usnounit *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 usnounit *)pp->unitptr;
- len = strlen(str);
-#ifdef DEBUG
- if (debug)
- printf("usno: state %d send %d %s\n", up->state, len,
- str);
-#endif
- code = write(pp->io.fd, str, (unsigned)len) == len;
- code |= write(pp->io.fd, &cr, 1) == 1;
- if (!code)
- refclock_report(peer, CEVNT_FAULT);
- return (code);
-}
-#endif /* 0 */
-
-#else
-int refclock_usno_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_wwv.c b/contrib/ntp/ntpd/refclock_wwv.c
deleted file mode 100644
index 11aae7f..0000000
--- a/contrib/ntp/ntpd/refclock_wwv.c
+++ /dev/null
@@ -1,2859 +0,0 @@
-/*
- * refclock_wwv - clock driver for NIST WWV/H time/frequency station
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_WWV)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-#include "audio.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <math.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
-#define ICOM 1
-
-#ifdef ICOM
-#include "icom.h"
-#endif /* ICOM */
-
-/*
- * Audio WWV/H demodulator/decoder
- *
- * This driver synchronizes the computer time using data encoded in
- * radio transmissions from NIST time/frequency stations WWV in Boulder,
- * CO, and WWVH in Kauai, HI. Transmissions are made continuously on
- * 2.5, 5, 10, 15 and 20 MHz in AM mode. An ordinary shortwave receiver
- * can be tuned manually to one of these frequencies or, in the case of
- * ICOM receivers, the receiver can be tuned automatically using this
- * program as propagation conditions change throughout the day and
- * night.
- *
- * The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a workstation running Solaris, SunOS
- * FreeBSD or Linux, and with a little help, other workstations with
- * similar codecs or sound cards. In this implementation, only one audio
- * driver and codec can be supported on a single machine.
- *
- * The demodulation and decoding algorithms used in this driver are
- * based on those developed for the TAPR DSP93 development board and the
- * TI 320C25 digital signal processor described in: Mills, D.L. A
- * precision radio clock for WWV transmissions. Electrical Engineering
- * Report 97-8-1, University of Delaware, August 1997, 25 pp., available
- * from www.eecis.udel.edu/~mills/reports.htm. The algorithms described
- * in this report have been modified somewhat to improve performance
- * under weak signal conditions and to provide an automatic station
- * identification feature.
- *
- * The ICOM code is normally compiled in the driver. It isn't used,
- * unless the mode keyword on the server configuration command specifies
- * a nonzero ICOM ID select code. The C-IV trace is turned on if the
- * debug level is greater than one.
- */
-/*
- * Interface definitions
- */
-#define DEVICE_AUDIO "/dev/audio" /* audio device name */
-#define AUDIO_BUFSIZ 320 /* audio buffer size (50 ms) */
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#define DESCRIPTION "WWV/H Audio Demodulator/Decoder" /* WRU */
-#define SECOND 8000 /* second epoch (sample rate) (Hz) */
-#define MINUTE (SECOND * 60) /* minute epoch */
-#define OFFSET 128 /* companded sample offset */
-#define SIZE 256 /* decompanding table size */
-#define MAXSIG 6000. /* max signal level reference */
-#define MAXCLP 100 /* max clips above reference per s */
-#define MAXSNR 30. /* max SNR reference */
-#define DGAIN 20. /* data channel gain reference */
-#define SGAIN 10. /* sync channel gain reference */
-#define MAXFREQ 1. /* max frequency tolerance (125 PPM) */
-#define PI 3.1415926535 /* the real thing */
-#define DATSIZ (170 * MS) /* data matched filter size */
-#define SYNSIZ (800 * MS) /* minute sync matched filter size */
-#define MAXERR 30 /* max data bit errors in minute */
-#define NCHAN 5 /* number of radio channels */
-#define AUDIO_PHI 5e-6 /* dispersion growth factor */
-#ifdef IRIG_SUCKS
-#define WIGGLE 11 /* wiggle filter length */
-#endif /* IRIG_SUCKS */
-
-/*
- * General purpose status bits (status)
- *
- * SELV and/or SELH are set when WWV or WWVH has been heard and cleared
- * on signal loss. SSYNC is set when the second sync pulse has been
- * acquired and cleared by signal loss. MSYNC is set when the minute
- * sync pulse has been acquired. DSYNC is set when a digit reaches the
- * threshold and INSYNC is set when all nine digits have reached the
- * threshold. The MSYNC, DSYNC and INSYNC bits are cleared only by
- * timeout, upon which the driver starts over from scratch.
- *
- * DGATE is set if a data bit is invalid and BGATE is set if a BCD digit
- * bit is invalid. SFLAG is set when during seconds 59, 0 and 1 while
- * probing alternate frequencies. LEPDAY is set when SECWAR of the
- * timecode is set on 30 June or 31 December. LEPSEC is set during the
- * last minute of the day when LEPDAY is set. At the end of this minute
- * the driver inserts second 60 in the seconds state machine and the
- * minute sync slips a second. The SLOSS and SJITR bits are for monitor
- * only.
- */
-#define MSYNC 0x0001 /* minute epoch sync */
-#define SSYNC 0x0002 /* second epoch sync */
-#define DSYNC 0x0004 /* minute units sync */
-#define INSYNC 0x0008 /* clock synchronized */
-#define FGATE 0x0010 /* frequency gate */
-#define DGATE 0x0020 /* data bit error */
-#define BGATE 0x0040 /* BCD digit bit error */
-#define SFLAG 0x1000 /* probe flag */
-#define LEPDAY 0x2000 /* leap second day */
-#define LEPSEC 0x4000 /* leap second minute */
-
-/*
- * Station scoreboard bits
- *
- * These are used to establish the signal quality for each of the five
- * frequencies and two stations.
- */
-#define SYNCNG 0x0001 /* sync or SNR below threshold */
-#define DATANG 0x0002 /* data or SNR below threshold */
-#define ERRRNG 0x0004 /* data error */
-#define SELV 0x0100 /* WWV station select */
-#define SELH 0x0200 /* WWVH station select */
-
-/*
- * Alarm status bits (alarm)
- *
- * These bits indicate various alarm conditions, which are decoded to
- * form the quality character included in the timecode. If not tracking
- * second sync, the SYNERR alarm is raised. The data error counter is
- * incremented for each invalid data bit. If too many data bit errors
- * are encountered in one minute, the MODERR alarm is raised. The DECERR
- * alarm is raised if a maximum likelihood digit fails to compare with
- * the current clock digit. If the probability of any miscellaneous bit
- * or any digit falls below the threshold, the SYMERR alarm is raised.
- */
-#define DECERR 1 /* BCD digit compare error */
-#define SYMERR 2 /* low bit or digit probability */
-#define MODERR 4 /* too many data bit errors */
-#define SYNERR 8 /* not synchronized to station */
-
-/*
- * Watchcat timeouts (watch)
- *
- * If these timeouts expire, the status bits are mashed to zero and the
- * driver starts from scratch. Suitably more refined procedures may be
- * developed in future. All these are in minutes.
- */
-#define ACQSN 5 /* station acquisition timeout */
-#define DIGIT 30 /* minute unit digit timeout */
-#define HOLD 30 /* reachable timeout */
-#define PANIC (2 * 1440) /* panic timeout */
-
-/*
- * Thresholds. These establish the minimum signal level, minimum SNR and
- * maximum jitter thresholds which establish the error and false alarm
- * rates of the driver. The values defined here may be on the
- * adventurous side in the interest of the highest sensitivity.
- */
-#define MTHR 13. /* acquisition signal gate (percent) */
-#define TTHR 50. /* tracking signal gate (percent) */
-#define ATHR 2000. /* acquisition amplitude threshold */
-#define ASNR 6. /* acquisition SNR threshold (dB) */
-#define AWND 20. /* acquisition jitter threshold (ms) */
-#define AMIN 3 /* min bit count */
-#define AMAX 6 /* max bit count */
-#define QTHR 2000 /* QSY sync threshold */
-#define QSNR 20. /* QSY sync SNR threshold (dB) */
-#define XTHR 1000. /* QSY data threshold */
-#define XSNR 10. /* QSY data SNR threshold (dB) */
-#define STHR 500 /* second sync amplitude threshold */
-#define SSNR 10. /* second sync SNR threshold */
-#define SCMP 10 /* second sync compare threshold */
-#define DTHR 1000 /* bit amplitude threshold */
-#define DSNR 10. /* bit SNR threshold (dB) */
-#define BTHR 1000 /* digit amplitude threshold */
-#define BSNR 3. /* digit likelihood threshold (dB) */
-#define BCMP 5 /* digit compare threshold */
-
-/*
- * Tone frequency definitions. The increments are for 4.5-deg sine
- * table.
- */
-#define MS (SECOND / 1000) /* samples per millisecond */
-#define IN100 ((100 * 80) / SECOND) /* 100 Hz increment */
-#define IN1000 ((1000 * 80) / SECOND) /* 1000 Hz increment */
-#define IN1200 ((1200 * 80) / SECOND) /* 1200 Hz increment */
-
-/*
- * Acquisition and tracking time constants. Usually powers of 2.
- */
-#define MINAVG 8 /* min time constant */
-#define MAXAVG 1024 /* max time constant */
-#define TCONST 16 /* data bit/digit time constant */
-
-/*
- * Miscellaneous status bits (misc)
- *
- * These bits correspond to designated bits in the WWV/H timecode. The
- * bit probabilities are exponentially averaged over several minutes and
- * processed by a integrator and threshold.
- */
-#define DUT1 0x01 /* 56 DUT .1 */
-#define DUT2 0x02 /* 57 DUT .2 */
-#define DUT4 0x04 /* 58 DUT .4 */
-#define DUTS 0x08 /* 50 DUT sign */
-#define DST1 0x10 /* 55 DST1 leap warning */
-#define DST2 0x20 /* 2 DST2 DST1 delayed one day */
-#define SECWAR 0x40 /* 3 leap second warning */
-
-/*
- * The on-time synchronization point for the driver is the second epoch
- * sync pulse produced by the FIR matched filters. As the 5-ms delay of
- * these filters is compensated, the program delay is 1.1 ms due to the
- * 600-Hz IIR bandpass filter. The measured receiver delay is 4.7 ms and
- * the codec delay less than 0.2 ms. The additional propagation delay
- * specific to each receiver location can be programmed in the fudge
- * time1 and time2 values for WWV and WWVH, respectively.
- */
-#define PDELAY (.0011 + .0047 + .0002) /* net system delay (s) */
-
-/*
- * Table of sine values at 4.5-degree increments. This is used by the
- * synchronous matched filter demodulators. The integral of sine-squared
- * over one complete cycle is PI, so the table is normallized by 1 / PI.
- */
-double sintab[] = {
- 0.000000e+00, 2.497431e-02, 4.979464e-02, 7.430797e-02, /* 0-3 */
- 9.836316e-02, 1.218119e-01, 1.445097e-01, 1.663165e-01, /* 4-7 */
- 1.870979e-01, 2.067257e-01, 2.250791e-01, 2.420447e-01, /* 8-11 */
- 2.575181e-01, 2.714038e-01, 2.836162e-01, 2.940800e-01, /* 12-15 */
- 3.027307e-01, 3.095150e-01, 3.143910e-01, 3.173286e-01, /* 16-19 */
- 3.183099e-01, 3.173286e-01, 3.143910e-01, 3.095150e-01, /* 20-23 */
- 3.027307e-01, 2.940800e-01, 2.836162e-01, 2.714038e-01, /* 24-27 */
- 2.575181e-01, 2.420447e-01, 2.250791e-01, 2.067257e-01, /* 28-31 */
- 1.870979e-01, 1.663165e-01, 1.445097e-01, 1.218119e-01, /* 32-35 */
- 9.836316e-02, 7.430797e-02, 4.979464e-02, 2.497431e-02, /* 36-39 */
--0.000000e+00, -2.497431e-02, -4.979464e-02, -7.430797e-02, /* 40-43 */
--9.836316e-02, -1.218119e-01, -1.445097e-01, -1.663165e-01, /* 44-47 */
--1.870979e-01, -2.067257e-01, -2.250791e-01, -2.420447e-01, /* 48-51 */
--2.575181e-01, -2.714038e-01, -2.836162e-01, -2.940800e-01, /* 52-55 */
--3.027307e-01, -3.095150e-01, -3.143910e-01, -3.173286e-01, /* 56-59 */
--3.183099e-01, -3.173286e-01, -3.143910e-01, -3.095150e-01, /* 60-63 */
--3.027307e-01, -2.940800e-01, -2.836162e-01, -2.714038e-01, /* 64-67 */
--2.575181e-01, -2.420447e-01, -2.250791e-01, -2.067257e-01, /* 68-71 */
--1.870979e-01, -1.663165e-01, -1.445097e-01, -1.218119e-01, /* 72-75 */
--9.836316e-02, -7.430797e-02, -4.979464e-02, -2.497431e-02, /* 76-79 */
- 0.000000e+00}; /* 80 */
-
-/*
- * Decoder operations at the end of each second are driven by a state
- * machine. The transition matrix consists of a dispatch table indexed
- * by second number. Each entry in the table contains a case switch
- * number and argument.
- */
-struct progx {
- int sw; /* case switch number */
- int arg; /* argument */
-};
-
-/*
- * Case switch numbers
- */
-#define IDLE 0 /* no operation */
-#define COEF 1 /* BCD bit */
-#define COEF2 2 /* BCD bit ignored */
-#define DECIM9 3 /* BCD digit 0-9 */
-#define DECIM6 4 /* BCD digit 0-6 */
-#define DECIM3 5 /* BCD digit 0-3 */
-#define DECIM2 6 /* BCD digit 0-2 */
-#define MSCBIT 7 /* miscellaneous bit */
-#define MSC20 8 /* miscellaneous bit */
-#define MSC21 9 /* QSY probe channel */
-#define MIN1 10 /* minute */
-#define MIN2 11 /* leap second */
-#define SYNC2 12 /* QSY data channel */
-#define SYNC3 13 /* QSY data channel */
-
-/*
- * Offsets in decoding matrix
- */
-#define MN 0 /* minute digits (2) */
-#define HR 2 /* hour digits (2) */
-#define DA 4 /* day digits (3) */
-#define YR 7 /* year digits (2) */
-
-struct progx progx[] = {
- {SYNC2, 0}, /* 0 latch sync max */
- {SYNC3, 0}, /* 1 QSY data channel */
- {MSCBIT, DST2}, /* 2 dst2 */
- {MSCBIT, SECWAR}, /* 3 lw */
- {COEF, 0}, /* 4 1 year units */
- {COEF, 1}, /* 5 2 */
- {COEF, 2}, /* 6 4 */
- {COEF, 3}, /* 7 8 */
- {DECIM9, YR}, /* 8 */
- {IDLE, 0}, /* 9 p1 */
- {COEF, 0}, /* 10 1 minute units */
- {COEF, 1}, /* 11 2 */
- {COEF, 2}, /* 12 4 */
- {COEF, 3}, /* 13 8 */
- {DECIM9, MN}, /* 14 */
- {COEF, 0}, /* 15 10 minute tens */
- {COEF, 1}, /* 16 20 */
- {COEF, 2}, /* 17 40 */
- {COEF2, 3}, /* 18 80 (not used) */
- {DECIM6, MN + 1}, /* 19 p2 */
- {COEF, 0}, /* 20 1 hour units */
- {COEF, 1}, /* 21 2 */
- {COEF, 2}, /* 22 4 */
- {COEF, 3}, /* 23 8 */
- {DECIM9, HR}, /* 24 */
- {COEF, 0}, /* 25 10 hour tens */
- {COEF, 1}, /* 26 20 */
- {COEF2, 2}, /* 27 40 (not used) */
- {COEF2, 3}, /* 28 80 (not used) */
- {DECIM2, HR + 1}, /* 29 p3 */
- {COEF, 0}, /* 30 1 day units */
- {COEF, 1}, /* 31 2 */
- {COEF, 2}, /* 32 4 */
- {COEF, 3}, /* 33 8 */
- {DECIM9, DA}, /* 34 */
- {COEF, 0}, /* 35 10 day tens */
- {COEF, 1}, /* 36 20 */
- {COEF, 2}, /* 37 40 */
- {COEF, 3}, /* 38 80 */
- {DECIM9, DA + 1}, /* 39 p4 */
- {COEF, 0}, /* 40 100 day hundreds */
- {COEF, 1}, /* 41 200 */
- {COEF2, 2}, /* 42 400 (not used) */
- {COEF2, 3}, /* 43 800 (not used) */
- {DECIM3, DA + 2}, /* 44 */
- {IDLE, 0}, /* 45 */
- {IDLE, 0}, /* 46 */
- {IDLE, 0}, /* 47 */
- {IDLE, 0}, /* 48 */
- {IDLE, 0}, /* 49 p5 */
- {MSCBIT, DUTS}, /* 50 dut+- */
- {COEF, 0}, /* 51 10 year tens */
- {COEF, 1}, /* 52 20 */
- {COEF, 2}, /* 53 40 */
- {COEF, 3}, /* 54 80 */
- {MSC20, DST1}, /* 55 dst1 */
- {MSCBIT, DUT1}, /* 56 0.1 dut */
- {MSCBIT, DUT2}, /* 57 0.2 */
- {MSC21, DUT4}, /* 58 0.4 QSY probe channel */
- {MIN1, 0}, /* 59 p6 latch sync min */
- {MIN2, 0} /* 60 leap second */
-};
-
-/*
- * BCD coefficients for maximum likelihood digit decode
- */
-#define P15 1. /* max positive number */
-#define N15 -1. /* max negative number */
-
-/*
- * Digits 0-9
- */
-#define P9 (P15 / 4) /* mark (+1) */
-#define N9 (N15 / 4) /* space (-1) */
-
-double bcd9[][4] = {
- {N9, N9, N9, N9}, /* 0 */
- {P9, N9, N9, N9}, /* 1 */
- {N9, P9, N9, N9}, /* 2 */
- {P9, P9, N9, N9}, /* 3 */
- {N9, N9, P9, N9}, /* 4 */
- {P9, N9, P9, N9}, /* 5 */
- {N9, P9, P9, N9}, /* 6 */
- {P9, P9, P9, N9}, /* 7 */
- {N9, N9, N9, P9}, /* 8 */
- {P9, N9, N9, P9}, /* 9 */
- {0, 0, 0, 0} /* backstop */
-};
-
-/*
- * Digits 0-6 (minute tens)
- */
-#define P6 (P15 / 3) /* mark (+1) */
-#define N6 (N15 / 3) /* space (-1) */
-
-double bcd6[][4] = {
- {N6, N6, N6, 0}, /* 0 */
- {P6, N6, N6, 0}, /* 1 */
- {N6, P6, N6, 0}, /* 2 */
- {P6, P6, N6, 0}, /* 3 */
- {N6, N6, P6, 0}, /* 4 */
- {P6, N6, P6, 0}, /* 5 */
- {N6, P6, P6, 0}, /* 6 */
- {0, 0, 0, 0} /* backstop */
-};
-
-/*
- * Digits 0-3 (day hundreds)
- */
-#define P3 (P15 / 2) /* mark (+1) */
-#define N3 (N15 / 2) /* space (-1) */
-
-double bcd3[][4] = {
- {N3, N3, 0, 0}, /* 0 */
- {P3, N3, 0, 0}, /* 1 */
- {N3, P3, 0, 0}, /* 2 */
- {P3, P3, 0, 0}, /* 3 */
- {0, 0, 0, 0} /* backstop */
-};
-
-/*
- * Digits 0-2 (hour tens)
- */
-#define P2 (P15 / 2) /* mark (+1) */
-#define N2 (N15 / 2) /* space (-1) */
-
-double bcd2[][4] = {
- {N2, N2, 0, 0}, /* 0 */
- {P2, N2, 0, 0}, /* 1 */
- {N2, P2, 0, 0}, /* 2 */
- {0, 0, 0, 0} /* backstop */
-};
-
-/*
- * DST decode (DST2 DST1) for prettyprint
- */
-char dstcod[] = {
- 'S', /* 00 standard time */
- 'I', /* 01 set clock ahead at 0200 local */
- 'O', /* 10 set clock back at 0200 local */
- 'D' /* 11 daylight time */
-};
-
-/*
- * The decoding matrix consists of nine row vectors, one for each digit
- * of the timecode. The digits are stored from least to most significant
- * order. The maximum likelihood timecode is formed from the digits
- * corresponding to the maximum likelihood values reading in the
- * opposite order: yy ddd hh:mm.
- */
-struct decvec {
- int radix; /* radix (3, 4, 6, 10) */
- int digit; /* current clock digit */
- int mldigit; /* maximum likelihood digit */
- int phase; /* maximum likelihood digit phase */
- int count; /* match count */
- double digprb; /* max digit probability */
- double digsnr; /* likelihood function (dB) */
- double like[10]; /* likelihood integrator 0-9 */
-};
-
-/*
- * The station structure is used to acquire the minute pulse from WWV
- * and/or WWVH. These stations are distinguished by the frequency used
- * for the second and minute sync pulses, 1000 Hz for WWV and 1200 Hz
- * for WWVH. Other than frequency, the format is the same.
- */
-struct sync {
- double epoch; /* accumulated epoch differences */
- double maxamp; /* sync max envelope (square) */
- double noiamp; /* sync noise envelope (square) */
- long pos; /* max amplitude position */
- long lastpos; /* last max position */
- long mepoch; /* minute synch epoch */
-
- double amp; /* sync amplitude (I, Q squares) */
- double synamp; /* sync max envelope at 800 ms */
- double synmax; /* sync envelope at 0 s */
- double synmin; /* sync envelope at 59, 1 s */
- double synsnr; /* sync signal SNR */
- int count; /* bit counter */
- char refid[5]; /* reference identifier */
- int select; /* select bits */
- int reach; /* reachability register */
-};
-
-/*
- * The channel structure is used to mitigate between channels.
- */
-struct chan {
- int gain; /* audio gain */
- double sigamp; /* data max envelope (square) */
- double noiamp; /* data noise envelope (square) */
- double datsnr; /* data signal SNR */
- struct sync wwv; /* wwv station */
- struct sync wwvh; /* wwvh station */
-};
-
-/*
- * WWV unit control structure
- */
-struct wwvunit {
- l_fp timestamp; /* audio sample timestamp */
- l_fp tick; /* audio sample increment */
- double phase, freq; /* logical clock phase and frequency */
- double monitor; /* audio monitor point */
- int fd_icom; /* ICOM file descriptor */
- int errflg; /* error flags */
- int watch; /* watchcat */
-
- /*
- * Audio codec variables
- */
- double comp[SIZE]; /* decompanding table */
- int port; /* codec port */
- int gain; /* codec gain */
- int mongain; /* codec monitor gain */
- int clipcnt; /* sample clipped count */
-#ifdef IRIG_SUCKS
- l_fp wigwag; /* wiggle accumulator */
- int wp; /* wiggle filter pointer */
- l_fp wiggle[WIGGLE]; /* wiggle filter */
- l_fp wigbot[WIGGLE]; /* wiggle bottom fisher*/
-#endif /* IRIG_SUCKS */
-
- /*
- * Variables used to establish basic system timing
- */
- int avgint; /* master time constant */
- int tepoch; /* sync epoch median */
- int yepoch; /* sync epoch */
- int repoch; /* buffered sync epoch */
- double epomax; /* second sync amplitude */
- double eposnr; /* second sync SNR */
- double irig; /* data I channel amplitude */
- double qrig; /* data Q channel amplitude */
- int datapt; /* 100 Hz ramp */
- double datpha; /* 100 Hz VFO control */
- int rphase; /* second sample counter */
- long mphase; /* minute sample counter */
-
- /*
- * Variables used to mitigate which channel to use
- */
- struct chan mitig[NCHAN]; /* channel data */
- struct sync *sptr; /* station pointer */
- int dchan; /* data channel */
- int schan; /* probe channel */
- int achan; /* active channel */
-
- /*
- * Variables used by the clock state machine
- */
- struct decvec decvec[9]; /* decoding matrix */
- int rsec; /* seconds counter */
- int digcnt; /* count of digits synchronized */
-
- /*
- * Variables used to estimate signal levels and bit/digit
- * probabilities
- */
- double sigsig; /* data max signal */
- double sigamp; /* data max envelope (square) */
- double noiamp; /* data noise envelope (square) */
- double datsnr; /* data SNR (dB) */
-
- /*
- * Variables used to establish status and alarm conditions
- */
- int status; /* status bits */
- int alarm; /* alarm flashers */
- int misc; /* miscellaneous timecode bits */
- int errcnt; /* data bit error counter */
- int errbit; /* data bit errors in minute */
-};
-
-/*
- * Function prototypes
- */
-static int wwv_start P((int, struct peer *));
-static void wwv_shutdown P((int, struct peer *));
-static void wwv_receive P((struct recvbuf *));
-static void wwv_poll P((int, struct peer *));
-
-/*
- * More function prototypes
- */
-static void wwv_epoch P((struct peer *));
-static void wwv_rf P((struct peer *, double));
-static void wwv_endpoc P((struct peer *, int));
-static void wwv_rsec P((struct peer *, double));
-static void wwv_qrz P((struct peer *, struct sync *,
- double, int));
-static void wwv_corr4 P((struct peer *, struct decvec *,
- double [], double [][4]));
-static void wwv_gain P((struct peer *));
-static void wwv_tsec P((struct wwvunit *));
-static double wwv_data P((struct wwvunit *, double));
-static int timecode P((struct wwvunit *, char *));
-static double wwv_snr P((double, double));
-static int carry P((struct decvec *));
-static void wwv_newchan P((struct peer *));
-static void wwv_newgame P((struct peer *));
-static double wwv_metric P((struct sync *));
-#ifdef ICOM
-static int wwv_qsy P((struct peer *, int));
-#endif /* ICOM */
-
-static double qsy[NCHAN] = {2.5, 5, 10, 15, 20}; /* frequencies (MHz) */
-
-/*
- * Transfer vector
- */
-struct refclock refclock_wwv = {
- wwv_start, /* start up driver */
- wwv_shutdown, /* shut down driver */
- wwv_poll, /* transmit poll message */
- noentry, /* not used (old wwv_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old wwv_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-/*
- * wwv_start - open the devices and initialize data for processing
- */
-static int
-wwv_start(
- int unit, /* instance number (used by PCM) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
-#ifdef ICOM
- int temp;
-#endif /* ICOM */
-
- /*
- * Local variables
- */
- int fd; /* file descriptor */
- int i; /* index */
- double step; /* codec adjustment */
-
- /*
- * Open audio device
- */
- fd = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
- if (fd < 0)
- return (0);
-#ifdef DEBUG
- if (debug)
- audio_show();
-#endif
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct wwvunit *)emalloc(sizeof(struct wwvunit)))) {
- close(fd);
- return (0);
- }
- memset(up, 0, sizeof(struct wwvunit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- pp->io.clock_recv = wwv_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
- close(fd);
- free(up);
- return (0);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
-
- /*
- * The companded samples are encoded sign-magnitude. The table
- * contains all the 256 values in the interest of speed.
- */
- up->comp[0] = up->comp[OFFSET] = 0.;
- up->comp[1] = 1; up->comp[OFFSET + 1] = -1.;
- up->comp[2] = 3; up->comp[OFFSET + 2] = -3.;
- step = 2.;
- for (i = 3; i < OFFSET; i++) {
- up->comp[i] = up->comp[i - 1] + step;
- up->comp[OFFSET + i] = -up->comp[i];
- if (i % 16 == 0)
- step *= 2.;
- }
- DTOLFP(1. / SECOND, &up->tick);
-
- /*
- * Initialize the decoding matrix with the radix for each digit
- * position.
- */
- up->decvec[MN].radix = 10; /* minutes */
- up->decvec[MN + 1].radix = 6;
- up->decvec[HR].radix = 10; /* hours */
- up->decvec[HR + 1].radix = 3;
- up->decvec[DA].radix = 10; /* days */
- up->decvec[DA + 1].radix = 10;
- up->decvec[DA + 2].radix = 4;
- up->decvec[YR].radix = 10; /* years */
- up->decvec[YR + 1].radix = 10;
- wwv_newgame(peer);
- up->schan = up->achan = 3;
-
- /*
- * Initialize autotune if available. Start out at 15 MHz. Note
- * that the ICOM select code must be less than 128, so the high
- * order bit can be used to select the line speed.
- */
-#ifdef ICOM
- temp = 0;
-#ifdef DEBUG
- if (debug > 1)
- temp = P_TRACE;
-#endif
- if (peer->ttl != 0) {
- if (peer->ttl & 0x80)
- up->fd_icom = icom_init("/dev/icom", B1200,
- temp);
- else
- up->fd_icom = icom_init("/dev/icom", B9600,
- temp);
- }
- if (up->fd_icom > 0) {
- if ((temp = wwv_qsy(peer, up->schan)) != 0) {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: radio not found");
- up->errflg = CEVNT_FAULT;
- close(up->fd_icom);
- up->fd_icom = 0;
- } else {
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "icom: autotune enabled");
- }
- }
-#endif /* ICOM */
- return (1);
-}
-
-
-/*
- * wwv_shutdown - shut down the clock
- */
-static void
-wwv_shutdown(
- int unit, /* instance number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
- io_closeclock(&pp->io);
- if (up->fd_icom > 0)
- close(up->fd_icom);
- free(up);
-}
-
-
-/*
- * wwv_receive - receive data from the audio device
- *
- * This routine reads input samples and adjusts the logical clock to
- * track the A/D sample clock by dropping or duplicating codec samples.
- * It also controls the A/D signal level with an AGC loop to mimimize
- * quantization noise and avoid overload.
- */
-static void
-wwv_receive(
- struct recvbuf *rbufp /* receive buffer structure pointer */
- )
-{
- struct peer *peer;
- struct refclockproc *pp;
- struct wwvunit *up;
-
- /*
- * Local variables
- */
- double sample; /* codec sample */
- u_char *dpt; /* buffer pointer */
- int bufcnt; /* buffer counter */
- l_fp ltemp;
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- /*
- * Main loop - read until there ain't no more. Note codec
- * samples are bit-inverted.
- */
- DTOLFP((double)rbufp->recv_length / SECOND, &ltemp);
- L_SUB(&rbufp->recv_time, &ltemp);
- up->timestamp = rbufp->recv_time;
- dpt = rbufp->recv_buffer;
- for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
- sample = up->comp[~*dpt++ & 0xff];
-
- /*
- * Clip noise spikes greater than MAXSIG. If no clips,
- * increase the gain a tad; if the clips are too high,
- * decrease a tad.
- */
- if (sample > MAXSIG) {
- sample = MAXSIG;
- up->clipcnt++;
- } else if (sample < -MAXSIG) {
- sample = -MAXSIG;
- up->clipcnt++;
- }
-
- /*
- * Variable frequency oscillator. The codec oscillator
- * runs at the nominal rate of 8000 samples per second,
- * or 125 us per sample. A frequency change of one unit
- * results in either duplicating or deleting one sample
- * per second, which results in a frequency change of
- * 125 PPM.
- */
- up->phase += up->freq / SECOND;
- if (up->phase >= .5) {
- up->phase -= 1.;
- } else if (up->phase < -.5) {
- up->phase += 1.;
- wwv_rf(peer, sample);
- wwv_rf(peer, sample);
- } else {
- wwv_rf(peer, sample);
- }
- L_ADD(&up->timestamp, &up->tick);
- }
-
- /*
- * Set the input port and monitor gain for the next buffer.
- */
- if (pp->sloppyclockflag & CLK_FLAG2)
- up->port = 2;
- else
- up->port = 1;
- if (pp->sloppyclockflag & CLK_FLAG3)
- up->mongain = MONGAIN;
- else
- up->mongain = 0;
-}
-
-
-/*
- * wwv_poll - called by the transmit procedure
- *
- * This routine keeps track of status. If no offset samples have been
- * processed during a poll interval, a timeout event is declared. If
- * errors have have occurred during the interval, they are reported as
- * well. Once the clock is set, it always appears reachable, unless
- * reset by watchdog timeout.
- */
-static void
-wwv_poll(
- int unit, /* instance number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
- if (pp->coderecv == pp->codeproc)
- up->errflg = CEVNT_TIMEOUT;
- if (up->errflg)
- refclock_report(peer, up->errflg);
- up->errflg = 0;
- pp->polls++;
-}
-
-
-/*
- * wwv_rf - process signals and demodulate to baseband
- *
- * This routine grooms and filters decompanded raw audio samples. The
- * output signals include the 100-Hz baseband data signal in quadrature
- * form, plus the epoch index of the second sync signal and the second
- * index of the minute sync signal.
- *
- * There are two 1-s ramps used by this program. Both count the 8000
- * logical clock samples spanning exactly one second. The epoch ramp
- * counts the samples starting at an arbitrary time. The rphase ramp
- * counts the samples starting at the 5-ms second sync pulse found
- * during the epoch ramp.
- *
- * There are two 1-m ramps used by this program. The mphase ramp counts
- * the 480,000 logical clock samples spanning exactly one minute and
- * starting at an arbitrary time. The rsec ramp counts the 60 seconds of
- * the minute starting at the 800-ms minute sync pulse found during the
- * mphase ramp. The rsec ramp drives the seconds state machine to
- * determine the bits and digits of the timecode.
- *
- * Demodulation operations are based on three synthesized quadrature
- * sinusoids: 100 Hz for the data signal, 1000 Hz for the WWV sync
- * signal and 1200 Hz for the WWVH sync signal. These drive synchronous
- * matched filters for the data signal (170 ms at 100 Hz), WWV minute
- * sync signal (800 ms at 1000 Hz) and WWVH minute sync signal (800 ms
- * at 1200 Hz). Two additional matched filters are switched in
- * as required for the WWV second sync signal (5 ms at 1000 Hz) and
- * WWVH second sync signal (5 ms at 1200 Hz).
- */
-static void
-wwv_rf(
- struct peer *peer, /* peerstructure pointer */
- double isig /* input signal */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
- struct sync *sp;
-
- static double lpf[5]; /* 150-Hz lpf delay line */
- double data; /* lpf output */
- static double bpf[9]; /* 1000/1200-Hz bpf delay line */
- double syncx; /* bpf output */
- static double mf[41]; /* 1000/1200-Hz mf delay line */
- double mfsync; /* mf output */
-
- static int iptr; /* data channel pointer */
- static double ibuf[DATSIZ]; /* data I channel delay line */
- static double qbuf[DATSIZ]; /* data Q channel delay line */
-
- static int jptr; /* sync channel pointer */
- static double cibuf[SYNSIZ]; /* wwv I channel delay line */
- static double cqbuf[SYNSIZ]; /* wwv Q channel delay line */
- static double ciamp; /* wwv I channel amplitude */
- static double cqamp; /* wwv Q channel amplitude */
- static int csinptr; /* wwv channel phase */
- static double hibuf[SYNSIZ]; /* wwvh I channel delay line */
- static double hqbuf[SYNSIZ]; /* wwvh Q channel delay line */
- static double hiamp; /* wwvh I channel amplitude */
- static double hqamp; /* wwvh Q channel amplitude */
- static int hsinptr; /* wwvh channels phase */
-
- static double epobuf[SECOND]; /* epoch sync comb filter */
- static double epomax; /* epoch sync amplitude buffer */
- static int epopos; /* epoch sync position buffer */
-
- static int iniflg; /* initialization flag */
- int epoch; /* comb filter index */
- int pdelay; /* propagation delay (samples) */
- double dtemp;
- int i;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- if (!iniflg) {
- iniflg = 1;
- memset((char *)lpf, 0, sizeof(lpf));
- memset((char *)bpf, 0, sizeof(bpf));
- memset((char *)mf, 0, sizeof(mf));
- memset((char *)ibuf, 0, sizeof(ibuf));
- memset((char *)qbuf, 0, sizeof(qbuf));
- memset((char *)cibuf, 0, sizeof(cibuf));
- memset((char *)cqbuf, 0, sizeof(cqbuf));
- memset((char *)hibuf, 0, sizeof(hibuf));
- memset((char *)hqbuf, 0, sizeof(hqbuf));
- memset((char *)epobuf, 0, sizeof(epobuf));
- }
-
- /*
- * Baseband data demodulation. The 100-Hz subcarrier is
- * extracted using a 150-Hz IIR lowpass filter. This attenuates
- * the 1000/1200-Hz sync signals, as well as the 440-Hz and
- * 600-Hz tones and most of the noise and voice modulation
- * components.
- *
- * Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB
- * passband ripple, -50 dB stopband ripple.
- */
- data = (lpf[4] = lpf[3]) * 8.360961e-01;
- data += (lpf[3] = lpf[2]) * -3.481740e+00;
- data += (lpf[2] = lpf[1]) * 5.452988e+00;
- data += (lpf[1] = lpf[0]) * -3.807229e+00;
- lpf[0] = isig - data;
- data = lpf[0] * 3.281435e-03
- + lpf[1] * -1.149947e-02
- + lpf[2] * 1.654858e-02
- + lpf[3] * -1.149947e-02
- + lpf[4] * 3.281435e-03;
-
- /*
- * The I and Q quadrature data signals are produced by
- * multiplying the filtered signal by 100-Hz sine and cosine
- * signals, respectively. The data signals are demodulated by
- * 170-ms synchronous matched filters to produce the amplitude
- * and phase signals used by the decoder.
- */
- i = up->datapt;
- up->datapt = (up->datapt + IN100) % 80;
- dtemp = sintab[i] * data / DATSIZ * DGAIN;
- up->irig -= ibuf[iptr];
- ibuf[iptr] = dtemp;
- up->irig += dtemp;
- i = (i + 20) % 80;
- dtemp = sintab[i] * data / DATSIZ * DGAIN;
- up->qrig -= qbuf[iptr];
- qbuf[iptr] = dtemp;
- up->qrig += dtemp;
- iptr = (iptr + 1) % DATSIZ;
-
- /*
- * Baseband sync demodulation. The 1000/1200 sync signals are
- * extracted using a 600-Hz IIR bandpass filter. This removes
- * the 100-Hz data subcarrier, as well as the 440-Hz and 600-Hz
- * tones and most of the noise and voice modulation components.
- *
- * Matlab 4th-order IIR elliptic, 800-1400 Hz bandpass, 0.2 dB
- * passband ripple, -50 dB stopband ripple.
- */
- syncx = (bpf[8] = bpf[7]) * 4.897278e-01;
- syncx += (bpf[7] = bpf[6]) * -2.765914e+00;
- syncx += (bpf[6] = bpf[5]) * 8.110921e+00;
- syncx += (bpf[5] = bpf[4]) * -1.517732e+01;
- syncx += (bpf[4] = bpf[3]) * 1.975197e+01;
- syncx += (bpf[3] = bpf[2]) * -1.814365e+01;
- syncx += (bpf[2] = bpf[1]) * 1.159783e+01;
- syncx += (bpf[1] = bpf[0]) * -4.735040e+00;
- bpf[0] = isig - syncx;
- syncx = bpf[0] * 8.203628e-03
- + bpf[1] * -2.375732e-02
- + bpf[2] * 3.353214e-02
- + bpf[3] * -4.080258e-02
- + bpf[4] * 4.605479e-02
- + bpf[5] * -4.080258e-02
- + bpf[6] * 3.353214e-02
- + bpf[7] * -2.375732e-02
- + bpf[8] * 8.203628e-03;
-
- /*
- * The I and Q quadrature minute sync signals are produced by
- * multiplying the filtered signal by 1000-Hz (WWV) and 1200-Hz
- * (WWVH) sine and cosine signals, respectively. The resulting
- * signals are demodulated by 800-ms synchronous matched filters
- * to synchronize the second and minute and to detect which one
- * (or both) the WWV or WWVH signal is present.
- *
- * Note the master timing ramps, which run continuously. The
- * minute counter (mphase) counts the samples in the minute,
- * while the second counter (epoch) counts the samples in the
- * second.
- */
- up->mphase = (up->mphase + 1) % MINUTE;
- epoch = up->mphase % SECOND;
- i = csinptr;
- csinptr = (csinptr + IN1000) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- ciamp = ciamp - cibuf[jptr] + dtemp;
- cibuf[jptr] = dtemp;
- i = (i + 20) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- cqamp = cqamp - cqbuf[jptr] + dtemp;
- cqbuf[jptr] = dtemp;
- sp = &up->mitig[up->schan].wwv;
- dtemp = ciamp * ciamp + cqamp * cqamp;
- sp->amp = dtemp;
- if (!(up->status & MSYNC))
- wwv_qrz(peer, sp, dtemp, (int)(pp->fudgetime1 *
- SECOND));
- i = hsinptr;
- hsinptr = (hsinptr + IN1200) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- hiamp = hiamp - hibuf[jptr] + dtemp;
- hibuf[jptr] = dtemp;
- i = (i + 20) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- hqamp = hqamp - hqbuf[jptr] + dtemp;
- hqbuf[jptr] = dtemp;
- sp = &up->mitig[up->schan].wwvh;
- dtemp = hiamp * hiamp + hqamp * hqamp;
- sp->amp = dtemp;
- if (!(up->status & MSYNC))
- wwv_qrz(peer, sp, dtemp, (int)(pp->fudgetime2 *
- SECOND));
- jptr = (jptr + 1) % SYNSIZ;
-
- /*
- * The following section is called once per minute. It does
- * housekeeping and timeout functions and empties the dustbins.
- */
- if (up->mphase == 0) {
- up->watch++;
- if (!(up->status & MSYNC)) {
-
- /*
- * If minute sync has not been acquired before
- * timeout, or if no signal is heard, the
- * program cycles to the next frequency and
- * tries again.
- */
- wwv_newchan(peer);
- if (!(up->status & (SELV | SELH)) || up->watch >
- ACQSN) {
- wwv_newgame(peer);
-#ifdef ICOM
- if (up->fd_icom > 0) {
- up->schan = (up->schan + 1) %
- NCHAN;
- wwv_qsy(peer, up->schan);
- }
-#endif /* ICOM */
- }
- } else {
-
- /*
- * If the leap bit is set, set the minute epoch
- * back one second so the station processes
- * don't miss a beat.
- */
- if (up->status & LEPSEC) {
- up->mphase -= SECOND;
- if (up->mphase < 0)
- up->mphase += MINUTE;
- }
- }
- }
-
- /*
- * When the channel metric reaches threshold and the second
- * counter matches the minute epoch within the second, the
- * driver has synchronized to the station. The second number is
- * the remaining seconds until the next minute epoch, while the
- * sync epoch is zero. Watch out for the first second; if
- * already synchronized to the second, the buffered sync epoch
- * must be set.
- */
- if (up->status & MSYNC) {
- wwv_epoch(peer);
- } else if ((sp = up->sptr) != NULL) {
- struct chan *cp;
-
- if (sp->count >= AMIN && epoch == sp->mepoch % SECOND) {
- up->rsec = 60 - sp->mepoch / SECOND;
- up->rphase = 0;
- up->status |= MSYNC;
- up->watch = 0;
- if (!(up->status & SSYNC))
- up->repoch = up->yepoch = epoch;
- else
- up->repoch = up->yepoch;
- for (i = 0; i < NCHAN; i++) {
- cp = &up->mitig[i];
- cp->wwv.count = cp->wwv.reach = 0;
- cp->wwvh.count = cp->wwvh.reach = 0;
- }
- }
- }
-
- /*
- * The second sync pulse is extracted using 5-ms (40 sample) FIR
- * matched filters at 1000 Hz for WWV or 1200 Hz for WWVH. This
- * pulse is used for the most precise synchronization, since if
- * provides a resolution of one sample (125 us). The filters run
- * only if the station has been reliably determined.
- */
- if (up->status & SELV) {
- pdelay = (int)(pp->fudgetime1 * SECOND);
-
- /*
- * WWV FIR matched filter, five cycles of 1000-Hz
- * sinewave.
- */
- mf[40] = mf[39];
- mfsync = (mf[39] = mf[38]) * 4.224514e-02;
- mfsync += (mf[38] = mf[37]) * 5.974365e-02;
- mfsync += (mf[37] = mf[36]) * 4.224514e-02;
- mf[36] = mf[35];
- mfsync += (mf[35] = mf[34]) * -4.224514e-02;
- mfsync += (mf[34] = mf[33]) * -5.974365e-02;
- mfsync += (mf[33] = mf[32]) * -4.224514e-02;
- mf[32] = mf[31];
- mfsync += (mf[31] = mf[30]) * 4.224514e-02;
- mfsync += (mf[30] = mf[29]) * 5.974365e-02;
- mfsync += (mf[29] = mf[28]) * 4.224514e-02;
- mf[28] = mf[27];
- mfsync += (mf[27] = mf[26]) * -4.224514e-02;
- mfsync += (mf[26] = mf[25]) * -5.974365e-02;
- mfsync += (mf[25] = mf[24]) * -4.224514e-02;
- mf[24] = mf[23];
- mfsync += (mf[23] = mf[22]) * 4.224514e-02;
- mfsync += (mf[22] = mf[21]) * 5.974365e-02;
- mfsync += (mf[21] = mf[20]) * 4.224514e-02;
- mf[20] = mf[19];
- mfsync += (mf[19] = mf[18]) * -4.224514e-02;
- mfsync += (mf[18] = mf[17]) * -5.974365e-02;
- mfsync += (mf[17] = mf[16]) * -4.224514e-02;
- mf[16] = mf[15];
- mfsync += (mf[15] = mf[14]) * 4.224514e-02;
- mfsync += (mf[14] = mf[13]) * 5.974365e-02;
- mfsync += (mf[13] = mf[12]) * 4.224514e-02;
- mf[12] = mf[11];
- mfsync += (mf[11] = mf[10]) * -4.224514e-02;
- mfsync += (mf[10] = mf[9]) * -5.974365e-02;
- mfsync += (mf[9] = mf[8]) * -4.224514e-02;
- mf[8] = mf[7];
- mfsync += (mf[7] = mf[6]) * 4.224514e-02;
- mfsync += (mf[6] = mf[5]) * 5.974365e-02;
- mfsync += (mf[5] = mf[4]) * 4.224514e-02;
- mf[4] = mf[3];
- mfsync += (mf[3] = mf[2]) * -4.224514e-02;
- mfsync += (mf[2] = mf[1]) * -5.974365e-02;
- mfsync += (mf[1] = mf[0]) * -4.224514e-02;
- mf[0] = syncx;
- } else if (up->status & SELH) {
- pdelay = (int)(pp->fudgetime2 * SECOND);
-
- /*
- * WWVH FIR matched filter, six cycles of 1200-Hz
- * sinewave.
- */
- mf[40] = mf[39];
- mfsync = (mf[39] = mf[38]) * 4.833363e-02;
- mfsync += (mf[38] = mf[37]) * 5.681959e-02;
- mfsync += (mf[37] = mf[36]) * 1.846180e-02;
- mfsync += (mf[36] = mf[35]) * -3.511644e-02;
- mfsync += (mf[35] = mf[34]) * -5.974365e-02;
- mfsync += (mf[34] = mf[33]) * -3.511644e-02;
- mfsync += (mf[33] = mf[32]) * 1.846180e-02;
- mfsync += (mf[32] = mf[31]) * 5.681959e-02;
- mfsync += (mf[31] = mf[30]) * 4.833363e-02;
- mf[30] = mf[29];
- mfsync += (mf[29] = mf[28]) * -4.833363e-02;
- mfsync += (mf[28] = mf[27]) * -5.681959e-02;
- mfsync += (mf[27] = mf[26]) * -1.846180e-02;
- mfsync += (mf[26] = mf[25]) * 3.511644e-02;
- mfsync += (mf[25] = mf[24]) * 5.974365e-02;
- mfsync += (mf[24] = mf[23]) * 3.511644e-02;
- mfsync += (mf[23] = mf[22]) * -1.846180e-02;
- mfsync += (mf[22] = mf[21]) * -5.681959e-02;
- mfsync += (mf[21] = mf[20]) * -4.833363e-02;
- mf[20] = mf[19];
- mfsync += (mf[19] = mf[18]) * 4.833363e-02;
- mfsync += (mf[18] = mf[17]) * 5.681959e-02;
- mfsync += (mf[17] = mf[16]) * 1.846180e-02;
- mfsync += (mf[16] = mf[15]) * -3.511644e-02;
- mfsync += (mf[15] = mf[14]) * -5.974365e-02;
- mfsync += (mf[14] = mf[13]) * -3.511644e-02;
- mfsync += (mf[13] = mf[12]) * 1.846180e-02;
- mfsync += (mf[12] = mf[11]) * 5.681959e-02;
- mfsync += (mf[11] = mf[10]) * 4.833363e-02;
- mf[10] = mf[9];
- mfsync += (mf[9] = mf[8]) * -4.833363e-02;
- mfsync += (mf[8] = mf[7]) * -5.681959e-02;
- mfsync += (mf[7] = mf[6]) * -1.846180e-02;
- mfsync += (mf[6] = mf[5]) * 3.511644e-02;
- mfsync += (mf[5] = mf[4]) * 5.974365e-02;
- mfsync += (mf[4] = mf[3]) * 3.511644e-02;
- mfsync += (mf[3] = mf[2]) * -1.846180e-02;
- mfsync += (mf[2] = mf[1]) * -5.681959e-02;
- mfsync += (mf[1] = mf[0]) * -4.833363e-02;
- mf[0] = syncx;
- } else {
- mfsync = 0;
- pdelay = 0;
- }
-
- /*
- * Enhance the seconds sync pulse using a 1-s (8000-sample) comb
- * filter. Correct for the FIR matched filter delay, which is 5
- * ms for both the WWV and WWVH filters, and also for the
- * propagation delay. Once each second look for second sync. If
- * not in minute sync, fiddle the codec gain. Note the SNR is
- * computed from the maximum sample and the two samples 6 ms
- * before and 6 ms after it, so if we slip more than a cycle the
- * SNR should plummet.
- */
- dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) /
- up->avgint);
- if (dtemp > epomax) {
- epomax = dtemp;
- epopos = epoch;
- }
- if (epoch == 0) {
- int k, j;
-
- up->epomax = epomax;
- k = epopos - 6 * MS;
- if (k < 0)
- k += SECOND;
- j = epopos + 6 * MS;
- if (j >= SECOND)
- i -= SECOND;
- up->eposnr = wwv_snr(epomax, max(abs(epobuf[k]),
- abs(epobuf[j])));
- epopos -= pdelay + 5 * MS;
- if (epopos < 0)
- epopos += SECOND;
- wwv_endpoc(peer, epopos);
- if (!(up->status & SSYNC))
- up->alarm |= SYNERR;
- epomax = 0;
- if (!(up->status & MSYNC))
- wwv_gain(peer);
- }
-}
-
-
-/*
- * wwv_qrz - identify and acquire WWV/WWVH minute sync pulse
- *
- * This routine implements a virtual station process used to acquire
- * minute sync and to mitigate among the ten frequency and station
- * combinations. During minute sync acquisition the process probes each
- * frequency in turn for the minute pulse from either station, which
- * involves searching through the entire minute of samples. After
- * finding a candidate, the process searches only the seconds before and
- * after the candidate for the signal and all other seconds for the
- * noise.
- *
- * Students of radar receiver technology will discover this algorithm
- * amounts to a range gate discriminator. The discriminator requires
- * that the peak minute pulse amplitude be at least 2000 and the SNR be
- * at least 6 dB. In addition after finding a candidate, The peak second
- * pulse amplitude must be at least 2000, the SNR at least 6 dB and the
- * difference between the current and previous epoch must be less than
- * 7.5 ms, which corresponds to a frequency error of 125 PPM.. A compare
- * counter keeps track of the number of successive intervals which
- * satisfy these criteria.
- *
- * Note that, while the minute pulse is found by by the discriminator,
- * the actual value is determined from the second epoch. The assumption
- * is that the discriminator peak occurs about 800 ms into the second,
- * so the timing is retarted to the previous second epoch.
- */
-static void
-wwv_qrz(
- struct peer *peer, /* peer structure pointer */
- struct sync *sp, /* sync channel structure */
- double syncx, /* bandpass filtered sync signal */
- int pdelay /* propagation delay (samples) */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
- char tbuf[80]; /* monitor buffer */
- double snr; /* on-pulse/off-pulse ratio (dB) */
- long epoch, fpoch;
- int isgood;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- /*
- * Find the sample with peak energy, which defines the minute
- * epoch. If a sample has been found with good amplitude,
- * accumulate the noise squares for all except the second before
- * and after that position.
- */
- isgood = up->epomax > STHR && up->eposnr > SSNR;
- if (isgood) {
- fpoch = up->mphase % SECOND - up->tepoch;
- if (fpoch < 0)
- fpoch += SECOND;
- } else {
- fpoch = pdelay + SYNSIZ;
- }
- epoch = up->mphase - fpoch;
- if (epoch < 0)
- epoch += MINUTE;
- if (syncx > sp->maxamp) {
- sp->maxamp = syncx;
- sp->pos = epoch;
- }
- if (abs((epoch - sp->lastpos) % MINUTE) > SECOND)
- sp->noiamp += syncx;
-
- /*
- * At the end of the minute, determine the epoch of the
- * sync pulse, as well as the SNR and difference between
- * the current and previous epoch, which represents the
- * intrinsic frequency error plus jitter.
- */
- if (up->mphase == 0) {
- sp->synmax = sqrt(sp->maxamp);
- sp->synmin = sqrt(sp->noiamp / (MINUTE - 2 * SECOND));
- epoch = (sp->pos - sp->lastpos) % MINUTE;
-
- /*
- * If not yet in minute sync, we have to do a little
- * dance to find a valid minute sync pulse, emphasis
- * valid.
- */
- snr = wwv_snr(sp->synmax, sp->synmin);
- isgood = isgood && sp->synmax > ATHR && snr > ASNR;
- switch (sp->count) {
-
- /*
- * In state 0 the station was not heard during the
- * previous probe. Look for the biggest blip greater
- * than the amplitude threshold in the minute and assume
- * that the minute sync pulse. We're fishing here, since
- * the range gate has not yet been determined. If found,
- * bump to state 1.
- */
- case 0:
- if (sp->synmax >= ATHR)
- sp->count++;
- break;
-
- /*
- * In state 1 a candidate blip has been found and the
- * next minute has been searched for another blip. If
- * none are found acceptable, drop back to state 0 and
- * hunt some more. Otherwise, a legitimate minute pulse
- * may have been found, so bump to state 2.
- */
- case 1:
- if (!isgood) {
- sp->count = 0;
- break;
- }
- sp->count++;
- break;
-
- /*
- * In states 2 and above, continue to groom samples as
- * before and drop back to state 0 if the groom fails.
- * If it succeeds, set the epoch and bump to the next
- * state until reaching the threshold, if ever.
- */
- default:
- if (!isgood || abs(epoch) > AWND * MS) {
- sp->count = 0;
- break;
- }
- sp->mepoch = sp->pos;
- sp->count++;
- break;
- }
- if (pp->sloppyclockflag & CLK_FLAG4) {
- sprintf(tbuf,
- "wwv8 %d %3d %s %d %5.0f %5.1f %5ld %5d %ld",
- up->port, up->gain, sp->refid, sp->count,
- sp->synmax, snr, sp->pos, up->tepoch,
- epoch);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif
- }
- sp->lastpos = sp->pos;
- sp->maxamp = sp->noiamp = 0;
- }
-}
-
-
-/*
- * wwv_endpoc - identify and acquire second sync pulse
- *
- * This routine is called at the end of the second sync interval. It
- * determines the second sync epoch position within the interval and
- * disciplines the sample clock using a frequency-lock loop (FLL).
- *
- * Second sync is determined in the RF input routine as the maximum
- * over all 8000 samples in the second comb filter. To assure accurate
- * and reliable time and frequency discipline, this routine performs a
- * great deal of heavy-handed heuristic data filtering and grooming.
- *
- * Note that, since the minute sync pulse is very wide (800 ms), precise
- * minute sync epoch acquisition requires at least a rough estimate of
- * the second sync pulse (5 ms). This becomes more important in choppy
- * conditions at the lower frequencies at night, since sferics and
- * cochannel crude can badly distort the minute pulse.
- */
-static void
-wwv_endpoc(
- struct peer *peer, /* peer structure pointer */
- int epopos /* epoch max position */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
- static int epoch_mf[3]; /* epoch median filter */
- static int xepoch; /* last second epoch */
- static int zepoch; /* last averaging interval epoch */
- static int syncnt; /* run length counter */
- static int maxrun; /* longest run length */
- static int mepoch; /* longest run epoch */
- static int avgcnt; /* averaging interval counter */
- static int avginc; /* averaging ratchet */
- static int iniflg; /* initialization flag */
- char tbuf[80]; /* monitor buffer */
- double dtemp;
- int tmp2;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
- if (!iniflg) {
- iniflg = 1;
- memset((char *)epoch_mf, 0, sizeof(epoch_mf));
- }
-
- /*
- * A three-stage median filter is used to help denoise the
- * second sync pulse. The median sample becomes the candidate
- * epoch.
- */
- epoch_mf[2] = epoch_mf[1];
- epoch_mf[1] = epoch_mf[0];
- epoch_mf[0] = epopos;
- if (epoch_mf[0] > epoch_mf[1]) {
- if (epoch_mf[1] > epoch_mf[2])
- up->tepoch = epoch_mf[1]; /* 0 1 2 */
- else if (epoch_mf[2] > epoch_mf[0])
- up->tepoch = epoch_mf[0]; /* 2 0 1 */
- else
- up->tepoch = epoch_mf[2]; /* 0 2 1 */
- } else {
- if (epoch_mf[1] < epoch_mf[2])
- up->tepoch = epoch_mf[1]; /* 2 1 0 */
- else if (epoch_mf[2] < epoch_mf[0])
- up->tepoch = epoch_mf[0]; /* 1 0 2 */
- else
- up->tepoch = epoch_mf[2]; /* 1 2 0 */
- }
-
- /*
- * If the signal amplitude or SNR fall below thresholds or if no
- * stations are heard, dim the second sync lamp and start over.
- */
- if (!(up->status & (SELV | SELH)) || up->epomax < STHR ||
- up->eposnr < SSNR) {
- up->status &= ~(SSYNC | FGATE);
- avgcnt = syncnt = maxrun = 0;
- return;
- }
- avgcnt++;
-
- /*
- * If the epoch candidate is the same as the last one, increment
- * the compare counter. If not, save the length and epoch of the
- * current run for use later and reset the counter.
- */
- tmp2 = (up->tepoch - xepoch) % SECOND;
- if (tmp2 == 0) {
- syncnt++;
- } else {
- if (maxrun > 0 && mepoch == xepoch) {
- maxrun += syncnt;
- } else if (syncnt > maxrun) {
- maxrun = syncnt;
- mepoch = xepoch;
- }
- syncnt = 0;
- }
- if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & (SSYNC |
- MSYNC))) {
- sprintf(tbuf,
- "wwv1 %04x %5.0f %5.1f %5d %5d %4d %4d",
- up->status, up->epomax, up->eposnr, up->tepoch,
- tmp2, avgcnt, syncnt);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif /* DEBUG */
- }
-
- /*
- * The sample clock frequency is disciplined using a first order
- * feedback loop with time constant consistent with the Allan
- * intercept of typical computer clocks.
- *
- * The frequency update is calculated from the epoch change in
- * 125-us units divided by the averaging interval in seconds.
- * The averaging interval affects other receiver functions,
- * including the the 1000/1200-Hz comb filter and codec clock
- * loop. It also affects the 100-Hz subcarrier loop and the bit
- * and digit comparison counter thresholds.
- */
- if (avgcnt < up->avgint) {
- xepoch = up->tepoch;
- return;
- }
-
- /*
- * During the averaging interval the longest run of identical
- * epoches is determined. If the longest run is at least 10
- * seconds, the SSYNC bit is lit and the value becomes the
- * reference epoch for the next interval. If not, the second
- * synd lamp is dark and flashers set.
- */
- if (maxrun > 0 && mepoch == xepoch) {
- maxrun += syncnt;
- } else if (syncnt > maxrun) {
- maxrun = syncnt;
- mepoch = xepoch;
- }
- xepoch = up->tepoch;
- if (maxrun > SCMP) {
- up->status |= SSYNC;
- up->yepoch = mepoch;
- } else {
- up->status &= ~SSYNC;
- }
-
- /*
- * If the epoch change over the averaging interval is less than
- * 1 ms, the frequency is adjusted, but clamped at +-125 PPM. If
- * greater than 1 ms, the counter is decremented. If the epoch
- * change is less than 0.5 ms, the counter is incremented. If
- * the counter increments to +3, the averaging interval is
- * doubled and the counter set to zero; if it increments to -3,
- * the interval is halved and the counter set to zero.
- *
- * Here be spooks. From careful observations, the epoch
- * sometimes makes a long run of identical samples, then takes a
- * lurch due apparently to lost interrupts or spooks. If this
- * happens, the epoch change times the maximum run length will
- * be greater than the averaging interval, so the lurch should
- * be believed but the frequency left alone. Really intricate
- * here.
- */
- if (maxrun == 0)
- mepoch = up->tepoch;
- dtemp = (mepoch - zepoch) % SECOND;
- if (up->status & FGATE) {
- if (abs(dtemp) < MAXFREQ * MINAVG) {
- if (maxrun * abs(mepoch - zepoch) <
- avgcnt) {
- up->freq += dtemp / avgcnt;
- if (up->freq > MAXFREQ)
- up->freq = MAXFREQ;
- else if (up->freq < -MAXFREQ)
- up->freq = -MAXFREQ;
- }
- if (abs(dtemp) < MAXFREQ * MINAVG / 2) {
- if (avginc < 3) {
- avginc++;
- } else {
- if (up->avgint < MAXAVG) {
- up->avgint <<= 1;
- avginc = 0;
- }
- }
- }
- } else {
- if (avginc > -3) {
- avginc--;
- } else {
- if (up->avgint > MINAVG) {
- up->avgint >>= 1;
- avginc = 0;
- }
- }
- }
- }
- if (pp->sloppyclockflag & CLK_FLAG4) {
- sprintf(tbuf,
- "wwv2 %04x %4.0f %4d %4d %2d %4d %4.0f %6.1f",
- up->status, up->epomax, mepoch, maxrun, avginc,
- avgcnt, dtemp, up->freq * 1e6 / SECOND);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif /* DEBUG */
- }
- up->status |= FGATE;
- zepoch = mepoch;
- avgcnt = syncnt = maxrun = 0;
-}
-
-
-/*
- * wwv_epoch - epoch scanner
- *
- * This routine scans the receiver second epoch to determine the signal
- * amplitudes and pulse timings. Receiver synchronization is determined
- * by the minute sync pulse detected in the wwv_rf() routine and the
- * second sync pulse detected in the wwv_epoch() routine. A pulse width
- * discriminator extracts data signals from the 100-Hz subcarrier. The
- * transmitted signals are delayed by the propagation delay, receiver
- * delay and filter delay of this program. Delay corrections are
- * introduced separately for WWV and WWVH.
- *
- * Most communications radios use a highpass filter in the audio stages,
- * which can do nasty things to the subcarrier phase relative to the
- * sync pulses. Therefore, the data subcarrier reference phase is
- * disciplined using the hardlimited quadrature-phase signal sampled at
- * the same time as the in-phase signal. The phase tracking loop uses
- * phase adjustments of plus-minus one sample (125 us).
- */
-static void
-wwv_epoch(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
- struct chan *cp;
- static double dpulse; /* data pulse length */
- double dtemp;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- /*
- * Sample the minute sync pulse envelopes at epoch 800 for both
- * the WWV and WWVH stations. This will be used later for
- * channel and station mitigation. Note that the seconds epoch
- * is set here well before the end of the second to make sure we
- * never seet the epoch backwards.
- */
- if (up->rphase == 800 * MS) {
- up->repoch = up->yepoch;
- cp = &up->mitig[up->achan];
- cp->wwv.synamp = cp->wwv.amp;
- cp->wwvh.synamp = cp->wwvh.amp;
- }
-
- /*
- * Sample the data subcarrier at epoch 15 ms, giving a guard
- * time of +-15 ms from the beginning of the second until the
- * pulse rises at 30 ms. The I-channel amplitude is used to
- * calculate the slice level. The envelope amplitude is used
- * during the probe seconds to determine the SNR. There is a
- * compromise here; we want to delay the sample as long as
- * possible to give the radio time to change frequency and the
- * AGC to stabilize, but as early as possible if the second
- * epoch is not exact.
- */
- if (up->rphase == 15 * MS) {
- up->noiamp = up->irig * up->irig + up->qrig * up->qrig;
-
- /*
- * Sample the data subcarrier at epoch 215 ms, giving a guard
- * time of +-15 ms from the earliest the pulse peak can be
- * reached to the earliest it can begin to fall. For the data
- * channel latch the I-channel amplitude for all except the
- * probe seconds and adjust the 100-Hz reference oscillator
- * phase using the Q-channel amplitude at this epoch. For the
- * probe channel latch the envelope amplitude.
- */
- } else if (up->rphase == 215 * MS) {
- up->sigsig = up->irig;
- if (up->sigsig < 0)
- up->sigsig = 0;
- up->datpha = up->qrig / up->avgint;
- if (up->datpha >= 0) {
- up->datapt++;
- if (up->datapt >= 80)
- up->datapt -= 80;
- } else {
- up->datapt--;
- if (up->datapt < 0)
- up->datapt += 80;
- }
- up->sigamp = up->irig * up->irig + up->qrig * up->qrig;
-
- /*
- * The slice level is set half way between the peak signal and
- * noise levels. Sample the negative zero crossing after epoch
- * 200 ms and record the epoch at that time. This defines the
- * length of the data pulse, which will later be converted into
- * scaled bit probabilities.
- */
- } else if (up->rphase > 200 * MS) {
- dtemp = (up->sigsig + sqrt(up->noiamp)) / 2;
- if (up->irig < dtemp && dpulse == 0)
- dpulse = up->rphase;
- }
-
- /*
- * At the end of the second crank the clock state machine and
- * adjust the codec gain. Note the epoch is buffered from the
- * center of the second in order to avoid jitter while the
- * seconds synch is diddling the epoch. Then, determine the true
- * offset and update the median filter in the driver interface.
- *
- * Sample the data subcarrier envelope at the end of the second
- * to determine the SNR for the pulse. This gives a guard time
- * of +-30 ms from the decay of the longest pulse to the rise of
- * the next pulse.
- */
- up->rphase++;
- if (up->mphase % SECOND == up->repoch) {
- up->datsnr = wwv_snr(up->sigsig, sqrt(up->noiamp));
- wwv_rsec(peer, dpulse);
- wwv_gain(peer);
- up->rphase = dpulse = 0;
- }
-}
-
-
-/*
- * wwv_rsec - process receiver second
- *
- * This routine is called at the end of each receiver second to
- * implement the per-second state machine. The machine assembles BCD
- * digit bits, decodes miscellaneous bits and dances the leap seconds.
- *
- * Normally, the minute has 60 seconds numbered 0-59. If the leap
- * warning bit is set, the last minute (1439) of 30 June (day 181 or 182
- * for leap years) or 31 December (day 365 or 366 for leap years) is
- * augmented by one second numbered 60. This is accomplished by
- * extending the minute interval by one second and teaching the state
- * machine to ignore it.
- */
-static void
-wwv_rsec(
- struct peer *peer, /* peer structure pointer */
- double dpulse
- )
-{
- static int iniflg; /* initialization flag */
- static double bcddld[4]; /* BCD data bits */
- static double bitvec[61]; /* bit integrator for misc bits */
- struct refclockproc *pp;
- struct wwvunit *up;
- struct chan *cp;
- struct sync *sp, *rp;
- l_fp offset; /* offset in NTP seconds */
- double bit; /* bit likelihood */
- char tbuf[80]; /* monitor buffer */
- int sw, arg, nsec;
-#ifdef IRIG_SUCKS
- int i;
- l_fp ltemp;
-#endif /* IRIG_SUCKS */
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
- if (!iniflg) {
- iniflg = 1;
- memset((char *)bitvec, 0, sizeof(bitvec));
- }
-
- /*
- * The bit represents the probability of a hit on zero (negative
- * values), a hit on one (positive values) or a miss (zero
- * value). The likelihood vector is the exponential average of
- * these probabilities. Only the bits of this vector
- * corresponding to the miscellaneous bits of the timecode are
- * used, but it's easier to do them all. After that, crank the
- * seconds state machine.
- */
- nsec = up->rsec + 1;
- bit = wwv_data(up, dpulse);
- bitvec[up->rsec] += (bit - bitvec[up->rsec]) / TCONST;
- sw = progx[up->rsec].sw;
- arg = progx[up->rsec].arg;
- switch (sw) {
-
- /*
- * Ignore this second.
- */
- case IDLE: /* 9, 45-49 */
- break;
-
- /*
- * Probe channel stuff
- *
- * The WWV/H format contains data pulses in second 59 (position
- * identifier), second 1 (not used) and the minute sync pulse in
- * second 0. At the end of second 58, QSY to the probe channel,
- * which rotates over all WWV/H frequencies. At the end of
- * second 1 QSY back to the data channel.
- *
- * At the end of second 0 save the minute sync pulse peak value
- * previously latched at 800 ms.
- */
- case SYNC2: /* 0 */
- cp = &up->mitig[up->achan];
- cp->wwv.synmax = sqrt(cp->wwv.synamp);
- cp->wwvh.synmax = sqrt(cp->wwvh.synamp);
- break;
-
- /*
- * At the end of second 1 determine the minute sync pulse
- * amplitude and SNR and set SYNCNG if these values are below
- * thresholds. Determine the data pulse amplitude and SNR and
- * set DATANG if these values are below thresholds. Set ERRRNG
- * if data pulses in second 59 and second 1 are decoded in
- * error. Shift a 1 into the reachability register if SYNCNG and
- * DATANG are both lit; otherwise shift a 0. Ignore ERRRNG for
- * the present. The number of 1 bits in the last six intervals
- * represents the channel metric used by the mitigation routine.
- * Finally, QSY back to the data channel.
- */
- case SYNC3: /* 1 */
- cp = &up->mitig[up->achan];
- cp->sigamp = sqrt(up->sigamp);
- cp->noiamp = sqrt(up->noiamp);
- cp->datsnr = wwv_snr(cp->sigamp, cp->noiamp);
-
- /*
- * WWV station
- */
- sp = &cp->wwv;
- sp->synmin = sqrt((sp->synmin + sp->synamp) / 2.);
- sp->synsnr = wwv_snr(sp->synmax, sp->synmin);
- sp->select &= ~(SYNCNG | DATANG | ERRRNG);
- if (sp->synmax < QTHR || sp->synsnr < QSNR)
- sp->select |= SYNCNG;
- if (cp->sigamp < XTHR || cp->datsnr < XSNR)
- sp->select |= DATANG;
- if (up->errcnt > 2)
- sp->select |= ERRRNG;
- sp->reach <<= 1;
- if (sp->reach & (1 << AMAX))
- sp->count--;
- if (!(sp->select & (SYNCNG | DATANG))) {
- sp->reach |= 1;
- sp->count++;
- }
-
- /*
- * WWVH station
- */
- rp = &cp->wwvh;
- rp->synmin = sqrt((rp->synmin + rp->synamp) / 2.);
- rp->synsnr = wwv_snr(rp->synmax, rp->synmin);
- rp->select &= ~(SYNCNG | DATANG | ERRRNG);
- if (rp->synmax < QTHR || rp->synsnr < QSNR)
- rp->select |= SYNCNG;
- if (cp->sigamp < XTHR || cp->datsnr < XSNR)
- rp->select |= DATANG;
- if (up->errcnt > 2)
- rp->select |= ERRRNG;
- rp->reach <<= 1;
- if (rp->reach & (1 << AMAX))
- rp->count--;
- if (!(rp->select & (SYNCNG | DATANG | ERRRNG))) {
- rp->reach |= 1;
- rp->count++;
- }
-
- /*
- * Set up for next minute.
- */
- if (pp->sloppyclockflag & CLK_FLAG4) {
- sprintf(tbuf,
- "wwv5 %2d %04x %3d %4d %d %.0f/%.1f %s %04x %.0f %.0f/%.1f %s %04x %.0f %.0f/%.1f",
- up->port, up->status, up->gain, up->yepoch,
- up->errcnt, cp->sigamp, cp->datsnr,
- sp->refid, sp->reach & 0xffff,
- wwv_metric(sp), sp->synmax, sp->synsnr,
- rp->refid, rp->reach & 0xffff,
- wwv_metric(rp), rp->synmax, rp->synsnr);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif /* DEBUG */
- }
-#ifdef ICOM
- if (up->fd_icom > 0)
- wwv_qsy(peer, up->dchan);
-#endif /* ICOM */
- up->status &= ~SFLAG;
- up->errcnt = 0;
- up->alarm = 0;
- wwv_newchan(peer);
- break;
-
- /*
- * Save the bit probability in the BCD data vector at the index
- * given by the argument. Note that all bits of the vector have
- * to be above the data gate threshold for the digit to be
- * considered valid. Bits not used in the digit are forced to
- * zero and not checked for errors.
- */
- case COEF: /* 4-7, 10-13, 15-17, 20-23,
- 25-26, 30-33, 35-38, 40-41,
- 51-54 */
- if (up->status & DGATE)
- up->status |= BGATE;
- bcddld[arg] = bit;
- break;
-
- case COEF2: /* 18, 27-28, 42-43 */
- bcddld[arg] = 0;
- break;
-
- /*
- * Correlate coefficient vector with each valid digit vector and
- * save in decoding matrix. We step through the decoding matrix
- * digits correlating each with the coefficients and saving the
- * greatest and the next lower for later SNR calculation.
- */
- case DECIM2: /* 29 */
- wwv_corr4(peer, &up->decvec[arg], bcddld, bcd2);
- break;
-
- case DECIM3: /* 44 */
- wwv_corr4(peer, &up->decvec[arg], bcddld, bcd3);
- break;
-
- case DECIM6: /* 19 */
- wwv_corr4(peer, &up->decvec[arg], bcddld, bcd6);
- break;
-
- case DECIM9: /* 8, 14, 24, 34, 39 */
- wwv_corr4(peer, &up->decvec[arg], bcddld, bcd9);
- break;
-
- /*
- * Miscellaneous bits. If above the positive threshold, declare
- * 1; if below the negative threshold, declare 0; otherwise
- * raise the SYMERR alarm. At the end of second 58, QSY to the
- * probe channel. The design is intended to preserve the bits
- * over periods of signal loss.
- */
- case MSC20: /* 55 */
- wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9);
- /* fall through */
-
- case MSCBIT: /* 2-3, 50, 56-57 */
- if (bitvec[up->rsec] > BTHR)
- up->misc |= arg;
- else if (bitvec[up->rsec] < -BTHR)
- up->misc &= ~arg;
- else
- up->alarm |= SYMERR;
- break;
-
- /*
- * Save the data channel gain, then QSY to the probe channel.
- */
- case MSC21: /* 58 */
- if (bitvec[up->rsec] > BTHR)
- up->misc |= arg;
- else if (bitvec[up->rsec] < -BTHR)
- up->misc &= ~arg;
- else
- up->alarm |= SYMERR;
- up->mitig[up->dchan].gain = up->gain;
-#ifdef ICOM
- if (up->fd_icom > 0) {
- up->schan = (up->schan + 1) % NCHAN;
- wwv_qsy(peer, up->schan);
- }
-#endif /* ICOM */
- up->status |= SFLAG | SELV | SELH;
- up->errbit = up->errcnt;
- up->errcnt = 0;
- break;
-
- /*
- * The endgames
- *
- * During second 59 the receiver and codec AGC are settling
- * down, so the data pulse is unusable. At the end of this
- * second, latch the minute sync pulse noise floor. Then do the
- * minute processing and update the system clock. If a leap
- * second sail on to the next second (60); otherwise, set up for
- * the next minute.
- */
- case MIN1: /* 59 */
- cp = &up->mitig[up->achan];
- cp->wwv.synmin = cp->wwv.synamp;
- cp->wwvh.synmin = cp->wwvh.synamp;
-
- /*
- * Dance the leap if necessary and the kernel has the
- * right stuff. Then, wind up the clock and initialize
- * for the following minute. If the leap dance, note the
- * kernel is armed one second before the actual leap is
- * scheduled.
- */
- if (up->status & SSYNC && up->digcnt >= 9)
- up->status |= INSYNC;
- if (up->status & LEPDAY) {
- pp->leap = LEAP_ADDSECOND;
- } else {
- pp->leap = LEAP_NOWARNING;
- wwv_tsec(up);
- nsec = up->digcnt = 0;
- }
- pp->lencode = timecode(up, pp->a_lastcode);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("wwv: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif /* DEBUG */
- if (up->status & INSYNC && up->watch < HOLD)
- refclock_receive(peer);
- break;
-
- /*
- * If LEPDAY is set on the last minute of 30 June or 31
- * December, the LEPSEC bit is set. At the end of the minute in
- * which LEPSEC is set the transmitter and receiver insert an
- * extra second (60) in the timescale and the minute sync skips
- * a second. We only get to test this wrinkle at intervals of
- * about 18 months; the actual mileage may vary.
- */
- case MIN2: /* 60 */
- wwv_tsec(up);
- nsec = up->digcnt = 0;
- break;
- }
-
- /*
- * If digit sync has not been acquired before timeout or if no
- * station has been heard, game over and restart from scratch.
- */
- if (!(up->status & DSYNC) && (!(up->status & (SELV | SELH)) ||
- up->watch > DIGIT)) {
- wwv_newgame(peer);
- return;
- }
-
- /*
- * If no timestamps have been struck before timeout, game over
- * and restart from scratch.
- */
- if (up->watch > PANIC) {
- wwv_newgame(peer);
- return;
- }
- pp->disp += AUDIO_PHI;
- up->rsec = nsec;
-
-#ifdef IRIG_SUCKS
- /*
- * You really don't wanna know what comes down here. Leave it to
- * say Solaris 2.8 broke the nice clean audio stream, apparently
- * affected by a 5-ms sawtooth jitter. Sundown on Solaris. This
- * leaves a little twilight.
- *
- * The scheme involves differentiation, forward learning and
- * integration. The sawtooth has a period of 11 seconds. The
- * timestamp differences are integrated and subtracted from the
- * signal.
- */
- ltemp = pp->lastrec;
- L_SUB(&ltemp, &pp->lastref);
- if (ltemp.l_f < 0)
- ltemp.l_i = -1;
- else
- ltemp.l_i = 0;
- pp->lastref = pp->lastrec;
- if (!L_ISNEG(&ltemp))
- L_CLR(&up->wigwag);
- else
- L_ADD(&up->wigwag, &ltemp);
- L_SUB(&pp->lastrec, &up->wigwag);
- up->wiggle[up->wp] = ltemp;
-
- /*
- * Bottom fisher. To understand this, you have to know about
- * velocity microphones and AM transmitters. No further
- * explanation is offered, as this is truly a black art.
- */
- up->wigbot[up->wp] = pp->lastrec;
- for (i = 0; i < WIGGLE; i++) {
- if (i != up->wp)
- up->wigbot[i].l_ui++;
- L_SUB(&pp->lastrec, &up->wigbot[i]);
- if (L_ISNEG(&pp->lastrec))
- L_ADD(&pp->lastrec, &up->wigbot[i]);
- else
- pp->lastrec = up->wigbot[i];
- }
- up->wp++;
- up->wp %= WIGGLE;
-#endif /* IRIG_SUCKS */
-
- /*
- * If victory has been declared and seconds sync is lit, strike
- * a timestamp. It should not be a surprise, especially if the
- * radio is not tunable, that sometimes no stations are above
- * the noise and the reference ID set to NONE.
- */
- if (up->status & INSYNC && up->status & SSYNC) {
- pp->second = up->rsec;
- pp->minute = up->decvec[MN].digit + up->decvec[MN +
- 1].digit * 10;
- pp->hour = up->decvec[HR].digit + up->decvec[HR +
- 1].digit * 10;
- pp->day = up->decvec[DA].digit + up->decvec[DA +
- 1].digit * 10 + up->decvec[DA + 2].digit * 100;
- pp->year = up->decvec[YR].digit + up->decvec[YR +
- 1].digit * 10;
- pp->year += 2000;
- L_CLR(&offset);
- if (!clocktime(pp->day, pp->hour, pp->minute,
- pp->second, GMT, up->timestamp.l_ui,
- &pp->yearstart, &offset.l_ui)) {
- up->errflg = CEVNT_BADTIME;
- } else {
- up->watch = 0;
- pp->disp = 0;
- refclock_process_offset(pp, offset,
- up->timestamp, PDELAY);
- }
- }
- if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
- DSYNC)) {
- sprintf(tbuf,
- "wwv3 %2d %04x %5.0f %5.1f %5.0f %5.1f %5.0f",
- up->rsec, up->status, up->epomax, up->eposnr,
- up->sigsig, up->datsnr, bit);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif /* DEBUG */
- }
-}
-
-
-/*
- * wwv_data - calculate bit probability
- *
- * This routine is called at the end of the receiver second to calculate
- * the probabilities that the previous second contained a zero (P0), one
- * (P1) or position indicator (P2) pulse. If not in sync or if the data
- * bit is bad, a bit error is declared and the probabilities are forced
- * to zero. Otherwise, the data gate is enabled and the probabilities
- * are calculated. Note that the data matched filter contributes half
- * the pulse width, or 85 ms.
- *
- * It's important to observe that there are three conditions to
- * determine: average to +1 (hit), average to -1 (miss) or average to
- * zero (erasure). The erasure condition results from insufficient
- * signal (noise) and has no bias toward either a hit or miss.
- */
-static double
-wwv_data(
- struct wwvunit *up, /* driver unit pointer */
- double pulse /* pulse length (sample units) */
- )
-{
- double p0, p1, p2; /* probabilities */
- double dpulse; /* pulse length in ms */
-
- p0 = p1 = p2 = 0;
- dpulse = pulse - DATSIZ / 2;
-
- /*
- * If no station is being tracked, if either the data amplitude
- * or SNR are below threshold or if the pulse length is less
- * than 170 ms, declare an erasure.
- */
- if (!(up->status & (SELV | SELH)) || up->sigsig < DTHR ||
- up->datsnr < DSNR || dpulse < DATSIZ) {
- up->status |= DGATE;
- up->errcnt++;
- if (up->errcnt > MAXERR)
- up->alarm |= MODERR;
- return (0);
- }
-
- /*
- * The probability of P0 is one below 200 ms falling to zero at
- * 500 ms. The probability of P1 is zero below 200 ms rising to
- * one at 500 ms and falling to zero at 800 ms. The probability
- * of P2 is zero below 500 ms, rising to one above 800 ms.
- */
- up->status &= ~DGATE;
- if (dpulse < (200 * MS)) {
- p0 = 1;
- } else if (dpulse < 500 * MS) {
- dpulse -= 200 * MS;
- p1 = dpulse / (300 * MS);
- p0 = 1 - p1;
- } else if (dpulse < 800 * MS) {
- dpulse -= 500 * MS;
- p2 = dpulse / (300 * MS);
- p1 = 1 - p2;
- } else {
- p2 = 1;
- }
-
- /*
- * The ouput is a metric that ranges from -1 (P0), to +1 (P1)
- * scaled for convenience. An output of zero represents an
- * erasure, either because of a data error or pulse length
- * greater than 500 ms. At the moment, we don't use P2.
- */
- return ((p1 - p0) * MAXSIG);
-}
-
-
-/*
- * wwv_corr4 - determine maximum likelihood digit
- *
- * This routine correlates the received digit vector with the BCD
- * coefficient vectors corresponding to all valid digits at the given
- * position in the decoding matrix. The maximum value corresponds to the
- * maximum likelihood digit, while the ratio of this value to the next
- * lower value determines the likelihood function. Note that, if the
- * digit is invalid, the likelihood vector is averaged toward a miss.
- */
-static void
-wwv_corr4(
- struct peer *peer, /* peer unit pointer */
- struct decvec *vp, /* decoding table pointer */
- double data[], /* received data vector */
- double tab[][4] /* correlation vector array */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
-
- double topmax, nxtmax; /* metrics */
- double acc; /* accumulator */
- char tbuf[80]; /* monitor buffer */
- int mldigit; /* max likelihood digit */
- int diff; /* decoding difference */
- int i, j;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- /*
- * Correlate digit vector with each BCD coefficient vector. If
- * any BCD digit bit is bad, consider all bits a miss.
- */
- mldigit = 0;
- topmax = nxtmax = -MAXSIG;
- for (i = 0; tab[i][0] != 0; i++) {
- acc = 0;
- for (j = 0; j < 4; j++) {
- if (!(up->status & BGATE))
- acc += data[j] * tab[i][j];
- }
- acc = (vp->like[i] += (acc - vp->like[i]) / TCONST);
- if (acc > topmax) {
- nxtmax = topmax;
- topmax = acc;
- mldigit = i;
- } else if (acc > nxtmax) {
- nxtmax = acc;
- }
- }
- vp->mldigit = mldigit;
- vp->digprb = topmax;
- vp->digsnr = wwv_snr(topmax, nxtmax);
-
- /*
- * The maximum likelihood digit is compared with the current
- * clock digit. The difference represents the decoding phase
- * error. If the clock is not yet synchronized, the phase error
- * is corrected even of the digit probability and likelihood are
- * below thresholds. This avoids lengthy averaging times should
- * a carry mistake occur. However, the digit is not declared
- * synchronized until these values are above thresholds and the
- * last five decoded values are identical. If the clock is
- * synchronized, the phase error is not corrected unless the
- * last five digits are all above thresholds and identical. This
- * avoids mistakes when the signal is coming out of the noise
- * and the SNR is very marginal.
- */
- diff = mldigit - vp->digit;
- if (diff < 0)
- diff += vp->radix;
- if (diff != vp->phase) {
- vp->count = 0;
- vp->phase = diff;
- }
- if (vp->digsnr < BSNR) {
- vp->count = 0;
- up->alarm |= SYMERR;
- } else if (vp->digprb < BTHR) {
- vp->count = 0;
- up->alarm |= SYMERR;
- if (!(up->status & INSYNC)) {
- vp->phase = 0;
- vp->digit = mldigit;
- }
- } else if (vp->count < BCMP) {
- vp->count++;
- up->status |= DSYNC;
- if (!(up->status & INSYNC)) {
- vp->phase = 0;
- vp->digit = mldigit;
- }
- } else {
- vp->phase = 0;
- vp->digit = mldigit;
- up->digcnt++;
- }
- if (vp->digit != mldigit)
- up->alarm |= DECERR;
- if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
- INSYNC)) {
- sprintf(tbuf,
- "wwv4 %2d %04x %5.0f %2d %d %d %d %d %5.0f %5.1f",
- up->rsec, up->status, up->epomax, vp->radix,
- vp->digit, vp->mldigit, vp->phase, vp->count,
- vp->digprb, vp->digsnr);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif /* DEBUG */
- }
- up->status &= ~BGATE;
-}
-
-
-/*
- * wwv_tsec - transmitter minute processing
- *
- * This routine is called at the end of the transmitter minute. It
- * implements a state machine that advances the logical clock subject to
- * the funny rules that govern the conventional clock and calendar.
- */
-static void
-wwv_tsec(
- struct wwvunit *up /* driver structure pointer */
- )
-{
- int minute, day, isleap;
- int temp;
-
- /*
- * Advance minute unit of the day.
- */
- temp = carry(&up->decvec[MN]); /* minute units */
-
- /*
- * Propagate carries through the day.
- */
- if (temp == 0) /* carry minutes */
- temp = carry(&up->decvec[MN + 1]);
- if (temp == 0) /* carry hours */
- temp = carry(&up->decvec[HR]);
- if (temp == 0)
- temp = carry(&up->decvec[HR + 1]);
-
- /*
- * Decode the current minute and day. Set leap day if the
- * timecode leap bit is set on 30 June or 31 December. Set leap
- * minute if the last minute on leap day. This code fails in
- * 2400 AD.
- */
- minute = up->decvec[MN].digit + up->decvec[MN + 1].digit *
- 10 + up->decvec[HR].digit * 60 + up->decvec[HR +
- 1].digit * 600;
- day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
- up->decvec[DA + 2].digit * 100;
- isleap = (up->decvec[YR].digit & 0x3) == 0;
- if (up->misc & SECWAR && (day == (isleap ? 182 : 183) || day ==
- (isleap ? 365 : 366)) && up->status & INSYNC && up->status &
- SSYNC)
- up->status |= LEPDAY;
- else
- up->status &= ~LEPDAY;
- if (up->status & LEPDAY && minute == 1439)
- up->status |= LEPSEC;
- else
- up->status &= ~LEPSEC;
-
- /*
- * Roll the day if this the first minute and propagate carries
- * through the year.
- */
- if (minute != 1440)
- return;
- minute = 0;
- while (carry(&up->decvec[HR]) != 0); /* advance to minute 0 */
- while (carry(&up->decvec[HR + 1]) != 0);
- day++;
- temp = carry(&up->decvec[DA]); /* carry days */
- if (temp == 0)
- temp = carry(&up->decvec[DA + 1]);
- if (temp == 0)
- temp = carry(&up->decvec[DA + 2]);
-
- /*
- * Roll the year if this the first day and propagate carries
- * through the century.
- */
- if (day != (isleap ? 365 : 366))
- return;
- day = 1;
- while (carry(&up->decvec[DA]) != 1); /* advance to day 1 */
- while (carry(&up->decvec[DA + 1]) != 0);
- while (carry(&up->decvec[DA + 2]) != 0);
- temp = carry(&up->decvec[YR]); /* carry years */
- if (temp)
- carry(&up->decvec[YR + 1]);
-}
-
-
-/*
- * carry - process digit
- *
- * This routine rotates a likelihood vector one position and increments
- * the clock digit modulo the radix. It returns the new clock digit or
- * zero if a carry occurred. Once synchronized, the clock digit will
- * match the maximum likelihood digit corresponding to that position.
- */
-static int
-carry(
- struct decvec *dp /* decoding table pointer */
- )
-{
- int temp;
- int j;
-
- dp->digit++; /* advance clock digit */
- if (dp->digit == dp->radix) { /* modulo radix */
- dp->digit = 0;
- }
- temp = dp->like[dp->radix - 1]; /* rotate likelihood vector */
- for (j = dp->radix - 1; j > 0; j--)
- dp->like[j] = dp->like[j - 1];
- dp->like[0] = temp;
- return (dp->digit);
-}
-
-
-/*
- * wwv_snr - compute SNR or likelihood function
- */
-static double
-wwv_snr(
- double signal, /* signal */
- double noise /* noise */
- )
-{
- double rval;
-
- /*
- * This is a little tricky. Due to the way things are measured,
- * either or both the signal or noise amplitude can be negative
- * or zero. The intent is that, if the signal is negative or
- * zero, the SNR must always be zero. This can happen with the
- * subcarrier SNR before the phase has been aligned. On the
- * other hand, in the likelihood function the "noise" is the
- * next maximum down from the peak and this could be negative.
- * However, in this case the SNR is truly stupendous, so we
- * simply cap at MAXSNR dB.
- */
- if (signal <= 0) {
- rval = 0;
- } else if (noise <= 0) {
- rval = MAXSNR;
- } else {
- rval = 20 * log10(signal / noise);
- if (rval > MAXSNR)
- rval = MAXSNR;
- }
- return (rval);
-}
-
-
-/*
- * wwv_newchan - change to new data channel
- *
- * The radio actually appears to have ten channels, one channel for each
- * of five frequencies and each of two stations (WWV and WWVH), although
- * if not tunable only the 15 MHz channels appear live. While the radio
- * is tuned to the working data channel frequency and station for most
- * of the minute, during seconds 59, 0 and 1 the radio is tuned to a
- * probe frequency in order to search for minute sync pulse and data
- * subcarrier from other transmitters.
- *
- * The search for WWV and WWVH operates simultaneously, with WWV minute
- * sync pulse at 1000 Hz and WWVH at 1200 Hz. The probe frequency
- * rotates each minute over 2.5, 5, 10, 15 and 20 MHz in order and yes,
- * we all know WWVH is dark on 20 MHz, but few remember when WWV was lit
- * on 25 MHz.
- *
- * This routine selects the best channel using a metric computed from
- * the reachability register and minute pulse amplitude. Normally, the
- * award goes to the the channel with the highest metric; but, in case
- * of ties, the award goes to the channel with the highest minute sync
- * pulse amplitude and then to the highest frequency.
- *
- * The routine performs an important squelch function to keep dirty data
- * from polluting the integrators. During acquisition and until the
- * clock is synchronized, the signal metric must be at least MTR (13);
- * after that the metrict must be at least TTHR (50). If either of these
- * is not true, the station select bits are cleared so the second sync
- * is disabled and the data bit integrators averaged to a miss.
- */
-static void
-wwv_newchan(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
- struct sync *sp, *rp;
- double rank, dtemp;
- int i, j;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- /*
- * Search all five station pairs looking for the channel with
- * maximum metric. If no station is found above thresholds, the
- * reference ID is set to NONE and we wait for hotter ions.
- */
- j = 0;
- sp = NULL;
- rank = 0;
- for (i = 0; i < NCHAN; i++) {
- rp = &up->mitig[i].wwvh;
- dtemp = wwv_metric(rp);
- if (dtemp >= rank) {
- rank = dtemp;
- sp = rp;
- j = i;
- }
- rp = &up->mitig[i].wwv;
- dtemp = wwv_metric(rp);
- if (dtemp >= rank) {
- rank = dtemp;
- sp = rp;
- j = i;
- }
- }
- up->dchan = j;
- up->sptr = sp;
- up->status &= ~(SELV | SELH);
- memcpy(&pp->refid, "NONE", 4);
- if ((!(up->status & INSYNC) && rank >= MTHR) || ((up->status &
- INSYNC) && rank >= TTHR)) {
- up->status |= sp->select & (SELV | SELH);
- memcpy(&pp->refid, sp->refid, 4);
- }
- if (peer->stratum <= 1)
- memcpy(&peer->refid, &pp->refid, 4);
-}
-
-
-/*
- * www_newgame - reset and start over
- */
-static void
-wwv_newgame(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
- struct chan *cp;
- int i;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- /*
- * Initialize strategic values. Note we set the leap bits
- * NOTINSYNC and the refid "NONE".
- */
- peer->leap = LEAP_NOTINSYNC;
- up->watch = up->status = up->alarm = 0;
- up->avgint = MINAVG;
- up->freq = 0;
- up->sptr = NULL;
- up->gain = MAXGAIN / 2;
-
- /*
- * Initialize the station processes for audio gain, select bit,
- * station/frequency identifier and reference identifier.
- */
- memset(up->mitig, 0, sizeof(up->mitig));
- for (i = 0; i < NCHAN; i++) {
- cp = &up->mitig[i];
- cp->gain = up->gain;
- cp->wwv.select = SELV;
- sprintf(cp->wwv.refid, "WV%.0f", floor(qsy[i]));
- cp->wwvh.select = SELH;
- sprintf(cp->wwvh.refid, "WH%.0f", floor(qsy[i]));
- }
- wwv_newchan(peer);
-}
-
-/*
- * wwv_metric - compute station metric
- *
- * The most significant bits represent the number of ones in the
- * reachability register. The least significant bits represent the
- * minute sync pulse amplitude. The combined value is scaled 0-100.
- */
-double
-wwv_metric(
- struct sync *sp /* station pointer */
- )
-{
- double dtemp;
-
- dtemp = sp->count * MAXSIG;
- if (sp->synmax < MAXSIG)
- dtemp += sp->synmax;
- else
- dtemp += MAXSIG - 1;
- dtemp /= (AMAX + 1) * MAXSIG;
- return (dtemp * 100.);
-}
-
-
-#ifdef ICOM
-/*
- * wwv_qsy - Tune ICOM receiver
- *
- * This routine saves the AGC for the current channel, switches to a new
- * channel and restores the AGC for that channel. If a tunable receiver
- * is not available, just fake it.
- */
-static int
-wwv_qsy(
- struct peer *peer, /* peer structure pointer */
- int chan /* channel */
- )
-{
- int rval = 0;
- struct refclockproc *pp;
- struct wwvunit *up;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
- if (up->fd_icom > 0) {
- up->mitig[up->achan].gain = up->gain;
- rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
- qsy[chan]);
- up->achan = chan;
- up->gain = up->mitig[up->achan].gain;
- }
- return (rval);
-}
-#endif /* ICOM */
-
-
-/*
- * timecode - assemble timecode string and length
- *
- * Prettytime format - similar to Spectracom
- *
- * sq yy ddd hh:mm:ss ld dut lset agc iden sig errs freq avgt
- *
- * s sync indicator ('?' or ' ')
- * q error bits (hex 0-F)
- * yyyy year of century
- * ddd day of year
- * hh hour of day
- * mm minute of hour
- * ss second of minute)
- * l leap second warning (' ' or 'L')
- * d DST state ('S', 'D', 'I', or 'O')
- * dut DUT sign and magnitude (0.1 s)
- * lset minutes since last clock update
- * agc audio gain (0-255)
- * iden reference identifier (station and frequency)
- * sig signal quality (0-100)
- * errs bit errors in last minute
- * freq frequency offset (PPM)
- * avgt averaging time (s)
- */
-static int
-timecode(
- struct wwvunit *up, /* driver structure pointer */
- char *ptr /* target string */
- )
-{
- struct sync *sp;
- int year, day, hour, minute, second, dut;
- char synchar, leapchar, dst;
- char cptr[50];
-
-
- /*
- * Common fixed-format fields
- */
- synchar = (up->status & INSYNC) ? ' ' : '?';
- year = up->decvec[YR].digit + up->decvec[YR + 1].digit * 10 +
- 2000;
- day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
- up->decvec[DA + 2].digit * 100;
- hour = up->decvec[HR].digit + up->decvec[HR + 1].digit * 10;
- minute = up->decvec[MN].digit + up->decvec[MN + 1].digit * 10;
- second = 0;
- leapchar = (up->misc & SECWAR) ? 'L' : ' ';
- dst = dstcod[(up->misc >> 4) & 0x3];
- dut = up->misc & 0x7;
- if (!(up->misc & DUTS))
- dut = -dut;
- sprintf(ptr, "%c%1X", synchar, up->alarm);
- sprintf(cptr, " %4d %03d %02d:%02d:%02d %c%c %+d",
- year, day, hour, minute, second, leapchar, dst, dut);
- strcat(ptr, cptr);
-
- /*
- * Specific variable-format fields
- */
- sp = up->sptr;
- sprintf(cptr, " %d %d %s %.0f %d %.1f %d", up->watch,
- up->mitig[up->dchan].gain, sp->refid, wwv_metric(sp),
- up->errbit, up->freq / SECOND * 1e6, up->avgint);
- strcat(ptr, cptr);
- return (strlen(ptr));
-}
-
-
-/*
- * wwv_gain - adjust codec gain
- *
- * This routine is called at the end of each second. It counts the
- * number of signal clips above the MAXSIG threshold during the previous
- * second. If there are no clips, the gain is bumped up; if too many
- * clips, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
- */
-static void
-wwv_gain(
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- struct wwvunit *up;
-
- pp = peer->procptr;
- up = (struct wwvunit *)pp->unitptr;
-
- /*
- * Apparently, the codec uses only the high order bits of the
- * gain control field. Thus, it may take awhile for changes to
- * wiggle the hardware bits.
- */
- if (up->clipcnt == 0) {
- up->gain += 4;
- if (up->gain > MAXGAIN)
- up->gain = MAXGAIN;
- } else if (up->clipcnt > MAXCLP) {
- up->gain -= 4;
- if (up->gain < 0)
- up->gain = 0;
- }
- audio_gain(up->gain, up->mongain, up->port);
- up->clipcnt = 0;
-#if DEBUG
- if (debug > 1)
- audio_show();
-#endif
-}
-
-
-#else
-int refclock_wwv_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_wwvb.c b/contrib/ntp/ntpd/refclock_wwvb.c
deleted file mode 100644
index c5ef9f9..0000000
--- a/contrib/ntp/ntpd/refclock_wwvb.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * refclock_wwvb - clock driver for Spectracom WWVB receivers
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_SPECTRACOM)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-/*
- * This driver supports the Spectracom Model 8170 and Netclock/2 WWVB
- * Synchronized Clocks and the Netclock/GPS Master Clock. Both the WWVB
- * and GPS clocks have proven reliable sources of time; however, the
- * WWVB clocks have proven vulnerable to high ambient conductive RF
- * interference. The claimed accuracy of the WWVB clocks is 100 us
- * relative to the broadcast signal, while the claimed accuracy of the
- * GPS clock is 50 ns; however, in most cases the actual accuracy is
- * limited by the resolution of the timecode and the latencies of the
- * serial interface and operating system.
- *
- * The WWVB and GPS clocks should be configured for 24-hour display,
- * AUTO DST off, time zone 0 (UTC), data format 0 or 2 (see below) and
- * baud rate 9600. If the clock is to used as the source for the IRIG
- * Audio Decoder (refclock_irig.c in this distribution), it should be
- * configured for AM IRIG output and IRIG format 1 (IRIG B with
- * signature control). The GPS clock can be configured either to respond
- * to a 'T' poll character or left running continuously.
- *
- * 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, specially modified 8170 and
- * GPS.
- *
- * 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)
- *
- * 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 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 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.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 clock. 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.
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/wwvb%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-13) /* precision assumed (about 100 us) */
-#define REFID "WWVB" /* reference ID */
-#define DESCRIPTION "Spectracom WWVB/GPS Receivers" /* WRU */
-
-#define LENWWVB0 22 /* format 0 timecode length */
-#define LENWWVB1 22 /* format 1 timecode length */
-#define LENWWVB2 24 /* format 2 timecode length */
-#define LENWWVB3 29 /* format 3 timecode length */
-#define MONLIN 15 /* number of monitoring lines */
-
-/*
- * WWVB unit control structure
- */
-struct wwvbunit {
- 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 */
-};
-
-/*
- * Function prototypes
- */
-static int wwvb_start P((int, struct peer *));
-static void wwvb_shutdown P((int, struct peer *));
-static void wwvb_receive P((struct recvbuf *));
-static void wwvb_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_wwvb = {
- 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_start - open the devices and initialize data for processing
- */
-static int
-wwvb_start(
- int unit,
- struct peer *peer
- )
-{
- register struct wwvbunit *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 wwvbunit *)
- emalloc(sizeof(struct wwvbunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct wwvbunit));
- pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
- 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);
- }
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- peer->burst = MAXSTAGE;
- return (1);
-}
-
-
-/*
- * wwvb_shutdown - shut down the clock
- */
-static void
-wwvb_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct wwvbunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct wwvbunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * wwvb_receive - receive data from the serial interface
- */
-static void
-wwvb_receive(
- struct recvbuf *rbufp
- )
-{
- struct wwvbunit *up;
- struct refclockproc *pp;
- struct peer *peer;
-
- l_fp trtmp; /* arrival timestamp */
- int tz; /* time zone */
- int day, month; /* ddd conversion */
- int temp; /* int temp */
- char syncchar; /* synchronization indicator */
- char qualchar; /* quality indicator */
- char leapchar; /* leap indicator */
- char dstchar; /* daylight/standard indicator */
- char tmpchar; /* trashbin */
-
- /*
- * Initialize pointers and read the timecode and timestamp
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct wwvbunit *)pp->unitptr;
- temp = refclock_gtlin(rbufp, pp->a_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
- * a Netclock/2 or upgraded 8170 the start bit is delayed 100
- * +-50 us relative to the pps; however, on an unmodified 8170
- * the start bit can be delayed up to 10 ms. In format 2 the
- * reading precision is only to the millisecond. Thus, unless
- * you have a pps gadget and don't have to have the year, format
- * 0 provides the lowest jitter.
- */
- if (temp == 0) {
- if (up->tcswitch == 0) {
- up->tcswitch = 1;
- up->laststamp = trtmp;
- } else
- up->tcswitch = 0;
- return;
- }
- pp->lencode = temp;
- pp->lastrec = up->laststamp;
- up->laststamp = trtmp;
- up->tcswitch = 1;
-
- /*
- * We get down to business, check the timecode format and decode
- * its contents. This code uses the timecode length to determine
- * format 0, 2 or 3. If the timecode has invalid length or is
- * not in proper format, we declare bad format and exit.
- */
- syncchar = qualchar = leapchar = dstchar = ' ';
- tz = 0;
- switch (pp->lencode) {
-
- case LENWWVB0:
-
- /*
- * Timecode format 0: "I ddd hh:mm:ss DTZ=nn"
- */
- if (sscanf(pp->a_lastcode,
- "%c %3d %2d:%2d:%2d%c%cTZ=%2d",
- &syncchar, &pp->day, &pp->hour, &pp->minute,
- &pp->second, &tmpchar, &dstchar, &tz) == 8)
- pp->nsec = 0;
- break;
-
- case LENWWVB2:
-
- /*
- * Timecode format 2: "IQyy ddd hh:mm:ss.mmm LD" */
- if (sscanf(pp->a_lastcode,
- "%c%c %2d %3d %2d:%2d:%2d.%3ld %c",
- &syncchar, &qualchar, &pp->year, &pp->day,
- &pp->hour, &pp->minute, &pp->second, &pp->nsec,
- &leapchar) == 9)
- pp->nsec *= 1000000;
- break;
-
- case LENWWVB3:
-
- /*
- * Timecode format 3: "0003I yyyymmdd hhmmss+0000SL#"
- */
- if (sscanf(pp->a_lastcode,
- "0003%c %4d%2d%2d %2d%2d%2d+0000%c%c",
- &syncchar, &pp->year, &month, &day, &pp->hour,
- &pp->minute, &pp->second, &dstchar, &leapchar) == 8)
- {
- pp->day = ymd2yd(pp->year, month, day);
- pp->nsec = 0;
- break;
- }
-
- default:
-
- /*
- * Unknown format: If dumping internal table, record
- * stats; otherwise, declare bad format.
- */
- if (up->linect > 0) {
- up->linect--;
- record_clock_stats(&peer->srcadr,
- pp->a_lastcode);
- } else {
- refclock_report(peer, CEVNT_BADREPLY);
- }
- return;
- }
-
- /*
- * 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 the
- * quality character.
- */
- switch (qualchar) {
-
- case ' ':
- pp->disp = .001;
- pp->lastref = pp->lastrec;
- break;
-
- case 'A':
- pp->disp = .01;
- break;
-
- case 'B':
- pp->disp = .1;
- break;
-
- case 'C':
- pp->disp = .5;
- break;
-
- case 'D':
- pp->disp = MAXDISPERSE;
- break;
-
- default:
- pp->disp = MAXDISPERSE;
- refclock_report(peer, CEVNT_BADREPLY);
- break;
- }
- if (syncchar != ' ')
- pp->leap = LEAP_NOTINSYNC;
- else if (leapchar == 'L')
- pp->leap = LEAP_ADDSECOND;
- else
- pp->leap = LEAP_NOWARNING;
-
- /*
- * Process the new sample in the median filter and determine the
- * timecode timestamp.
- */
- if (!refclock_process(pp))
- refclock_report(peer, CEVNT_BADTIME);
-}
-
-
-/*
- * wwvb_poll - called by the transmit procedure
- */
-static void
-wwvb_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct wwvbunit *up;
- struct refclockproc *pp;
- char pollchar; /* character sent to clock */
-
- /*
- * 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 the clock becomes
- * unreachable, declare a timeout and keep going.
- */
- pp = peer->procptr;
- up = (struct wwvbunit *)pp->unitptr;
- if (up->linect > 0)
- pollchar = 'R';
- else
- pollchar = 'T';
- if (write(pp->io.fd, &pollchar, 1) != 1)
- refclock_report(peer, CEVNT_FAULT);
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
- }
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("wwvb: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
- peer->burst = MAXSTAGE;
- pp->polls++;
-
- /*
- * 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 <
- (int)up->lasthour)
- up->linect = MONLIN;
- up->lasthour = pp->hour;
-}
-
-#else
-int refclock_wwvb_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_zyfer.c b/contrib/ntp/ntpd/refclock_zyfer.c
deleted file mode 100644
index 44f2c4d..0000000
--- a/contrib/ntp/ntpd/refclock_zyfer.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * refclock_zyfer - clock driver for the Zyfer GPSTarplus Clock
- *
- * Harlan Stenn, Jan 2002
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_ZYFER)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-#include "ntp_unixtime.h"
-
-#include <stdio.h>
-#include <ctype.h>
-
-#ifdef HAVE_SYS_TERMIOS_H
-# include <sys/termios.h>
-#endif
-#ifdef HAVE_SYS_PPSCLOCK_H
-# include <sys/ppsclock.h>
-#endif
-
-/*
- * This driver provides support for the TOD serial port of a Zyfer GPStarplus.
- * This clock also provides PPS as well as IRIG outputs.
- * Precision is limited by the serial driver, etc.
- *
- * If I was really brave I'd hack/generalize the serial driver to deal
- * with arbitrary on-time characters. This clock *begins* the stream with
- * `!`, the on-time character, and the string is *not* EOL-terminated.
- *
- * Configure the beast for 9600, 8N1. While I see leap-second stuff
- * in the documentation, the published specs on the TOD format only show
- * the seconds going to '59'. I see no leap warning in the TOD format.
- *
- * The clock sends the following message once per second:
- *
- * !TIME,2002,017,07,59,32,2,4,1
- * YYYY DDD HH MM SS m T O
- *
- * ! On-time character
- * YYYY Year
- * DDD 001-366 Day of Year
- * HH 00-23 Hour
- * MM 00-59 Minute
- * SS 00-59 Second (probably 00-60)
- * m 1-5 Time Mode:
- * 1 = GPS time
- * 2 = UTC time
- * 3 = LGPS time (Local GPS)
- * 4 = LUTC time (Local UTC)
- * 5 = Manual time
- * T 4-9 Time Figure Of Merit:
- * 4 x <= 1us
- * 5 1us < x <= 10 us
- * 6 10us < x <= 100us
- * 7 100us < x <= 1ms
- * 8 1ms < x <= 10ms
- * 9 10ms < x
- * O 0-4 Operation Mode:
- * 0 Warm-up
- * 1 Time Locked
- * 2 Coasting
- * 3 Recovering
- * 4 Manual
- *
- */
-
-/*
- * Interface definitions
- */
-#define DEVICE "/dev/zyfer%d" /* device name and unit */
-#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS\0" /* reference ID */
-#define DESCRIPTION "Zyfer GPStarplus" /* WRU */
-
-#define LENZYFER 29 /* timecode length */
-
-/*
- * Unit control structure
- */
-struct zyferunit {
- u_char Rcvbuf[LENZYFER + 1];
- u_char polled; /* poll message flag */
- int pollcnt;
- l_fp tstamp; /* timestamp of last poll */
- int Rcvptr;
-};
-
-/*
- * Function prototypes
- */
-static int zyfer_start P((int, struct peer *));
-static void zyfer_shutdown P((int, struct peer *));
-static void zyfer_receive P((struct recvbuf *));
-static void zyfer_poll P((int, struct peer *));
-
-/*
- * Transfer vector
- */
-struct refclock refclock_zyfer = {
- zyfer_start, /* start up driver */
- zyfer_shutdown, /* shut down driver */
- zyfer_poll, /* transmit poll message */
- noentry, /* not used (old zyfer_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old zyfer_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-/*
- * zyfer_start - open the devices and initialize data for processing
- */
-static int
-zyfer_start(
- int unit,
- struct peer *peer
- )
-{
- register struct zyferunit *up;
- struct refclockproc *pp;
- int fd;
- char device[20];
-
- /*
- * Open serial port.
- * Something like LDISC_ACTS that looked for ! would be nice...
- */
- (void)sprintf(device, DEVICE, unit);
- if ( !(fd = refclock_open(device, SPEED232, LDISC_RAW)) )
- return (0);
-
- msyslog(LOG_NOTICE, "zyfer(%d) fd: %d dev <%s>", unit, fd, device);
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct zyferunit *)
- emalloc(sizeof(struct zyferunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct zyferunit));
- pp = peer->procptr;
- pp->io.clock_recv = zyfer_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;
- up->polled = 0; /* May not be needed... */
-
- return (1);
-}
-
-
-/*
- * zyfer_shutdown - shut down the clock
- */
-static void
-zyfer_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct zyferunit *up;
- struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct zyferunit *)pp->unitptr;
- io_closeclock(&pp->io);
- free(up);
-}
-
-
-/*
- * zyfer_receive - receive data from the serial interface
- */
-static void
-zyfer_receive(
- struct recvbuf *rbufp
- )
-{
- register struct zyferunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- int tmode; /* Time mode */
- int tfom; /* Time Figure Of Merit */
- int omode; /* Operation mode */
- u_char *p;
-#ifdef PPS
- struct ppsclockev ppsev;
- int request;
-#ifdef HAVE_CIOGETEV
- request = CIOGETEV;
-#endif
-#ifdef HAVE_TIOCGPPSEV
- request = TIOCGPPSEV;
-#endif
-#endif /* PPS */
-
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct zyferunit *)pp->unitptr;
- p = (u_char *) &rbufp->recv_space;
- /*
- * If lencode is 0:
- * - if *rbufp->recv_space is !
- * - - call refclock_gtlin to get things going
- * - else flush
- * else stuff it on the end of lastcode
- * If we don't have LENZYFER bytes
- * - wait for more data
- * Crack the beast, and if it's OK, process it.
- *
- * We use refclock_gtlin() because we might use LDISC_CLK.
- *
- * Under FreeBSD, we get the ! followed by two 14-byte packets.
- */
-
- if (pp->lencode >= LENZYFER)
- pp->lencode = 0;
-
- if (!pp->lencode) {
- if (*p == '!')
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode,
- BMAX, &pp->lastrec);
- else
- return;
- } else {
- memcpy(pp->a_lastcode + pp->lencode, p, rbufp->recv_length);
- pp->lencode += rbufp->recv_length;
- pp->a_lastcode[pp->lencode] = '\0';
- }
-
- if (pp->lencode < LENZYFER)
- return;
-
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-
- /*
- * 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 != LENZYFER) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
- /*
- * Timecode sample: "!TIME,2002,017,07,59,32,2,4,1"
- */
- if (sscanf(pp->a_lastcode, "!TIME,%4d,%3d,%2d,%2d,%2d,%d,%d,%d",
- &pp->year, &pp->day, &pp->hour, &pp->minute, &pp->second,
- &tmode, &tfom, &omode) != 8) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- if (tmode != 2) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
- /* Should we make sure tfom is 4? */
-
- if (omode != 1) {
- pp->leap = LEAP_NOTINSYNC;
- return;
- }
-#ifdef PPS
- if(ioctl(fdpps,request,(caddr_t) &ppsev) >=0) {
- ppsev.tv.tv_sec += (u_int32) JAN_1970;
- TVTOTS(&ppsev.tv,&up->tstamp);
- }
- /* record the last ppsclock event time stamp */
- pp->lastrec = up->tstamp;
-#endif /* PPS */
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
- }
-
- /*
- * Good place for record_clock_stats()
- */
- up->pollcnt = 2;
-
- if (up->polled) {
- up->polled = 0;
- refclock_receive(peer);
- }
-}
-
-
-/*
- * zyfer_poll - called by the transmit procedure
- */
-static void
-zyfer_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct zyferunit *up;
- struct refclockproc *pp;
-
- /*
- * We don't really do anything here, except arm the receiving
- * side to capture a sample and check for timeouts.
- */
- pp = peer->procptr;
- up = (struct zyferunit *)pp->unitptr;
- if (!up->pollcnt)
- refclock_report(peer, CEVNT_TIMEOUT);
- else
- up->pollcnt--;
- pp->polls++;
- up->polled = 1;
-}
-
-#else
-int refclock_zyfer_bs;
-#endif /* REFCLOCK */
OpenPOWER on IntegriCloud