summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd
diff options
context:
space:
mode:
authorroberto <roberto@FreeBSD.org>2004-07-20 15:01:56 +0000
committerroberto <roberto@FreeBSD.org>2004-07-20 15:01:56 +0000
commit118e757284cbb8fc4f43a713e892b41504b50a5f (patch)
tree528d12dda44ebdc3ffcc38050f159ac553a69c17 /contrib/ntp/ntpd
parenta85d9ae25e8e8696677bc30feb6eaf7fc150e529 (diff)
downloadFreeBSD-src-118e757284cbb8fc4f43a713e892b41504b50a5f.zip
FreeBSD-src-118e757284cbb8fc4f43a713e892b41504b50a5f.tar.gz
Virgin import of ntpd 4.2.0
Diffstat (limited to 'contrib/ntp/ntpd')
-rw-r--r--contrib/ntp/ntpd/Makefile.am28
-rw-r--r--contrib/ntp/ntpd/Makefile.in941
-rw-r--r--contrib/ntp/ntpd/check_y2k.c3
-rw-r--r--contrib/ntp/ntpd/cmd_args.c131
-rw-r--r--contrib/ntp/ntpd/ntp_config.c781
-rw-r--r--contrib/ntp/ntpd/ntp_control.c315
-rw-r--r--contrib/ntp/ntpd/ntp_crypto.c4815
-rw-r--r--contrib/ntp/ntpd/ntp_filegen.c8
-rw-r--r--contrib/ntp/ntpd/ntp_intres.c110
-rw-r--r--contrib/ntp/ntpd/ntp_io.c1933
-rw-r--r--contrib/ntp/ntpd/ntp_loopfilter.c312
-rw-r--r--contrib/ntp/ntpd/ntp_monitor.c144
-rw-r--r--contrib/ntp/ntpd/ntp_peer.c209
-rw-r--r--contrib/ntp/ntpd/ntp_proto.c2561
-rw-r--r--contrib/ntp/ntpd/ntp_refclock.c144
-rw-r--r--contrib/ntp/ntpd/ntp_request.c1143
-rw-r--r--contrib/ntp/ntpd/ntp_restrict.c724
-rw-r--r--contrib/ntp/ntpd/ntp_timer.c88
-rw-r--r--contrib/ntp/ntpd/ntp_util.c420
-rw-r--r--contrib/ntp/ntpd/ntpd.c248
-rw-r--r--contrib/ntp/ntpd/ntpsim.c368
-rw-r--r--contrib/ntp/ntpd/refclock_acts.c5
-rw-r--r--contrib/ntp/ntpd/refclock_arbiter.c3
-rw-r--r--contrib/ntp/ntpd/refclock_arc.c372
-rw-r--r--contrib/ntp/ntpd/refclock_as2201.c5
-rw-r--r--contrib/ntp/ntpd/refclock_atom.c28
-rw-r--r--contrib/ntp/ntpd/refclock_bancomm.c3
-rw-r--r--contrib/ntp/ntpd/refclock_chronolog.c4
-rw-r--r--contrib/ntp/ntpd/refclock_chu.c487
-rw-r--r--contrib/ntp/ntpd/refclock_conf.c2
-rw-r--r--contrib/ntp/ntpd/refclock_datum.c2
-rw-r--r--contrib/ntp/ntpd/refclock_dumbclock.c20
-rw-r--r--contrib/ntp/ntpd/refclock_fg.c12
-rw-r--r--contrib/ntp/ntpd/refclock_gpsvme.c13
-rw-r--r--contrib/ntp/ntpd/refclock_heath.c68
-rw-r--r--contrib/ntp/ntpd/refclock_hopfpci.c21
-rw-r--r--contrib/ntp/ntpd/refclock_hopfser.c22
-rw-r--r--contrib/ntp/ntpd/refclock_hpgps.c1
-rw-r--r--contrib/ntp/ntpd/refclock_irig.c363
-rw-r--r--contrib/ntp/ntpd/refclock_jjy.c22
-rw-r--r--contrib/ntp/ntpd/refclock_jupiter.c1192
-rw-r--r--contrib/ntp/ntpd/refclock_leitch.c1
-rw-r--r--contrib/ntp/ntpd/refclock_local.c131
-rw-r--r--contrib/ntp/ntpd/refclock_msfees.c4
-rw-r--r--contrib/ntp/ntpd/refclock_mx4200.c26
-rw-r--r--contrib/ntp/ntpd/refclock_neoclock4x.c580
-rw-r--r--contrib/ntp/ntpd/refclock_nmea.c32
-rw-r--r--contrib/ntp/ntpd/refclock_oncore.c3763
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.c87
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.h1
-rw-r--r--contrib/ntp/ntpd/refclock_parse.c36
-rw-r--r--contrib/ntp/ntpd/refclock_pcf.c5
-rw-r--r--contrib/ntp/ntpd/refclock_pst.c44
-rw-r--r--contrib/ntp/ntpd/refclock_ripencc.c10
-rw-r--r--contrib/ntp/ntpd/refclock_shm.c13
-rw-r--r--contrib/ntp/ntpd/refclock_tpro.c10
-rw-r--r--contrib/ntp/ntpd/refclock_trak.c1
-rw-r--r--contrib/ntp/ntpd/refclock_true.c4
-rw-r--r--contrib/ntp/ntpd/refclock_ulink.c13
-rw-r--r--contrib/ntp/ntpd/refclock_usno.c5
-rw-r--r--contrib/ntp/ntpd/refclock_wwv.c2143
-rw-r--r--contrib/ntp/ntpd/refclock_wwvb.c37
62 files changed, 15524 insertions, 9493 deletions
diff --git a/contrib/ntp/ntpd/Makefile.am b/contrib/ntp/ntpd/Makefile.am
index 94dfd09..0fa4e21 100644
--- a/contrib/ntp/ntpd/Makefile.am
+++ b/contrib/ntp/ntpd/Makefile.am
@@ -1,31 +1,39 @@
#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
AUTOMAKE_OPTIONS = ../util/ansi2knr
-bin_PROGRAMS = ntpd
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/librsaref
-# LDADD might need RESLIB and ADJLIB
-LDADD = version.o @LIBPARSE@ ../libntp/libntp.a @LIBRSAREF@
+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) -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
+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 jupiter.h map_vme.c ntp_config.c ntp_control.c \
+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_io.c ntp_loopfilter.c ntp_monitor.c ntp_peer.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 ntpd.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 \
@@ -47,6 +55,6 @@ $(PROGRAMS): $(LDADD)
../libparse/libparse.a:
cd ../libparse && $(MAKE)
-version.o: $(ntpd_OBJECTS) ../libntp/libntp.a @LIBPARSE@ @LIBRSAREF@ Makefile
+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
index 2622b3b..eef0774 100644
--- a/contrib/ntp/ntpd/Makefile.in
+++ b/contrib/ntp/ntpd/Makefile.in
@@ -1,6 +1,7 @@
-# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+# Makefile.in generated by automake 1.7.7 from Makefile.am.
+# @configure_input@
-# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# 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,
@@ -13,82 +14,79 @@
@SET_MAKE@
-#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
-
-SHELL = @SHELL@
-
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-
-bindir = @bindir@
-sbindir = @sbindir@
-libexecdir = @libexecdir@
-datadir = @datadir@
-sysconfdir = @sysconfdir@
-sharedstatedir = @sharedstatedir@
-localstatedir = @localstatedir@
-libdir = @libdir@
-infodir = @infodir@
-mandir = @mandir@
-includedir = @includedir@
-oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
-ACLOCAL = @ACLOCAL@
-AUTOCONF = @AUTOCONF@
-AUTOMAKE = @AUTOMAKE@
-AUTOHEADER = @AUTOHEADER@
-
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+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@
+transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
-build_alias = @build_alias@
build_triplet = @build@
-host_alias = @host_alias@
host_triplet = @host@
-target_alias = @target_alias@
target_triplet = @target@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
-AUTOKEY = @AUTOKEY@
+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@
-LIBRSAREF = @LIBRSAREF@
+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_LIBRSAREF = @MAKE_LIBRSAREF@
+MAKE_NTPDSIM = @MAKE_NTPDSIM@
MAKE_NTPTIME = @MAKE_NTPTIME@
-MAKE_NTP_GENKEYS = @MAKE_NTP_GENKEYS@
+MAKE_NTP_KEYGEN = @MAKE_NTP_KEYGEN@
MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
+MAKE_SNTP = @MAKE_SNTP@
MAKE_TICKADJ = @MAKE_TICKADJ@
MAKE_TIMETRIM = @MAKE_TIMETRIM@
OBJEXT = @OBJEXT@
@@ -96,45 +94,97 @@ 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@
-RSADIR = @RSADIR@
-RSAOBJS = @RSAOBJS@
-RSAREF = @RSAREF@
-RSASRCS = @RSASRCS@
+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
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/librsaref
-# LDADD might need RESLIB and ADJLIB
-LDADD = version.o @LIBPARSE@ ../libntp/libntp.a @LIBRSAREF@
+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) -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
+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 jupiter.h map_vme.c ntp_config.c ntp_control.c \
+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_io.c ntp_loopfilter.c ntp_monitor.c ntp_peer.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 ntpd.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 \
@@ -149,122 +199,143 @@ ntpd_SOURCES = cmd_args.c jupiter.h map_vme.c ntp_config.c ntp_control.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 =
-EXTRA_PROGRAMS = check_y2k$(EXEEXT)
-bin_PROGRAMS = ntpd$(EXEEXT)
+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_LDADD = $(LDADD)
-check_y2k_DEPENDENCIES = version.o ../libntp/libntp.a
+check_y2k_DEPENDENCIES = version.o libntpd.a libntpd.a \
+ ../libntp/libntp.a
check_y2k_LDFLAGS =
-am_ntpd_OBJECTS = cmd_args$U.$(OBJEXT) map_vme$U.$(OBJEXT) \
- ntp_config$U.$(OBJEXT) ntp_control$U.$(OBJEXT) \
- ntp_crypto$U.$(OBJEXT) ntp_filegen$U.$(OBJEXT) \
- ntp_intres$U.$(OBJEXT) ntp_io$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) ntpd$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)
+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 ../libntp/libntp.a
+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 =
-DEFS = @DEFS@
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/depcomp
-@AMDEP_TRUE@DEP_FILES = $(DEPDIR)/check_y2k$U.Po $(DEPDIR)/cmd_args$U.Po \
-@AMDEP_TRUE@ $(DEPDIR)/map_vme$U.Po $(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 $(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 $(DEPDIR)/ntp_util$U.Po \
-@AMDEP_TRUE@ $(DEPDIR)/ntpd$U.Po $(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
+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 = check_y2k.c $(ntpd_SOURCES)
-DIST_COMMON = Makefile.am Makefile.in
-SOURCES = check_y2k.c $(ntpd_SOURCES)
+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
@@ -274,9 +345,17 @@ $(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) && \
- CONFIG_HEADERS= CONFIG_LINKS= \
- CONFIG_FILES=$(subdir)/$@ $(SHELL) ./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)
@@ -284,16 +363,16 @@ install-binPROGRAMS: $(bin_PROGRAMS)
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
; then \
- f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \
- $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \
+ 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/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
rm -f $(DESTDIR)$(bindir)/$$f; \
done
@@ -309,6 +388,9 @@ check_y2k$(EXEEXT): $(check_y2k_OBJECTS) $(check_y2k_DEPENDENCIES)
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
@@ -321,287 +403,442 @@ ANSI2KNR = ../util/ansi2knr
cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr
mostlyclean-kr:
- -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)/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@
-
-distclean-depend:
- -rm -rf $(DEPDIR)
+ -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:
-@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- $(COMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+@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:
-@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
-@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- $(COMPILE) -c `cygpath -w $<`
-CCDEPMODE = @CCDEPMODE@
+@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) > check_y2k_.c || rm -f check_y2k_.c
+ $(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) > cmd_args_.c || rm -f cmd_args_.c
+ $(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) > map_vme_.c || rm -f map_vme_.c
+ $(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) > ntp_config_.c || rm -f ntp_config_.c
+ $(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) > ntp_control_.c || rm -f ntp_control_.c
+ $(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) > ntp_crypto_.c || rm -f ntp_crypto_.c
+ $(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) > ntp_filegen_.c || rm -f ntp_filegen_.c
+ $(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) > ntp_intres_.c || rm -f ntp_intres_.c
+ $(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) > ntp_io_.c || rm -f ntp_io_.c
+ $(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) > ntp_loopfilter_.c || rm -f ntp_loopfilter_.c
+ $(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) > ntp_monitor_.c || rm -f ntp_monitor_.c
+ $(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) > ntp_peer_.c || rm -f ntp_peer_.c
+ $(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) > ntp_proto_.c || rm -f ntp_proto_.c
+ $(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) > ntp_refclock_.c || rm -f ntp_refclock_.c
+ $(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) > ntp_request_.c || rm -f ntp_request_.c
+ $(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) > ntp_restrict_.c || rm -f ntp_restrict_.c
+ $(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) > ntp_timer_.c || rm -f ntp_timer_.c
+ $(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) > ntp_util_.c || rm -f ntp_util_.c
+ $(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) > ntpd_.c || rm -f ntpd_.c
+ $(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) > refclock_acts_.c || rm -f refclock_acts_.c
+ $(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) > refclock_arbiter_.c || rm -f refclock_arbiter_.c
+ $(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) > refclock_arc_.c || rm -f refclock_arc_.c
+ $(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) > refclock_as2201_.c || rm -f refclock_as2201_.c
+ $(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) > refclock_atom_.c || rm -f refclock_atom_.c
+ $(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) > refclock_bancomm_.c || rm -f refclock_bancomm_.c
+ $(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) > refclock_chronolog_.c || rm -f refclock_chronolog_.c
+ $(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) > refclock_chu_.c || rm -f refclock_chu_.c
+ $(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) > refclock_conf_.c || rm -f refclock_conf_.c
+ $(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) > refclock_datum_.c || rm -f refclock_datum_.c
+ $(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) > refclock_dumbclock_.c || rm -f refclock_dumbclock_.c
+ $(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) > refclock_fg_.c || rm -f refclock_fg_.c
+ $(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) > refclock_gpsvme_.c || rm -f refclock_gpsvme_.c
+ $(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) > refclock_heath_.c || rm -f refclock_heath_.c
+ $(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) > refclock_hopfpci_.c || rm -f refclock_hopfpci_.c
+ $(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) > refclock_hopfser_.c || rm -f refclock_hopfser_.c
+ $(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) > refclock_hpgps_.c || rm -f refclock_hpgps_.c
+ $(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) > refclock_irig_.c || rm -f refclock_irig_.c
+ $(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) > refclock_jjy_.c || rm -f refclock_jjy_.c
+ $(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) > refclock_jupiter_.c || rm -f refclock_jupiter_.c
+ $(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) > refclock_leitch_.c || rm -f refclock_leitch_.c
+ $(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) > refclock_local_.c || rm -f refclock_local_.c
+ $(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) > refclock_msfees_.c || rm -f refclock_msfees_.c
+ $(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) > refclock_mx4200_.c || rm -f refclock_mx4200_.c
+ $(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) > refclock_neoclock4x_.c || rm -f refclock_neoclock4x_.c
+ $(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) > refclock_nmea_.c || rm -f refclock_nmea_.c
+ $(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) > refclock_oncore_.c || rm -f refclock_oncore_.c
+ $(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) > refclock_palisade_.c || rm -f refclock_palisade_.c
+ $(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) > refclock_parse_.c || rm -f refclock_parse_.c
+ $(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) > refclock_pcf_.c || rm -f refclock_pcf_.c
+ $(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) > refclock_pst_.c || rm -f refclock_pst_.c
+ $(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) > refclock_ptbacts_.c || rm -f refclock_ptbacts_.c
+ $(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) > refclock_ripencc_.c || rm -f refclock_ripencc_.c
+ $(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) > refclock_shm_.c || rm -f refclock_shm_.c
+ $(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) > refclock_tpro_.c || rm -f refclock_tpro_.c
+ $(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) > refclock_trak_.c || rm -f refclock_trak_.c
+ $(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) > refclock_true_.c || rm -f refclock_true_.c
+ $(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) > refclock_tt560_.c || rm -f refclock_tt560_.c
+ $(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) > refclock_ulink_.c || rm -f refclock_ulink_.c
+ $(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) > refclock_usno_.c || rm -f refclock_usno_.c
+ $(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) > refclock_wwv_.c || rm -f refclock_wwv_.c
+ $(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) > refclock_wwvb_.c || rm -f refclock_wwvb_.c
+ $(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) > refclock_zyfer_.c || rm -f refclock_zyfer_.c
+ $(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) 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)
+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) $(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 $(LISP)
+ mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(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; }'`; \
- test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
- || etags $(ETAGS_ARGS) $$tags $$unique $(LISP)
+ 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=`CDPATH=: && cd $(top_builddir) && pwd` \
+ here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
-
+ -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)
- @for file in $(DISTFILES); do \
- if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ @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 \
- $(mkinstalldirs) "$(distdir)/$$dir"; \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
fi; \
if test -d $$d/$$file; then \
- cp -pR $$d/$$file $(distdir) \
- || exit 1; \
+ 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 \
@@ -612,11 +849,10 @@ check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-local
check: check-am
-all-am: Makefile $(PROGRAMS)
+all-am: Makefile $(LIBRARIES) $(PROGRAMS)
installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
-
install: install-am
install-exec: install-exec-am
install-data: install-data-am
@@ -628,6 +864,7 @@ install-am: all-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:
@@ -635,7 +872,7 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
- -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+ -rm -f $(CONFIG_CLEAN_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@@ -644,12 +881,14 @@ maintainer-clean-generic:
clean: clean-am
clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
- mostlyclean-am
+ clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-depend \
- distclean-generic distclean-tags
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
dvi: dvi-am
@@ -670,6 +909,8 @@ install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -677,19 +918,27 @@ 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: GTAGS all all-am check check-am check-local clean \
- clean-binPROGRAMS clean-checkPROGRAMS clean-generic distclean \
- distclean-compile distclean-depend 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 tags uninstall 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@
@@ -703,7 +952,7 @@ $(PROGRAMS): $(LDADD)
../libparse/libparse.a:
cd ../libparse && $(MAKE)
-version.o: $(ntpd_OBJECTS) ../libntp/libntp.a @LIBPARSE@ @LIBRSAREF@ Makefile
+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.
diff --git a/contrib/ntp/ntpd/check_y2k.c b/contrib/ntp/ntpd/check_y2k.c
index f0f4480..6b83115 100644
--- a/contrib/ntp/ntpd/check_y2k.c
+++ b/contrib/ntp/ntpd/check_y2k.c
@@ -45,6 +45,9 @@
# 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>
diff --git a/contrib/ntp/ntpd/cmd_args.c b/contrib/ntp/ntpd/cmd_args.c
index 9f61b4a..3ed9b66 100644
--- a/contrib/ntp/ntpd/cmd_args.c
+++ b/contrib/ntp/ntpd/cmd_args.c
@@ -9,13 +9,21 @@
#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 = 0;
+int listen_to_virtual_ips = 1;
+
+#ifdef SYS_WINNT
+extern BOOL NoWinService;
+#endif
-static const char *ntp_options = "aAbc:dD:f:gk:l:LmnN:p:P:qr:s:t:v:V:x";
+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;
@@ -72,18 +80,23 @@ getstartup(
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");
+ fprintf(stderr, "ntpd not compiled with -DDEBUG option - no DEBUG support\n");
++errflg;
break;
#endif
case 'L':
- listen_to_virtual_ips = 1;
+ listen_to_virtual_ips = 0;
break;
case 'l':
{
FILE *new_file;
- new_file = fopen(ntp_optarg, "a");
+ 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);
@@ -104,16 +117,38 @@ getstartup(
case 'n':
case 'q':
++nofork;
+#ifdef SYS_WINNT
+ NoWinService = TRUE;
+#endif
break;
case 'N':
- priority_done = strcmp(ntp_optarg, "high");
+ 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;
}
@@ -126,6 +161,9 @@ getstartup(
#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 */
@@ -152,6 +190,7 @@ getCmdOpts(
)
{
extern char *config_file;
+ struct sockaddr_in inaddrntp;
int errflg;
int c;
@@ -171,15 +210,15 @@ getCmdOpts(
while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF) {
switch (c) {
case 'a':
- proto_config(PROTO_AUTHENTICATE, 1, 0.);
+ proto_config(PROTO_AUTHENTICATE, 1, 0., NULL);
break;
case 'A':
- proto_config(PROTO_AUTHENTICATE, 0, 0.);
+ proto_config(PROTO_AUTHENTICATE, 0, 0., NULL);
break;
case 'b':
- proto_config(PROTO_BROADCLIENT, 1, 0.);
+ proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
break;
case 'c':
@@ -214,6 +253,16 @@ getCmdOpts(
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;
@@ -223,7 +272,10 @@ getCmdOpts(
break;
case 'm':
- proto_config(PROTO_MULTICAST_ADD, htonl(INADDR_NTP), 0.);
+ 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;
@@ -259,11 +311,24 @@ getCmdOpts(
"command line broadcast delay value %s undecodable",
ntp_optarg);
} else {
- proto_config(PROTO_BROADDELAY, 0, tmp);
+ 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;
@@ -286,13 +351,50 @@ getCmdOpts(
case 'v':
case 'V':
set_sys_var(ntp_optarg, strlen(ntp_optarg)+1,
- RW | ((c == 'V') ? DEF : 0));
+ (u_short) (RW | ((c == 'V') ? DEF : 0)));
break;
case 'x':
- allow_step = FALSE;
+ 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;
@@ -307,6 +409,9 @@ getCmdOpts(
#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/ntp_config.c b/contrib/ntp/ntpd/ntp_config.c
index 660d2c5..f1428b1 100644
--- a/contrib/ntp/ntpd/ntp_config.c
+++ b/contrib/ntp/ntpd/ntp_config.c
@@ -18,10 +18,6 @@
#include "ntp_config.h"
#include "ntp_cmdargs.h"
-#ifdef PUBKEY
-# include "ntp_crypto.h"
-#endif /* PUBKEY */
-
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_SYS_PARAM_H
@@ -42,6 +38,8 @@
extern HANDLE ResolverThreadHandle;
#endif /* SYS_WINNT */
+#include <netdb.h>
+
extern int priority_done;
/*
@@ -51,43 +49,6 @@ extern int priority_done;
* Lines are considered terminated when a '#' is encountered. Blank
* lines are ignored.
*/
-
-/*
- * We understand the following configuration entries and defaults.
- *
- * peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
- * server [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
- * broadcast [ addr ] [ version 3 ] [ key 0 ] [ ttl 1 ]
- * broadcastclient
- * multicastclient [ 224.0.1.1 ]
- * manycastclient [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
- * manycastserver [ 224.0.1.1 ]
- * broadcastdelay 0.0102
- * restrict [ addr ] [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery
- * driftfile file_name
- * keys file_name
- * publickey file_name
- * privatekey file_name
- * statsdir /var/NTP/
- * filegen peerstats [ file peerstats ] [ type day ] [ link ]
- * clientlimit [ n ]
- * clientperiod [ 3600 ]
- * trustedkey [ key ]
- * requestkey [ key]
- * controlkey [ key ]
- * trap [ addr ]
- * fudge [ addr ] [ stratum ] [ refid ] ...
- * pidfile [ ]
- * setvar [ ]
- * logfile logfile
- * logconfig [+|-|=][{sync|sys|peer|clock}{{,all}{info|statistics|events|status}}]...
- * enable auth|bclient|pll|kernel|monitor|stats|calibrate
- * disable auth|bclient|pll|kernel|monitor|stats|calibrate
- * phone ...
- * pps device [assert|clear] [hardpps]
- * priority high|normal
- */
-
/*
* Translation table - keywords to function index
*/
@@ -100,16 +61,14 @@ struct keyword {
* Command keywords
*/
static struct keyword keywords[] = {
- { "authenticate", CONFIG_AUTHENTICATE },
{ "automax", CONFIG_AUTOMAX },
{ "broadcast", CONFIG_BROADCAST },
{ "broadcastclient", CONFIG_BROADCASTCLIENT },
{ "broadcastdelay", CONFIG_BDELAY },
- { "clientlimit", CONFIG_CLIENTLIMIT },
- { "clientperiod", CONFIG_CLIENTPERIOD },
-#ifdef PUBKEY
+ { "calldelay", CONFIG_CDELAY},
+#ifdef OPENSSL
{ "crypto", CONFIG_CRYPTO },
-#endif /* PUBKEY */
+#endif /* OPENSSL */
{ "controlkey", CONFIG_CONTROLKEY },
{ "disable", CONFIG_DISABLE },
{ "driftfile", CONFIG_DRIFTFILE },
@@ -118,9 +77,7 @@ static struct keyword keywords[] = {
{ "fudge", CONFIG_FUDGE },
{ "includefile", CONFIG_INCLUDEFILE },
{ "keys", CONFIG_KEYS },
-#ifdef PUBKEY
{ "keysdir", CONFIG_KEYSDIR },
-#endif /* PUBKEY */
{ "logconfig", CONFIG_LOGCONFIG },
{ "logfile", CONFIG_LOGFILE },
{ "manycastclient", CONFIG_MANYCASTCLIENT },
@@ -129,7 +86,7 @@ static struct keyword keywords[] = {
{ "peer", CONFIG_PEER },
{ "phone", CONFIG_PHONE },
{ "pidfile", CONFIG_PIDFILE },
- { "pps", CONFIG_PPS },
+ { "discard", CONFIG_DISCARD },
{ "requestkey", CONFIG_REQUESTKEY },
{ "restrict", CONFIG_RESTRICT },
{ "revoke", CONFIG_REVOKE },
@@ -137,9 +94,12 @@ static struct keyword keywords[] = {
{ "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 }
};
@@ -156,9 +116,6 @@ static struct keyword mod_keywords[] = {
{ "mode", CONF_MOD_MODE }, /* refclocks */
{ "noselect", CONF_MOD_NOSELECT },
{ "prefer", CONF_MOD_PREFER },
-#ifdef PUBKEY
- { "publickey", CONF_MOD_PUBLICKEY },
-#endif /* PUBKEY */
{ "ttl", CONF_MOD_TTL }, /* NTP peers */
{ "version", CONF_MOD_VERSION },
{ "", CONFIG_UNKNOWN }
@@ -208,7 +165,6 @@ static struct keyword fudge_keywords[] = {
{ "", CONFIG_UNKNOWN }
};
-
/*
* "filegen" modifier keywords
*/
@@ -252,12 +208,12 @@ static struct keyword flags_keywords[] = {
};
/*
- * "pps" modifier keywords
+ * "discard" modifier keywords
*/
-static struct keyword pps_keywords[] = {
- { "assert", CONF_PPS_ASSERT },
- { "clear", CONF_PPS_CLEAR },
- { "hardpps", CONF_PPS_HARDPPS },
+static struct keyword discard_keywords[] = {
+ { "average", CONF_DISCARD_AVERAGE },
+ { "minimum", CONF_DISCARD_MINIMUM },
+ { "monitor", CONF_DISCARD_MONITOR },
{ "", CONFIG_UNKNOWN }
};
@@ -269,25 +225,51 @@ static struct keyword tinker_keywords[] = {
{ "panic", CONF_CLOCK_PANIC },
{ "dispersion", CONF_CLOCK_PHI },
{ "stepout", CONF_CLOCK_MINSTEP },
- { "minpoll", CONF_CLOCK_MINPOLL },
{ "allan", CONF_CLOCK_ALLAN },
{ "huffpuff", CONF_CLOCK_HUFFPUFF },
+ { "freq", CONF_CLOCK_FREQ },
{ "", CONFIG_UNKNOWN }
};
-#ifdef PUBKEY
+/*
+ * "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[] = {
- { "dh", CONF_CRYPTO_DH },
- { "flags", CONF_CRYPTO_FLAGS },
+ { "cert", CONF_CRYPTO_CERT },
+ { "gqpar", CONF_CRYPTO_GQPAR },
+ { "host", CONF_CRYPTO_RSA },
+ { "iffpar", CONF_CRYPTO_IFFPAR },
{ "leap", CONF_CRYPTO_LEAP },
- { "privatekey", CONF_CRYPTO_PRIVATEKEY },
- { "publickey", CONF_CRYPTO_PUBLICKEY },
+ { "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 }
};
-#endif /* PUBKEY */
/*
* "logconfig" building blocks
@@ -345,6 +327,7 @@ static struct masks logcfg_item[] = {
* 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 */
@@ -358,9 +341,8 @@ static char res_file[MAX_PATH];
*/
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 */
-int pps_assert;
-int pps_hardpps;
#if defined(HAVE_SCHED_SETSCHEDULER)
int config_priority_override = 0;
int config_priority;
@@ -403,13 +385,13 @@ 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 *));
-static int getnetnum P((const char *, struct sockaddr_in *, 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)
+#if !defined(VMS) && !defined(SYS_WINNT)
static RETSIGTYPE catchchild P((int));
#endif /* VMS */
@@ -490,6 +472,7 @@ getconfig(
register int i;
int c;
int errflg;
+ int istart;
int peerversion;
int minpoll;
int maxpoll;
@@ -501,14 +484,14 @@ getconfig(
u_long fudgeflag;
u_int peerflags;
int hmode;
- struct sockaddr_in peeraddr;
- struct sockaddr_in maskaddr;
+ 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;
+ int ntokens = 0;
int tok = CONFIG_UNKNOWN;
struct interface *localaddr;
struct refclockstat clock_stat;
@@ -627,7 +610,20 @@ getconfig(
break;
}
- if (!getnetnum(tokens[1], &peeraddr, 0)) {
+ 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;
@@ -639,7 +635,7 @@ getconfig(
ISBADADR(&peeraddr)) {
msyslog(LOG_ERR,
"attempt to configure invalid address %s",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
break;
}
/*
@@ -647,23 +643,45 @@ getconfig(
* address for server/peer!
* and unicast address for manycastclient!
*/
- if (((tok == CONFIG_SERVER) ||
- (tok == CONFIG_PEER)) &&
+ if (peeraddr.ss_family == AF_INET) {
+ if (((tok == CONFIG_SERVER) ||
+ (tok == CONFIG_PEER)) &&
#ifdef REFCLOCK
- !ISREFCLOCKADR(&peeraddr) &&
+ !ISREFCLOCKADR(&peeraddr) &&
#endif
- IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- ntoa(&peeraddr));
- break;
+ 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;
+ }
}
- if ((tok == CONFIG_MANYCASTCLIENT) &&
- !IN_CLASSD(ntohl(peeraddr.sin_addr.s_addr))) {
- msyslog(LOG_ERR,
- "attempt to configure invalid address %s",
- ntoa(&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;
+ }
}
}
@@ -671,11 +689,12 @@ getconfig(
minpoll = NTP_MINDPOLL;
maxpoll = NTP_MAXDPOLL;
peerkey = 0;
- peerkeystr = "*";
+ peerkeystr = (u_char *)"*";
peerflags = 0;
ttl = 0;
- for (i = 2; i < ntokens; i++)
- switch (matchkey(tokens[i], mod_keywords)) {
+ 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,
@@ -752,43 +771,34 @@ getconfig(
case CONF_MOD_IBURST:
peerflags |= FLAG_IBURST;
break;
-#ifdef AUTOKEY
+#ifdef OPENSSL
case CONF_MOD_SKEY:
peerflags |= FLAG_SKEY |
FLAG_AUTHENABLE;
break;
-
-#ifdef PUBKEY
- case CONF_MOD_PUBLICKEY:
- if (i >= ntokens - 1) {
- msyslog(LOG_ERR,
- "Public key file name required");
- errflg = 1;
- break;
- }
- peerflags |= FLAG_SKEY |
- FLAG_AUTHENABLE;
- peerkeystr = tokens[++i];
- break;
-#endif /* PUBKEY */
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
case CONF_MOD_TTL:
if (i >= ntokens-1) {
- msyslog(LOG_ERR,
- "ttl: argument required");
- errflg = 1;
- break;
+ 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;
+ msyslog(LOG_ERR,
+ "mode: argument required");
+ errflg = 1;
+ break;
}
ttl = atoi(tokens[++i]);
break;
@@ -798,17 +808,22 @@ getconfig(
break;
}
if (minpoll > maxpoll) {
- msyslog(LOG_ERR, "config error: minpoll > maxpoll");
+ msyslog(LOG_ERR,
+ "config error: minpoll > maxpoll");
errflg = 1;
}
if (errflg == 0) {
- if (peer_config(&peeraddr, any_interface, hmode,
- peerversion, minpoll, maxpoll, peerflags,
- ttl, peerkey, peerkeystr) == 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",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
}
+ if (tok == CONFIG_MANYCASTCLIENT)
+ proto_config(PROTO_MULTICAST_ADD,
+ 0, 0., &peeraddr);
} else if (errflg == -1) {
save_resolve(tokens[1], hmode, peerversion,
@@ -910,48 +925,63 @@ getconfig(
break;
case CONFIG_BROADCASTCLIENT:
- proto_config(PROTO_BROADCLIENT, 1, 0.);
+ proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
break;
-
+
case CONFIG_MULTICASTCLIENT:
case CONFIG_MANYCASTSERVER:
if (ntokens > 1) {
- for (i = 1; i < ntokens; i++) {
+ 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,
- peeraddr.sin_addr.s_addr, 0.);
+ 0, 0., &peeraddr);
}
} else
proto_config(PROTO_MULTICAST_ADD,
- htonl(INADDR_NTP), 0.);
+ 0, 0., NULL);
if (tok == CONFIG_MULTICASTCLIENT)
sys_bclient = 1;
else if (tok == CONFIG_MANYCASTSERVER)
sys_manycastserver = 1;
break;
- case CONFIG_AUTHENTICATE:
- errflg = 0;
+ case CONFIG_KEYS:
if (ntokens >= 2) {
- if (STREQ(tokens[1], "yes"))
- proto_config(PROTO_AUTHENTICATE, 1, 0.);
- else if (STREQ(tokens[1], "no"))
- proto_config(PROTO_AUTHENTICATE, 0, 0.);
- else
- errflg++;
- } else {
- errflg++;
+ getauthkeys(tokens[1]);
}
-
- if (errflg)
- msyslog(LOG_ERR,
- "should be `authenticate yes|no'");
break;
- case CONFIG_KEYS:
- if (ntokens >= 2) {
- getauthkeys(tokens[1]);
+ 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:
@@ -959,8 +989,7 @@ getconfig(
int temp;
double ftemp;
- temp = matchkey(tokens[i++],
- tinker_keywords);
+ temp = matchkey(tokens[i++], tinker_keywords, 1);
if (i > ntokens - 1) {
msyslog(LOG_ERR,
"tinker: missing argument");
@@ -969,6 +998,7 @@ getconfig(
}
sscanf(tokens[i], "%lf", &ftemp);
switch(temp) {
+
case CONF_CLOCK_MAX:
loop_config(LOOP_MAX, ftemp);
break;
@@ -985,10 +1015,6 @@ getconfig(
loop_config(LOOP_MINSTEP, ftemp);
break;
- case CONF_CLOCK_MINPOLL:
- loop_config(LOOP_MINPOLL, ftemp);
- break;
-
case CONF_CLOCK_ALLAN:
loop_config(LOOP_ALLAN, ftemp);
break;
@@ -996,14 +1022,96 @@ getconfig(
case CONF_CLOCK_HUFFPUFF:
loop_config(LOOP_HUFFPUFF, ftemp);
break;
+
+ case CONF_CLOCK_FREQ:
+ loop_config(LOOP_FREQ, ftemp);
+ break;
}
}
break;
-#ifdef AUTOKEY
+ 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 = 1 << max(atoi(tokens[1]), 10);
+ sys_revoke = (u_char) max(atoi(tokens[1]), KEY_REVOKE);
break;
case CONFIG_AUTOMAX:
@@ -1011,25 +1119,16 @@ getconfig(
sys_automax = 1 << max(atoi(tokens[1]), 10);
break;
-#ifdef PUBKEY
- case CONFIG_KEYSDIR:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "Keys directory name required");
- break;
- }
- crypto_config(CRYPTO_CONF_KEYS, tokens[1]);
- break;
-
case CONFIG_CRYPTO:
if (ntokens == 1) {
- crypto_config(CRYPTO_CONF_FLAGS , "0");
+ crypto_config(CRYPTO_CONF_NONE, NULL);
break;
}
for (i = 1; i < ntokens; i++) {
int temp;
- temp = matchkey(tokens[i++], crypto_keywords);
+ temp = matchkey(tokens[i++],
+ crypto_keywords, 1);
if (i > ntokens - 1) {
msyslog(LOG_ERR,
"crypto: missing argument");
@@ -1037,48 +1136,88 @@ getconfig(
break;
}
switch(temp) {
- case CONF_CRYPTO_FLAGS:
- crypto_config(CRYPTO_CONF_FLAGS, tokens[i]);
+
+ case CONF_CRYPTO_CERT:
+ crypto_config(CRYPTO_CONF_CERT,
+ tokens[i]);
break;
- case CONF_CRYPTO_LEAP:
- crypto_config(CRYPTO_CONF_LEAP, tokens[i]);
+ case CONF_CRYPTO_RSA:
+ crypto_config(CRYPTO_CONF_PRIV,
+ tokens[i]);
break;
- case CONF_CRYPTO_DH:
- crypto_config(CRYPTO_CONF_DH, tokens[i]);
+ case CONF_CRYPTO_IFFPAR:
+ crypto_config(CRYPTO_CONF_IFFPAR,
+ tokens[i]);
break;
- case CONF_CRYPTO_PRIVATEKEY:
- crypto_config(CRYPTO_CONF_PRIV, tokens[i]);
+ case CONF_CRYPTO_GQPAR:
+ crypto_config(CRYPTO_CONF_GQPAR,
+ tokens[i]);
break;
- case CONF_CRYPTO_PUBLICKEY:
- crypto_config(CRYPTO_CONF_PUBL, tokens[i]);
+ case CONF_CRYPTO_MVPAR:
+ crypto_config(CRYPTO_CONF_MVPAR,
+ tokens[i]);
break;
- case CONF_CRYPTO_CERT:
- crypto_config(CRYPTO_CONF_CERT, tokens[i]);
+ 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");
+ msyslog(LOG_ERR,
+ "crypto: unknown keyword");
break;
}
}
break;
-#endif /* PUBKEY */
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
case CONFIG_RESTRICT:
if (ntokens < 2) {
msyslog(LOG_ERR, "restrict requires an address");
break;
}
- if (STREQ(tokens[1], "default"))
- peeraddr.sin_addr.s_addr = htonl(INADDR_ANY);
- else if (!getnetnum(tokens[1], &peeraddr, 1))
- 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.
@@ -1086,9 +1225,10 @@ getconfig(
peerversion = 0;
peerkey = 0;
errflg = 0;
- maskaddr.sin_addr.s_addr = ~(u_int32)0;
- for (i = 2; i < ntokens; i++) {
- switch (matchkey(tokens[i], res_keywords)) {
+ 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,
@@ -1154,8 +1294,8 @@ getconfig(
break;
}
}
- if (SRCADR(&peeraddr) == htonl(INADDR_ANY))
- maskaddr.sin_addr.s_addr = 0;
+ if (SOCKNUL(&peeraddr))
+ ANYSOCK(&maskaddr);
if (!errflg)
hack_restrict(RESTRICT_FLAGS, &peeraddr, &maskaddr,
(int)peerkey, peerversion);
@@ -1170,11 +1310,23 @@ getconfig(
"broadcastdelay value %s undecodable",
tokens[1]);
} else {
- proto_config(PROTO_BROADDELAY, 0, tmp);
+ 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;
@@ -1232,7 +1384,20 @@ getconfig(
"no address for trap command, line ignored");
break;
}
- if (!getnetnum(tokens[1], &peeraddr, 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;
+ }
+
+ if (!getnetnum(tokens[istart], &peeraddr, 1))
break;
/*
@@ -1241,8 +1406,9 @@ getconfig(
errflg = 0;
peerversion = 0;
localaddr = 0;
- for (i = 2; i < ntokens-1; i++)
- switch (matchkey(tokens[i], trap_keywords)) {
+ 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,
@@ -1268,6 +1434,9 @@ getconfig(
break;
}
+ memset((char *)&maskaddr, 0,
+ sizeof(maskaddr));
+ maskaddr.ss_family = peeraddr.ss_family;
if (!getnetnum(tokens[++i],
&maskaddr, 1)) {
errflg = 1;
@@ -1278,7 +1447,7 @@ getconfig(
if (localaddr == NULL) {
msyslog(LOG_ERR,
"can't find interface with address %s",
- ntoa(&maskaddr));
+ stoa(&maskaddr));
errflg = 1;
}
break;
@@ -1290,16 +1459,16 @@ getconfig(
if (!errflg) {
if (peerversion != 0)
- peeraddr.sin_port = htons( (u_short) peerversion);
+ ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons( (u_short) peerversion);
else
- peeraddr.sin_port = htons(TRAPPORT);
+ ((struct sockaddr_in6*)&peeraddr)->sin6_port = htons(TRAPPORT);
if (localaddr == NULL)
- localaddr = any_interface;
+ localaddr = ANY_INTERFACE_CHOOSE(&peeraddr);
if (!ctlsettrap(&peeraddr, localaddr, 0,
NTP_VERSION))
msyslog(LOG_ERR,
"can't set trap for %s, no resources",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
}
break;
@@ -1309,13 +1478,14 @@ getconfig(
"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",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
break;
}
@@ -1324,13 +1494,13 @@ getconfig(
errflg = 0;
for (i = 2; i < ntokens-1; i++) {
switch (c = matchkey(tokens[i],
- fudge_keywords)) {
+ 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",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
errflg = i;
break;
}
@@ -1342,7 +1512,7 @@ getconfig(
&clock_stat.fudgetime2) != 1) {
msyslog(LOG_ERR,
"fudge %s time2 value in error",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
errflg = i;
break;
}
@@ -1355,7 +1525,7 @@ getconfig(
{
msyslog(LOG_ERR,
"fudge %s stratum value in error",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
errflg = i;
break;
}
@@ -1379,7 +1549,7 @@ getconfig(
|| fudgeflag > 1) {
msyslog(LOG_ERR,
"fudge %s flag value in error",
- ntoa(&peeraddr));
+ stoa(&peeraddr));
errflg = i;
break;
}
@@ -1475,7 +1645,8 @@ getconfig(
errflg = 0;
for (i = 2; i < ntokens; i++) {
- switch (matchkey(tokens[i], filegen_keywords)) {
+ switch (matchkey(tokens[i],
+ filegen_keywords, 1)) {
case CONF_FGEN_FILE:
if (i >= ntokens - 1) {
msyslog(LOG_ERR,
@@ -1494,7 +1665,8 @@ getconfig(
errflg = i;
break;
}
- peerkey = matchkey(tokens[++i], fgen_types);
+ peerkey = matchkey(tokens[++i],
+ fgen_types, 1);
if (peerkey == CONFIG_UNKNOWN) {
msyslog(LOG_ERR,
"filegen %s unknown type \"%s\"",
@@ -1532,55 +1704,12 @@ getconfig(
"no value for setvar command - line ignored");
} else {
set_sys_var(tokens[1], strlen(tokens[1])+1,
- RW |
+ (u_short) (RW |
((((ntokens > 2)
&& !strcmp(tokens[2],
"default")))
? DEF
- : 0));
- }
- break;
-
- case CONFIG_CLIENTLIMIT:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no value for clientlimit command - line ignored");
- } else {
- u_long ui;
-
- if (!atouint(tokens[1], &ui) || !ui) {
- msyslog(LOG_ERR,
- "illegal value for clientlimit command - line ignored");
- } else {
- char bp[80];
-
-#ifdef DEBUG
- if (debug)
- sprintf(bp, "client_limit=%lu", ui);
-#endif
- set_sys_var(bp, strlen(bp)+1, RO);
- client_limit = ui;
- }
- }
- break;
-
- case CONFIG_CLIENTPERIOD:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "no value for clientperiod command - line ignored");
- } else {
- u_long ui;
-
- if (!atouint(tokens[1], &ui) || ui < 64) {
- msyslog(LOG_ERR,
- "illegal value for clientperiod command - line ignored");
- } else {
- char bp[80];
-
- sprintf(bp, "client_limit_period=%ld", ui);
- set_sys_var(bp, strlen(bp)+1, RO);
- client_limit_period = ui;
- }
+ : 0)));
}
break;
@@ -1588,7 +1717,7 @@ getconfig(
for (i = 1; i < ntokens; i++) {
int flag;
- flag = matchkey(tokens[i], flags_keywords);
+ flag = matchkey(tokens[i], flags_keywords, 1);
if (flag == CONFIG_UNKNOWN) {
msyslog(LOG_ERR,
"enable unknown flag %s",
@@ -1596,7 +1725,7 @@ getconfig(
errflg = 1;
break;
}
- proto_config(flag, 1, 0.);
+ proto_config(flag, 1, 0., NULL);
}
break;
@@ -1604,7 +1733,7 @@ getconfig(
for (i = 1; i < ntokens; i++) {
int flag;
- flag = matchkey(tokens[i], flags_keywords);
+ flag = matchkey(tokens[i], flags_keywords, 1);
if (flag == CONFIG_UNKNOWN) {
msyslog(LOG_ERR,
"disable unknown flag %s",
@@ -1612,7 +1741,7 @@ getconfig(
errflg = 1;
break;
}
- proto_config(flag, 0, 0.);
+ proto_config(flag, 0, 0., NULL);
}
break;
@@ -1624,38 +1753,14 @@ getconfig(
sys_phone[i - 1][0] = '\0';
break;
- case CONFIG_PPS:
- if (ntokens < 2) {
- msyslog(LOG_ERR,
- "pps missing device name");
- break;
- }
- (void)strncpy(pps_device, tokens[1], MAXPPS);
- for (i = 2; i < ntokens; i++) {
- int flag;
+ case CONFIG_ADJ: {
+ double ftemp;
- flag = matchkey(tokens[i], pps_keywords);
- switch(flag) {
- case CONF_PPS_ASSERT:
- pps_assert = 0;
- break;
- case CONF_PPS_CLEAR:
- pps_assert = 1;
- break;
- case CONF_PPS_HARDPPS:
- pps_hardpps = 1;
- break;
- default:
- msyslog(LOG_ERR,
- "pps unknown flag %s",
- tokens[i]);
- errflg = 1;
- break;
- }
- if(errflg)
- break;
+ sscanf(tokens[1], "%lf", &ftemp);
+ proto_config(PROTO_ADJ, 0, ftemp, NULL);
}
break;
+
}
}
if (fp[0])
@@ -1680,7 +1785,7 @@ getconfig(
for (i = 0; i < 8; i++)
for (j = 1; j < 100; ++j) {
- rankey[i] = RANDOM & 0xff;
+ rankey[i] = (char) (RANDOM & 0xff);
if (rankey[i] != 0) break;
}
rankey[8] = 0;
@@ -1697,10 +1802,12 @@ getconfig(
#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
if (res_fp != NULL) {
- /*
- * Need name resolution
- */
- do_resolve_internal();
+ if (call_resolver) {
+ /*
+ * Need name resolution
+ */
+ do_resolve_internal();
+ }
}
}
@@ -1801,7 +1908,7 @@ gettokens_netinfo (
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))))
+ if (! (val_list[index] = (char*)malloc(strlen(value)+1)))
{ msyslog(LOG_ERR, "out of memory while configuring"); break; }
strcpy(val_list[index], value);
@@ -1921,7 +2028,7 @@ gettokens (
* Return the match
*/
*ntokens = ntok + 1;
- ntok = matchkey(tokenlist[0], keywords);
+ ntok = matchkey(tokenlist[0], keywords, 1);
if (ntok == CONFIG_UNKNOWN)
goto again;
return ntok;
@@ -1935,14 +2042,16 @@ gettokens (
static int
matchkey(
register char *word,
- register struct keyword *keys
+ register struct keyword *keys,
+ int complain
)
{
for (;;) {
if (keys->keytype == CONFIG_UNKNOWN) {
- msyslog(LOG_ERR,
- "configure: keyword \"%s\" unknown, line ignored",
- word);
+ if (complain)
+ msyslog(LOG_ERR,
+ "configure: keyword \"%s\" unknown, line ignored",
+ word);
return CONFIG_UNKNOWN;
}
if (STRSAME(word, keys->text))
@@ -1958,77 +2067,53 @@ matchkey(
static int
getnetnum(
const char *num,
- struct sockaddr_in *addr,
+ struct sockaddr_storage *addr,
int complain
)
{
- register const char *cp;
- register char *bp;
- register int i;
- register int temp;
- char buf[80]; /* will core dump on really stupid stuff */
- u_int32 netnum;
-
- /* XXX ELIMINATE replace with decodenetnum */
- cp = num;
- netnum = 0;
- for (i = 0; i < 4; i++) {
- bp = buf;
- while (isdigit((int)*cp))
- *bp++ = *cp++;
- if (bp == buf)
- break;
+ struct addrinfo hints;
+ struct addrinfo *ptr;
- if (i < 3) {
- if (*cp++ != '.')
- break;
- } else if (*cp != '\0')
- break;
+ /* 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;
- *bp = '\0';
- temp = atoi(buf);
- if (temp > 255)
- break;
- netnum <<= 8;
- netnum += temp;
+ hints.ai_socktype = SOCK_DGRAM;
#ifdef DEBUG
if (debug > 3)
- printf("getnetnum %s step %d buf %s temp %d netnum %lu\n",
- num, i, buf, temp, (u_long)netnum);
+ printf("getaddrinfo %s\n", num);
#endif
- }
-
- if (i < 4) {
+ if (getaddrinfo(num, "ntp", &hints, &ptr)!=0) {
if (complain)
msyslog(LOG_ERR,
- "getnetnum: \"%s\" invalid host number, line ignored",
+ "getaddrinfo: \"%s\" invalid host address, line ignored",
num);
#ifdef DEBUG
if (debug > 3)
printf(
- "getnetnum: \"%s\" invalid host number, line ignored\n",
- num);
+ "getaddrinfo: \"%s\" invalid host address%s.\n",
+ num, (complain)
+ ? ", line ignored"
+ : "");
#endif
return 0;
}
- /*
- * make up socket address. Clear it out for neatness.
- */
- memset((void *)addr, 0, sizeof(struct sockaddr_in));
- addr->sin_family = AF_INET;
- addr->sin_port = htons(NTP_PORT);
- addr->sin_addr.s_addr = htonl(netnum);
+ memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
#ifdef DEBUG
if (debug > 1)
- printf("getnetnum given %s, got %s (%lx)\n",
- num, ntoa(addr), (u_long)netnum);
+ printf("getnetnum given %s, got %s \n",
+ num, stoa(addr));
#endif
+ freeaddrinfo(ptr);
return 1;
}
-#if !defined(VMS)
+#if !defined(VMS) && !defined(SYS_WINNT)
/*
* catchchild - receive the resolver's exit status
*/
@@ -2072,8 +2157,7 @@ save_resolve(
#else
/* no /tmp directory under NT */
{
- DWORD len;
- if(!(len = GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
+ if(!(GetTempPath((DWORD)MAX_PATH, (LPTSTR)res_file))) {
msyslog(LOG_ERR, "cannot get pathname for temporary directory: %m");
return;
}
@@ -2211,7 +2295,7 @@ do_resolve_internal(void)
*/
closelog();
- kill_asyncio();
+ kill_asyncio(0);
(void) signal_no_reset(SIGCHLD, SIG_DFL);
@@ -2266,13 +2350,14 @@ do_resolve_internal(void)
*/
DWORD dwThreadId;
fflush(stdout);
- if (!(ResolverThreadHandle = CreateThread(
- NULL, /* no security attributes */
- 0, /* use default stack size */
+ 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 */
+ 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();
}
diff --git a/contrib/ntp/ntpd/ntp_control.c b/contrib/ntp/ntpd/ntp_control.c
index d7109ca..0ac0404 100644
--- a/contrib/ntp/ntpd/ntp_control.c
+++ b/contrib/ntp/ntpd/ntp_control.c
@@ -18,10 +18,6 @@
#include <netinet/in.h>
#include <arpa/inet.h>
-#ifdef PUBKEY
-#include "ntp_crypto.h"
-#endif /* PUBKEY */
-
/*
* Structure to hold request procedure information
*/
@@ -46,7 +42,9 @@ struct ctl_proc {
* 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 *,
@@ -56,7 +54,7 @@ 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));
+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));
@@ -74,7 +72,7 @@ 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_in *,
+static struct ctl_trap *ctlfindtrap P((struct sockaddr_storage *,
struct interface *));
static struct ctl_proc control_codes[] = {
@@ -114,16 +112,16 @@ static struct ctl_var sys_var[] = {
{ CS_VERSION, RO, "version" }, /* 17 */
{ CS_STABIL, RO, "stability" }, /* 18 */
{ CS_VARLIST, RO, "sys_var_list" }, /* 19 */
-#ifdef PUBKEY
+#ifdef OPENSSL
{ CS_FLAGS, RO, "flags" }, /* 20 */
{ CS_HOST, RO, "hostname" }, /* 21 */
- { CS_PUBLIC, RO, "publickey" }, /* 22 */
- { CS_CERTIF, RO, "certificate" }, /* 23 */
- { CS_DHPARAMS, RO, "params" }, /* 24 */
- { CS_REVTIME, RO, "refresh" }, /* 25 */
- { CS_LEAPTAB, RO, "leapseconds" }, /* 26 */
- { CS_TAI, RO, "tai"}, /* 27 */
-#endif /* PUBKEY */
+ { 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 */
};
@@ -152,14 +150,15 @@ static u_char def_sys_var[] = {
CS_DRIFT,
CS_JITTER,
CS_STABIL,
-#ifdef PUBKEY
- CS_FLAGS,
+#ifdef OPENSSL
CS_HOST,
- CS_CERTIF,
- CS_DHPARAMS,
+ CS_DIGEST,
+ CS_FLAGS,
+ CS_PUBLIC,
CS_REVTIME,
CS_LEAPTAB,
-#endif /* PUBKEY */
+ CS_CERTIF,
+#endif /* OPENSSL */
0
};
@@ -205,20 +204,18 @@ static struct ctl_var peer_var[] = {
{ CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
{ CP_FLASH, RO, "flash" }, /* 35 */
{ CP_TTL, RO, "ttl" }, /* 36 */
- { CP_TTLMAX, RO, "ttlmax" }, /* 37 */
+ { CP_RANK, RO, "rank" }, /* 37 */
{ CP_VARLIST, RO, "peer_var_list" }, /* 38 */
-#ifdef PUBKEY
- { CP_FLAGS, RO, "flags" }, /* 38 */
- { CP_HOST, RO, "hostname" }, /* 39 */
- { CP_PUBLIC, RO, "publickey" }, /* 40 */
- { CP_CERTIF, RO, "certificate" }, /* 41 */
- { CP_SESKEY, RO, "pcookie" }, /* 42 */
- { CP_SASKEY, RO, "hcookie" }, /* 43 */
- { CP_INITSEQ, RO, "initsequence" }, /* 44 */
- { CP_INITKEY, RO, "initkey" }, /* 45 */
- { CP_INITTSP, RO, "timestamp" }, /* 46 */
-#endif /* PUBKEY */
- { 0, EOV, "" } /* 47 */
+#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 */
};
@@ -245,7 +242,6 @@ static u_char def_peer_var[] = {
CP_FLASH,
CP_KEYID,
CP_TTL,
- CP_TTLMAX,
CP_OFFSET,
CP_DELAY,
CP_DISPERSION,
@@ -257,13 +253,13 @@ static u_char def_peer_var[] = {
CP_FILTDELAY,
CP_FILTOFFSET,
CP_FILTERROR,
-#ifdef PUBKEY
- CP_FLAGS,
+#ifdef OPENSSL
CP_HOST,
- CP_CERTIF,
- CP_SESKEY,
+ CP_DIGEST,
+ CP_FLAGS,
+ CP_IDENT,
CP_INITSEQ,
-#endif /* PUBKEY */
+#endif /* OPENSSL */
0
};
@@ -450,7 +446,7 @@ static u_char * datapt;
static u_char * dataend;
static int datalinelen;
static int datanotbinflag;
-static struct sockaddr_in *rmt_addr;
+static struct sockaddr_storage *rmt_addr;
static struct interface *lcl_inter;
static u_char res_authenticate;
@@ -735,14 +731,16 @@ ctlpeerstatus(
/*
* 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) |
- (u_short)(this_clock->lastevent);
+ return ((u_short)(((this_clock->currentstatus) << 8) |
+ (this_clock->lastevent)));
}
+#endif
/*
@@ -1074,12 +1072,13 @@ ctl_putts(
/*
- * ctl_putadr - write a dotted quad IP address into the response
+ * ctl_putadr - write an IP address into the response
*/
static void
ctl_putadr(
const char *tag,
- u_int32 addr
+ u_int32 addr32,
+ struct sockaddr_storage* addr
)
{
register char *cp;
@@ -1092,7 +1091,10 @@ ctl_putadr(
*cp++ = *cq++;
*cp++ = '=';
- cq = numtoa(addr);
+ if (addr == NULL)
+ cq = numtoa(addr32);
+ else
+ cq = stoa(addr);
while (*cq != '\0')
*cp++ = *cq++;
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
@@ -1139,7 +1141,6 @@ ctl_putarray(
register const char *cq;
char buffer[200];
int i;
-
cp = buffer;
cq = tag;
while (*cq != '\0')
@@ -1166,9 +1167,11 @@ ctl_putsys(
)
{
l_fp tmp;
-#ifdef HAVE_UNAME
char str[256];
-#endif
+#ifdef OPENSSL
+ struct cert_info *cp;
+ char cbuf[256];
+#endif /* OPENSSL */
switch (varid) {
@@ -1195,8 +1198,8 @@ ctl_putsys(
break;
case CS_REFID:
- if (sys_stratum > 1)
- ctl_putadr(sys_var[CS_REFID].text, sys_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);
@@ -1254,8 +1257,7 @@ ctl_putsys(
ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
sizeof(str_system) - 1);
#else
- (void)strcpy(str, utsnamebuf.sysname);
- (void)strcat(str, utsnamebuf.release);
+ sprintf(str, "%s/%s", utsnamebuf.sysname, utsnamebuf.release);
ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
#endif /* HAVE_UNAME */
break;
@@ -1333,37 +1335,50 @@ ctl_putsys(
}
break;
-#ifdef PUBKEY
+#ifdef OPENSSL
case CS_FLAGS:
- if (crypto_flags)
- ctl_puthex(sys_var[CS_FLAGS].text,
- crypto_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:
- ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
- strlen(sys_hostname));
- if (host.fstamp != 0)
- ctl_putuint(sys_var[CS_PUBLIC].text,
- ntohl(host.fstamp));
+ if (sys_hostname != NULL)
+ ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
+ strlen(sys_hostname));
break;
case CS_CERTIF:
- if (certif.fstamp != 0)
- ctl_putuint(sys_var[CS_CERTIF].text,
- ntohl(certif.fstamp));
+ 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_DHPARAMS:
- if (dhparam.fstamp != 0)
- ctl_putuint(sys_var[CS_DHPARAMS].text,
- ntohl(dhparam.fstamp));
+ case CS_PUBLIC:
+ if (hostval.fstamp != 0)
+ ctl_putuint(sys_var[CS_PUBLIC].text,
+ ntohl(hostval.fstamp));
break;
case CS_REVTIME:
- if (host.tstamp != 0)
+ if (hostval.tstamp != 0)
ctl_putuint(sys_var[CS_REVTIME].text,
- ntohl(host.tstamp));
+ ntohl(hostval.tstamp));
break;
case CS_LEAPTAB:
@@ -1373,7 +1388,7 @@ ctl_putsys(
if (sys_tai != 0)
ctl_putuint(sys_var[CS_TAI].text, sys_tai);
break;
-#endif /* PUBKEY */
+#endif /* OPENSSL */
}
}
@@ -1387,6 +1402,11 @@ ctl_putpeer(
struct peer *peer
)
{
+#ifdef OPENSSL
+ char str[256];
+ struct autokey *ap;
+#endif /* OPENSSL */
+
switch (varid) {
case CP_CONFIG:
@@ -1405,24 +1425,24 @@ ctl_putpeer(
break;
case CP_SRCADR:
- ctl_putadr(peer_var[CP_SRCADR].text,
- peer->srcadr.sin_addr.s_addr);
+ ctl_putadr(peer_var[CP_SRCADR].text, 0,
+ &peer->srcadr);
break;
case CP_SRCPORT:
ctl_putuint(peer_var[CP_SRCPORT].text,
- ntohs(peer->srcadr.sin_port));
+ ntohs(((struct sockaddr_in*)&peer->srcadr)->sin_port));
break;
case CP_DSTADR:
- ctl_putadr(peer_var[CP_DSTADR].text,
- peer->dstadr->sin.sin_addr.s_addr);
+ 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(peer->dstadr->sin.sin_port) : 0));
+ ntohs(((struct sockaddr_in*)&peer->dstadr->sin)->sin_port) : 0));
break;
case CP_LEAP:
@@ -1461,16 +1481,22 @@ ctl_putpeer(
break;
case CP_REFID:
- if (peer->stratum > 1) {
- if (peer->flags & FLAG_REFCLOCK)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->srcadr.sin_addr.s_addr);
+ 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_putadr(peer_var[CP_REFID].text,
- peer->refid);
+ ctl_putid(peer_var[CP_REFID].text,
+ (char *)&peer->refid);
} else {
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
+ 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;
@@ -1499,21 +1525,17 @@ ctl_putpeer(
break;
case CP_TTL:
- if (!(peer->cast_flags & MDF_ACAST))
- break;
- ctl_putint(peer_var[CP_TTL].text, peer->ttl);
- break;
-
- case CP_TTLMAX:
- if (!(peer->cast_flags & (MDF_MCAST | MDF_ACAST)))
- break;
- ctl_putint(peer_var[CP_TTLMAX].text, peer->ttlmax);
+ 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);
@@ -1607,47 +1629,44 @@ ctl_putpeer(
ctl_putdata(buf, (unsigned)(s - buf), 0);
}
break;
-#ifdef PUBKEY
+#ifdef OPENSSL
case CP_FLAGS:
if (peer->crypto)
ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
break;
- case CP_HOST:
- if (peer->keystr != NULL)
- ctl_putstr(peer_var[CP_HOST].text, peer->keystr,
- strlen(peer->keystr));
- if (peer->pubkey.fstamp != 0)
- ctl_putuint(peer_var[CP_PUBLIC].text,
- peer->pubkey.fstamp);
+ 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_CERTIF:
- if (peer->certif.fstamp != 0)
- ctl_putuint(peer_var[CP_CERTIF].text,
- peer->certif.fstamp);
+ case CP_HOST:
+ if (peer->subject != NULL)
+ ctl_putstr(peer_var[CP_HOST].text, peer->subject,
+ strlen(peer->subject));
break;
- case CP_SESKEY:
- if (peer->pcookie.key != 0)
- ctl_puthex(peer_var[CP_SESKEY].text,
- peer->pcookie.key);
- if (peer->hcookie != 0)
- ctl_puthex(peer_var[CP_SASKEY].text,
- peer->hcookie);
+ case CP_IDENT:
+ if (peer->issuer != NULL)
+ ctl_putstr(peer_var[CP_IDENT].text, peer->issuer,
+ strlen(peer->issuer));
break;
case CP_INITSEQ:
- if (peer->recauto.key == 0)
+ if ((ap = (struct autokey *)peer->recval.ptr) == NULL)
break;
- ctl_putint(peer_var[CP_INITSEQ].text,
- peer->recauto.seq);
- ctl_puthex(peer_var[CP_INITKEY].text,
- peer->recauto.key);
+ 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,
- peer->recauto.tstamp);
+ ntohl(peer->recval.tstamp));
break;
-#endif /* PUBKEY */
+#endif /* OPENSSL */
}
}
@@ -1717,7 +1736,7 @@ ctl_putclock(
if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
if (clock_stat->fudgeval1 > 1)
ctl_putadr(clock_var[CC_FUDGEVAL2].text,
- (u_int32)clock_stat->fudgeval2);
+ (u_int32)clock_stat->fudgeval2, NULL);
else
ctl_putid(clock_var[CC_FUDGEVAL2].text,
(char *)&clock_stat->fudgeval2);
@@ -1876,7 +1895,7 @@ ctl_getitem(
numctlbadpkts++;
msyslog(LOG_WARNING,
"Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
- inet_ntoa(rmt_addr->sin_addr), ntohs(rmt_addr->sin_port)
+ stoa(rmt_addr), SRCPORT(rmt_addr)
);
return (0);
}
@@ -1884,10 +1903,10 @@ ctl_getitem(
if (cp < reqend)
cp++;
*tp-- = '\0';
- while (tp > buf) {
- *tp-- = '\0';
+ while (tp >= buf) {
if (!isspace((int)(*tp)))
break;
+ *tp-- = '\0';
}
reqpt = cp;
*data = buf;
@@ -2130,7 +2149,7 @@ write_variables(
register struct ctl_var *v;
register int ext_var;
char *valuep;
- long val;
+ long val = 0;
/*
* If he's trying to write into a peer tell him no way
@@ -2434,7 +2453,7 @@ unset_trap(
*/
int
ctlsettrap(
- struct sockaddr_in *raddr,
+ struct sockaddr_storage *raddr,
struct interface *linter,
int traptype,
int version
@@ -2539,7 +2558,7 @@ ctlsettrap(
tptouse->tr_sequence = 1;
tptouse->tr_addr = *raddr;
tptouse->tr_localaddr = linter;
- tptouse->tr_version = version;
+ tptouse->tr_version = (u_char) version;
tptouse->tr_flags = TRAP_INUSE;
if (traptype == TRAP_TYPE_CONFIG)
tptouse->tr_flags |= TRAP_CONFIGURED;
@@ -2555,7 +2574,7 @@ ctlsettrap(
*/
int
ctlclrtrap(
- struct sockaddr_in *raddr,
+ struct sockaddr_storage *raddr,
struct interface *linter,
int traptype
)
@@ -2580,18 +2599,18 @@ ctlclrtrap(
*/
static struct ctl_trap *
ctlfindtrap(
- struct sockaddr_in *raddr,
+ 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 && NSRCADR(raddr) ==
- NSRCADR(&tp->tr_addr) && NSRCPORT(raddr) ==
- NSRCPORT(&tp->tr_addr) && linter ==
- tp->tr_localaddr)
- return (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;
}
@@ -2612,7 +2631,7 @@ report_event(
* Record error code in proper spots, but have mercy on the
* log file.
*/
- if (!(err & PEER_EVENT)) {
+ 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) {
@@ -2634,10 +2653,10 @@ report_event(
#ifdef REFCLOCK
if (ISREFCLOCKADR(&peer->srcadr))
- src = refnumtoa(peer->srcadr.sin_addr.s_addr);
+ src = refnumtoa(&peer->srcadr);
else
#endif
- src = ntoa(&peer->srcadr);
+ src = stoa(&peer->srcadr);
peer->last_event = (u_char)(err & ~PEER_EVENT);
if (peer->num_events < CTL_PEER_MAXEVENTS)
@@ -2690,10 +2709,10 @@ report_event(
* variables. Don't send crypto strings.
*/
for (i = 1; i <= CS_MAXCODE; i++) {
-#ifdef PUBKEY
+#ifdef OPENSSL
if (i > CS_VARLIST)
continue;
-#endif /* PUBKEY */
+#endif /* OPENSSL */
ctl_putsys(i);
}
#ifdef REFCLOCK
@@ -2719,7 +2738,7 @@ report_event(
strlen(kv->text), 0);
free_varlist(clock_stat.kv_list);
}
-#endif /*REFCLOCK*/
+#endif /* REFCLOCK */
} else {
rpkt.associd = htons(peer->associd);
rpkt.status = htons(ctlpeerstatus(peer));
@@ -2727,12 +2746,13 @@ report_event(
/*
* Dump it all. Later, maybe less.
*/
- for (i = 1; i <= CP_MAXCODE; i++)
-#ifdef PUBKEY
+ for (i = 1; i <= CP_MAXCODE; i++) {
+#ifdef OPENSSL
if (i > CP_VARLIST)
continue;
-#endif /* PUBKEY */
+#endif /* OPENSSL */
ctl_putpeer(i, peer);
+ }
#ifdef REFCLOCK
/*
* for clock exception events: add clock variables to
@@ -2758,7 +2778,7 @@ report_event(
strlen(kv->text), 0);
free_varlist(clock_stat.kv_list);
}
-#endif /*REFCLOCK*/
+#endif /* REFCLOCK */
}
/*
@@ -2812,7 +2832,7 @@ char *
add_var(
struct ctl_var **kv,
u_long size,
- int def
+ u_short def
)
{
register u_long c;
@@ -2841,7 +2861,7 @@ set_var(
struct ctl_var **kv,
const char *data,
u_long size,
- int def
+ u_short def
)
{
register struct ctl_var *k;
@@ -2852,7 +2872,8 @@ set_var(
if (!data || !size)
return;
- if ((k = *kv)) {
+ k = *kv;
+ if (k != NULL) {
while (!(k->flags & EOV)) {
s = data;
t = k->text;
@@ -2887,7 +2908,7 @@ void
set_sys_var(
char *data,
u_long size,
- int def
+ u_short def
)
{
set_var(&ext_sys_var, data, size, def);
diff --git a/contrib/ntp/ntpd/ntp_crypto.c b/contrib/ntp/ntpd/ntp_crypto.c
index 19f902a..3e67703 100644
--- a/contrib/ntp/ntpd/ntp_crypto.c
+++ b/contrib/ntp/ntpd/ntp_crypto.c
@@ -5,136 +5,167 @@
#include <config.h>
#endif
-#ifdef AUTOKEY
+#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 "ntp_crypto.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 formats
- *
- * +-------+-------+ +-------+-------+ +-------+-------+
- * 0 | 3 | len | | 2,4 | len | | 5-9 | len |
- * +-------+-------+ +-------+-------+ +-------+-------+
- * 1 | assocID | | assocID | | assocID |
- * +---------------+ +---------------+ +---------------+
- * 2 | timestamp | | timestamp | | timestamp |
- * +---------------+ +---------------+ +---------------+
- * 3 | final seq | | cookie/flags | | filestamp |
- * +---------------+ +---------------+ +---------------+
- * 4 | final key | | signature len | | value len |
- * +---------------+ +---------------+ +---------------+
- * 5 | signature len | | | | |
- * +---------------+ = signature = = value =
- * 6 | | | | | |
- * = signature = +---------------+ +---------------+
- * 7 | | CRYPTO_ASSOC rsp | signature len |
- * +---------------+ CRYPTO_PRIV rsp +---------------+
- * CRYPTO_AUTO rsp | |
- * = signature =
- * | |
- * +---------------+
- * CRYPTO_DHPAR rsp
- * CRYPTO_DH rsp
- * CRYPTO_NAME rsp
- * CRYPTO_CERT rsp
- * CRYPTO_TAI rsp
- *
- * CRYPTO_STAT 1 - offer/select
- * CRYPTO_ASSOC 2 20 association ID
- * CRYPTO_AUTO 3 88 autokey values
- * CRYPTO_PRIV 4 84 cookie value
- * CRYPTO_DHPAR 5 220 agreement parameters
- * CRYPTO_DH 6 152 public value
- * CRYPTO_NAME 7 460 host name/public key
- * CRYPTO_CERT 8 ? certificate
- * CRYPTO_TAI 9 144 leapseconds table
- *
- * Note: requests carry the association ID of the receiver; responses
- * carry the association ID of the sender.
+ * 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.
*/
/*
- * Minimum sizes of fields
+ * Cryptodefines
*/
-#define COOKIE_LEN (5 * 4)
-#define AUTOKEY_LEN (6 * 4)
-#define VALUE_LEN (6 * 4)
+#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.
+ * Global cryptodata in host byte order
*/
-u_int crypto_flags; /* status word */
+u_int32 crypto_flags = 0x0; /* status word */
u_int sys_tai; /* current UTC offset from TAI */
-#ifdef PUBKEY
/*
- * Cryptodefines
- */
-#define TAI_1972 10 /* initial TAI offset */
-#define MAX_LEAP 100 /* max UTC leapseconds */
-#define MAX_LINLEN 1024 /* max line */
-#define MAX_KEYLEN 1024 /* max key */
-#define MAX_ENCLEN (ENCODED_CONTENT_LEN(1024)) /* max enc key */
-
-/*
- * Private cryptodata in network byte order.
+ * Global cryptodata in network byte order
*/
-static R_RSA_PRIVATE_KEY private_key; /* private key */
-static R_RSA_PUBLIC_KEY public_key; /* public key */
-static R_DH_PARAMS dh_params; /* agreement parameters */
-static u_char *dh_private; /* private value */
-static u_int dh_keyLen; /* private value length */
-static char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
-static char *private_key_file = NULL; /* private key file */
-static char *public_key_file = NULL; /* public key file */
-static char *certif_file = NULL; /* certificate file */
-static char *dh_params_file = NULL; /* agreement parameters file */
-static char *tai_leap_file = NULL; /* leapseconds file */
+struct cert_info *cinfo = NULL; /* certificate info/value */
+struct value hostval; /* host value */
+struct value pubkey; /* public key */
+struct value tai_leap; /* leapseconds table */
/*
- * Global cryptodata in network byte order
+ * Private cryptodata in host byte order
*/
-struct value host; /* host name/public key */
-struct value certif; /* certificate */
-struct value dhparam; /* agreement parameters */
-struct value dhpub; /* public value */
-struct value tai_leap; /* leapseconds table */
+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 u_int crypto_rsa P((char *, u_char *, u_int));
-static void crypto_cert P((char *));
-static void crypto_dh P((char *));
+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 *));
-#endif /* PUBKEY */
-/*
- * Autokey protocol status codes
- */
-#define RV_OK 0 /* success */
-#define RV_LEN 1 /* invalid field length */
-#define RV_TSP 2 /* invalid timestamp */
-#define RV_FSP 3 /* invalid filestamp */
-#define RV_PUB 4 /* missing public key */
-#define RV_KEY 5 /* invalid RSA modulus */
-#define RV_SIG 6 /* invalid signature length */
-#define RV_DH 7 /* invalid agreement parameters */
-#define RV_FIL 8 /* missing or corrupted key file */
-#define RV_DAT 9 /* missing or corrupted data */
-#define RV_DEC 10 /* PEM decoding error */
-#define RV_DUP 11 /* duplicate flags */
-#define RV_VN 12 /* incorrect version */
+#ifdef SYS_WINNT
+int
+readlink(char * link, char * file, int len) {
+ return (-1);
+}
+#endif
/*
* session_key - generate session key
@@ -143,43 +174,61 @@ static void crypto_tai P((char *));
* 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 /* returns next key ID */
+keyid_t
session_key(
- struct sockaddr_in *srcadr, /* source address */
- struct sockaddr_in *dstadr, /* destination address */
- keyid_t keyno, /* key ID */
- keyid_t private, /* private value */
- u_long lifetime /* key lifetime */
+ 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 */
)
{
- MD5_CTX ctx; /* MD5 context */
- keyid_t keyid; /* key identifer */
- u_int32 header[4]; /* data in network byte order */
- u_char digest[16]; /* message digest */
+ 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.
*/
- header[0] = srcadr->sin_addr.s_addr;
- header[1] = dstadr->sin_addr.s_addr;
- header[2] = htonl(keyno);
- header[3] = htonl(private);
- MD5Init(&ctx);
- MD5Update(&ctx, (u_char *)header, sizeof(header));
- MD5Final(digest, &ctx);
- memcpy(&keyid, digest, 4);
+ 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, digest, 16);
+ 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",
- numtoa(header[0]), numtoa(header[1]), keyno,
+ stoa(srcadr), stoa(dstadr), keyno,
private, keyid, lifetime);
#endif
return (keyid);
@@ -201,26 +250,22 @@ make_keylist(
struct interface *dstadr /* interface */
)
{
+ EVP_MD_CTX ctx; /* signature context */
+ tstamp_t tstamp; /* NTP timestamp */
struct autokey *ap; /* autokey pointer */
- keyid_t keyid; /* next key ID */
- keyid_t cookie; /* private value */
- l_fp tstamp; /* NTP timestamp */
- u_long ltemp;
- int i;
-#ifdef PUBKEY
- R_SIGNATURE_CTX ctx; /* signature context */
- int rval; /* return value */
- u_int len;
-#endif /* PUBKEY */
+ 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.
*/
- L_CLR(&tstamp);
- if (sys_leap != LEAP_NOTINSYNC)
- get_systime(&tstamp);
+ tstamp = crypto_time();
if (peer->keylist == NULL)
- peer->keylist = (keyid_t *)emalloc(sizeof(keyid_t) *
+ peer->keylist = emalloc(sizeof(keyid_t) *
NTP_MAXSESSION);
/*
@@ -243,55 +288,57 @@ make_keylist(
* included in the hash is zero if broadcast mode, the peer
* cookie if client mode or the host cookie if symmetric modes.
*/
- ltemp = min(sys_automax, NTP_MAXSESSION * (1 << (peer->kpoll)));
- peer->hcookie = session_key(&dstadr->sin, &peer->srcadr, 0,
- sys_private, 0);
+ lifetime = min(sys_automax, (unsigned long) NTP_MAXSESSION * (1 <<(peer->kpoll)));
if (peer->hmode == MODE_BROADCAST)
cookie = 0;
else
- cookie = peer->pcookie.key;
+ 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, ltemp);
- ltemp -= 1 << peer->kpoll;
+ cookie, lifetime);
+ lifetime -= 1 << peer->kpoll;
if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
- ltemp <= (1 << (peer->kpoll)))
+ 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.
+ * careful not to use invalid key media. Use the public values
+ * timestamp as filestamp.
*/
- ap = &peer->sndauto;
- ap->tstamp = htonl(tstamp.l_ui);
+ 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);
- ap->siglen = 0;
-#if DEBUG
+ 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 poll %d\n",
+ printf("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
ntohl(ap->seq), ntohl(ap->key), cookie,
- ntohl(ap->tstamp), peer->kpoll);
+ ntohl(vp->tstamp), ntohl(vp->fstamp), peer->kpoll);
#endif
-#ifdef PUBKEY
- if(!crypto_flags)
- return;
- if (ap->sig == NULL)
- ap->sig = emalloc(private_key.bits / 8);
- EVP_SignInit(&ctx, DA_MD5);
- EVP_SignUpdate(&ctx, (u_char *)ap, 12);
- rval = EVP_SignFinal(&ctx, ap->sig, &len, &private_key);
- if (rval != RV_OK)
- msyslog(LOG_ERR, "crypto: keylist signature fails %x",
- rval);
- else
- ap->siglen = htonl(len);
- peer->flags |= FLAG_ASSOC;
-#endif /* PUBKEY */
}
@@ -303,688 +350,778 @@ make_keylist(
* 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 authentic
+ * are believed even if the signature fails, but only if the proventic
* bit is not set.
*/
-void
+int
crypto_recv(
struct peer *peer, /* peer structure pointer */
struct recvbuf *rbufp /* packet buffer pointer */
)
{
- u_int32 *pkt; /* packet pointer */
- struct autokey *ap; /* autokey pointer */
- struct cookie *cp; /* cookie pointer */
- int has_mac; /* length of MAC field */
- int authlen; /* offset of MAC field */
- int len; /* extension field length */
- u_int code; /* extension field opcode */
- tstamp_t tstamp; /* timestamp */
- int i, rval;
- u_int temp;
-#ifdef PUBKEY
- R_SIGNATURE_CTX ctx; /* signature context */
- struct value *vp; /* value pointer */
- u_char dh_key[MAX_KEYLEN]; /* agreed key */
- R_RSA_PUBLIC_KEY *kp; /* temporary public key pointer */
- tstamp_t fstamp; /* filestamp */
- u_int32 *pp; /* packet pointer */
- u_int rsalen = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int) + 4;
- u_int bits;
- int j;
+ 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 */
-#endif /* PUBKEY */
/*
* Initialize. Note that the packet has already been checked for
- * valid format and extension field lengths. We first extract
- * the field length, command code and timestamp in host byte
- * order. These are used with all commands and modes. We discard
- * old timestamps and filestamps; but, for duplicate timestamps
- * we discard only if the authentic bit is set. Cute.
+ * 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.
*/
- pkt = (u_int32 *)&rbufp->recv_pkt;
authlen = LEN_PKT_NOMAC;
while ((has_mac = rbufp->recv_length - authlen) > MAX_MAC_LEN) {
- i = authlen / 4;
- len = ntohl(pkt[i]) & 0xffff;
- code = (ntohl(pkt[i]) >> 16) & 0xffff;
- temp = (code >> 8) & 0x3f;
- if (temp != CRYPTO_VN) {
- sys_unknownversion++;
-#ifdef DEBUG
- if (debug)
- printf(
- "crypto_recv: incorrect version %d should be %d\n",
- temp, CRYPTO_VN);
-#endif
- return;
- }
- tstamp = ntohl(pkt[i + 2]);
+ 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: ext offset %d len %d code %x assocID %d\n",
- authlen, len, code, (u_int32)ntohl(pkt[i +
- 1]));
+ "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 association ID and status word.
+ * 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:
- cp = (struct cookie *)&pkt[i + 2];
- temp = ntohl(cp->key);
- if (len < COOKIE_LEN) {
- rval = RV_LEN;
- } else if (tstamp == 0) {
- rval = RV_TSP;
- } else {
- if (!peer->crypto)
- peer->crypto = temp;
- if (ntohl(pkt[i + 1]) != 0)
- peer->assoc = ntohl(pkt[i + 1]);
- rval = RV_OK;
+
+ /*
+ * 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: verify %d flags 0x%x ts %u\n",
- rval, temp, tstamp);
+ printf("crypto_recv: %s\n", statstr);
#endif
break;
/*
- * Install autokey values in broadcast client and
- * symmetric modes.
+ * 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_AUTO | CRYPTO_RESP:
- if (!(peer->flags & FLAG_AUTOKEY) &&
- ntohl(pkt[i + 1]) != 0)
- peer->assoc = ntohl(pkt[i + 1]);
- ap = (struct autokey *)&pkt[i + 2];
-#ifdef PUBKEY
- temp = ntohl(ap->siglen);
- kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
- if (len < AUTOKEY_LEN) {
- rval = RV_LEN;
- } else if (tstamp == 0 || tstamp <
- peer->recauto.tstamp || (tstamp ==
- peer->recauto.tstamp && (peer->flags &
- FLAG_AUTOKEY))) {
- rval = RV_TSP;
- } else if (!crypto_flags) {
- rval = RV_OK;
- } else if (kp == NULL) {
- rval = RV_PUB;
- } else if (temp != kp->bits / 8) {
- rval = RV_SIG;
- } else {
- EVP_VerifyInit(&ctx, DA_MD5);
- EVP_VerifyUpdate(&ctx, (u_char *)ap,
- 12);
- rval = EVP_VerifyFinal(&ctx,
- (u_char *)ap->pkt, temp, kp);
+ 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);
}
-#else /* PUBKEY */
- if (tstamp < peer->recauto.tstamp || (tstamp ==
- peer->recauto.tstamp && (peer->flags &
- FLAG_AUTOKEY)))
- rval = RV_TSP;
- else
- rval = RV_OK;
-#endif /* PUBKEY */
+ 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: verify %x autokey %d %08x ts %u (%u)\n",
- rval, ntohl(ap->seq),
- ntohl(ap->key), tstamp,
- peer->recauto.tstamp);
+ printf("crypto_recv: %s\n", statstr);
#endif
- if (rval != RV_OK) {
- if (rval != RV_TSP)
- msyslog(LOG_ERR,
- "crypto: %x autokey %d %08x ts %u (%u)\n",
- rval, ntohl(ap->seq),
- ntohl(ap->key), tstamp,
- peer->recauto.tstamp);
- break;
- }
- peer->flags |= FLAG_AUTOKEY;
- peer->flash &= ~TEST10;
- peer->assoc = ntohl(pkt[i + 1]);
- peer->recauto.tstamp = tstamp;
- peer->recauto.seq = ntohl(ap->seq);
- peer->recauto.key = ntohl(ap->key);
- peer->pkeyid = peer->recauto.key;
break;
/*
- * Install session cookie in client mode. Use this also
- * in symmetric modes for test when rsaref20 has not
- * been installed.
+ * 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_PRIV:
- peer->cmmd = ntohl(pkt[i]);
- /* fall through */
+ case CRYPTO_IFF | CRYPTO_RESP:
- case CRYPTO_PRIV | CRYPTO_RESP:
- cp = (struct cookie *)&pkt[i + 2];
-#ifdef PUBKEY
- temp = ntohl(cp->siglen);
- kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
- if (len < COOKIE_LEN) {
- rval = RV_LEN;
- } else if (tstamp == 0 || tstamp <
- peer->pcookie.tstamp || (tstamp ==
- peer->pcookie.tstamp && (peer->flags &
- FLAG_AUTOKEY))) {
- rval = RV_TSP;
- } else if (!crypto_flags) {
- rval = RV_OK;
- } else if (kp == NULL) {
- rval = RV_PUB;
- } else if (temp != kp->bits / 8) {
- rval = RV_SIG;
- } else {
- EVP_VerifyInit(&ctx, DA_MD5);
- EVP_VerifyUpdate(&ctx, (u_char *)cp, 8);
- rval = EVP_VerifyFinal(&ctx,
- (u_char *)cp->pkt, temp, kp);
- }
-#else /* PUBKEY */
- if (tstamp <= peer->pcookie.tstamp || (tstamp ==
- peer->pcookie.tstamp && (peer->flags &
- FLAG_AUTOKEY)))
- rval = RV_TSP;
- else
- rval = RV_OK;
-#endif /* PUBKEY */
+ /*
+ * 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;
/*
- * Tricky here. If in client mode, use the
- * server cookie; otherwise, use EXOR of both
- * peer cookies. We call this Daffy-Hooligan
- * agreement.
+ * 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 (peer->hmode == MODE_CLIENT)
- temp = ntohl(cp->key);
- else
- temp = ntohl(cp->key) ^ peer->hcookie;
+ 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: verify %x cookie %08x ts %u (%u)\n",
- rval, temp, tstamp,
- peer->pcookie.tstamp);
+ printf("crypto_recv: %s\n", statstr);
#endif
- if (rval != RV_OK) {
- if (rval != RV_TSP)
- msyslog(LOG_ERR,
- "crypto: %x cookie %08x ts %u (%u)\n",
- rval, temp, tstamp,
- peer->pcookie.tstamp);
- peer->cmmd |= CRYPTO_ERROR;
- break;
- }
- if (!(peer->cast_flags & MDF_BCLNT))
- peer->flags |= FLAG_AUTOKEY;
- peer->flash &= ~TEST10;
- peer->assoc = ntohl(pkt[i + 1]);
- peer->pcookie.tstamp = tstamp;
- if (temp != peer->pcookie.key) {
- peer->pcookie.key = temp;
- key_expire(peer);
- }
break;
/*
- * The following commands and responses work only when
- * public-key cryptography has been configured. If
- * configured, but disabled due to no crypto command in
- * the configuration file, they are ignored.
+ * 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.
*/
-#ifdef PUBKEY
- /*
- * Install public key and host name.
- */
- case CRYPTO_NAME | CRYPTO_RESP:
- if (!crypto_flags)
+ case CRYPTO_GQ | CRYPTO_RESP:
+
+ /*
+ * Discard the message if invalid or identity
+ * already confirmed.
+ */
+ if (peer->crypto & CRYPTO_FLAG_VRFY)
break;
- vp = (struct value *)&pkt[i + 2];
- fstamp = ntohl(vp->fstamp);
- temp = ntohl(vp->vallen);
- j = i + 5 + ntohl(vp->vallen) / 4;
- bits = ntohl(pkt[i + 5]);
- if (len < VALUE_LEN) {
- rval = RV_LEN;
- } else if (temp < rsalen || bits <
- MIN_RSA_MODULUS_BITS || bits >
- MAX_RSA_MODULUS_BITS) {
- rval = RV_KEY;
- } else if (ntohl(pkt[j]) != bits / 8) {
- rval = RV_SIG;
- } else if (tstamp == 0 || tstamp <
- peer->pubkey.tstamp || (tstamp ==
- peer->pubkey.tstamp && (peer->flags &
- FLAG_AUTOKEY))) {
- rval = RV_TSP;
- } else if (tstamp < peer->pubkey.fstamp ||
- fstamp < peer->pubkey.fstamp) {
- rval = RV_FSP;
- } else if (fstamp == peer->pubkey.fstamp &&
- (peer->flags & FLAG_AUTOKEY)) {
- rval = RV_FSP;
- } else {
- EVP_VerifyInit(&ctx, DA_MD5);
- EVP_VerifyUpdate(&ctx, (u_char *)vp,
- temp + 12);
- kp = emalloc(sizeof(R_RSA_PUBLIC_KEY));
- kp->bits = bits;
- memcpy(kp->modulus, &pkt[i + 6],
- rsalen - 4);
- rval = EVP_VerifyFinal(&ctx,
- (u_char *)&pkt[j + 1],
- ntohl(pkt[j]), kp);
- if (rval != 0) {
- free(kp);
- } else {
- j = i + 5 + rsalen / 4;
- peer->pubkey.ptr = (u_char *)kp;
- temp = strlen((char *)&pkt[j]);
- peer->keystr = emalloc(temp +
- 1);
- strcpy(peer->keystr,
- (char *)&pkt[j]);
- peer->pubkey.tstamp = tstamp;
- peer->pubkey.fstamp = fstamp;
- peer->flash &= ~TEST10;
- if (!(peer->crypto &
- CRYPTO_FLAG_CERT))
- peer->flags |=
- FLAG_PROVEN;
- }
- }
+
+ 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: verify %x host %s ts %u fs %u\n",
- rval, (char *)&pkt[i + 5 + rsalen /
- 4], tstamp, fstamp);
+ printf("crypto_recv: %s\n", statstr);
#endif
- if (rval != RV_OK) {
- if (rval != RV_TSP)
- msyslog(LOG_ERR,
- "crypto: %x host %s ts %u fs %u\n",
- rval, (char *)&pkt[i + 5 +
- rsalen / 4], tstamp,
- fstamp);
- }
break;
/*
- * Install certificate.
+ * MV
*/
- case CRYPTO_CERT | CRYPTO_RESP:
- if (!crypto_flags)
+ case CRYPTO_MV | CRYPTO_RESP:
+
+ /*
+ * Discard the message if invalid or identity
+ * already confirmed.
+ */
+ if (peer->crypto & CRYPTO_FLAG_VRFY)
break;
- vp = (struct value *)&pkt[i + 2];
- fstamp = ntohl(vp->fstamp);
- temp = ntohl(vp->vallen);
- kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
- j = i + 5 + temp / 4;
- if (len < VALUE_LEN) {
- rval = RV_LEN;
- } else if (kp == NULL) {
- rval = RV_PUB;
- } else if (ntohl(pkt[j]) != kp->bits / 8) {
- rval = RV_SIG;
- } else if (tstamp == 0) {
- rval = RV_TSP;
- } else if (tstamp <
- ntohl(peer->certif.fstamp) || fstamp <
- ntohl(peer->certif.fstamp)) {
- rval = RV_FSP;
- } else if (fstamp ==
- ntohl(peer->certif.fstamp) && (peer->flags &
- FLAG_AUTOKEY)) {
- peer->crypto &= ~CRYPTO_FLAG_CERT;
- rval = RV_FSP;
- } else {
- EVP_VerifyInit(&ctx, DA_MD5);
- EVP_VerifyUpdate(&ctx, (u_char *)vp,
- temp + 12);
- rval = EVP_VerifyFinal(&ctx,
- (u_char *)&pkt[j + 1],
- ntohl(pkt[j]), kp);
- }
+
+ 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: verify %x certificate %u ts %u fs %u\n",
- rval, temp, tstamp, fstamp);
+ 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:
/*
- * If the peer data are newer than the host
- * data, replace the host data. Otherwise,
- * wait for the peer to fetch the host data.
+ * Discard the message if invalid or identity
+ * not confirmed.
*/
- if (rval != RV_OK || temp == 0) {
- if (rval != RV_TSP)
- msyslog(LOG_ERR,
- "crypto: %x certificate %u ts %u fs %u\n",
- rval, temp, tstamp, fstamp);
+ if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+ break;
+
+ if ((rval = crypto_verify(ep, NULL, peer)) !=
+ XEVNT_OK)
break;
- }
- peer->flash &= ~TEST10;
- peer->flags |= FLAG_PROVEN;
- peer->crypto &= ~CRYPTO_FLAG_CERT;
/*
- * Initialize agreement parameters and extension
- * field in network byte order. Note the private
- * key length is set arbitrarily at half the
- * prime length.
+ * Scan the certificate list to delete old
+ * versions and link the newest version first on
+ * the list.
*/
- peer->certif.tstamp = vp->tstamp;
- peer->certif.fstamp = vp->fstamp;
- peer->certif.vallen = vp->vallen;
- if (peer->certif.ptr == NULL)
- free(peer->certif.ptr);
- peer->certif.ptr = emalloc(temp);
- memcpy(peer->certif.ptr, vp->pkt, temp);
- crypto_agree();
+ 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;
/*
- * Install agreement parameters in symmetric modes.
+ * Cookie request in symmetric modes. Roll a random
+ * cookie and install in symmetric mode. Encrypt for the
+ * response, which is transmitted later.
*/
- case CRYPTO_DHPAR | CRYPTO_RESP:
- if (!crypto_flags)
+ 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;
- vp = (struct value *)&pkt[i + 2];
- fstamp = ntohl(vp->fstamp);
- temp = ntohl(vp->vallen);
- kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
- j = i + 5 + temp / 4;
- if (len < VALUE_LEN) {
- rval = RV_LEN;
- } else if (kp == NULL) {
- rval = RV_PUB;
- } else if (ntohl(pkt[j]) != kp->bits / 8) {
- rval = RV_SIG;
- } else if (tstamp == 0) {
- rval = RV_TSP;
- } else if (tstamp < ntohl(dhparam.fstamp) ||
- fstamp < ntohl(dhparam.fstamp)) {
- rval = RV_FSP;
- } else if (fstamp == ntohl(dhparam.fstamp) &&
- (peer->flags & FLAG_AUTOKEY)) {
- peer->crypto &= ~CRYPTO_FLAG_DH;
- rval = RV_FSP;
- } else {
- EVP_VerifyInit(&ctx, DA_MD5);
- EVP_VerifyUpdate(&ctx, (u_char *)vp,
- temp + 12);
- rval = EVP_VerifyFinal(&ctx,
- (u_char *)&pkt[j + 1],
- ntohl(pkt[j]), kp);
}
+
+ /*
+ * 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: verify %x parameters %u ts %u fs %u\n",
- rval, temp, tstamp, fstamp);
+ 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:
/*
- * If the peer data are newer than the host
- * data, replace the host data. Otherwise,
- * wait for the peer to fetch the host data.
+ * Discard the message if invalid or identity
+ * not confirmed or signature not verified with
+ * respect to the cookie values.
*/
- if (rval != RV_OK || temp == 0) {
- if (rval != RV_TSP)
- msyslog(LOG_ERR,
- "crypto: %x parameters %u ts %u fs %u\n",
- rval, temp, tstamp, fstamp);
+ if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+ break;
+
+ if ((rval = crypto_verify(ep, &peer->cookval,
+ peer)) != XEVNT_OK)
break;
- }
- peer->flash &= ~TEST10;
- crypto_flags |= CRYPTO_FLAG_DH;
- peer->crypto &= ~CRYPTO_FLAG_DH;
/*
- * Initialize agreement parameters and extension
- * field in network byte order. Note the private
- * key length is set arbitrarily at half the
- * prime length.
+ * Decrypt the cookie, hunting all the time for
+ * errors.
*/
- dhparam.tstamp = vp->tstamp;
- dhparam.fstamp = vp->fstamp;
- dhparam.vallen = vp->vallen;
- if (dhparam.ptr != NULL)
- free(dhparam.ptr);
- pp = emalloc(temp);
- dhparam.ptr = (u_char *)pp;
- memcpy(pp, vp->pkt, temp);
- dh_params.primeLen = ntohl(*pp++);
- dh_params.prime = (u_char *)pp;
- pp += dh_params.primeLen / 4;
- dh_params.generatorLen = ntohl(*pp++);
- dh_params.generator = (u_char *)pp;
- dh_keyLen = dh_params.primeLen / 2;
- if (dh_private != NULL)
- free(dh_private);
- dh_private = emalloc(dh_keyLen);
- if (dhparam.sig == NULL)
- dhparam.sig = emalloc(private_key.bits /
- 8);
+ 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;
+ }
/*
- * Initialize public value extension field.
+ * Install cookie values and light the cookie
+ * bit. If this is not broadcast client mode, we
+ * are done here.
*/
- dhpub.tstamp = vp->tstamp;
- dhpub.fstamp = vp->fstamp;
- dhpub.vallen = htonl(dh_params.primeLen);
- if (dhpub.ptr != NULL)
- free(dhpub.ptr);
- dhpub.ptr = emalloc(dh_params.primeLen);
- if (dhpub.sig == NULL)
- dhpub.sig = emalloc(private_key.bits /
- 8);
- crypto_agree();
+ 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;
/*
- * Verify public value and compute agreed key in
- * symmetric modes.
+ * 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_DH:
- peer->cmmd = ntohl(pkt[i]);
- if (!crypto_flags)
- peer->cmmd |= CRYPTO_ERROR;
- /* fall through */
+ case CRYPTO_AUTO | CRYPTO_RESP:
- case CRYPTO_DH | CRYPTO_RESP:
- if (!crypto_flags)
+ /*
+ * 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;
- vp = (struct value *)&pkt[i + 2];
- fstamp = ntohl(vp->fstamp);
- temp = ntohl(vp->vallen);
- kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
- j = i + 5 + temp / 4;
- if (len < VALUE_LEN) {
- rval = RV_LEN;
- } else if (temp != dh_params.primeLen) {
- rval = RV_DH;
- } else if (kp == NULL) {
- rval = RV_PUB;
- } else if (ntohl(pkt[j]) != kp->bits / 8) {
- rval = RV_SIG;
- } else if (tstamp == 0 || tstamp <
- peer->pcookie.tstamp || (tstamp ==
- peer->pcookie.tstamp && (peer->flags &
- FLAG_AUTOKEY))) {
- rval = RV_TSP;
- } else {
- EVP_VerifyInit(&ctx, DA_MD5);
- EVP_VerifyUpdate(&ctx, (u_char *)vp,
- temp + 12);
- rval = EVP_VerifyFinal(&ctx,
- (u_char *)&pkt[j + 1],
- ntohl(pkt[j]), kp);
- }
/*
- * Run the agreement algorithm and stash the key
- * value. We use only the first u_int32 for the
- * host cookie. Wasteful. If the association ID
- * is zero, the other guy hasn't seen us as
- * synchronized, in which case both of us should
- * be using a zero cookie.
+ * Install autokey values and light the
+ * autokey bit. This is not hard.
*/
- if (rval != RV_OK) {
- temp = 0;
- } else if (fstamp > dhparam.fstamp) {
- crypto_flags &= ~CRYPTO_FLAG_DH;
- rval = RV_FSP;
- } else {
- rval = R_ComputeDHAgreedKey(dh_key,
- (u_char *)&pkt[i + 5], dh_private,
- dh_keyLen, &dh_params);
- temp = ntohl(*(u_int32 *)dh_key);
- }
+ 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: verify %x agreement %08x ts %u (%u) fs %u\n",
- rval, temp, tstamp,
- peer->pcookie.tstamp, fstamp);
+ printf("crypto_recv: %s\n", statstr);
#endif
- if (rval != RV_OK) {
- if (rval != RV_TSP)
- msyslog(LOG_ERR,
- "crypto: %x agreement %08x ts %u (%u) fs %u\n",
- rval, temp, tstamp,
- peer->pcookie.tstamp,
- fstamp);
- peer->cmmd |= CRYPTO_ERROR;
- break;
- }
- peer->flash &= ~TEST10;
- peer->flags &= ~FLAG_AUTOKEY;
- peer->assoc = ntohl(pkt[i + 1]);
- peer->pcookie.tstamp = tstamp;
- if (temp != peer->pcookie.key) {
- peer->pcookie.key = temp;
- key_expire(peer);
- }
break;
/*
- * Install leapseconds table.
+ * 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 | CRYPTO_RESP:
- if (!crypto_flags)
+ 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;
- vp = (struct value *)&pkt[i + 2];
- fstamp = ntohl(vp->fstamp);
- temp = ntohl(vp->vallen);
- kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
- j = i + 5 + temp / 4;
- if (len < VALUE_LEN) {
- rval = RV_LEN;
- } if (kp == NULL) {
- rval = RV_PUB;
- } else if (ntohl(pkt[j]) != kp->bits / 8) {
- rval = RV_SIG;
- } else if (tstamp == 0) {
- rval = RV_TSP;
- } else if (tstamp < ntohl(tai_leap.fstamp) ||
- fstamp < ntohl(tai_leap.fstamp)) {
- rval = RV_FSP;
- } else if (fstamp == ntohl(tai_leap.fstamp) &&
- (peer->flags & FLAG_AUTOKEY)) {
- peer->crypto &= ~CRYPTO_FLAG_TAI;
- rval = RV_FSP;
- } else {
- EVP_VerifyInit(&ctx, DA_MD5);
- EVP_VerifyUpdate(&ctx, (u_char *)vp,
- temp + 12);
- rval = EVP_VerifyFinal(&ctx,
- (u_char *)&pkt[j + 1],
- ntohl(pkt[j]), kp);
}
-#ifdef DEBUG
- if (debug)
- printf(
- "crypto_recv: verify %x leapseconds %u ts %u fs %u\n",
- rval, temp, tstamp, fstamp);
-#endif
+ /* fall through */
+
+ case CRYPTO_TAI | CRYPTO_RESP:
/*
- * If the peer data are newer than the host
- * data, replace the host data. Otherwise,
- * wait for the peer to fetch the host data.
+ * Discard the message if invalid or identity
+ * not confirmed or signature not verified with
+ * respect to the leapsecond table values.
*/
- if (rval != RV_OK || temp == 0) {
- if (rval != RV_TSP)
- msyslog(LOG_ERR,
- "crypto: %x leapseconds %u ts %u fs %u\n",
- rval, temp, tstamp, fstamp);
+ 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;
}
- peer->flash &= ~TEST10;
crypto_flags |= CRYPTO_FLAG_TAI;
- peer->crypto &= ~CRYPTO_FLAG_TAI;
- sys_tai = temp / 4 + TAI_1972 - 1;
+ 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 */
-
- /*
- * Initialize leapseconds table and extension
- * field in network byte order.
- */
- tai_leap.tstamp = vp->tstamp;
- tai_leap.fstamp = vp->fstamp;
- tai_leap.vallen = vp->vallen;
- if (tai_leap.ptr == NULL)
- free(tai_leap.ptr);
- tai_leap.ptr = emalloc(temp);
- memcpy(tai_leap.ptr, vp->pkt, temp);
- if (tai_leap.sig == NULL)
- tai_leap.sig =
- emalloc(private_key.bits / 8);
- crypto_agree();
+ 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;
-#endif /* PUBKEY */
/*
- * For other requests, save the request code for later;
- * for unknown responses or errors, just ignore for now.
+ * 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.
*/
- default:
- if (code & (CRYPTO_RESP | CRYPTO_ERROR))
+ case CRYPTO_IFF:
+ case CRYPTO_GQ:
+ case CRYPTO_MV:
+ case CRYPTO_SIGN:
+ if (len < VALUE_LEN) {
+ rval = XEVNT_LEN;
break;
- peer->cmmd = ntohl(pkt[i]);
- 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);
}
@@ -992,255 +1129,248 @@ crypto_recv(
* 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 now is to retrieve
- * the autokey information, in which case the caller has to provide the
+ * 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 /* return length of extension field */
+int
crypto_xmit(
- u_int32 *xpkt, /* packet pointer */
- int start, /* offset to extension field */
- u_int code, /* extension field code */
- keyid_t cookie, /* session cookie */
- u_int associd /* association ID */
+ 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 */
- struct autokey *ap; /* autokey pointer */
- struct cookie *cp; /* cookie pointer */
- int len; /* extension field length */
- u_int opcode; /* extension field opcode */
- int i;
-#ifdef PUBKEY
- R_SIGNATURE_CTX ctx; /* signature context */
- struct value *vp; /* value pointer */
- int rval; /* return value */
- u_int temp;
- int j;
-#endif /* PUBKEY */
+ 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. Note that several extension fields are
- * used with and without public-key cryptography. If public-key
- * cryptography has not been configured, we do the same thing,
- * but leave off the signature.
- */
- i = start / 4;
- opcode = code;
- xpkt[i + 1] = htonl(associd);
+ * 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;
- switch (opcode) {
+ rval = XEVNT_OK;
+ switch (opcode & 0xffff0000) {
/*
- * Send association ID, timestamp and status word.
+ * 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:
- cp = (struct cookie *)&xpkt[i + 2];
-#ifdef PUBKEY
- cp->tstamp = host.tstamp;
-#else
- cp->tstamp = 0;
-#endif /* PUBKEY */
- cp->key = htonl(crypto_flags);
- cp->siglen = 0;
- len += 12;
+ case CRYPTO_ASSOC:
+ len += crypto_send(fp, &hostval);
+ if (crypto_time() == 0)
+ fp->fstamp = 0;
+ else
+ fp->fstamp = htonl(crypto_flags);
break;
/*
- * Find peer and send autokey data and signature in broadcast
- * server and symmetric modes. If no association is found,
- * either the server has restarted with new associations or some
- * perp has replayed an old message.
+ * Send certificate request. Use the values from the extension
+ * field.
*/
- case CRYPTO_AUTO | CRYPTO_RESP:
- peer = findpeerbyassoc(associd);
- if (peer == NULL) {
+ 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';
}
- peer->flags &= ~FLAG_ASSOC;
- ap = (struct autokey *)&xpkt[i + 2];
- ap->tstamp = peer->sndauto.tstamp;
- ap->seq = peer->sndauto.seq;
- ap->key = peer->sndauto.key;
- ap->siglen = peer->sndauto.siglen;
- len += 16;
-#ifdef PUBKEY
- if (!crypto_flags)
- break;
- temp = ntohl(ap->siglen);
- if (temp != 0)
- memcpy(ap->pkt, peer->sndauto.sig, temp);
- len += temp;
-#endif /* PUBKEY */
+ 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 peer cookie and signature in server mode.
+ * Send challenge in Schnorr (IFF) identity scheme.
*/
- case CRYPTO_PRIV:
- case CRYPTO_PRIV | CRYPTO_RESP:
- cp = (struct cookie *)&xpkt[i + 2];
- cp->key = htonl(cookie);
- cp->siglen = 0;
- len += 12;
-#ifdef PUBKEY
- cp->tstamp = host.tstamp;
- if (!crypto_flags)
- break;
- EVP_SignInit(&ctx, DA_MD5);
- EVP_SignUpdate(&ctx, (u_char *)cp, 8);
- rval = EVP_SignFinal(&ctx, (u_char *)cp->pkt, &temp,
- &private_key);
- if (rval != RV_OK) {
- msyslog(LOG_ERR,
- "crypto: cookie signature fails %x", rval);
+ case CRYPTO_IFF:
+ if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
+ opcode |= CRYPTO_ERROR;
break;
}
- cp->siglen = htonl(temp);
- len += temp;
-#endif /* PUBKEY */
+ if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK)
+ len += crypto_send(fp, &vtemp);
+ value_free(&vtemp);
break;
-#ifdef PUBKEY
/*
- * The following commands and responses work only when public-
- * key cryptography has been configured. If configured, but
- * disabled due to no crypto command in the configuration file,
- * they are ignored and an error response is returned.
+ * 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 certificate, timestamp and signature.
+ * Send challenge in Guillou-Quisquater (GQ) identity scheme.
*/
- case CRYPTO_CERT | CRYPTO_RESP:
- if (!crypto_flags) {
+ case CRYPTO_GQ:
+ if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
opcode |= CRYPTO_ERROR;
break;
}
- vp = (struct value *)&xpkt[i + 2];
- vp->tstamp = certif.tstamp;
- vp->fstamp = certif.fstamp;
- vp->vallen = 0;
- len += 12;
- temp = ntohl(certif.vallen);
- if (temp == 0)
- break;
- vp->vallen = htonl(temp);
- memcpy(vp->pkt, certif.ptr, temp);
- len += temp;
- j = i + 5 + temp / 4;
- temp = public_key.bits / 8;
- xpkt[j++] = htonl(temp);
- memcpy(&xpkt[j], certif.sig, temp);
- len += temp + 4;
+ 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 agreement parameters, timestamp and signature.
+ * Send challenge in MV identity scheme.
*/
- case CRYPTO_DHPAR | CRYPTO_RESP:
- if (!crypto_flags) {
+ case CRYPTO_MV:
+ if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
opcode |= CRYPTO_ERROR;
break;
}
- vp = (struct value *)&xpkt[i + 2];
- vp->tstamp = dhparam.tstamp;
- vp->fstamp = dhparam.fstamp;
- vp->vallen = 0;
- len += 12;
- temp = ntohl(dhparam.vallen);
- if (temp == 0)
- break;
- vp->vallen = htonl(temp);
- memcpy(vp->pkt, dhparam.ptr, temp);
- len += temp;
- j = i + 5 + temp / 4;
- temp = public_key.bits / 8;
- xpkt[j++] = htonl(temp);
- memcpy(&xpkt[j], dhparam.sig, temp);
- len += temp + 4;
+ if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK)
+ len += crypto_send(fp, &vtemp);
+ value_free(&vtemp);
break;
/*
- * Send public value, timestamp and signature.
+ * Send response in MV identity scheme.
*/
- case CRYPTO_DH:
- case CRYPTO_DH | CRYPTO_RESP:
- if (!crypto_flags) {
+ 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;
}
- vp = (struct value *)&xpkt[i + 2];
- vp->tstamp = dhpub.tstamp;
- vp->fstamp = dhpub.fstamp;
- vp->vallen = 0;
- len += 12;
- temp = ntohl(dhpub.vallen);
- if (temp == 0)
- break;
- vp->vallen = htonl(temp);
- memcpy(vp->pkt, dhpub.ptr, temp);
- len += temp;
- j = i + 5 + temp / 4;
- temp = public_key.bits / 8;
- xpkt[j++] = htonl(temp);
- memcpy(&xpkt[j], dhpub.sig, temp);
- len += temp + 4;
+ 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;
/*
- * Send public key, host name, timestamp and signature.
+ * 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_NAME | CRYPTO_RESP:
- if (!crypto_flags) {
+ case CRYPTO_AUTO | CRYPTO_RESP:
+ if ((peer = findpeerbyassoc(associd)) == NULL) {
opcode |= CRYPTO_ERROR;
break;
}
- vp = (struct value *)&xpkt[i + 2];
- vp->tstamp = host.tstamp;
- vp->fstamp = host.fstamp;
- vp->vallen = 0;
- len += 12;
- temp = ntohl(host.vallen);
- if (temp == 0)
- break;
- vp->vallen = htonl(temp);
- memcpy(vp->pkt, host.ptr, temp);
- len += temp;
- j = i + 5 + temp / 4;
- temp = public_key.bits / 8;
- xpkt[j++] = htonl(temp);
- memcpy(&xpkt[j], host.sig, temp);
- len += temp + 4;
+ peer->flags &= ~FLAG_ASSOC;
+ len += crypto_send(fp, &peer->sndval);
break;
/*
- * Send leapseconds table, timestamp and signature.
+ * 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) {
- opcode |= CRYPTO_ERROR;
- break;
- }
- vp = (struct value *)&xpkt[i + 2];
- vp->tstamp = tai_leap.tstamp;
- vp->fstamp = tai_leap.fstamp;
- vp->vallen = 0;
- len += 12;
- temp = ntohl(tai_leap.vallen);
- if (temp == 0)
- break;
- vp->vallen = htonl(temp);
- memcpy(vp->pkt, tai_leap.ptr, temp);
- len += temp;
- j = i + 5 + temp / 4;
- temp = public_key.bits / 8;
- xpkt[j++] = htonl(temp);
- memcpy(&xpkt[j], tai_leap.sig, temp);
- len += temp + 4;
+ if (crypto_flags & CRYPTO_FLAG_TAI)
+ len += crypto_send(fp, &tai_leap);
break;
-#endif /* PUBKEY */
/*
* Default - Fall through for requests; for unknown responses,
@@ -1249,626 +1379,2226 @@ crypto_xmit(
default:
if (opcode & CRYPTO_RESP)
opcode |= CRYPTO_ERROR;
- break;
}
/*
- * Round up the field length to a multiple of 8 octets and save
- * the request code and length.
+ * 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.
*/
- len = ((len + 7) / 8) * 8;
- if (len >= 4) {
- xpkt[i] = htonl((u_int32)((opcode << 16) | len));
+ 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: ext offset %d len %d code %x assocID %d\n",
- start, len, code, associd);
+ 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);
}
-#ifdef PUBKEY
+
/*
- * crypto_setup - load private key, public key, optional agreement
- * parameters and optional leapseconds table, then initialize extension
- * fields for later signatures.
+ * 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
*/
-void
-crypto_setup(void)
+static int
+crypto_verify(
+ struct exten *ep, /* extension pointer */
+ struct value *vp, /* value pointer */
+ struct peer *peer /* peer structure pointer */
+ )
{
- char filename[MAXFILENAME];
- u_int fstamp; /* filestamp */
- u_int len, temp;
- u_int32 *pp;
+ 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;
/*
- * Initialize structures.
+ * 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.
*/
- memset(&private_key, 0, sizeof(private_key));
- memset(&public_key, 0, sizeof(public_key));
- memset(&certif, 0, sizeof(certif));
- memset(&dh_params, 0, sizeof(dh_params));
- memset(&host, 0, sizeof(host));
- memset(&dhparam, 0, sizeof(dhparam));
- memset(&dhpub, 0, sizeof(dhpub));
- memset(&tai_leap, 0, sizeof(tai_leap));
- if (!crypto_flags)
- return;
+ 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);
+ }
/*
- * Load required private key from file, default "ntpkey".
+ * 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.
*/
- if (private_key_file == NULL)
- private_key_file = "ntpkey";
- host.fstamp = htonl(crypto_rsa(private_key_file,
- (u_char *)&private_key, sizeof(R_RSA_PRIVATE_KEY)));
+ 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;
/*
- * Load required public key from file, default
- * "ntpkey_host", where "host" is the canonical name of this
- * machine.
+ * 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.
*/
- if (public_key_file == NULL) {
- snprintf(filename, MAXFILENAME, "ntpkey_%s",
- sys_hostname);
- public_key_file = emalloc(strlen(filename) + 1);
- strcpy(public_key_file, filename);
+ } 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;
+ }
}
- fstamp = htonl(crypto_rsa(public_key_file,
- (u_char *)&public_key, sizeof(R_RSA_PUBLIC_KEY)));
- if (fstamp != host.fstamp || strstr(public_key_file,
- sys_hostname) == NULL) {
- msyslog(LOG_ERR,
- "crypto: public/private key files mismatch");
- exit (-1);
+#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);
}
- crypto_flags |= CRYPTO_FLAG_RSA;
/*
- * Assemble public key and host name in network byte order.
- * These data will later be signed and sent in response to
- * a client request. Note that the modulus must be a u_int32 in
- * network byte order independent of the host order or u_int
- * size.
+ * Encrypt the cookie, encode in ASN.1 and sign.
*/
- strcpy(filename, sys_hostname);
- for (len = strlen(filename) + 1; len % 4 != 0; len++)
- filename[len - 1] = 0;
- temp = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int) + 4;
- host.vallen = htonl(temp + len);
- pp = emalloc(temp + len);
- host.ptr = (u_char *)pp;
- *pp++ = htonl(public_key.bits);
- memcpy(pp--, public_key.modulus, temp - 4);
- pp += temp / 4;
- memcpy(pp, filename, len);
- host.sig = emalloc(private_key.bits / 8);
+ 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];
/*
- * Load optional certificate from file, default "ntpkey_certif".
- * If the file is missing or defective, the values can later be
- * retrieved from a server.
+ * 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 (certif_file == NULL)
- snprintf(filename, MAXFILENAME, "ntpkey_certif_%s",
+ 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);
- certif_file = emalloc(strlen(filename) + 1);
- strcpy(certif_file, filename);
- crypto_cert(certif_file);
+ peer->ident_pkey = crypto_key(filename, &peer->fstamp);
+ if (peer->ident_pkey != NULL)
+ return (CRYPTO_MV);
+ }
/*
- * Load optional agreement parameters from file, default
- * "ntpkey_dh". If the file is missing or defective, the values
- * can later be retrieved from a server.
+ * No compatible identity scheme is available. Use the default
+ * TC scheme.
*/
- if (dh_params_file == NULL)
- dh_params_file = "ntpkey_dh";
- crypto_dh(dh_params_file);
+ 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);
/*
- * Load optional leapseconds from file, default "ntpkey_leap".
- * If the file is missing or defective, the values can later be
- * retrieved from a server.
+ * If a response, send our ID; if a request, send the
+ * responder's ID.
*/
- if (tai_leap_file == NULL)
- tai_leap_file = "ntpkey_leap";
- crypto_tai(tai_leap_file);
+ 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_agree - compute new public value and sign extension fields.
+ * 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.
*/
-void
-crypto_agree(void)
+u_int
+crypto_send(
+ struct exten *ep, /* extension field pointer */
+ struct value *vp /* value pointer */
+ )
{
- R_RANDOM_STRUCT randomstr; /* wiggle bits */
- R_SIGNATURE_CTX ctx; /* signature context */
- l_fp lstamp; /* NTP time */
- tstamp_t tstamp; /* seconds timestamp */
- u_int len, temp;
- int rval, i;
+ u_int len, temp32;
+ int i;
/*
- * Sign host name and timestamps, but only if the clock is
- * synchronized.
+ * Copy data. If the data field is empty or zero length, encode
+ * an empty value with length zero.
*/
- if (sys_leap == LEAP_NOTINSYNC)
- return;
- get_systime(&lstamp);
- tstamp = lstamp.l_ui;
- host.tstamp = htonl(tstamp);
- if (!crypto_flags)
+ 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;
- EVP_SignInit(&ctx, DA_MD5);
- EVP_SignUpdate(&ctx, (u_char *)&host, 12);
- EVP_SignUpdate(&ctx, host.ptr, ntohl(host.vallen));
- rval = EVP_SignFinal(&ctx, host.sig, &len, &private_key);
- if (rval != RV_OK || len != private_key.bits / 8) {
- msyslog(LOG_ERR, "crypto: host signature fails %x",
- rval);
- exit (-1);
- }
- host.siglen = ntohl(len);
+ hostval.tstamp = htonl(tstamp);
/*
- * Sign certificate and timestamps.
+ * Sign public key and timestamps. The filestamp is derived from
+ * the host key file extension from wherever the file was
+ * generated.
*/
- if (certif.vallen != 0) {
- certif.tstamp = htonl(tstamp);
- EVP_SignInit(&ctx, DA_MD5);
- EVP_SignUpdate(&ctx, (u_char *)&certif, 12);
- EVP_SignUpdate(&ctx, certif.ptr,
- ntohl(certif.vallen));
- rval = EVP_SignFinal(&ctx, certif.sig, &len,
- &private_key);
- if (rval != RV_OK || len != private_key.bits / 8) {
- msyslog(LOG_ERR,
- "crypto: certificate signature fails %x",
- rval);
- exit (-1);
- }
- certif.siglen = ntohl(len);
+ 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 agreement parameters and timestamps.
+ * 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.
*/
- if (dhparam.vallen != 0) {
- dhparam.tstamp = htonl(tstamp);
- EVP_SignInit(&ctx, DA_MD5);
- EVP_SignUpdate(&ctx, (u_char *)&dhparam, 12);
- EVP_SignUpdate(&ctx, dhparam.ptr,
- ntohl(dhparam.vallen));
- rval = EVP_SignFinal(&ctx, dhparam.sig, &len,
- &private_key);
- if (rval != RV_OK || len != private_key.bits / 8) {
- msyslog(LOG_ERR,
- "crypto: parameters signature fails %x",
- rval);
- exit (-11);
- }
- dhparam.siglen = ntohl(len);
-
- /*
- * Compute public value.
- */
- R_RandomInit(&randomstr);
- R_GetRandomBytesNeeded(&len, &randomstr);
- for (i = 0; i < len; i++) {
- temp = RANDOM;
- R_RandomUpdate(&randomstr, (u_char *)&temp, 1);
- }
- rval = R_SetupDHAgreement(dhpub.ptr, dh_private,
- dh_keyLen, &dh_params, &randomstr);
- if (rval != RV_OK) {
- msyslog(LOG_ERR,
- "crypto: invalid public value");
- exit (-1);
+ 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 public value and timestamps.
- */
- dhpub.tstamp = htonl(tstamp);
- EVP_SignInit(&ctx, DA_MD5);
- EVP_SignUpdate(&ctx, (u_char *)&dhpub, 12);
- EVP_SignUpdate(&ctx, dhpub.ptr, ntohl(dhpub.vallen));
- rval = EVP_SignFinal(&ctx, dhpub.sig, &len,
- &private_key);
- if (rval != RV_OK || len != private_key.bits / 8) {
- msyslog(LOG_ERR,
- "crypto: public value signature fails %x",
- rval);
- exit (-1);
- }
- dhpub.siglen = ntohl(len);
}
/*
- * Sign leapseconds table and timestamps.
+ * 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 = htonl(tstamp);
- EVP_SignInit(&ctx, DA_MD5);
+ 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));
- rval = EVP_SignFinal(&ctx, tai_leap.sig, &len,
- &private_key);
- if (rval != RV_OK || len != private_key.bits / 8) {
- msyslog(LOG_ERR,
- "crypto: leapseconds signature fails %x",
- rval);
- exit (-1);
- }
- tai_leap.siglen = ntohl(len);
+ 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(
- "cypto_agree: ts %u host %u par %u pub %u leap %u\n",
- tstamp, ntohl(host.fstamp), ntohl(dhparam.fstamp),
- ntohl(dhpub.fstamp), ntohl(tai_leap.fstamp));
+ printf("crypto_update: %s\n", statstr);
#endif
}
/*
- * crypto_rsa - read RSA key, decode and check for errors.
+ * value_free - free value structure components.
+ *
+ * Returns void (no errors)
*/
-static u_int
-crypto_rsa(
- char *cp, /* file name */
- u_char *key, /* key pointer */
- u_int keylen /* key length */
+void
+value_free(
+ struct value *vp /* value structure */
)
{
- FILE *str; /* file handle */
- u_char buf[MAX_LINLEN]; /* file line buffer */
- u_char encoded_key[MAX_ENCLEN]; /* encoded key buffer */
- char filename[MAXFILENAME]; /* name of parameter file */
- char linkname[MAXFILENAME]; /* file link (for filestamp) */
- u_int fstamp; /* filestamp */
- u_int bits, len;
- char *rptr;
- int rval;
+ 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 */
/*
- * Open the file and discard comment lines. If the first
- * character of the file name is not '/', prepend the keys
- * directory string.
+ * 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 (*cp == '/')
- strcpy(filename, cp);
- else
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
- str = fopen(filename, "r");
- if (str == NULL) {
- msyslog(LOG_ERR, "crypto: RSA file %s not found",
- filename);
- exit (-1);
+ 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);
}
/*
- * Ignore initial comments and empty lines.
+ * 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.
*/
- while ((rptr = fgets(buf, MAX_LINLEN - 1, str)) != NULL) {
- len = strlen(buf);
- if (len < 1)
- continue;
- if (*buf == '#' || *buf == '\r' || *buf == '\0')
- continue;
- break;
+ 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;
/*
- * We are rather paranoid here, since an intruder might cause a
- * coredump by infiltrating a naughty key. The line must contain
- * a single integer followed by a PEM encoded, null-terminated
- * string.
- */
- if (rptr == NULL)
- rval = RV_DAT;
- else if (sscanf(buf, "%d %s", &bits, encoded_key) != 2)
- rval = RV_DAT;
- else if (R_DecodePEMBlock(&buf[sizeof(u_int)], &len,
- encoded_key, strlen(encoded_key)))
- rval = RV_DEC;
- else if ((len += sizeof(u_int)) != keylen)
- rval = RV_KEY;
- else if (bits < MIN_RSA_MODULUS_BITS || bits >
- MAX_RSA_MODULUS_BITS)
- rval = RV_KEY;
+ * 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
- rval = RV_OK;
- if (rval != RV_OK) {
- fclose(str);
- msyslog(LOG_ERR, "crypto: RSA file %s error %x", cp,
- rval);
- exit (-1);
+ 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);
}
- fclose(str);
- *(u_int *)buf = bits;
- memcpy(key, buf, keylen);
/*
- * Extract filestamp if present.
+ * 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.
*/
- rval = readlink(filename, linkname, MAXFILENAME - 1);
- if (rval > 0) {
- linkname[rval] = '\0';
- rptr = strrchr(linkname, '.');
- } else {
- rptr = strrchr(filename, '.');
+ 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);
}
- if (rptr != NULL)
- sscanf(++rptr, "%u", &fstamp);
+
+ /*
+ * 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
- fstamp = 0;
-#ifdef DEBUG
- if (debug)
- printf(
- "crypto_rsa: key file %s link %d fs %u modulus %d\n",
- cp, rval, fstamp, bits);
-#endif
- return (fstamp);
+ return (XEVNT_ID);
}
/*
- * crypto_cert - read certificate
+ ***********************************************************************
+ * *
+ * The following routines implement the Mu-Varadharajan (MV) identity *
+ * scheme *
+ * *
+ ***********************************************************************
*/
-static void
-crypto_cert(
- char *cp /* file name */
+/*
+ * 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 */
)
{
- u_char buf[5000]; /* file line buffer */
- char filename[MAXFILENAME]; /* name of certificate file */
- char linkname[MAXFILENAME]; /* file link (for filestamp) */
- u_int fstamp; /* filestamp */
- u_int32 *pp;
- u_int len;
- char *rptr;
- int rval, fd;
+ DSA *dsa; /* MV parameters */
+ BN_CTX *bctx; /* BIGNUM context */
+ EVP_MD_CTX ctx; /* signature context */
+ tstamp_t tstamp;
+ u_int len;
/*
- * 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.
+ * The identity parameters must have correct format and content.
*/
- if (*cp == '/')
- strcpy(filename, cp);
+ 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
- snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
- fd = open(filename, O_RDONLY, 0777);
- if (fd <= 0) {
+ 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,
- "crypto: certificate file %s not found",
- filename);
- return;
+ "cert_parse: expired %s",
+ ret->subject);
+ cert_free(ret);
+ X509_free(cert);
+ return (NULL);
}
/*
- * We are rather paranoid here, since an intruder might cause a
- * coredump by infiltrating naughty values.
+ * Build the value structure to sign and send later.
*/
- rval = RV_OK;
- len = read(fd, buf, 5000);
- close(fd);
- if (rval != RV_OK) {
- msyslog(LOG_ERR,
- "crypto: certificate file %s error %d", cp,
- rval);
- exit (-1);
+ 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);
}
/*
- * The extension field entry consists of the raw certificate.
+ * 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.
*/
- certif.vallen = htonl(200); /* xxxxxxxxxxxxxxxxxx */
- pp = emalloc(len);
- certif.ptr = (u_char *)pp;
- memcpy(pp, buf, len);
- certif.sig = emalloc(private_key.bits / 8);
- crypto_flags |= CRYPTO_FLAG_CERT;
+ 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);
/*
- * Extract filestamp if present.
+ * Sign and verify the certificate.
*/
- rval = readlink(filename, linkname, MAXFILENAME - 1);
- if (rval > 0) {
- linkname[rval] = '\0';
- rptr = strrchr(linkname, '.');
- } else {
- rptr = strrchr(filename, '.');
+ 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);
}
- if (rptr != NULL)
- sscanf(++rptr, "%u", &fstamp);
- else
- fstamp = 0;
- certif.fstamp = htonl(fstamp);
+ 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)
- printf(
- "crypto_cert: certif file %s link %d fs %u len %d\n",
- cp, rval, fstamp, len);
+ if (debug > 1)
+ X509_print_fp(stdout, cert);
#endif
+ X509_free(cert);
+ return (XEVNT_OK);
}
/*
- * crypto_dh - read agreement parameters, decode and check for errors.
+ * 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
*/
-static void
-crypto_dh(
- char *cp /* file name */
+int
+cert_valid(
+ struct cert_info *cinf, /* certificate information structure */
+ EVP_PKEY *pkey /* public key */
)
{
- FILE *str; /* file handle */
- u_char buf[MAX_LINLEN]; /* file line buffer */
- u_char encoded_key[MAX_ENCLEN]; /* encoded key buffer */
- u_char prime[MAX_KEYLEN]; /* decoded prime */
- u_char generator[MAX_KEYLEN]; /* decode generator */
- u_int primelen; /* prime length (octets) */
- u_int generatorlen; /* generator length (octets) */
- char filename[MAXFILENAME]; /* name of parameter file */
- char linkname[MAXFILENAME]; /* file link (for filestamp) */
- u_int fstamp; /* filestamp */
- u_int32 *pp;
- u_int len;
- char *rptr;
- int rval;
+ 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;
/*
- * 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.
+ * 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) {
- msyslog(LOG_INFO,
- "crypto: parameters file %s not found", filename);
- return;
- }
+ if (str == NULL)
+ return (NULL);
/*
- * Ignore initial comments and empty lines.
+ * Read the filestamp, which is contained in the first line.
*/
- while ((rptr = fgets(buf, MAX_LINLEN - 1, str)) != NULL) {
- if (strlen(buf) < 1)
- continue;
- if (*buf == '#' || *buf == '\r' || *buf == '\0')
- continue;
- break;
+ 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);
}
/*
- * We are rather paranoid here, since an intruder might cause a
- * coredump by infiltrating a naughty key. There must be two
- * lines; the first contains the prime, the second the
- * generator. Each line must contain a single integer followed
- * by a PEM encoded, null-terminated string.
- */
- if (rptr == NULL)
- rval = RV_DAT;
- else if (sscanf(buf, "%u %s", &primelen, encoded_key) != 2)
- rval = RV_DAT;
- else if (primelen > MAX_KEYLEN)
- rval = RV_KEY;
- else if (R_DecodePEMBlock(prime, &len, encoded_key,
- strlen(encoded_key)))
- rval = RV_DEC;
- else if (primelen != len || primelen >
- DECODED_CONTENT_LEN(strlen(encoded_key)))
- rval = RV_DAT;
- else if (fscanf(str, "%u %s", &generatorlen, encoded_key) != 2)
- rval = RV_DAT;
- else if (generatorlen > MAX_KEYLEN)
- rval = RV_KEY;
- else if (R_DecodePEMBlock(generator, &len, encoded_key,
- strlen(encoded_key)))
- rval = RV_DEC;
- else if (generatorlen != len || generatorlen >
- DECODED_CONTENT_LEN(strlen(encoded_key)))
- rval = RV_DAT;
- else
- rval = RV_OK;
- if (rval != RV_OK) {
- msyslog(LOG_ERR,
- "crypto: parameters file %s error %x", cp,
- rval);
- exit (-1);
- }
+ * 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);
+ }
/*
- * Initialize agreement parameters and extension field in
- * network byte order. Note the private key length is set
- * arbitrarily at half the prime length.
+ * Leave tracks in the cryptostats.
*/
- len = 4 + primelen + 4 + generatorlen;
- dhparam.vallen = htonl(len);
- pp = emalloc(len);
- dhparam.ptr = (u_char *)pp;
- *pp++ = htonl(primelen);
- memcpy(pp, prime, primelen);
- dh_params.prime = (u_char *)pp;
- pp += primelen / 4;
- *pp++ = htonl(generatorlen);
- memcpy(pp, &generator, generatorlen);
- dh_params.generator = (u_char *)pp;
+ 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);
+}
- dh_params.primeLen = primelen;
- dh_params.generatorLen = generatorlen;
- dh_keyLen = primelen / 2;
- dh_private = emalloc(dh_keyLen);
- dhparam.sig = emalloc(private_key.bits / 8);
- crypto_flags |= CRYPTO_FLAG_DH;
+
+/*
+ * 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;
/*
- * Initialize public value extension field.
+ * 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.
*/
- dhpub.vallen = htonl(dh_params.primeLen);
- dhpub.ptr = emalloc(dh_params.primeLen);
- dhpub.sig = emalloc(private_key.bits / 8);
+ if (*cp == '/')
+ strcpy(filename, cp);
+ else
+ snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
+ str = fopen(filename, "r");
+ if (str == NULL)
+ return (NULL);
/*
- * Extract filestamp if present.
+ * Read the filestamp, which is contained in the first line.
*/
- rval = readlink(filename, linkname, MAXFILENAME - 1);
- if (rval > 0) {
- linkname[rval] = '\0';
- rptr = strrchr(linkname, '.');
- } else {
- rptr = strrchr(filename, '.');
+ if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
+ msyslog(LOG_ERR, "crypto_cert: no data %s\n",
+ filename);
+ return (NULL);
}
- if (rptr != NULL)
- sscanf(++rptr, "%u", &fstamp);
- else
- fstamp = 0;
- dhparam.fstamp = htonl(fstamp);
- dhpub.fstamp = htonl(fstamp);
+ 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_dh: pars file %s link %d fs %u prime %u gen %u\n",
- cp, rval, fstamp, dh_params.primeLen,
- dh_params.generatorLen);
+ printf("crypto_cert: %s\n", statstr);
#endif
+ return (ret);
}
/*
- * crypto_tai - read leapseconds table and check for errors.
+ * 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 */
+ char *cp /* file name */
)
{
- FILE *str; /* file handle */
- u_char buf[MAX_LINLEN]; /* 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) */
- u_int fstamp; /* filestamp */
- u_int32 *pp;
- u_int len;
- char *rptr;
- int rval, i;
+ 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 */
@@ -1886,13 +3616,24 @@ crypto_tai(
strcpy(filename, cp);
else
snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
- str = fopen(filename, "r");
- if (str == NULL) {
- msyslog(LOG_INFO,
- "crypto: leapseconds file %s not found",
- filename);
+ 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
@@ -1905,10 +3646,9 @@ crypto_tai(
* 1972 plus one second for each succeeding insertion.
*/
i = 0;
- rval = RV_OK;
while (i < MAX_LEAP) {
- rptr = fgets(buf, MAX_LINLEN - 1, str);
- if (rptr == NULL)
+ ptr = fgets(buf, NTP_MAXSTRLEN - 1, str);
+ if (ptr == NULL)
break;
if (strlen(buf) < 1)
continue;
@@ -1916,16 +3656,15 @@ crypto_tai(
continue;
if (sscanf(buf, "%u %u", &leapsec[i], &offset) != 2)
continue;
- if (i != offset - TAI_1972) {
- rval = RV_DAT;
+ if (i != (int)(offset - TAI_1972)) {
break;
}
i++;
}
fclose(str);
- if (rval != RV_OK || i == 0) {
- msyslog(LOG_ERR,
- "crypto: leapseconds file %s error %d", cp,
+ if (ptr != NULL) {
+ msyslog(LOG_INFO,
+ "crypto_tai: leapseconds file %s error %d", cp,
rval);
exit (-1);
}
@@ -1937,12 +3676,11 @@ crypto_tai(
*/
len = i * 4;
tai_leap.vallen = htonl(len);
- pp = emalloc(len);
- tai_leap.ptr = (u_char *)pp;
+ ptr = emalloc(len);
+ tai_leap.ptr = (unsigned char *) ptr;
for (; i >= 0; i--) {
- *pp++ = htonl(leapsec[i]);
+ *ptr++ = (char) htonl(leapsec[i]);
}
- tai_leap.sig = emalloc(private_key.bits / 8);
crypto_flags |= CRYPTO_FLAG_TAI;
sys_tai = len / 4 + TAI_1972 - 1;
#ifdef KERNEL_PLL
@@ -1950,109 +3688,344 @@ crypto_tai(
ntv.modes = MOD_TAI;
ntv.constant = sys_tai;
if (ntp_adjtime(&ntv) == TIME_ERROR)
- msyslog(LOG_ERR,
- "crypto: kernel TAI update failed");
+ 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;
+
/*
- * Extract filestamp if present.
+ * Initialize structures.
*/
- rval = readlink(filename, linkname, MAXFILENAME - 1);
- if (rval > 0) {
- linkname[rval] = '\0';
- rptr = strrchr(linkname, '.');
- } else {
- rptr = strrchr(filename, '.');
+ 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 (rptr != NULL)
- sscanf(++rptr, "%u", &fstamp);
- else
- fstamp = 0;
- tai_leap.fstamp = htonl(fstamp);
+ 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_tai: leapseconds file %s link %d fs %u offset %u\n",
- cp, rval, fstamp, ntohl(tai_leap.vallen) / 4 +
- TAI_1972);
+ "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 crypto data from crypto configuration
- * command.
+ * crypto_config - configure data from crypto configuration command.
*/
void
crypto_config(
- int item, /* configuration item */
- char *cp /* file name */
+ int item, /* configuration item */
+ char *cp /* file name */
)
{
switch (item) {
/*
- * Initialize flags
+ * 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_FLAGS:
- sscanf(cp, "%x", &crypto_flags);
+ case CRYPTO_CONF_PW:
+ passwd = emalloc(strlen(cp) + 1);
+ strcpy(passwd, cp);
break;
/*
- * Set private key file name.
+ * Set host file name.
*/
case CRYPTO_CONF_PRIV:
- private_key_file = emalloc(strlen(cp) + 1);
- strcpy(private_key_file, cp);
+ host_file = emalloc(strlen(cp) + 1);
+ strcpy(host_file, cp);
break;
/*
- * Set public key file name.
+ * Set sign key file name.
*/
- case CRYPTO_CONF_PUBL:
- public_key_file = emalloc(strlen(cp) + 1);
- strcpy(public_key_file, cp);
+ case CRYPTO_CONF_SIGN:
+ sign_file = emalloc(strlen(cp) + 1);
+ strcpy(sign_file, cp);
break;
/*
- * Set certificate file name.
+ * Set iff parameters file name.
*/
- case CRYPTO_CONF_CERT:
- certif_file = emalloc(strlen(cp) + 1);
- strcpy(certif_file, cp);
+ case CRYPTO_CONF_IFFPAR:
+ iffpar_file = emalloc(strlen(cp) + 1);
+ strcpy(iffpar_file, cp);
break;
/*
- * Set agreement parameter file name.
+ * Set gq parameters file name.
*/
- case CRYPTO_CONF_DH:
- dh_params_file = emalloc(strlen(cp) + 1);
- strcpy(dh_params_file, cp);
+ case CRYPTO_CONF_GQPAR:
+ gqpar_file = emalloc(strlen(cp) + 1);
+ strcpy(gqpar_file, cp);
break;
/*
- * Set leapseconds table file name.
+ * Set mv parameters file name.
*/
- case CRYPTO_CONF_LEAP:
- tai_leap_file = emalloc(strlen(cp) + 1);
- strcpy(tai_leap_file, cp);
+ 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 crypto keys directory.
+ * Set leapseconds file name.
*/
- case CRYPTO_CONF_KEYS:
- keysdir = emalloc(strlen(cp) + 1);
- strcpy(keysdir, cp);
+ 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 /* PUBKEY */
-#else
-int ntp_crypto_bs_autokey;
-#endif /* AUTOKEY */
+# endif /* OPENSSL */
diff --git a/contrib/ntp/ntpd/ntp_filegen.c b/contrib/ntp/ntpd/ntp_filegen.c
index bcf3f9c..59a1d91 100644
--- a/contrib/ntp/ntpd/ntp_filegen.c
+++ b/contrib/ntp/ntpd/ntp_filegen.c
@@ -214,7 +214,7 @@ filegen_open(
*
* 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 loosing output
+ * but I think this is still better than losing output
*
* ignore errors due to missing directories
*/
@@ -316,7 +316,7 @@ filegen_setup(
case FILEGEN_MONTH:
caljulian(now, &cal);
- cal.yearday -= cal.monthday - 1;
+ cal.yearday = (u_short) (cal.yearday - cal.monthday + 1);
cal.monthday = 1;
cal.hour = cal.minute = cal.second = 0;
new_gen = caltontp(&cal);
@@ -378,8 +378,8 @@ filegen_config(
gen->basename = (char*)emalloc(strlen(basename) + 1);
strcpy(gen->basename, basename);
}
- gen->type = type;
- gen->flag = flag;
+ gen->type = (u_char) type;
+ gen->flag = (u_char) flag;
/*
* make filegen use the new settings
diff --git a/contrib/ntp/ntpd/ntp_intres.c b/contrib/ntp/ntpd/ntp_intres.c
index b6cd45b..7f27f21 100644
--- a/contrib/ntp/ntpd/ntp_intres.c
+++ b/contrib/ntp/ntpd/ntp_intres.c
@@ -50,8 +50,10 @@ 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
@@ -123,8 +125,7 @@ static int resolve_value; /* next value of resolve timer */
/*
* File descriptor for ntp request code.
*/
-static int sockfd = -1;
-
+static SOCKET sockfd = INVALID_SOCKET; /* NT uses SOCKET */
/* stuff to be filled in by caller */
@@ -410,6 +411,8 @@ addentry(
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;
@@ -446,18 +449,18 @@ findhostaddr(
struct conf_entry *entry
)
{
- struct hostent *hp;
- struct in_addr in;
+ struct addrinfo *addr;
+ int error;
checkparent(); /* make sure our guy is still running */
- if (entry->ce_name && entry->ce_peeraddr) {
+ 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 && !entry->ce_peeraddr) {
+ if (entry->ce_name == NULL && !SOCKNUL(&entry->peer_store)) {
msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
return 0;
}
@@ -468,20 +471,33 @@ findhostaddr(
msyslog(LOG_INFO, "findhostaddr: Resolving <%s>",
entry->ce_name);
#endif /* DEBUG */
- hp = gethostbyname(entry->ce_name);
+ 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 %x>",
- entry->ce_peeraddr);
+ msyslog(LOG_INFO, "findhostaddr: Resolving %s>",
+ stoa(&entry->peer_store));
#endif
- in.s_addr = entry->ce_peeraddr;
- hp = gethostbyaddr((const char *)&in,
- sizeof entry->ce_peeraddr,
- AF_INET);
+ 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 (hp == NULL) {
+ if (error != 0) {
/*
* If the resolver is in use, see if the failure is
* temporary. If so, return success.
@@ -496,29 +512,11 @@ findhostaddr(
if (debug > 2)
msyslog(LOG_INFO, "findhostaddr: name resolved.");
#endif
- /*
- * Use the first address. We don't have any way to tell
- * preferences and older gethostbyname() implementations
- * only return one.
- */
- memmove((char *)&(entry->ce_peeraddr),
- (char *)hp->h_addr,
- sizeof(struct in_addr));
- if (entry->ce_keystr[0] == '*')
- strncpy((char *)&(entry->ce_keystr), hp->h_name,
- MAXFILENAME);
- } else {
- char *cp;
- size_t s;
#ifdef DEBUG
if (debug > 2)
msyslog(LOG_INFO, "findhostaddr: address resolved.");
#endif
- s = strlen(hp->h_name) + 1;
- cp = (char *)emalloc(s);
- strcpy(cp, hp->h_name);
- entry->ce_name = cp;
}
return (1);
@@ -531,22 +529,26 @@ findhostaddr(
static void
openntp(void)
{
- struct sockaddr_in saddr;
+ struct addrinfo hints;
+ struct addrinfo *addrResult;
if (sockfd >= 0)
return;
-
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ 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);
}
- memset((char *)&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(NTP_PORT); /* trash */
- saddr.sin_addr.s_addr = htonl(LOCALHOST); /* garbage */
-
/*
* Make the socket non-blocking. We'll wait with select()
*/
@@ -575,12 +577,11 @@ openntp(void)
}
}
#endif /* SYS_WINNT */
-
-
- if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
+ if (connect(sockfd, addrResult->ai_addr, addrResult->ai_addrlen) == -1) {
msyslog(LOG_ERR, "openntp: connect() failed: %m");
exit(1);
}
+ freeaddrinfo(addrResult);
}
@@ -711,7 +712,8 @@ request(
if (n < 0)
{
- msyslog(LOG_ERR, "select() fails: %m");
+ if (errno != EINTR)
+ msyslog(LOG_ERR, "select() fails: %m");
return 0;
}
else if (n == 0)
@@ -832,32 +834,32 @@ request(
case INFO_ERR_IMPL:
msyslog(LOG_ERR,
- "server reports implementation mismatch!!");
+ "ntpd reports implementation mismatch!");
return 0;
case INFO_ERR_REQ:
msyslog(LOG_ERR,
- "server claims configuration request is unknown");
+ "ntpd says configuration request is unknown!");
return 0;
case INFO_ERR_FMT:
msyslog(LOG_ERR,
- "server indicates a format error occurred(!!)");
+ "ntpd indicates a format error occurred!");
return 0;
case INFO_ERR_NODATA:
msyslog(LOG_ERR,
- "server indicates no data available (shouldn't happen)");
+ "ntpd indicates no data available!");
return 0;
case INFO_ERR_AUTH:
msyslog(LOG_ERR,
- "server returns a permission denied error");
+ "ntpd returns a permission denied error!");
return 0;
default:
msyslog(LOG_ERR,
- "server returns unknown error code %d", n);
+ "ntpd returns unknown error code %d!", n);
return 0;
}
}
@@ -1029,10 +1031,10 @@ doconfigure(
#ifdef DEBUG
if (debug > 1)
msyslog(LOG_INFO,
- "doconfigure: <%s> has peeraddr %#x",
- ce->ce_name, ce->ce_peeraddr);
+ "doconfigure: <%s> has peeraddr %s",
+ ce->ce_name, stoa(&ce->peer_store));
#endif
- if (dores && ce->ce_peeraddr == 0) {
+ if (dores && !SOCKNUL(&(ce->peer_store))) {
if (!findhostaddr(ce)) {
msyslog(LOG_ERR,
"couldn't resolve `%s', giving up on it",
@@ -1044,7 +1046,7 @@ doconfigure(
}
}
- if (ce->ce_peeraddr != 0) {
+ if (!SOCKNUL(&ce->peer_store)) {
if (request(&ce->ce_config)) {
ceremove = ce;
ce = ceremove->ce_next;
diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c
index ef0c146..9f2acea 100644
--- a/contrib/ntp/ntpd/ntp_io.c
+++ b/contrib/ntp/ntpd/ntp_io.c
@@ -14,6 +14,17 @@
#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>
@@ -43,46 +54,20 @@
extern int listen_to_virtual_ips;
-#if _BSDI_VERSION >= 199510
-# include <ifaddrs.h>
+#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
-#if defined(VMS) /* most likely UCX-specific */
-
-#include <UCX$INETDEF.H>
-
-/* "un*x"-compatible names for some items in UCX$INETDEF.H */
-#define ifreq IFREQDEF
-#define ifr_name IFR$T_NAME
-#define ifr_addr IFR$R_DUMMY.IFR$T_ADDR
-#define ifr_broadaddr IFR$R_DUMMY.IFR$T_BROADADDR
-#define ifr_flags IFR$R_DUMMY.IFR$R_DUMMY_1_OVRL.IFR$W_FLAGS
-#define IFF_UP IFR$M_IFF_UP
-#define IFF_BROADCAST IFR$M_IFF_BROADCAST
-#define IFF_LOOPBACK IFR$M_IFF_LOOPBACK
-
-#endif /* VMS */
-
-
-#if defined(VMS) || defined(SYS_WINNT)
-/* structure used in SIOCGIFCONF request (after [KSR] OSF/1) */
-struct ifconf {
- int ifc_len; /* size of buffer */
- union {
- caddr_t ifcu_buf;
- struct ifreq *ifcu_req;
- } ifc_ifcu;
-};
-#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
-#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
-
-#endif /* VMS */
-
-#if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
-# if defined(SYS_AIX) && defined(_IO) /* XXX Identify AIX some other way */
-# undef _IO
-# endif
-# include <stropts.h>
#endif
/*
@@ -118,10 +103,15 @@ u_long io_timereset; /* time counters were reset */
/*
* Interface stuff
*/
-struct interface *any_interface; /* default interface */
-struct interface *loopback_interface; /* loopback interface */
-struct interface inter_list[MAXINTERFACES];
-int ninterfaces;
+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
/*
@@ -131,18 +121,94 @@ int ninterfaces;
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_int));
-static int open_socket P((struct sockaddr_in *, int, int));
-static void close_socket P((int));
-static void close_file P((int));
+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
*/
@@ -150,8 +216,6 @@ void
init_io(void)
{
#ifdef SYS_WINNT
- WORD wVersionRequested;
- WSADATA wsaData;
init_transmitbuff();
#endif /* SYS_WINNT */
@@ -165,7 +229,8 @@ init_io(void)
packets_sent = packets_notsent = 0;
handler_calls = handler_pkts = 0;
io_timereset = 0;
- loopback_interface = 0;
+ loopback_interface = NULL;
+ loopback6_interface = NULL;
#ifdef REFCLOCK
refio = 0;
@@ -176,14 +241,17 @@ init_io(void)
#endif
#ifdef SYS_WINNT
- wVersionRequested = MAKEWORD(1,1);
- if (WSAStartup(wVersionRequested, &wsaData))
+ if (!Win32InitSockets())
{
- msyslog(LOG_ERR, "No useable winsock.dll: %m");
+ 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
*/
@@ -197,456 +265,274 @@ init_io(void)
#endif
}
-/*
- * 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_int port
- )
-{
-#if _BSDI_VERSION >= 199510
- int i, j;
- struct ifaddrs *ifaddrs, *ifap;
- struct sockaddr_in resmask;
-#if _BSDI_VERSION < 199701
- struct ifaddrs *lp;
- int num_if;
-#endif
-#else /* _BSDI_VERSION >= 199510 */
-# ifdef STREAMS_TLI
- struct strioctl ioc;
-# endif /* STREAMS_TLI */
- char buf[MAXINTERFACES*sizeof(struct ifreq)];
- struct ifconf ifc;
- struct ifreq ifreq, *ifr;
- int n, i, j, vs, size = 0;
- struct sockaddr_in resmask;
-#endif /* _BSDI_VERSION >= 199510 */
+int
+create_wildcards(u_short port) {
-#ifdef DEBUG
- if (debug)
- printf("create_sockets(%d)\n", ntohs( (u_short) port));
-#endif
+ 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 address
+ * create pseudo-interface with wildcard IPv6 address
*/
- inter_list[0].sin.sin_family = AF_INET;
- inter_list[0].sin.sin_port = port;
- inter_list[0].sin.sin_addr.s_addr = htonl(INADDR_ANY);
- (void) strncpy(inter_list[0].name, "wildcard",
- sizeof(inter_list[0].name));
- inter_list[0].mask.sin_addr.s_addr = htonl(~ (u_int32)0);
- inter_list[0].received = 0;
- inter_list[0].sent = 0;
- inter_list[0].notsent = 0;
- inter_list[0].flags = INT_BROADCAST;
- any_interface = &inter_list[0];
-
-#if _BSDI_VERSION >= 199510
-#if _BSDI_VERSION >= 199701
- if (getifaddrs(&ifaddrs) < 0)
- {
- msyslog(LOG_ERR, "getifaddrs: %m");
- exit(1);
+ 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++;
}
- i = 1;
- for (ifap = ifaddrs; ifap != NULL; ifap = ifap->ifa_next)
-#else
- if (getifaddrs(&ifaddrs, &num_if) < 0)
- {
- msyslog(LOG_ERR, "create_sockets: getifaddrs() failed: %m");
- exit(1);
- }
+#endif
+ return (idx);
+}
- i = 1;
+isc_boolean_t
+address_okay(isc_interface_t *isc_if) {
- for (ifap = ifaddrs, lp = ifap + num_if; ifap < lp; ifap++)
+#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
- {
- struct sockaddr_in *sin;
- if (!ifap->ifa_addr)
- continue;
+ if (listen_to_virtual_ips == 0 && (strchr(isc_if->name, (int)':') != NULL))
+ return (ISC_FALSE);
- if (ifap->ifa_addr->sa_family != AF_INET)
- continue;
+ /* 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;
+ }
- if ((ifap->ifa_flags & IFF_UP) == 0)
- continue;
+ 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 (debug)
- printf("after getifaddrs(), considering %s (%s)\n",
- ifap->ifa_name,
- inet_ntoa(((struct sockaddr_in *)ifap->ifa_addr)->sin_addr));
-
- if (ifap->ifa_flags & IFF_LOOPBACK) {
- sin = (struct sockaddr_in *)ifap->ifa_addr;
- if (ntohl(sin->sin_addr.s_addr) != 0x7f000001 &&
- !listen_to_virtual_ips)
- continue;
- }
- inter_list[i].flags = 0;
- if (ifap->ifa_flags & IFF_BROADCAST)
- inter_list[i].flags |= INT_BROADCAST;
- strcpy(inter_list[i].name, ifap->ifa_name);
- sin = (struct sockaddr_in *)ifap->ifa_addr;
- inter_list[i].sin = *sin;
- inter_list[i].sin.sin_port = port;
- if (ifap->ifa_flags & IFF_LOOPBACK) {
- inter_list[i].flags = INT_LOOPBACK;
- if (loopback_interface == NULL
- || ntohl(sin->sin_addr.s_addr) != 0x7f000001)
- loopback_interface = &inter_list[i];
- }
- if (inter_list[i].flags & INT_BROADCAST) {
- sin = (struct sockaddr_in *)ifap->ifa_broadaddr;
- inter_list[i].bcast = *sin;
- inter_list[i].bcast.sin_port = port;
- }
- if (ifap->ifa_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) {
- inter_list[i].mask.sin_addr.s_addr = 0xffffffff;
- } else {
- sin = (struct sockaddr_in *)ifap->ifa_netmask;
- inter_list[i].mask = *sin;
+ if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback_interface == NULL))
+ {
+ loopback_interface = itf;
}
- inter_list[i].mask.sin_family = AF_INET;
- inter_list[i].mask.sin_len = sizeof *sin;
-
- /*
- * look for an already existing source interface address. If
- * the machine has multiple point to point interfaces, then
- * the local address may appear more than once.
- *
- * A second problem exists if we have two addresses on
- * the same network (via "ifconfig alias ..."). Don't
- * make two xntp interfaces for the two aliases on the
- * one physical interface. -wsr
- */
- for (j=0; j < i; j++)
- if ((inter_list[j].sin.sin_addr.s_addr &
- inter_list[j].mask.sin_addr.s_addr) ==
- (inter_list[i].sin.sin_addr.s_addr &
- inter_list[i].mask.sin_addr.s_addr))
- {
- if (inter_list[j].flags & INT_LOOPBACK)
- inter_list[j] = inter_list[i];
- break;
- }
- if (j == i)
- i++;
- if (i > MAXINTERFACES)
- break;
}
- free(ifaddrs);
-#else /* _BSDI_VERSION >= 199510 */
-# ifdef USE_STREAMS_DEVICE_FOR_IF_CONFIG
- if ((vs = open("/dev/ip", O_RDONLY)) < 0)
- {
- msyslog(LOG_ERR, "create_sockets: open(/dev/ip) failed: %m");
- exit(1);
- }
-# else /* not USE_STREAMS_DEVICE_FOR_IF_CONFIG */
- if (
- (vs = socket(AF_INET, SOCK_DGRAM, 0))
-# ifndef SYS_WINNT
- < 0
-# else /* SYS_WINNT */
- == INVALID_SOCKET
-# endif /* SYS_WINNT */
- ) {
- msyslog(LOG_ERR, "create_sockets: socket(AF_INET, SOCK_DGRAM) failed: %m");
- exit(1);
+#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 /* not USE_STREAMS_DEVICE_FOR_IF_CONFIG */
+#endif /* HAVE_IPV6 */
- i = 1;
-# if !defined(SYS_WINNT)
- ifc.ifc_len = sizeof(buf);
-# endif
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFCONF;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)buf;
- ioc.ic_len = sizeof(buf);
- if(ioctl(vs, I_STR, &ioc) < 0 ||
- ioc.ic_len < sizeof(struct ifreq))
- {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFCONF) failed: %m - exiting");
- exit(1);
- }
-# ifdef SIZE_RETURNED_IN_BUFFER
- ifc.ifc_len = ioc.ic_len - sizeof(int);
- ifc.ifc_buf = buf + sizeof(int);
-# else /* not SIZE_RETURNED_IN_BUFFER */
- ifc.ifc_len = ioc.ic_len;
- ifc.ifc_buf = buf;
-# endif /* not SIZE_RETURNED_IN_BUFFER */
-
-# else /* not STREAMS_TLI */
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_buf = buf;
-# ifndef SYS_WINNT
- if (ioctl(vs, SIOCGIFCONF, (char *)&ifc) < 0)
-# else
- if (WSAIoctl(vs, SIO_GET_INTERFACE_LIST, 0, 0, ifc.ifc_buf, ifc.ifc_len, &ifc.ifc_len, 0, 0) == SOCKET_ERROR)
-# endif /* SYS_WINNT */
-{
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFCONF) failed: %m - exiting");
- exit(1);
+ /* 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;
-# endif /* not STREAMS_TLI */
+#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
- for(n = ifc.ifc_len, ifr = ifc.ifc_req; n > 0;
- ifr = (struct ifreq *)((char *)ifr + size))
+ 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))
{
- size = sizeof(*ifr);
+ isc_interface_t isc_if;
+ unsigned int family;
-# ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
- if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
- size += ifr->ifr_addr.sa_len - sizeof(struct sockaddr);
-# endif
- n -= size;
+ result = isc_interfaceiter_current(iter, &isc_if);
+ if (result != ISC_R_SUCCESS)
+ break;
-# if !defined(SYS_WINNT)
- /* Exclude logical interfaces (indicated by ':' in the interface name) */
- if (debug)
- printf("interface <%s> ", ifr->ifr_name);
- if ((listen_to_virtual_ips == 0)
- && (strchr(ifr->ifr_name, (int)':') != NULL)) {
- if (debug)
- printf("ignored\n");
+ /* See if we have a valid family to use */
+ family = isc_if.address.family;
+ if (family != AF_INET && family != AF_INET6)
continue;
- }
- if (debug)
- printf("OK\n");
-
- if (
-# ifdef VMS /* VMS+UCX */
- (((struct sockaddr *)&(ifr->ifr_addr))->sa_family != AF_INET)
-# else
- (ifr->ifr_addr.sa_family != AF_INET)
-# endif /* VMS+UCX */
- ) {
- if (debug)
- printf("ignoring %s - not AF_INET\n",
- ifr->ifr_name);
+ if (scan_ipv4 == ISC_FALSE && family == AF_INET)
continue;
- }
-# endif /* SYS_WINNT */
- ifreq = *ifr;
- inter_list[i].flags = 0;
- /* is it broadcast capable? */
-# ifndef SYS_WINNT
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFFLAGS;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if(ioctl(vs, I_STR, &ioc)) {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFFLAGS) failed: %m");
- continue;
- }
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
- if (errno != ENXIO)
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFFLAGS) failed: %m");
+ if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
continue;
- }
-# endif /* not STREAMS_TLI */
- if ((ifreq.ifr_flags & IFF_UP) == 0) {
- if (debug)
- printf("ignoring %s - interface not UP\n",
- ifr->ifr_name);
- continue;
- }
- inter_list[i].flags = 0;
- if (ifreq.ifr_flags & IFF_BROADCAST)
- inter_list[i].flags |= INT_BROADCAST;
-# endif /* not SYS_WINNT */
-# if !defined(SUN_3_3_STINKS)
- if (
-# if defined(IFF_LOCAL_LOOPBACK) /* defined(SYS_HPUX) && (SYS_HPUX < 8) */
- (ifreq.ifr_flags & IFF_LOCAL_LOOPBACK)
-# elif defined(IFF_LOOPBACK)
- (ifreq.ifr_flags & IFF_LOOPBACK)
-# else /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */
- /* test against 127.0.0.1 (yuck!!) */
- ((*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr.s_addr == inet_addr("127.0.0.1"))
-# endif /* not IFF_LOCAL_LOOPBACK and not IFF_LOOPBACK */
- )
- {
-# ifndef SYS_WINNT
- inter_list[i].flags |= INT_LOOPBACK;
-# endif /* not SYS_WINNT */
- if (loopback_interface == 0)
- {
- loopback_interface = &inter_list[i];
- }
- }
-# endif /* not SUN_3_3_STINKS */
-#if 0
-# ifndef SYS_WINNT
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFADDR;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if (ioctl(vs, I_STR, &ioc))
- {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFADDR) failed: %m");
- 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++;
}
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFADDR, (char *)&ifreq) < 0)
- {
- if (errno != ENXIO)
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFADDR) failed: %m");
- continue;
- }
-# endif /* not STREAMS_TLI */
-# endif /* not SYS_WINNT */
-#endif /* 0 */
-# if defined(SYS_WINNT)
- {int TODO_FillInTheNameWithSomeThingReasonble;}
-# else
- (void)strncpy(inter_list[i].name, ifreq.ifr_name,
- sizeof(inter_list[i].name));
-# endif
- inter_list[i].sin = *(struct sockaddr_in *)&ifr->ifr_addr;
- inter_list[i].sin.sin_family = AF_INET;
- inter_list[i].sin.sin_port = port;
-
-# if defined(SUN_3_3_STINKS)
- /*
- * Oh, barf! I'm too disgusted to even explain this
- */
- if (SRCADR(&inter_list[i].sin) == 0x7f000001)
- {
- inter_list[i].flags |= INT_LOOPBACK;
- if (loopback_interface == 0)
- loopback_interface = &inter_list[i];
- }
-# endif /* SUN_3_3_STINKS */
-# if !defined SYS_WINNT && !defined SYS_CYGWIN32 /* no interface flags on NT */
- if (inter_list[i].flags & INT_BROADCAST) {
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFBRDADDR;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if(ioctl(vs, I_STR, &ioc)) {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFBRDADDR) failed: %m");
- exit(1);
- }
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFBRDADDR) failed: %m");
- exit(1);
- }
-# endif /* not STREAMS_TLI */
-
-# ifndef ifr_broadaddr
- inter_list[i].bcast =
- *(struct sockaddr_in *)&ifreq.ifr_addr;
-# else
- inter_list[i].bcast =
- *(struct sockaddr_in *)&ifreq.ifr_broadaddr;
-# endif /* ifr_broadaddr */
- inter_list[i].bcast.sin_family = AF_INET;
- inter_list[i].bcast.sin_port = port;
- }
-
-# ifdef STREAMS_TLI
- ioc.ic_cmd = SIOCGIFNETMASK;
- ioc.ic_timout = 0;
- ioc.ic_dp = (caddr_t)&ifreq;
- ioc.ic_len = sizeof(struct ifreq);
- if(ioctl(vs, I_STR, &ioc)) {
- msyslog(LOG_ERR, "create_sockets: ioctl(I_STR:SIOCGIFNETMASK) failed: %m");
- exit(1);
- }
-# else /* not STREAMS_TLI */
- if (ioctl(vs, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
- msyslog(LOG_ERR, "create_sockets: ioctl(SIOCGIFNETMASK) failed: %m");
- exit(1);
- }
-# endif /* not STREAMS_TLI */
- inter_list[i].mask = *(struct sockaddr_in *)&ifreq.ifr_addr;
-# else
- /* winnt here */
- inter_list[i].bcast = ifreq.ifr_broadaddr;
- inter_list[i].bcast.sin_family = AF_INET;
- inter_list[i].bcast.sin_port = port;
- inter_list[i].mask = ifreq.ifr_mask;
-# endif /* not SYS_WINNT */
-
- /*
- * look for an already existing source interface address. If
- * the machine has multiple point to point interfaces, then
- * the local address may appear more than once.
- */
- for (j=0; j < i; j++)
- if (inter_list[j].sin.sin_addr.s_addr ==
- inter_list[i].sin.sin_addr.s_addr) {
- break;
- }
- if (j == i)
- i++;
- if (i > MAXINTERFACES)
- break;
}
- closesocket(vs);
-#endif /* _BSDI_VERSION >= 199510 */
+ isc_interfaceiter_destroy(&iter);
- ninterfaces = i;
+ 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);
- }
-
- /*
- * Now that we have opened all the sockets, turn off the reuse flag for
- * security.
- */
- for (i = 0; i < ninterfaces; i++) {
- int off = 0;
-
- /*
- * if inter_list[ n ].fd is -1, we might have a adapter
- * configured but not present
- */
- if ( inter_list[ i ].fd != -1 ) {
- if (setsockopt(inter_list[i].fd, SOL_SOCKET,
- SO_REUSEADDR, (char *)&off,
- sizeof(off))) {
- msyslog(LOG_ERR, "create_sockets: setsockopt(SO_REUSEADDR,off) failed: %m");
- }
+ 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
}
-#if defined(MCAST)
/*
- * enable possible multicast reception on the broadcast socket
+ * Now that we have opened all the sockets, turn off the reuse
+ * flag for security.
*/
- inter_list[0].bcast.sin_addr.s_addr = htonl(INADDR_ANY);
- inter_list[0].bcast.sin_family = AF_INET;
- inter_list[0].bcast.sin_port = port;
-#endif /* MCAST */
+ set_reuseaddr(0);
/*
* Blacklist all bound interface addresses
+ * Wildcard interfaces are ignored.
*/
- resmask.sin_addr.s_addr = ~ (u_int32)0;
- for (i = 1; i < ninterfaces; i++)
+
+ 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);
@@ -659,20 +545,15 @@ create_sockets(
inter_list[i].flags);
/* Leave these as three printf calls. */
printf(" sin=%s",
- inet_ntoa((inter_list[i].sin.sin_addr)));
+ stoa((&inter_list[i].sin)));
if (inter_list[i].flags & INT_BROADCAST)
printf(" bcast=%s,",
- inet_ntoa((inter_list[i].bcast.sin_addr)));
+ stoa((&inter_list[i].bcast)));
printf(" mask=%s\n",
- inet_ntoa((inter_list[i].mask.sin_addr)));
+ stoa((&inter_list[i].mask)));
}
}
#endif
-#if defined (HAVE_IO_COMPLETION_PORT)
- for (i = 0; i < ninterfaces; i++) {
- io_completion_port_add_socket(&inter_list[i]);
- }
-#endif
return ninterfaces;
}
@@ -684,10 +565,19 @@ io_setbclient(void)
{
int i;
- for (i = 1; i < ninterfaces; 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;
@@ -697,8 +587,54 @@ io_setbclient(void)
#ifdef OPEN_BCAST_SOCKET /* Was: !SYS_DOMAINOS && !SYS_LINUX */
inter_list[i].bfd = open_socket(&inter_list[i].bcast,
INT_BROADCAST, 1);
- inter_list[i].flags |= INT_BCASTOPEN;
+ 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");
+ }
+ }
}
}
@@ -708,83 +644,196 @@ io_setbclient(void)
*/
void
io_multicast_add(
- u_int32 addr
+ struct sockaddr_storage addr
)
{
#ifdef MCAST
struct ip_mreq mreq;
int i = ninterfaces; /* Use the next interface */
- u_int32 haddr = ntohl(addr);
+ u_int32 haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
struct in_addr iaddr;
- int s;
+ SOCKET s;
struct sockaddr_in *sinp;
- iaddr.s_addr = addr;
- if (!IN_CLASSD(haddr)) {
- msyslog(LOG_ERR,
- "multicast address %s not class D",
- inet_ntoa(iaddr));
- return;
- }
- for (i = 0; i < ninterfaces; i++) {
- /* Already have this address */
- if (inter_list[i].sin.sin_addr.s_addr == addr)
+#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;
- /* found a free slot */
- if (inter_list[i].sin.sin_addr.s_addr == 0 &&
- inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
- inter_list[i].flags == 0)
+ }
+ 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;
- }
- sinp = &(inter_list[i].sin);
- memset((char *)&mreq, 0, sizeof(mreq));
- memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
- sinp->sin_family = AF_INET;
- sinp->sin_addr = iaddr;
- sinp->sin_port = htons(123);
- /*
- * Try opening a socket for the specified class D address. This
- * works under SunOS 4.x, but not OSF1 .. :-(
- */
- s = open_socket(sinp, 0, 1);
- if (s < 0) {
- memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
- i = 0;
- /* HACK ! -- stuff in an address */
- inter_list[i].bcast.sin_addr.s_addr = addr;
- msyslog(LOG_ERR,
- "...multicast address %s using wildcard socket",
- inet_ntoa(iaddr));
- } else {
- inter_list[i].fd = s;
- inter_list[i].bfd = -1;
- (void) strncpy(inter_list[i].name, "multicast",
- sizeof(inter_list[i].name));
- inter_list[i].mask.sin_addr.s_addr = htonl(~(u_int32)0);
+#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 */
}
- /*
- * 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)
- msyslog(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;
- if (i >= ninterfaces)
- ninterfaces = i+1;
+#ifdef DEBUG
+ if (debug)
+ printf("io_multicast_add %s\n", stoa(&addr));
+#endif
#else /* MCAST */
- struct in_addr iaddr;
-
- iaddr.s_addr = addr;
- msyslog(LOG_ERR,
+ netsyslog(LOG_ERR,
"cannot add multicast address %s as no MCAST support",
- inet_ntoa(iaddr));
+ stoa(&addr));
#endif /* MCAST */
}
@@ -796,12 +845,12 @@ io_unsetbclient(void)
{
int i;
- for (i = 1; i < ninterfaces; 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 = -1;
+ inter_list[i].bfd = INVALID_SOCKET;
inter_list[i].flags &= ~INT_BCASTOPEN;
}
}
@@ -812,57 +861,125 @@ io_unsetbclient(void)
*/
void
io_multicast_del(
- u_int32 addr
+ struct sockaddr_storage addr
)
{
#ifdef MCAST
int i;
struct ip_mreq mreq;
- u_int32 haddr = ntohl(addr);
- struct sockaddr_in sinaddr;
+ u_int32 haddr;
- if (!IN_CLASSD(haddr))
- {
- sinaddr.sin_addr.s_addr = addr;
- msyslog(LOG_ERR,
- "invalid multicast address %s", ntoa(&sinaddr));
- return;
- }
+#ifdef HAVE_IPV6
+ struct ipv6_mreq mreq6;
+ struct in6_addr haddr6;
+#endif /* HAVE_IPV6 */
- /*
- * Disable reception of multicast packets
- */
- mreq.imr_multiaddr.s_addr = addr;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- for (i = 0; i < ninterfaces; i++)
+ switch (addr.ss_family)
{
- if (!(inter_list[i].flags & INT_MULTICAST))
- continue;
- if (!(inter_list[i].fd < 0))
- continue;
- if (addr != inter_list[i].sin.sin_addr.s_addr)
- continue;
- if (i != 0)
+ case AF_INET :
+
+ haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
+
+ if (!IN_CLASSD(haddr))
{
- /* we have an explicit fd, so we can close it */
- close_socket(inter_list[i].fd);
- memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
- inter_list[i].fd = -1;
- inter_list[i].bfd = -1;
+ netsyslog(LOG_ERR,
+ "invalid multicast address %s", stoa(&addr));
+ return;
}
- else
+
+ /*
+ * 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++)
{
- /* 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)
- msyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails: %m");
- /* This is **WRONG** -- there may be others ! */
- /* There should be a count of users ... */
- inter_list[i].flags &= ~INT_MULTICAST;
+ /* 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 */
- msyslog(LOG_ERR, "this function requires multicast kernel");
+ netsyslog(LOG_ERR, "this function requires multicast kernel");
#endif /* not MCAST */
}
@@ -870,87 +987,163 @@ io_multicast_del(
/*
* open_socket - open a socket, returning the file descriptor
*/
-static int
+
+static SOCKET
open_socket(
- struct sockaddr_in *addr,
+ struct sockaddr_storage *addr,
int flags,
int turn_off_reuse
)
{
- int fd;
+ 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 */
- if ( (fd = socket(AF_INET, SOCK_DGRAM, 0))
#ifndef SYS_WINNT
- < 0
+ 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
- == INVALID_SOCKET
-#endif /* SYS_WINNT */
- )
- {
- msyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed: %m");
+ 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)))
{
- msyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails: %m");
+ 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 (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)) < 0)
- {
- msyslog(LOG_ERR, "setsockopt IPTOS_LOWDELAY on fails: %m");
- }
+ 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, sizeof(*addr)) < 0) {
+ if (bind(fd, (struct sockaddr *)addr, SOCKLEN(addr)) < 0) {
char buff[160];
- sprintf(buff,
- "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=%d fails: %%m",
- fd, addr->sin_family, (int)ntohs(addr->sin_port),
- ntoa(addr),
- IN_CLASSD(ntohl(addr->sin_addr.s_addr)), flags);
- msyslog(LOG_ERR, buff);
+
+ 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 class D address
+ * soft fail if opening a multicast address
*/
- if (IN_CLASSD(ntohl(addr->sin_addr.s_addr)))
- return -1;
+ 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 -1;
+ return INVALID_SOCKET;
#endif
}
#ifdef DEBUG
if (debug)
printf("bind() fd %d, family %d, port %d, addr %s, flags=%d\n",
fd,
- addr->sin_family,
- (int)ntohs(addr->sin_port),
- ntoa(addr),
+ 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,
*/
@@ -967,43 +1160,46 @@ open_socket(
#if defined(O_NONBLOCK) /* POSIX */
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
{
- msyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails: %m");
+ 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)
{
- msyslog(LOG_ERR, "fcntl(FNDELAY) fails: %m");
+ 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)
{
- msyslog(LOG_ERR, "fcntl(O_NDELAY) fails: %m");
+ netsyslog(LOG_ERR, "fcntl(O_NDELAY) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
#elif defined(FIONBIO)
- if (
# if defined(VMS)
- (ioctl(fd,FIONBIO,&1) < 0)
+ if (ioctl(fd,FIONBIO,&on) < 0)
# elif defined(SYS_WINNT)
- (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
+ if (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
# else
- (ioctl(fd,FIONBIO,&on) < 0)
+ if (ioctl(fd,FIONBIO,&on) < 0)
# endif
- )
{
- msyslog(LOG_ERR, "ioctl(FIONBIO) fails: %m");
+ netsyslog(LOG_ERR, "ioctl(FIONBIO) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
#elif defined(FIOSNBIO)
if (ioctl(fd,FIOSNBIO,&on) < 0)
{
- msyslog(LOG_ERR, "ioctl(FIOSNBIO) fails: %m");
+ netsyslog(LOG_ERR, "ioctl(FIOSNBIO) fails on address %s: %m",
+ stoa(addr));
exit(1);
/*NOTREACHED*/
}
@@ -1025,7 +1221,8 @@ open_socket(
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *)&off, sizeof(off)))
{
- msyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails: %m");
+ netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails on address %s: %m",
+ stoa(addr));
}
#ifdef SO_BROADCAST
@@ -1035,7 +1232,8 @@ open_socket(
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
(char *)&on, sizeof(on)))
{
- msyslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m");
+ netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) on address %s: %m",
+ stoa(addr));
}
}
#endif /* SO_BROADCAST */
@@ -1057,21 +1255,29 @@ open_socket(
*/
static void
close_socket(
- int fd
+ SOCKET fd
)
{
- int i, newmax;
+ 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) {
+ 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);
+
}
@@ -1079,24 +1285,33 @@ close_socket(
* 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(
- int fd
+ 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) {
+ 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 */
@@ -1107,7 +1322,7 @@ close_file(
*/
void
sendpkt(
- struct sockaddr_in *dest,
+ struct sockaddr_storage *dest,
struct interface *inter,
int ttl,
struct pkt *pkt,
@@ -1120,7 +1335,7 @@ sendpkt(
#endif /* SYS_WINNT */
/*
- * Send error cache. Empty slots have port == 0
+ * Send error caches. Empty slots have port == 0
* Set ERRORCACHESIZE to 0 to disable
*/
struct cache {
@@ -1128,57 +1343,121 @@ sendpkt(
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, ntoa(dest),
- ntoa(&inter->sin), ttl, len);
+ inter->fd, stoa(dest),
+ stoa(&inter->sin), ttl, len);
#endif
#ifdef MCAST
- /*
- * for the moment we use the bcast option to set multicast ttl
- */
- if (ttl > 0 && ttl != inter->last_ttl) {
- char mttl = ttl;
+
+ switch (inter->sin.ss_family) {
+
+ case AF_INET :
/*
- * set the multicast ttl for outgoing packets
+ * 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 (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
- &mttl, sizeof(mttl)) == -1)
- msyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails: %m");
- else
- inter->last_ttl = ttl;
+ 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 (badaddrs[slot].port == dest->sin_port &&
- badaddrs[slot].addr.s_addr == dest->sin_addr.s_addr)
- break;
+ 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
- cc = sendto(inter->fd, (char *)pkt, (size_t)len, 0, (struct sockaddr *)dest,
- sizeof(struct sockaddr_in));
+#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)
@@ -1187,14 +1466,37 @@ sendpkt(
/*
* Remember this, if there's an empty slot
*/
- for (slot = ERRORCACHESIZE; --slot >= 0; )
- if (badaddrs[slot].port == 0)
- {
- badaddrs[slot].port = dest->sin_port;
- badaddrs[slot].addr = dest->sin_addr;
- break;
- }
- msyslog(LOG_ERR, "sendto(%s): %m", ntoa(dest));
+ 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
@@ -1206,8 +1508,17 @@ sendpkt(
*/
if (slot >= 0)
{
- msyslog(LOG_INFO, "Connection re-established to %s", ntoa(dest));
- badaddrs[slot].port = 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 */
+ }
}
}
}
@@ -1249,7 +1560,7 @@ input_handler(
register int i, n;
register struct recvbuf *rb;
register int doing;
- register int fd;
+ register SOCKET fd;
struct timeval tvzero;
int fromlen;
l_fp ts; /* Timestamp at BOselect() gob */
@@ -1315,14 +1626,17 @@ input_handler(
if (rb->recv_length == -1)
{
- msyslog(LOG_ERR, "clock read fd %d: %m", fd);
+ 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.
+ * 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;
@@ -1333,13 +1647,25 @@ input_handler(
if (rp->io_input)
{
/*
- * have direct input routine for refclocks
+ * have direct
+ * input routine
+ * for refclocks
*/
if (rp->io_input(rb) == 0)
{
/*
- * data was consumed - nothing to pass up
- * into block input machine
+ * data
+ * was
+ * consumed
+ * -
+ * nothing
+ * to
+ * pass
+ * up
+ * into
+ * block
+ * input
+ * machine
*/
freerecvbuf(rb);
#if 1
@@ -1360,7 +1686,8 @@ input_handler(
#endif /* REFCLOCK */
/*
- * Loop through the interfaces looking for data to read.
+ * Loop through the interfaces looking for data
+ * to read.
*/
for (i = ninterfaces - 1; (i >= 0) && (n > 0); i--)
{
@@ -1382,9 +1709,12 @@ input_handler(
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
+ * 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 (
@@ -1395,23 +1725,24 @@ input_handler(
*/
(free_recvbuffs() == 0)
#else
- ((i == 0) || (free_recvbuffs() == 0))
+ ((i == wildipv4) || (i == wildipv6)||
+ (free_recvbuffs() == 0))
#endif
)
{
char buf[RX_BUFF_SIZE];
- struct sockaddr from;
+ struct sockaddr_storage from;
fromlen = sizeof from;
- (void) recvfrom(fd, buf, sizeof(buf), 0, &from, &fromlen);
+ (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,
- inet_ntoa(((struct sockaddr_in *) &from)->sin_addr));
+ stoa(&from));
#endif
- if (i == 0)
+ if (i == wildipv4 || i == wildipv6)
packets_ignored++;
else
packets_dropped++;
@@ -1420,7 +1751,7 @@ input_handler(
rb = get_free_recv_buffer();
- fromlen = sizeof(struct sockaddr_in);
+ fromlen = sizeof(struct sockaddr_storage);
rb->recv_length = recvfrom(fd,
(char *)&rb->recv_space,
sizeof(rb->recv_space), 0,
@@ -1439,8 +1770,8 @@ input_handler(
}
else if (rb->recv_length < 0)
{
- msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
- inet_ntoa(rb->recv_srcadr.sin_addr), fd);
+ 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);
@@ -1449,12 +1780,18 @@ input_handler(
continue;
}
#ifdef DEBUG
- if (debug > 2)
- printf("input_handler: if=%d fd=%d length %d from %08lx %s\n",
- i, fd, rb->recv_length,
- (u_long)ntohl(rb->recv_srcadr.sin_addr.s_addr) &
- 0x00000000ffffffff,
- inet_ntoa(rb->recv_srcadr.sin_addr));
+ 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
/*
@@ -1467,7 +1804,7 @@ input_handler(
rb->receiver = receive;
add_full_recv_buffer(rb);
-
+
inter_list[i].received++;
packets_received++;
goto select_again;
@@ -1491,19 +1828,20 @@ input_handler(
if (select_count == 0) /* We really had nothing to do */
{
if (debug)
- msyslog(LOG_DEBUG, "input_handler: select() returned 0");
+ 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.
+ * (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)
- msyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
+ netsyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
/* just bail. */
--handler_count;
@@ -1516,8 +1854,11 @@ input_handler(
/*
* extended FAU debugging output
*/
- msyslog(LOG_ERR, "select(%d, %s, 0L, 0L, &0.000000) error: %m",
- maxactivefd+1, fdbits(maxactivefd, &activefds));
+ 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;
@@ -1526,7 +1867,7 @@ input_handler(
if (
(FD_ISSET(j, &fds) && (read(j, &b, 0) == -1))
)
- msyslog(LOG_ERR, "Bad file descriptor %d", j);
+ netsyslog(LOG_ERR, "Bad file descriptor %d", j);
}
--handler_count;
return;
@@ -1538,70 +1879,91 @@ input_handler(
}
#endif
-
/*
* findinterface - find interface corresponding to address
*/
struct interface *
findinterface(
- struct sockaddr_in *addr
+ struct sockaddr_storage *addr
)
{
- int s, rtn, i;
- struct sockaddr_in saddr;
- int saddrlen = sizeof(saddr);
- u_int32 xaddr;
-
+ 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.
*/
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = addr->sin_addr.s_addr;
- saddr.sin_port = htons(2000);
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- return (any_interface);
-
- rtn = connect(s, (struct sockaddr *)&saddr, sizeof(saddr));
+ 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)
- return (any_interface);
+#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)
- return (any_interface);
-
- close(s);
- xaddr = NSRCADR(&saddr);
- for (i = 1; i < ninterfaces; i++) {
+#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 (NSRCADR(&inter_list[i].sin) == xaddr)
+ if (SOCKCMP(&inter_list[i].sin, &saddr))
return (&inter_list[i]);
}
- return (any_interface);
+ return ANY_INTERFACE_CHOOSE(addr);
}
-
/*
* findbcastinter - find broadcast interface corresponding to address
*/
struct interface *
findbcastinter(
- struct sockaddr_in *addr
+ struct sockaddr_storage *addr
)
{
#if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT))
register int i;
- register u_int32 xaddr;
-
- xaddr = NSRCADR(addr);
- for (i = 1; i < ninterfaces; 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
@@ -1610,15 +1972,23 @@ findbcastinter(
*/
if (!(inter_list[i].flags & INT_BROADCAST))
continue;
- if (NSRCADR(&inter_list[i].bcast) == xaddr)
- return (&inter_list[i]);
- if ((NSRCADR(&inter_list[i].sin) &
- NSRCADR(&inter_list[i].mask)) == (xaddr &
- NSRCADR(&inter_list[i].mask)))
- return (&inter_list[i]);
+ 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);
+ return ANY_INTERFACE_CHOOSE(addr);
}
@@ -1659,9 +2029,14 @@ io_addclock_simple(
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;
}
@@ -1693,16 +2068,21 @@ io_addclock(
# 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;
}
@@ -1751,12 +2131,127 @@ io_closeclock(
}
#endif /* REFCLOCK */
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
void
-kill_asyncio(void)
+kill_asyncio(
+ int startfd
+ )
{
- int i;
+ SOCKET i;
BLOCKIO();
- for (i = 0; i <= maxactivefd; i++)
+ 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
index 1d24897..99d1cc4 100644
--- a/contrib/ntp/ntpd/ntp_loopfilter.c
+++ b/contrib/ntp/ntpd/ntp_loopfilter.c
@@ -1,6 +1,8 @@
/*
* 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>
@@ -32,18 +34,17 @@
* 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 offset (s) */
-#define CLOCK_PANIC 1000. /* default panic offset (s) */
+#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 SHIFT_PLL 4 /* PLL loop gain (shift) */
+#define CLOCK_PLL 16. /* PLL loop gain */
#define CLOCK_FLL 8. /* FLL loop gain */
#define CLOCK_AVG 4. /* parameter averaging constant */
-#define CLOCK_MINSEC 256. /* min FLL update interval (s) */
-#define CLOCK_MINSTEP 900. /* step-change timeout (s) */
-#define CLOCK_DAY 86400. /* one day of seconds (s) */
+#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 CLOCK_ALLAN 10 /* min Allan intercept (log2 s) */
#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
/*
@@ -108,22 +109,11 @@
/*
* Program variables that can be tinkered.
*/
-double clock_max = CLOCK_MAX; /* max offset before step (s) */
-double clock_panic = CLOCK_PANIC; /* max offset before panic (s) */
+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 clock_minstep = CLOCK_MINSTEP; /* step timeout (s) */
-u_char allan_xpt = CLOCK_ALLAN; /* minimum Allan intercept (log2 s) */
-
-/*
- * Hybrid PLL/FLL parameters. These were chosen by experiment using a
- * MatLab program. The parameters were fudged to match a pure PLL at
- * poll intervals of 64 s and lower and a pure FLL at poll intervals of
- * 4096 s and higher. Between these extremes the parameters were chosen
- * as a geometric series of intervals while holding the overshoot to
- * less than 5 percent.
- */
-static double fll[] = {0., 1./64, 1./32, 1./16, 1./8, 1./4, 1.};
-static double pll[] = {1., 1.4, 2., 2.8, 4.1, 7., 12.};
+double allan_xpt = CLOCK_ALLAN; /* Allan intercept (s) */
/*
* Program variables
@@ -132,7 +122,7 @@ 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, double, double)); /* transition function */
+static void rstclock P((int, u_long, double)); /* transition function */
#ifdef KERNEL_PLL
struct timex ntv; /* kernel API parameters */
@@ -149,17 +139,15 @@ 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_step = TRUE; /* allow step correction */
int allow_panic = FALSE; /* allow panic correction */
int mode_ntpdate = FALSE; /* exit on first clock set */
/*
* Clock state machine variables
*/
-u_char sys_minpoll = NTP_MINDPOLL; /* min sys poll interval (log2 s) */
u_char sys_poll = NTP_MINDPOLL; /* system poll interval (log2 s) */
int state; /* clock discipline state */
-int tc_counter; /* poll-adjust counter */
+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) */
@@ -200,6 +188,9 @@ init_loopfilter(void)
/*
* 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(
@@ -208,14 +199,13 @@ local_clock(
double epsil /* jittter (square s*s) */
)
{
- double mu; /* interval since last update (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 */
- int i;
/*
* If the loop is opened, monitor and record the offsets
@@ -224,9 +214,14 @@ local_clock(
#ifdef DEBUG
if (debug)
printf(
- "local_clock: assocID %d off %.6f jit %.6f sta %d\n",
+ "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);
@@ -262,19 +257,16 @@ local_clock(
* so the termination comments print directly to the console.
*/
if (mode_ntpdate) {
- if (allow_step && fabs(fp_offset) > clock_max &&
- clock_max > 0) {
+ if (fabs(fp_offset) > clock_max && clock_max > 0) {
step_systime(fp_offset);
- NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
- msyslog(LOG_NOTICE, "time reset %.6f s",
+ msyslog(LOG_NOTICE, "time reset %+.6f s",
fp_offset);
- printf("ntpd: time reset %.6fs\n", fp_offset);
+ printf("ntpd: time set %+.6fs\n", fp_offset);
} else {
adj_systime(fp_offset);
- NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
- msyslog(LOG_NOTICE, "time slew %.6f s",
+ msyslog(LOG_NOTICE, "time slew %+.6f s",
fp_offset);
- printf("ntpd: time slew %.6fs\n", fp_offset);
+ printf("ntpd: time slew %+.6fs\n", fp_offset);
}
record_loop_stats(fp_offset, drift_comp, SQRT(epsil),
clock_stability, sys_poll);
@@ -289,9 +281,12 @@ local_clock(
* get here again.
*/
if (state == S_NSET) {
- step_systime(fp_offset);
- NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
- msyslog(LOG_NOTICE, "time set %.6f s", fp_offset);
+ 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);
}
@@ -396,20 +391,12 @@ local_clock(
* reset or shaken, but never stirred.
*/
default:
- if (allow_step) {
- step_systime(fp_offset);
- NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
- msyslog(LOG_NOTICE, "time reset %.6f s",
- fp_offset);
- rstclock(S_TSET, peer->epoch, 0);
- retval = 1;
- } else {
- NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
- msyslog(LOG_NOTICE, "time slew %.6f s",
- fp_offset);
- rstclock(S_FREQ, peer->epoch,
- fp_offset);
- }
+ 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 {
@@ -449,58 +436,52 @@ local_clock(
/*
* We come here in the normal case for linear phase and
- * frequency adjustments. If the offset exceeds the
- * previous time error estimate by CLOCK_SGATE and the
- * interval since the last update is less than twice the
- * poll interval, consider the update a popcorn spike
- * and ignore it.
+ * 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;
- if (fabs(fp_offset - last_offset) >
- CLOCK_SGATE * oerror && mu <
- ULOGTOD(sys_poll + 1)) {
+ 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",
- fabs(fp_offset -
- last_offset), CLOCK_SGATE *
- oerror);
+ dtemp, oerror);
#endif
last_offset = fp_offset;
return (0);
}
+*/
/*
- * Compute the FLL and PLL frequency adjustments
- * conditioned on intricate weighting factors.
- * The gain factors depend on the poll interval
- * and Allan intercept. For the FLL, the
- * averaging interval is clamped to a minimum of
- * 1024 s and the gain increased in stages from
- * zero for poll intervals below half the Allan
- * intercept to unity above twice the Allan
- * intercept. For the PLL, the averaging
- * interval is clamped not to exceed the poll
- * interval. No gain factor is necessary, since
- * the frequency steering above the Allan
- * intercept is negligible. Particularly for the
- * PLL, these measures allow oversampling, but
- * not undersampling and insure stability even
- * when the rules of fair engagement are broken.
+ * 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.
*/
- i = sys_poll - allan_xpt + 4;
- if (i < 0)
- i = 0;
- else if (i > 6)
- i = 6;
- etemp = fll[i];
- dtemp = max(mu, ULOGTOD(allan_xpt));
- flladj = (fp_offset - clock_offset) * etemp /
- (dtemp * CLOCK_FLL);
- dtemp = ULOGTOD(SHIFT_PLL + 2 + sys_poll);
- etemp = min(mu, ULOGTOD(sys_poll));
+ 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;
@@ -508,7 +489,7 @@ local_clock(
}
}
-#if defined(KERNEL_PLL)
+#ifdef KERNEL_PLL
/*
* This code segment works when clock adjustments are made using
* precision time kernel support and the ntp_adjtime() system
@@ -607,10 +588,17 @@ local_clock(
*/
if (ntp_adjtime(&ntv) == TIME_ERROR) {
if (ntv.status != pll_status)
- msyslog(LOG_ERR,
- "kernel time discipline status change %x",
+ 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)
@@ -640,15 +628,23 @@ local_clock(
* drift_comp is a sham and used only for updating the drift
* file and for billboard eye candy.
*/
- etemp = clock_frequency + flladj + plladj;
- drift_comp += etemp;
- if (drift_comp > NTP_MAXFREQ)
+ dtemp = clock_frequency + flladj + plladj;
+ etemp = drift_comp + dtemp;
+ if (etemp > NTP_MAXFREQ)
drift_comp = NTP_MAXFREQ;
- else if (drift_comp <= -NTP_MAXFREQ)
+ else if (etemp <= -NTP_MAXFREQ)
drift_comp = -NTP_MAXFREQ;
- dtemp = SQUARE(clock_stability);
- etemp = SQUARE(etemp) - dtemp;
- clock_stability = SQRT(dtemp + etemp / CLOCK_AVG);
+ 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
@@ -660,7 +656,7 @@ local_clock(
* helps calm the dance. Works best using burst mode.
*/
if (state == S_SYNC) {
- if (sys_jitter / ULOGTOD(sys_poll) > clock_stability &&
+ if (sys_jitter > ULOGTOD(sys_poll) * clock_stability &&
fabs(clock_offset) < CLOCK_PGATE * sys_jitter) {
tc_counter += sys_poll;
if (tc_counter > CLOCK_LIMIT) {
@@ -685,33 +681,38 @@ local_clock(
/*
* Update the system time variables.
*/
- dtemp = peer->disp + sys_jitter;
- if ((peer->flags & FLAG_REFCLOCK) == 0 && dtemp < MINDISPERSE)
+ 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 %.0f noi %.3f stb %.3f pol %d cnt %d\n",
- mu, sys_jitter * 1e6, clock_stability * 1e6, sys_poll,
+ "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;
- int i;
+ double adjustment;
/*
* Update the dispersion since the last update. In contrast to
@@ -725,24 +726,23 @@ adj_host_clock(
*/
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_SYSEVENT) /* conditional if clause */
- msyslog(LOG_INFO, "pps sync disabled");
+ NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
+ msyslog(LOG_NOTICE, "pps sync disabled");
pps_control = 0;
}
- if (!ntp_enable)
- return;
/*
- * If the phase-lock loop is implemented in the kernel, we
- * have no business going further.
+ * If NTP is disabled or ntpdate mode enabled or the kernel
+ * discipline enabled, we have no business going further.
*/
- if (pll_control && kern_enable)
+ if (!ntp_enable || mode_ntpdate || (pll_control && kern_enable))
return;
/*
@@ -759,19 +759,13 @@ adj_host_clock(
}
/*
- * This ugly bit of business is necessary in order to move the
- * pole frequency higher in FLL mode. This is necessary for loop
- * stability.
+ * Implement the phase and frequency adjustments. Note the
+ * black art formerly practiced here has been whitewashed.
*/
- i = sys_poll - allan_xpt + 4;
- if (i < 0)
- i = 0;
- else if (i > 6)
- i = 6;
- adjustment = clock_offset / (pll[i] * ULOGTOD(SHIFT_PLL +
- sys_poll));
+ adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
clock_offset -= adjustment;
adj_systime(adjustment + drift_comp);
+#endif /* LOCKCLOCK */
}
@@ -781,7 +775,7 @@ adj_host_clock(
static void
rstclock(
int trans, /* new state */
- double epoch, /* last time */
+ u_long epoch, /* last time */
double offset /* last offset */
)
{
@@ -790,6 +784,11 @@ rstclock(
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
}
@@ -815,6 +814,8 @@ huffpuff()
/*
* loop_config - configure the loop filter
+ *
+ * LOCKCLOCK: The LOOP_DRIFTINIT and LOOP_DRIFTCOMP cases are no-ops.
*/
void
loop_config(
@@ -828,6 +829,7 @@ loop_config(
case LOOP_DRIFTINIT:
+#ifndef LOCKCLOCK
#ifdef KERNEL_PLL
/*
* Assume the kernel supports the ntp_adjtime() syscall.
@@ -836,7 +838,15 @@ loop_config(
* 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
@@ -879,27 +889,31 @@ loop_config(
if (pll_status & STA_CLK)
ext_enable = 1;
#endif /* STA_NANO */
- msyslog(LOG_NOTICE,
- "kernel time discipline status %04x",
+ 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
/*
- * Initialize the kernel frequency and clamp to
- * reasonable value. Also set the initial state to
- * S_FSET to indicated the frequency has been
- * initialized from the previously saved drift file.
+ * 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.
*/
- rstclock(S_FSET, current_time, 0);
- drift_comp = freq;
- if (drift_comp > NTP_MAXFREQ)
- drift_comp = NTP_MAXFREQ;
- if (drift_comp < -NTP_MAXFREQ)
- drift_comp = -NTP_MAXFREQ;
+ if (freq <= NTP_MAXFREQ && freq >= -NTP_MAXFREQ) {
+ drift_comp = freq;
+ rstclock(S_FSET, current_time, 0);
+ } else {
+ drift_comp = 0;
+ }
#ifdef KERNEL_PLL
/*
@@ -921,6 +935,7 @@ loop_config(
(void)ntp_adjtime(&ntv);
}
#endif /* KERNEL_PLL */
+#endif /* LOCKCLOCK */
break;
/*
@@ -930,7 +945,7 @@ loop_config(
clock_max = freq;
break;
- case LOOP_PANIC: /* panic exit threshold */
+ case LOOP_PANIC: /* panic threshold */
clock_panic = freq;
break;
@@ -942,16 +957,8 @@ loop_config(
clock_minstep = freq;
break;
- case LOOP_MINPOLL: /* ephemeral association poll */
- if (freq < NTP_MINPOLL)
- freq = NTP_MINPOLL;
- sys_minpoll = (u_char)freq;
- break;
-
- case LOOP_ALLAN: /* minimum Allan intercept */
- if (freq < CLOCK_ALLAN)
- freq = CLOCK_ALLAN;
- allan_xpt = (u_char)freq;
+ case LOOP_ALLAN: /* Allan intercept */
+ allan_xpt = freq;
break;
case LOOP_HUFFPUFF: /* huff-n'-puff filter length */
@@ -964,6 +971,11 @@ loop_config(
sys_huffpuff[i] = 1e9;
sys_mindly = 1e9;
break;
+
+ case LOOP_FREQ: /* initial frequency */
+ drift_comp = freq / 1e6;
+ rstclock(S_FSET, current_time, 0);
+ break;
}
}
diff --git a/contrib/ntp/ntpd/ntp_monitor.c b/contrib/ntp/ntpd/ntp_monitor.c
index 8526aac..6b288fc 100644
--- a/contrib/ntp/ntpd/ntp_monitor.c
+++ b/contrib/ntp/ntpd/ntp_monitor.c
@@ -1,7 +1,6 @@
/*
- * ntp_monitor.c - monitor who is using the ntpd server
+ * ntp_monitor - monitor ntpd statistics
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -18,30 +17,29 @@
#endif
/*
- * I'm still not sure I like what I've done here. It certainly consumes
+ * 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.
+ * 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.
+ * 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
+ * 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
@@ -62,31 +60,31 @@
*/
#define MON_HASH_SIZE 128
#define MON_HASH_MASK (MON_HASH_SIZE-1)
-#define MON_HASH(addr) ((int)(ntohl((addr)) & MON_HASH_MASK))
+#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.
+ * for the hash and count tables is only allocated if monitoring is
+ * turned on.
*/
-static struct mon_data *mon_hash[MON_HASH_SIZE]; /* array of list ptrs */
-struct mon_data mon_mru_list;
-struct mon_data mon_fifo_list;
+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; /* the free list or null if none */
-
-static int mon_total_mem; /* total number of structures allocated */
-static int mon_mem_increments; /* number of times we've called malloc() */
+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;
+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 *));
@@ -106,9 +104,8 @@ init_mon(void)
mon_total_mem = 0;
mon_mem_increments = 0;
mon_free = NULL;
- memset((char *)&mon_hash[0], 0, sizeof mon_hash);
- memset((char *)&mon_mru_list, 0, sizeof mon_mru_list);
- memset((char *)&mon_fifo_list, 0, sizeof mon_fifo_list);
+ memset(&mon_hash[0], 0, sizeof mon_hash);
+ memset(&mon_mru_list, 0, sizeof mon_mru_list);
}
@@ -126,7 +123,7 @@ mon_start(
return;
}
if (mode == MON_OFF)
- return; /* Ooops.. */
+ return;
if (!mon_have_memory) {
mon_total_mem = 0;
@@ -138,10 +135,6 @@ mon_start(
mon_mru_list.mru_next = &mon_mru_list;
mon_mru_list.mru_prev = &mon_mru_list;
-
- mon_fifo_list.fifo_next = &mon_fifo_list;
- mon_fifo_list.fifo_prev = &mon_fifo_list;
-
mon_enabled = mode;
}
@@ -182,9 +175,6 @@ mon_stop(
mon_mru_list.mru_next = &mon_mru_list;
mon_mru_list.mru_prev = &mon_mru_list;
-
- mon_fifo_list.fifo_next = &mon_fifo_list;
- mon_fifo_list.fifo_prev = &mon_fifo_list;
}
@@ -198,31 +188,34 @@ ntp_monitor(
{
register struct pkt *pkt;
register struct mon_data *md;
- register u_long netnum;
+ struct sockaddr_storage addr;
register int hash;
register int mode;
if (mon_enabled == MON_OFF)
- return;
+ return;
pkt = &rbufp->recv_pkt;
- netnum = NSRCADR(&rbufp->recv_srcadr);
- hash = MON_HASH(netnum);
+ 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) {
- if (md->rmtadr == netnum &&
- /* ?? md->interface == rbufp->dstadr && ?? */
- md->mode == (u_char)mode) {
+
+ /*
+ * 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->version = PKT_VERSION(pkt->li_vn_mode);
md->rmtport = NSRCPORT(&rbufp->recv_srcadr);
+ md->mode = (u_char) mode;
+ md->version = PKT_VERSION(pkt->li_vn_mode);
/*
- * Shuffle him to the head of the
- * mru list. What a crock.
+ * Shuffle to the head of the MRU list.
*/
md->mru_next->mru_prev = md->mru_prev;
md->mru_prev->mru_next = md->mru_next;
@@ -230,7 +223,6 @@ ntp_monitor(
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;
@@ -242,24 +234,21 @@ ntp_monitor(
* or from the tail of the MRU list.
*/
if (mon_free == NULL && mon_total_mem >= MAXMONMEM) {
+
/*
- * Get it from MRU list
+ * 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);
-
- /*
- * Get it from FIFO list
- */
- md->fifo_prev->fifo_next = md->fifo_next;
- md->fifo_next->fifo_prev = md->fifo_prev;
-
} else {
- if (mon_free == NULL) /* if free list empty */
- mon_getmoremem(); /* then get more */
+ if (mon_free == NULL)
+ mon_getmoremem();
md = mon_free;
mon_free = md->hash_next;
}
@@ -267,36 +256,30 @@ ntp_monitor(
/*
* Got one, initialize it
*/
- md->lasttime = md->firsttime = current_time;
- md->lastdrop = 0;
+ md->avg_interval = 0;
+ md->lasttime = current_time;
md->count = 1;
- md->rmtadr = netnum;
+ 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 = ((rbufp->dstadr->flags & INT_MULTICAST) &&
- rbufp->fd == md->interface->fd) ? MDF_MCAST: rbufp->fd ==
- md->interface->bfd ? MDF_BCAST : MDF_UCAST;
+ 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
- * and at bottom of FIFO list
+ * 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;
-
- md->fifo_prev = mon_fifo_list.fifo_prev;
- md->fifo_next = &mon_fifo_list;
- mon_fifo_list.fifo_prev->fifo_next = md;
- mon_fifo_list.fifo_prev = md;
}
@@ -310,10 +293,10 @@ mon_getmoremem(void)
register int i;
struct mon_data *freedata; /* 'old' free list (null) */
- md = (struct mon_data *)emalloc(MONMEMINC * sizeof(struct mon_data));
+ 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++;
@@ -323,7 +306,6 @@ mon_getmoremem(void)
* md now points at the last. Link in the rest of the chain.
*/
md->hash_next = freedata;
-
mon_total_mem += MONMEMINC;
mon_mem_increments++;
}
@@ -336,7 +318,7 @@ remove_from_hash(
register int hash;
register struct mon_data *md_prev;
- hash = MON_HASH(md->rmtadr);
+ hash = MON_HASH(&md->rmtadr);
if (mon_hash[hash] == md) {
mon_hash[hash] = md->hash_next;
} else {
diff --git a/contrib/ntp/ntpd/ntp_peer.c b/contrib/ntp/ntpd/ntp_peer.c
index b164181..cf8a600 100644
--- a/contrib/ntp/ntpd/ntp_peer.c
+++ b/contrib/ntp/ntpd/ntp_peer.c
@@ -10,9 +10,9 @@
#include "ntpd.h"
#include "ntp_stdlib.h"
-#ifdef AUTOKEY
-#include "ntp_crypto.h"
-#endif /* AUTOKEY */
+#ifdef OPENSSL
+#include "openssl/rand.h"
+#endif /* OPENSSL */
/*
* Table of valid association combinations
@@ -181,7 +181,7 @@ getmorepeermem(void)
*/
struct peer *
findexistingpeer(
- struct sockaddr_in *addr,
+ struct sockaddr_storage *addr,
struct peer *start_peer,
int mode
)
@@ -198,7 +198,7 @@ findexistingpeer(
peer = start_peer->next;
while (peer != 0) {
- if (NSRCADR(addr) == NSRCADR(&peer->srcadr)
+ if (SOCKCMP(addr, &peer->srcadr)
&& NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {
if (mode == -1)
return (peer);
@@ -216,7 +216,7 @@ findexistingpeer(
*/
struct peer *
findpeer(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *dstadr,
int fd,
int pkt_mode,
@@ -228,11 +228,11 @@ findpeer(
findpeer_calls++;
hash = HASH_ADDR(srcadr);
- for (peer = peer_hash[hash]; peer != 0; peer = peer->next) {
- if (NSRCADR(srcadr) == NSRCADR(&peer->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.
@@ -312,7 +312,13 @@ clear_all(void)
for (n = 0; n < HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
- peer_clear(peer);
+ if (peer->flags & FLAG_CONFIG) {
+ if (!(peer->cast_flags & (MDF_ACAST |
+ MDF_MCAST | MDF_BCAST)))
+ peer_clear(peer, "STEP");
+ } else {
+ unpeer(peer);
+ }
}
}
#ifdef DEBUG
@@ -331,14 +337,26 @@ unpeer(
)
{
int hash;
-
- peer_associations--;
+#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);
+ peer_clear(peer_to_remove, "NULL");
hash = HASH_ADDR(&peer_to_remove->srcadr);
peer_hash_count[hash]--;
peer_demobilizations++;
@@ -362,7 +380,7 @@ unpeer(
if (peer == 0) {
peer_hash_count[hash]++;
msyslog(LOG_ERR, "peer struct for %s not in table!",
- ntoa(&peer->srcadr));
+ stoa(&peer->srcadr));
} else {
peer->next = peer_to_remove->next;
}
@@ -386,7 +404,7 @@ unpeer(
assoc_hash_count[hash]++;
msyslog(LOG_ERR,
"peer struct for %s not in association table!",
- ntoa(&peer->srcadr));
+ stoa(&peer->srcadr));
} else {
peer->ass_next = peer_to_remove->ass_next;
}
@@ -394,6 +412,7 @@ unpeer(
peer_to_remove->next = peer_free;
peer_free = peer_to_remove;
peer_free_count++;
+ peer_associations--;
}
@@ -402,7 +421,7 @@ unpeer(
*/
struct peer *
peer_config(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *dstadr,
int hmode,
int version,
@@ -415,7 +434,7 @@ peer_config(
)
{
register struct peer *peer;
- u_int cast_flags;
+ u_char cast_flags;
/*
* First search from the beginning for an association with given
@@ -440,22 +459,39 @@ peer_config(
switch (hmode) {
case MODE_BROADCAST:
- if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
- cast_flags = MDF_MCAST;
- else
- cast_flags = MDF_BCAST;
- break;
+ 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 (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
- cast_flags = MDF_ACAST;
- else
- cast_flags = MDF_UCAST;
- break;
+ 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;
- break;
}
/*
@@ -464,24 +500,26 @@ peer_config(
*/
if (peer != 0) {
peer->hmode = (u_char)hmode;
- peer->version = (u_char)version;
- peer->minpoll = (u_char)minpoll;
- peer->maxpoll = (u_char)maxpoll;
- peer->hpoll = peer->kpoll = peer->minpoll;
- peer->ppoll = peer->maxpoll;
+ 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->ttlmax = ttl;
+ 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.
+ * 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);
@@ -493,20 +531,23 @@ peer_config(
*/
struct peer *
newpeer(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *dstadr,
int hmode,
int version,
int minpoll,
int maxpoll,
u_int flags,
- u_int cast_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
@@ -521,6 +562,13 @@ newpeer(
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
@@ -530,9 +578,15 @@ newpeer(
*/
if (ISREFCLOCKADR(srcadr))
peer->dstadr = loopback_interface;
- else if (cast_flags & MDF_BCLNT)
+ else if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
peer->dstadr = findbcastinter(srcadr);
- else if (dstadr != any_interface)
+ /*
+ * 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);
@@ -541,23 +595,27 @@ newpeer(
peer->version = (u_char)version;
peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
- peer->flags = flags | (key > NTP_MAXKEY ? FLAG_SKEY : 0);
+ peer->flags = flags;
+ if (key != 0)
+ peer->flags |= FLAG_AUTHENABLE;
+ if (key > NTP_MAXKEY)
+ peer->flags |= FLAG_SKEY;
peer->cast_flags = cast_flags;
- peer->ttlmax = ttl;
+ peer->ttl = (u_char)ttl;
peer->keyid = key;
peer->precision = sys_precision;
- peer_clear(peer);
+ 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++;
/*
- * Assign an association ID and increment the system variable.
- */
- peer->associd = current_association_ID;
- if (++current_association_ID == 0)
- ++current_association_ID;
-
- /*
* Note time on statistics timers.
*/
peer->timereset = current_time;
@@ -594,14 +652,25 @@ newpeer(
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 %x %x ttl %d key %08x\n",
- ntoa(&peer->dstadr->sin), ntoa(&peer->srcadr),
+ "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->ttlmax, peer->keyid);
+ peer->ttl, peer->keyid);
#endif
return (peer);
}
@@ -612,7 +681,7 @@ newpeer(
*/
int
peer_unconfig(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *dstadr,
int mode
)
@@ -681,6 +750,7 @@ peer_reset(
peer->oldpkt = 0;
peer->seldisptoolarge = 0;
peer->selbroken = 0;
+ peer->rank = 0;
peer->timereset = current_time;
}
@@ -700,7 +770,7 @@ peer_all_reset(void)
}
-#ifdef AUTOKEY
+#ifdef OPENSSL
/*
* expire_all - flush all crypto data and update timestamps.
*/
@@ -718,30 +788,29 @@ expire_all(void)
* 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->cast_flags & MDF_ACAST) {
- peer_clear(peer);
-#ifdef AUTOKEY
- } else {
+ 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->pcookie.tstamp = 0;
-#endif /* AUTOKEY */
+ peer->crypto &= ~(CRYPTO_FLAG_AUTO |
+ CRYPTO_FLAG_AGREE);
}
}
}
- sys_private = (u_int32)RANDOM & 0xffffffff;
-#ifdef PUBKEY
- crypto_agree();
-#endif /* PUBKEY */
-#ifdef DEBUG
- if (debug)
- printf("expire_all: at %lu\n", current_time);
-#endif
+ RAND_bytes((u_char *)&sys_private, 4);
+ crypto_update();
+ resetmanycast();
}
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
/*
@@ -804,7 +873,7 @@ resetmanycast(void)
peer->next) {
if (peer->cast_flags & MDF_ACAST) {
peer->ttl = 0;
- poll_update(peer, peer->hpoll);
+ poll_update(peer, 0);
}
}
}
diff --git a/contrib/ntp/ntpd/ntp_proto.c b/contrib/ntp/ntpd/ntp_proto.c
index fc95016..451bc9a 100644
--- a/contrib/ntp/ntpd/ntp_proto.c
+++ b/contrib/ntp/ntpd/ntp_proto.c
@@ -1,5 +1,8 @@
/*
* 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>
@@ -10,7 +13,6 @@
#include "ntp_unixtime.h"
#include "ntp_control.h"
#include "ntp_string.h"
-#include "ntp_crypto.h"
#include <stdio.h>
@@ -32,45 +34,61 @@ 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_peer; /* our current peer */
struct peer *sys_prefer; /* our cherished peer */
-#ifdef AUTOKEY
+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 /* AUTOKEY */
+#endif /* OPENSSL */
/*
* Nonspecified system state variables.
*/
-int sys_bclient; /* we set our time to broadcasts */
-double sys_bdelay; /* broadcast client default delay */
+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_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_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 */
-u_int sys_survivors; /* truest of the truechimers */
int peer_ntpdate; /* active peers in ntpdate mode */
-#ifdef AUTOKEY
+int sys_survivors; /* truest of the truechimers */
+#ifdef OPENSSL
char *sys_hostname; /* gethostname() name */
-#endif /* AUTOKEY */
+#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 when we started recording */
-u_long sys_badstratum; /* packets with invalid stratum */
-u_long sys_oldversionpkt; /* old version packets received */
-u_long sys_newversionpkt; /* new version packets received */
-u_long sys_unknownversion; /* don't know version packets */
-u_long sys_badlength; /* packets with bad length */
+u_long sys_stattime; /* time since reset */
+u_long sys_received; /* packets received */
u_long sys_processed; /* packets processed */
-u_long sys_badauth; /* packets dropped because of auth */
-u_long sys_limitrejected; /* pkts rejected due to client count per net */
+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));
@@ -78,7 +96,7 @@ 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
@@ -89,180 +107,193 @@ transmit(
struct peer *peer /* peer structure pointer */
)
{
- int hpoll;
+ 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->burst == 0) {
- u_char oreach;
+ if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {
/*
- * 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...
+ * In broadcast mode the poll interval is fixed
+ * at minpoll.
*/
- if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {
+ hpoll = peer->minpoll;
+ } else if (peer->cast_flags & MDF_ACAST) {
- /*
- * In broadcast mode the poll interval is fixed
- * at minpoll and the ttl at ttlmax.
- */
- hpoll = peer->minpoll;
- peer->ttl = peer->ttlmax;
-#ifdef AUTOKEY
- } 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 {
- /*
- * 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 three
- * 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 three
- * 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 < NTP_MINCLOCK && peer->ttl <
- peer->ttlmax)
- peer->ttl++;
- hpoll = sys_poll;
-#endif /* AUTOKEY */
- } 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) {
- /*
- * 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 peer is
- * demobilized if not configured and just
- * cleared if it is, but in this case the poll
- * interval is bumped by one.
- */
- if (peer->unreach < NTP_UNREACH) {
- peer->unreach++;
- } else 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);
- clock_select();
return;
-
- } else {
- peer_clear(peer);
- hpoll++;
}
}
- oreach = peer->reach;
- peer->reach <<= 1;
- if (peer->reach == 0) {
+ if (peer->burst == 0) {
+ u_char oreach;
- /*
- * 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)) {
- unpeer(peer);
+ 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();
- return;
- } else {
- peer_clear(peer);
- hpoll = peer->minpoll;
}
+ if (peer_unfit(peer))
+ hpoll++;
+ else
+ hpoll = sys_poll;
+ if (peer->flags & FLAG_BURST)
+ peer->burst = NTP_BURST;
}
- if (peer->flags & FLAG_IBURST)
- peer->burst = NTP_SHIFT;
} 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 a synchronization
- * candidate, use the system poll interval. If
- * the peer is not sane, increase it by one. If
- * the number of valid updates is not greater
- * than half the register size, clamp it to the
- * minimum. This is to quickly recover the time
- * variables when a noisy peer shows life.
+ * Source rate control. If we are restrained,
+ * each burst consists of only one packet.
*/
- if (!(peer->reach & 0x07)) {
- clock_filter(peer, 0., 0., MAXDISPERSE);
- clock_select();
- }
- if ((peer->stratum > 1 && peer->refid ==
- peer->dstadr->sin.sin_addr.s_addr) ||
- peer->stratum >= STRATUM_UNSPEC)
- hpoll++;
+ if (memcmp((char *)&peer->refid, "RSTR", 4) ==
+ 0)
+ peer->burst = 0;
else
- hpoll = sys_poll;
- if (peer->flags & FLAG_BURST)
- peer->burst = NTP_SHIFT;
- }
- } 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 AUTOKEY
- key_expire(peer);
-#endif /* AUTOKEY */
- }
- poll_update(peer, hpoll);
- clock_select();
+ 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)
- return;
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "no reply; clock not set");
- printf(
- "ntpd: no reply; clock not set\n");
- exit(0);
+ /*
+ * 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;
}
- return;
-
}
}
peer->outdate = current_time;
- poll_update(peer, hpoll);
/*
- * We need to be very careful about honking uncivilized time.
- * Never transmit if in broadcast client mode or access denied.
- * If in broadcast mode, transmit only if synchronized to a
- * valid source.
+ * 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;
- } else if (peer->hmode == MODE_BROADCAST) {
- if (sys_peer == NULL)
- return;
}
peer_xmit(peer);
+ poll_update(peer, hpoll);
}
/*
@@ -273,20 +304,24 @@ receive(
struct recvbuf *rbufp
)
{
- register struct peer *peer;
- register struct pkt *pkt;
- int hismode;
- int oflags;
- int restrict_mask;
- int has_mac; /* length of MAC field */
- int authlen; /* offset of MAC field */
- int is_authentic; /* cryptosum ok */
- keyid_t skeyid; /* cryptographic keys */
- struct sockaddr_in *dstadr_sin; /* active runway */
-#ifdef AUTOKEY
- keyid_t pkeyid, tkeyid; /* cryptographic keys */
-#endif /* AUTOKEY */
- struct peer *peer2;
+ 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;
/*
@@ -299,61 +334,103 @@ receive(
* 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 > 2)
- printf("receive: at %ld %s<-%s restrict %02x\n",
- current_time, ntoa(&rbufp->dstadr->sin),
- ntoa(&rbufp->recv_srcadr), restrict_mask);
+ 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)
+ if (restrict_mask & RES_IGNORE) {
+ sys_restricted++;
return; /* no anything */
-
- pkt = &rbufp->recv_pkt;
- 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++; /* old version */
- } else {
- sys_unknownversion++;
- return; /* invalid version */
}
- if (PKT_MODE(pkt->li_vn_mode) == MODE_PRIVATE) {
- if (restrict_mask & RES_NOQUERY)
+ 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 (PKT_MODE(pkt->li_vn_mode) == MODE_CONTROL) {
- if (restrict_mask & RES_NOQUERY)
+ 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 */
+ }
/*
- * Validate mode. Note that NTPv1 is no longer supported.
+ * 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.
*/
- hismode = (int)PKT_MODE(pkt->li_vn_mode);
if (hismode == MODE_UNSPEC) {
- sys_badlength++;
- return; /* invalid mode */
+ if (PKT_VERSION(pkt->li_vn_mode) == NTP_OLDVERSION) {
+ hismode = MODE_CLIENT;
+ } else {
+ sys_badlength++;
+ return; /* invalid mode */
+ }
}
/*
- * Discard broadcast packets received on the wildcard interface
- * or if not enabled as broadcast client.
+ * 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 (PKT_MODE(pkt->li_vn_mode) == MODE_BROADCAST &&
- (rbufp->dstadr == any_interface || !sys_bclient))
- return;
+ 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
@@ -366,17 +443,14 @@ receive(
* an extension field is present. If 2 or 4, the packet is a
* runt and goes poof! with a brilliant flash.
*/
- skeyid = 0;
-#ifdef AUTOKEY
- pkeyid = tkeyid = 0;
-#endif /* AUTOKEY */
authlen = LEN_PKT_NOMAC;
- while ((has_mac = rbufp->recv_length - authlen) > 0) {
+ has_mac = rbufp->recv_length - authlen;
+ while (has_mac > 0) {
int temp;
if (has_mac % 4 != 0 || has_mac < 0) {
sys_badlength++;
- return;
+ return; /* bad MAC length */
}
if (has_mac == 1 * 4 || has_mac == 3 * 4 || has_mac ==
MAX_MAC_LEN) {
@@ -386,23 +460,28 @@ receive(
} else if (has_mac > MAX_MAC_LEN) {
temp = ntohl(((u_int32 *)pkt)[authlen / 4]) &
0xffff;
- if (temp < 4 || temp % 4 != 0) {
+ if (temp < 4 || temp > NTP_MAXEXTEN || temp % 4
+ != 0) {
sys_badlength++;
- return;
+ return; /* bad MAC length */
}
authlen += temp;
+ has_mac -= temp;
} else {
sys_badlength++;
- return;
+ 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 or DES cycles, again to reduce exposure. There may be no
+ * 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
@@ -424,11 +503,12 @@ receive(
#ifdef DEBUG
if (debug)
printf("receive: at %ld %s<-%s mode %d code %d\n",
- current_time, ntoa(&rbufp->dstadr->sin),
- ntoa(&rbufp->recv_srcadr), hismode, retcode);
+ current_time, stoa(&rbufp->dstadr->sin),
+ stoa(&rbufp->recv_srcadr), hismode,
+ retcode);
#endif
} else {
-#ifdef AUTOKEY
+#ifdef OPENSSL
/*
* For autokey modes, generate the session key
* and install in the key cache. Use the socket
@@ -471,8 +551,7 @@ receive(
* mobilized.
*/
pkeyid = 0;
- if (rbufp->dstadr->bcast.sin_addr.s_addr
- != 0)
+ if (!SOCKNUL(&rbufp->dstadr->bcast))
dstadr_sin =
&rbufp->dstadr->bcast;
} else if (peer == NULL) {
@@ -480,7 +559,7 @@ receive(
&rbufp->recv_srcadr, dstadr_sin, 0,
sys_private, 0);
} else {
- pkeyid = peer->pcookie.key;
+ pkeyid = peer->pcookie;
}
/*
@@ -503,29 +582,32 @@ receive(
}
}
-#endif /* AUTOKEY */
+#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.
+ * again. If the packet is authentic, it may mobilize an
+ * association.
*/
if (authdecrypt(skeyid, (u_int32 *)pkt, authlen,
- has_mac))
+ has_mac)) {
is_authentic = 1;
- else
+ restrict_mask &= ~RES_DONTTRUST;
+ } else {
sys_badauth++;
-#ifdef AUTOKEY
+ }
+#ifdef OPENSSL
if (skeyid > NTP_MAXKEY)
authtrust(skeyid, 0);
-#endif /* AUTOKEY */
+#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, ntoa(dstadr_sin),
- ntoa(&rbufp->recv_srcadr), hismode, retcode,
+ current_time, stoa(dstadr_sin),
+ stoa(&rbufp->recv_srcadr), hismode, retcode,
skeyid, authlen, has_mac,
is_authentic);
#endif
@@ -537,9 +619,10 @@ receive(
* 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 server packet mobilizes a client association;
- * a symmetric active packet mobilizes a symmetric passive
- * association. And, the adventure continues...
+ * 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:
@@ -555,33 +638,29 @@ receive(
INT_MULTICAST)) {
/*
- * We are picky about responding to a
- * manycaster. There is no reason to respond to
- * a request if our time is worse than the
- * manycaster. We certainly don't reply if not
- * synchronized to proventic time.
+ * 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)
- return;
-
- /*
- * We don't reply if the our stratum is greater
- * than the manycaster.
- */
- if (PKT_TO_STRATUM(pkt->stratum) < sys_stratum)
- return;
+ 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
- * set the key ID to zero to tell the caller about this.
+ * send a crypto-NAK to tell the caller about this.
*/
- if (is_authentic)
+ if (has_mac && !is_authentic)
+ fast_xmit(rbufp, MODE_SERVER, 0, restrict_mask);
+ else
fast_xmit(rbufp, MODE_SERVER, skeyid,
restrict_mask);
- else
- fast_xmit(rbufp, MODE_SERVER, 0, restrict_mask);
return;
case AM_MANYCAST:
@@ -594,100 +673,166 @@ receive(
* 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. If so and
- * the manycast association is found, we mobilize a
- * client mode association, copy pertinent variables
- * from the manycast to the client mode association and
- * wind up the spring.
+ * 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.
+ * immediately. If the guy is already here, don't fire
+ * up a duplicate.
*/
- if ((restrict_mask & (RES_DONTSERVE | RES_LIMITED |
- RES_NOPEER)) || (sys_authenticate &&
- !is_authentic))
- return;
+ if (restrict_mask & RES_DONTTRUST) {
+ sys_restricted++;
+ return; /* no trust */
+ }
- peer2 = findmanycastpeer(rbufp);
- if (peer2 == 0)
- return;
+ if (sys_authenticate && !is_authentic)
+ return; /* bad auth */
- peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
+ 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),
- sys_minpoll, NTP_MAXDPOLL, FLAG_IBURST |
- (peer2->flags & (FLAG_AUTHENABLE | FLAG_SKEY)),
- MDF_UCAST, 0, skeyid);
- if (peer == NULL)
- return;
+ 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 the packet is
- * authentic. If so, mobilize a symmetric passive
- * association.
+ * 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_DONTSERVE | RES_LIMITED |
- RES_NOPEER)) || (sys_authenticate &&
- !is_authentic)) {
+ if (restrict_mask & RES_DONTTRUST) {
+ sys_restricted++;
+ return; /* no trust */
+ }
+ if (sys_authenticate && !is_authentic) {
fast_xmit(rbufp, MODE_PASSIVE, 0,
restrict_mask);
- return;
+ return; /* bad auth */
}
- peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
+ if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode),
- sys_minpoll, NTP_MAXDPOLL, sys_authenticate ?
- FLAG_AUTHENABLE : 0, MDF_UCAST, 0, skeyid);
- if (peer == NULL)
- return;
+ 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 the packet is authentic, not
- * restricted and that we are a broadcast or multicast
- * client. If so, mobilize a broadcast client
- * association.
+ * 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_DONTSERVE | RES_LIMITED |
- RES_NOPEER)) || (sys_authenticate &&
- !is_authentic) || !sys_bclient)
- return;
+ if (restrict_mask & RES_DONTTRUST) {
+ sys_restricted++;
+ return; /* no trust */
+ }
+ if (sys_authenticate && !is_authentic)
+ return; /* bad auth */
- peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
+ if (!sys_bclient)
+ return; /* not a client */
+
+ if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
- sys_minpoll, NTP_MAXDPOLL, FLAG_MCAST |
- FLAG_IBURST | (sys_authenticate ?
- FLAG_AUTHENABLE : 0), MDF_BCLNT, 0, skeyid);
-#ifdef AUTOKEY
-#ifdef PUBKEY
- if (peer == NULL)
- return;
- if (peer->flags & FLAG_SKEY)
- crypto_recv(peer, rbufp);
-#endif /* PUBKEY */
-#endif /* AUTOKEY */
+ 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:
/*
- * Happiness and nothing broke. Earn some revenue.
+ * 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. Leave the island
- * immediately.
+ * 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);
@@ -696,128 +841,242 @@ receive(
}
/*
- * If the peer isn't configured, set his authenable and autokey
- * status based on the packet. Once the status is set, it can't
- * be unset. It seems like a silly idea to do this here, rather
- * in the configuration routine, but in some goofy cases the
- * first packet sent cannot be authenticated and we need a way
- * for the dude to change his mind.
+ * 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.
*/
- oflags = peer->flags;
peer->timereceived = current_time;
peer->received++;
- if (!(peer->flags & FLAG_CONFIG) && has_mac) {
- peer->flags |= FLAG_AUTHENABLE;
-#ifdef AUTOKEY
- if (skeyid > NTP_MAXKEY)
- peer->flags |= FLAG_SKEY;
-#endif /* AUTOKEY */
- }
+ 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);
/*
- * A valid packet must be from an authentic and allowed source.
- * All packets must pass the authentication allowed tests.
- * Autokey authenticated packets must pass additional tests and
- * public-key authenticated packets must have the credentials
- * verified. If all tests are passed, the packet is forwarded
- * for processing. If not, the packet is discarded and the
- * association demobilized if appropriate.
+ * 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.
*/
- peer->flash = 0;
- if (is_authentic) {
- peer->flags |= FLAG_AUTHENTIC;
} else {
- peer->flags &= ~FLAG_AUTHENTIC;
- }
- if (peer->hmode == MODE_BROADCAST &&
- (restrict_mask & RES_DONTTRUST)) /* test 4 */
- peer->flash |= TEST4; /* access denied */
- if (peer->flags & FLAG_AUTHENABLE) {
- if (!(peer->flags & FLAG_AUTHENTIC)) /* test 5 */
- peer->flash |= TEST5; /* auth failed */
- else if (!(oflags & FLAG_AUTHENABLE))
- report_event(EVNT_PEERAUTH, peer);
- }
- if (peer->flash) {
-#ifdef DEBUG
+ 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: bad auth %03x\n", peer->flash);
+ 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 AUTOKEY
+#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 an extension field contains a verified signature, it is
+ * 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.
*
- * 3. If this is a server reply, check only to see that the
+ * 4. If this is a server reply, check only to see that the
* transmitted key ID matches the received key ID.
*
- * 4. Check to see that one or more hashes of the current 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 (peer->flags & FLAG_SKEY) {
+ if (crypto_flags && (peer->flags & FLAG_SKEY)) {
peer->flash |= TEST10;
- crypto_recv(peer, rbufp);
- poll_update(peer, peer->hpoll);
- if (hismode == MODE_SERVER) {
+ 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 {
+ } else if ((ap = (struct autokey *)peer->recval.ptr) !=
+ NULL) {
int i;
for (i = 0; ; i++) {
if (tkeyid == peer->pkeyid ||
- tkeyid == peer->recauto.key) {
+ tkeyid == ap->key) {
peer->flash &= ~TEST10;
peer->pkeyid = skeyid;
break;
}
- if (i > peer->recauto.seq)
+ if (i > ap->seq)
break;
tkeyid = session_key(
&rbufp->recv_srcadr, dstadr_sin,
tkeyid, pkeyid, 0);
}
}
-#ifdef PUBKEY
+ if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 11 */
+ peer->flash |= TEST11; /* not proventic */
/*
- * This is delicious. Ordinarily, we kick out all errors
- * at this point; however, in symmetric mode and just
- * warming up, an unsynchronized peer must inject the
- * timestamps, even if it fails further up the road. So,
- * let the dude by here, but only if the jerk is not yet
- * reachable. After that, he's on his own.
+ * If the transmit queue is nonempty, clamp the host
+ * poll interval to the packet poll interval.
*/
- if (!(peer->flags & FLAG_PROVEN))
- peer->flash |= TEST11;
- if (peer->flash && peer->reach) {
+ 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 autokey %03x\n",
+ 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 /* PUBKEY */
}
-#endif /* AUTOKEY */
+#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.
+ * 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);
}
@@ -833,15 +1092,15 @@ void
process_packet(
register struct peer *peer,
register struct pkt *pkt,
- l_fp *recv_ts
+ l_fp *recv_ts
)
{
- l_fp t10, t23;
- double p_offset, p_del, p_disp;
- double dtemp;
- l_fp p_rec, p_xmt, p_org, p_reftime;
- l_fp ci;
- int pmode, pleap, pstratum;
+ 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
@@ -856,70 +1115,46 @@ process_packet(
NTOHL_FP(&pkt->reftime, &p_reftime);
NTOHL_FP(&pkt->rec, &p_rec);
NTOHL_FP(&pkt->xmt, &p_xmt);
- if (PKT_MODE(pkt->li_vn_mode) != MODE_BROADCAST)
+ 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 old, duplicate or unsynch packets (tests 1-3).
+ * Test for unsynchronized server.
*/
- peer->rec = *recv_ts;
- pmode = PKT_MODE(pkt->li_vn_mode);
- pleap = PKT_LEAP(pkt->li_vn_mode);
- pstratum = PKT_TO_STRATUM(pkt->stratum);
if (L_ISHIS(&peer->org, &p_xmt)) /* count old packets */
peer->oldpkt++;
- if (L_ISEQU(&peer->org, &p_xmt)) /* 1 */
- peer->flash |= TEST1; /* dupe */
- if (pmode != MODE_BROADCAST) {
- if (!L_ISEQU(&peer->xmt, &p_org)) /* 2 */
- peer->flash |= TEST2; /* bogus */
- if (L_ISZERO(&p_rec) || L_ISZERO(&p_org)) /* test 3 */
- peer->flash |= TEST3; /* unsynch */
- }
- if (L_ISZERO(&p_xmt)) /* 3 */
+ 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 */
- peer->org = p_xmt;
/*
- * If tests 1-3 fail, the packet is discarded leaving only the
- * receive and origin timestamps and poll interval, which is
- * enough to get the protocol started.
+ * 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\n",
- peer->flash);
+ printf("packet: bad data %03x from address: %s\n",
+ peer->flash, stoa(&peer->srcadr));
#endif
return;
}
-
- /*
- * A kiss-of-death (kod) packet is returned by a server in case
- * the client is denied access. It consists of the client
- * request packet with the leap bits indicating never
- * synchronized, stratum zero and reference ID field the ASCII
- * string "DENY". If the packet originate timestamp matches the
- * association transmit timestamp the kod is legitimate. If the
- * peer leap bits indicate never synchronized, this must be
- * access deny and the association is disabled; otherwise this
- * must be a limit reject. In either case a naughty message is
- * forced to the system log.
- */
- if (pleap == LEAP_NOTINSYNC && pstratum >= STRATUM_UNSPEC &&
- memcmp(&pkt->refid, "DENY", 4) == 0) {
- if (peer->leap == LEAP_NOTINSYNC) {
- peer->stratum = STRATUM_UNSPEC;
- peer->flash |= TEST4;
- memcpy(&peer->refid, &pkt->refid, 4);
- msyslog(LOG_INFO, "access denied");
- } else {
- msyslog(LOG_INFO, "limit reject");
- }
- return;
- }
+ peer->leap = pleap;
+ peer->stratum = pstratum;
+ peer->refid = pkt->refid;
/*
* Test for valid peer data (tests 6-8)
@@ -927,18 +1162,20 @@ process_packet(
ci = p_xmt;
L_SUB(&ci, &p_reftime);
LFPTOD(&ci, dtemp);
- if (pleap == LEAP_NOTINSYNC || /* 6 */
+ if (pleap == LEAP_NOTINSYNC || /* test 6 */
pstratum >= STRATUM_UNSPEC || dtemp < 0)
peer->flash |= TEST6; /* bad synch */
- if (!(peer->flags & FLAG_CONFIG) && sys_peer != NULL) { /* 7 */
- if (pstratum > sys_stratum && pmode != MODE_ACTIVE) {
+ if (!(peer->flags & FLAG_CONFIG) && sys_peer != NULL) { /* test 7 */
+ if (pstratum > sys_stratum && pmode != MODE_ACTIVE)
peer->flash |= TEST7; /* bad stratum */
- sys_badstratum++;
- }
}
- if (p_del < 0 || p_disp < 0 || p_del / /* 8 */
+ if (p_del < 0 || p_disp < 0 || p_del / /* test 8 */
2 + p_disp >= MAXDISPERSE)
- peer->flash |= TEST8; /* bad peer distance */
+ peer->flash |= TEST8; /* bad peer values */
+
+ /*
+ * If any tests fail at this point, the packet is discarded.
+ */
if (peer->flash) {
#ifdef DEBUG
if (debug)
@@ -954,14 +1191,11 @@ process_packet(
*/
record_raw_stats(&peer->srcadr, &peer->dstadr->sin, &p_org,
&p_rec, &p_xmt, &peer->rec);
- peer->leap = pleap;
peer->pmode = pmode;
- peer->stratum = pstratum;
peer->ppoll = pkt->ppoll;
peer->precision = pkt->precision;
peer->rootdelay = p_del;
peer->rootdispersion = p_disp;
- peer->refid = pkt->refid;
peer->reftime = p_reftime;
if (!(peer->reach)) {
report_event(EVNT_REACH, peer);
@@ -969,7 +1203,7 @@ process_packet(
}
peer->reach |= 1;
peer->unreach = 0;
- poll_update(peer, peer->hpoll);
+ poll_update(peer, 0);
/*
* If running in a client/server association, calculate the
@@ -980,16 +1214,16 @@ process_packet(
* the system precision plus that due to the frequency error
* since the originate time.
*
- * c = ((t2 - t3) + (t1 - t0)) / 2
- * d = (t2 - t3) - (t1 - t0)
- * e = (org - rec) (seconds only)
+ * Let t1 = p_org, t2 = p_rec, t3 = p_xmt, t4 = peer->rec:
*/
- t10 = p_xmt; /* compute t1 - t0 */
- L_SUB(&t10, &peer->rec);
- t23 = p_rec; /* compute t2 - t3 */
- L_SUB(&t23, &p_org);
- ci = t10;
- p_disp = clock_phi * (peer->rec.l_ui - p_org.l_ui);
+ 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
@@ -1000,6 +1234,7 @@ process_packet(
* 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);
@@ -1009,20 +1244,20 @@ process_packet(
peer->flags &= ~FLAG_MCAST;
}
- DTOLFP(peer->estbdelay, &t10);
- L_ADD(&ci, &t10);
+ DTOLFP(peer->estbdelay, &t34);
+ L_ADD(&ci, &t34);
p_del = peer->delay;
} else {
- L_ADD(&ci, &t23);
+ L_ADD(&ci, &t21); /* (t2 - t1) + (t3 - t4) */
L_RSHIFT(&ci);
- L_SUB(&t23, &t10);
- LFPTOD(&t23, p_del);
+ 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) /* 9 */
- peer->flash |= TEST9; /* bad peer distance */
+ p_disp >= MAXDISPERSE) /* test 9 */
+ peer->flash |= TEST9; /* bad root distance */
/*
* If any flasher bits remain set at this point, abandon ship.
@@ -1055,14 +1290,13 @@ clock_update(void)
/*
* Reset/adjust the system clock. Do this only if there is a
- * system peer and we haven't seen that peer lately. Watch for
- * timewarps here.
+ * system peer and the peer epoch is not older than the last
+ * update.
*/
if (sys_peer == NULL)
return;
- if (sys_peer->pollsw == FALSE || sys_peer->burst > 0)
+ if (sys_peer->epoch <= last_time)
return;
- sys_peer->pollsw = FALSE;
#ifdef DEBUG
if (debug)
printf("clock_update: at %ld assoc %d \n", current_time,
@@ -1076,8 +1310,8 @@ clock_update(void)
* Clock is too screwed up. Just exit for now.
*/
case -1:
- report_event(EVNT_SYSFAULT, (struct peer *)0);
- exit(1);
+ report_event(EVNT_SYSFAULT, NULL);
+ exit (-1);
/*NOTREACHED*/
/*
@@ -1087,10 +1321,13 @@ clock_update(void)
clear_all();
sys_peer = NULL;
sys_stratum = STRATUM_UNSPEC;
+ memcpy(&sys_refid, "STEP", 4);
sys_poll = NTP_MINPOLL;
- NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO, "synchronisation lost");
- report_event(EVNT_CLOCKRESET, (struct peer *)0);
+ report_event(EVNT_CLOCKRESET, NULL);
+#ifdef OPENSSL
+ if (oleap != LEAP_NOTINSYNC)
+ expire_all();
+#endif /* OPENSSL */
break;
/*
@@ -1100,23 +1337,23 @@ clock_update(void)
* changes, we gotta reroll the keys.
*/
default:
- sys_stratum = sys_peer->stratum + 1;
- if (sys_stratum == 1)
+ 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->srcadr.sin_addr.s_addr;
+ 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, (struct peer *)0);
-#ifdef AUTOKEY
- expire_all();
-#endif /* AUTOKEY */
+ if (oleap == LEAP_NOTINSYNC) {
+ report_event(EVNT_SYNCCHG, NULL);
+#ifdef OPENSSL
+ expire_all();
+#endif /* OPENSSL */
+ }
}
if (ostratum != sys_stratum)
- report_event(EVNT_PEERSTCHG, (struct peer *)0);
+ report_event(EVNT_PEERSTCHG, NULL);
}
@@ -1126,12 +1363,12 @@ clock_update(void)
void
poll_update(
struct peer *peer,
- int hpoll
+ int hpoll
)
{
-#ifdef AUTOKEY
- int oldpoll;
-#endif /* AUTOKEY */
+#ifdef OPENSSL
+ int oldpoll;
+#endif /* OPENSSL */
/*
* A little foxtrot to determine what controls the poll
@@ -1141,56 +1378,65 @@ poll_update(
* association to ramp up the poll interval for useless sources
* and to clamp it to the minimum when first starting up.
*/
-#ifdef AUTOKEY
+#ifdef OPENSSL
oldpoll = peer->kpoll;
-#endif /* AUTOKEY */
- if (hpoll > peer->maxpoll)
- peer->hpoll = peer->maxpoll;
- else if (hpoll < peer->minpoll)
- peer->hpoll = peer->minpoll;
- else
- peer->hpoll = hpoll;
+#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 timeout,
- * just slink away. If timeout, figure what the next timeout
- * should be. If IBURST or a reference clock, use one second. If
- * not and the dude was reachable during the previous poll
- * interval, randomize over 1-4 seconds; otherwise, randomize
- * over 15-18 seconds. This is to give time for a modem to
- * complete the call, for example. If not during a burst,
- * randomize over the poll interval -1 to +2 seconds.
+ * 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 17.1 s, the beacon interval settles up to 2.3 hours.
+ * 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) {
- if (peer->nextdate != current_time)
+#endif /* OPENSSL */
+ if (hpoll == 0 && peer->nextdate != current_time)
return;
#ifdef REFCLOCK
else if (peer->flags & FLAG_REFCLOCK)
- peer->nextdate++;
+ peer->nextdate += RESP_DELAY;
#endif
- else if (peer->reach & 0x1)
- peer->nextdate += RANDPOLL(BURST_INTERVAL2);
+ else if (peer->flags & (FLAG_IBURST | FLAG_BURST) &&
+ peer->burst == NTP_BURST)
+ peer->nextdate += sys_calldelay;
else
- peer->nextdate += RANDPOLL(BURST_INTERVAL1);
+ peer->nextdate += BURST_DELAY;
} else if (peer->cast_flags & MDF_ACAST) {
- if (sys_survivors < NTP_MINCLOCK)
- peer->kpoll = peer->hpoll;
+ if (sys_survivors >= sys_minclock || peer->ttl >=
+ sys_ttlmax)
+ peer->kpoll = (u_char) (peer->hpoll + 3);
else
- peer->kpoll = peer->hpoll + 3;
+ peer->kpoll = peer->hpoll;
peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
} else {
- peer->kpoll = max(min(peer->ppoll, peer->hpoll),
- peer->minpoll);
+ 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 AUTOKEY
+#ifdef OPENSSL
/*
* Bit of crass arrogance at this point. If the poll interval
* has changed and we have a keylist, the lifetimes in the
@@ -1199,7 +1445,7 @@ poll_update(
*/
if (peer->kpoll != oldpoll)
key_expire(peer);
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
#ifdef DEBUG
if (debug > 1)
printf("poll_update: at %lu %s flags %04x poll %d burst %d last %lu next %lu\n",
@@ -1215,11 +1461,11 @@ poll_update(
*/
void
peer_clear(
- register struct peer *peer
+ struct peer *peer, /* peer structure */
+ char *ident /* tally lights */
)
{
- register int i;
- u_long u_rand;
+ u_char oreach, i;
/*
* If cryptographic credentials have been acquired, toss them to
@@ -1230,47 +1476,51 @@ peer_clear(
* purged, too. This makes it much harder to sneak in some
* unauthenticated data in the clock filter.
*/
-#ifdef DEBUG
- if (debug)
- printf("peer_clear: at %ld assoc ID %d\n", current_time,
- peer->associd);
-#endif
-#ifdef AUTOKEY
+ oreach = peer->reach;
+#ifdef OPENSSL
key_expire(peer);
-#ifdef PUBKEY
- if (peer->keystr != NULL)
- free(peer->keystr);
- if (peer->pubkey.ptr != NULL)
- free(peer->pubkey.ptr);
- if (peer->certif.ptr != NULL)
- free(peer->certif.ptr);
-#endif /* PUBKEY */
-#endif /* AUTOKEY */
- memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
+ 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 */
/*
- * 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. Note that there is no need to call
- * clock_select(), since the perp has already been voted off
- * the island at this point.
+ * Wipe the association clean and initialize the nonzero values.
*/
- if (peer->cast_flags & MDF_BCLNT) {
- peer->flags |= FLAG_MCAST;
- peer->hmode = MODE_CLIENT;
- }
- peer->flags &= ~(FLAG_AUTOKEY | FLAG_ASSOC);
+ 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->pollsw = FALSE;
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;
@@ -1279,12 +1529,35 @@ peer_clear(
}
/*
- * Randomize the first poll over 1-16s to avoid bunching.
+ * 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.
*/
- peer->update = peer->outdate = current_time;
- u_rand = RANDOM;
- peer->nextdate = current_time + (u_rand & ((1 <<
- BURST_INTERVAL1) - 1)) + 1;
+ 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
}
@@ -1294,16 +1567,16 @@ peer_clear(
*/
void
clock_filter(
- register struct peer *peer, /* peer structure pointer */
- double sample_offset, /* clock offset */
- double sample_delay, /* roundtrip delay */
- double sample_disp /* dispersion */
+ 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 */
- register int i, j, k, m;
- double dsp, jit, dtemp, etemp;
+ 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
@@ -1320,9 +1593,8 @@ clock_filter(
peer->filter_offset[j] = sample_offset;
peer->filter_delay[j] = max(0, sample_delay);
peer->filter_disp[j] = dsp;
- peer->filter_epoch[j] = current_time;
- j++; j %=NTP_SHIFT;
- peer->filter_nextpt = j;
+ j++; j %= NTP_SHIFT;
+ peer->filter_nextpt = (u_short) j;
/*
* Update dispersions since the last update and at the same
@@ -1334,21 +1606,21 @@ clock_filter(
dtemp = clock_phi * (current_time - peer->update);
peer->update = current_time;
for (i = NTP_SHIFT - 1; i >= 0; i--) {
- if (i != 0) {
+ 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)
+ 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];
+ 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.
@@ -1374,7 +1646,7 @@ clock_filter(
*/
m = 0;
for (i = 0; i < NTP_SHIFT; i++) {
- peer->filter_order[i] = ord[i];
+ peer->filter_order[i] = (u_char) ord[i];
if (dst[i] >= MAXDISPERSE || (m >= 2 && dst[i] >=
MAXDISTANCE))
continue;
@@ -1387,8 +1659,7 @@ clock_filter(
* 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.
+ * tiptoe home leaving only the dispersion.
*/
jit = 0;
peer->disp = 0;
@@ -1411,7 +1682,8 @@ clock_filter(
*/
if (m == 0)
return;
- etemp = peer->offset;
+ 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)
@@ -1420,9 +1692,10 @@ clock_filter(
/*
* A new sample is useful only if it is younger than the last
- * one used.
+ * one used, but only if the sucker has been synchronized.
*/
- if (peer->filter_epoch[k] <= peer->epoch) {
+ if (peer->filter_epoch[k] <= peer->epoch && sys_leap !=
+ LEAP_NOTINSYNC) {
#ifdef DEBUG
if (debug)
printf("clock_filter: discard %lu\n",
@@ -1433,27 +1706,26 @@ clock_filter(
/*
* If the difference between the last offset and the current one
- * exceeds the jitter by CLOCK_SGATE (4) and the interval since
- * the last update is less than twice the system poll interval,
+ * 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 && fabs(peer->offset - etemp) > SQRT(peer->jitter) *
- CLOCK_SGATE && peer->filter_epoch[k] - peer->epoch <
- (1 << (sys_poll + 1))) {
+ 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: n %d popcorn spike %.6f jitter %.6f\n",
- m, peer->offset, SQRT(peer->jitter));
+ printf("clock_filter: popcorn %.6f %.6f\n",
+ etemp, dtemp);
#endif
return;
}
/*
* The mitigated sample statistics are saved for later
- * processing, but can be processed only once.
+ * processing.
*/
peer->epoch = peer->filter_epoch[k];
- peer->pollsw = TRUE;
#ifdef DEBUG
if (debug)
printf(
@@ -1466,17 +1738,23 @@ clock_filter(
/*
* 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)
{
- register struct peer *peer;
- int i, j, k, n;
- int nreach, nlist, nl3;
- double d, e, f;
- int allow, found, sw;
- double high, low;
- double synch[NTP_MAXCLOCK], error[NTP_MAXCLOCK];
+ 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;
@@ -1497,10 +1775,15 @@ clock_select(void)
*/
osys_peer = sys_peer;
sys_peer = NULL;
+ osurv = sys_survivors;
+ sys_survivors = 0;
sys_prefer = NULL;
- nreach = nlist = 0;
- low = 1e9;
- high = -1e9;
+#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) {
@@ -1515,9 +1798,9 @@ clock_select(void)
indx_size += 5 * 3 * sizeof(*indx);
peer_list_size += 5 * sizeof(*peer_list);
}
- endpoint = (struct endpoint *)emalloc(endpoint_size);
- indx = (int *)emalloc(indx_size);
- peer_list = (struct peer **)emalloc(peer_list_size);
+ endpoint = emalloc(endpoint_size);
+ indx = emalloc(indx_size);
+ peer_list = emalloc(peer_list_size);
}
/*
@@ -1527,8 +1810,8 @@ clock_select(void)
* 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 NTP_MINCLOCK (3), the survivors split a
- * million bucks and collectively crank the chimes.
+ * 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++) {
@@ -1538,18 +1821,10 @@ clock_select(void)
peer->status = CTL_PST_SEL_REJECT;
/*
- * A peer leaves the island immediately if
- * unreachable, synchronized to us or suffers
- * excessive root distance. Careful with the
- * root distance, since the poll interval can
- * increase to a day and a half.
- */
- if (!peer->reach || (peer->stratum > 1 &&
- peer->refid ==
- peer->dstadr->sin.sin_addr.s_addr) ||
- peer->stratum >= STRATUM_UNSPEC ||
- (root_distance(peer) >= MAXDISTANCE + 2 *
- clock_phi * ULOGTOD(sys_poll)))
+ * Leave the island immediately if the peer is
+ * unfit to synchronize.
+ */
+ if (peer_unfit(peer))
continue;
/*
@@ -1561,13 +1836,18 @@ clock_select(void)
*/
if (peer->refclktype == REFCLK_LOCALCLOCK
#if defined(VMS) && defined(VMS_LOCALUNIT)
- /* wjm: local unit VMS_LOCALUNIT taken seriously */
- && REFCLOCKUNIT(&peer->srcadr) != 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;
@@ -1580,7 +1860,6 @@ clock_select(void)
* island, but does not yet have the immunity
* idol.
*/
- nreach++;
peer->status = CTL_PST_SEL_SANE;
peer_list[nlist++] = peer;
@@ -1601,7 +1880,7 @@ clock_select(void)
endpoint[nl3++].val = e;
e = e - f; /* Center point */
- for ( ; i >= 0; i--) {
+ for (; i >= 0; i--) {
if (e >= endpoint[indx[i]].val)
break;
indx[i + 2] = indx[i];
@@ -1611,7 +1890,7 @@ clock_select(void)
endpoint[nl3++].val = e;
e = e - f; /* Lower end */
- for ( ; i >= 0; i--) {
+ for (; i >= 0; i--) {
if (e >= endpoint[indx[i]].val)
break;
indx[i + 1] = indx[i];
@@ -1628,39 +1907,81 @@ clock_select(void)
endpoint[indx[i]].type,
endpoint[indx[i]].val);
#endif
- i = 0;
- j = nl3 - 1;
- allow = nlist; /* falsetickers assumed */
- found = 0;
- while (allow > 0) {
- allow--;
- for (n = 0; i <= j; i++) {
- n += endpoint[indx[i]].type;
- if (n < 0)
+ /*
+ * 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++;
}
- for (n = 0; i <= j; j--) {
+ n = 0;
+ for (j = nl3 - 1; j >= 0; j--) {
+ high = endpoint[indx[j]].val;
n += endpoint[indx[j]].type;
- if (n > 0)
+ 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;
- low = endpoint[indx[i++]].val;
- high = endpoint[indx[j--]].val;
}
/*
* 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 declare
- * us unsynchronized.
+ * of them as the only survivor. Otherwise, give up and leave
+ * the island to the rats.
*/
- if ((allow << 1) >= nlist) {
+ if (high <= low) {
if (typeacts != 0) {
typeacts->status = CTL_PST_SEL_SANE;
peer_list[0] = typeacts;
@@ -1674,42 +1995,58 @@ clock_select(void)
sys_poll = NTP_MINPOLL;
NLOG(NLOG_SYNCSTATUS)
msyslog(LOG_INFO,
- "synchronisation lost");
- report_event(EVNT_PEERSTCHG,
- (struct peer *)0);
+ "no servers reachable");
+ report_event(EVNT_PEERSTCHG, NULL);
}
- sys_survivors = 0;
-#ifdef AUTOKEY
- resetmanycast();
-#endif /* AUTOKEY */
+ if (osurv > 0)
+ resetmanycast();
return;
}
}
-#ifdef DEBUG
- if (debug > 2)
- printf("select: low %.6f high %.6f\n", low, high);
-#endif
+
+ /*
+ * 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. If we have more than
- * MAXCLOCK peers, keep only the best 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. We must leave at least one peer to collect
- * the million bucks.
+ * 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 && (low >= peer->offset || peer->offset >=
+ if (nlist > 1 && (peer->offset <= low || peer->offset >=
high)) {
if (!(peer->flags & FLAG_CONFIG))
unpeer(peer);
continue;
}
peer->status = CTL_PST_SEL_DISTSYSPEER;
- d = root_distance(peer) + peer->stratum * MAXDISPERSE;
+ 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;
@@ -1729,20 +2066,28 @@ clock_select(void)
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\n",
- ntoa(&peer_list[i]->srcadr), synch[i]);
+ 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 NTP_MINCLOCK survivors and the minimum select jitter
+ * 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.
@@ -1752,7 +2097,6 @@ clock_select(void)
e = -1e9;
k = 0;
for (i = 0; i < nlist; i++) {
-
if (error[i] < d)
d = error[i];
f = 0;
@@ -1762,24 +2106,25 @@ clock_select(void)
peer_list[i]->offset);
f /= nlist - 1;
}
- f = max(f, SQUARE(LOGTOD(sys_precision)));
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: survivors %d select %.6f peer %.6f\n",
- k, SQRT(sys_selerr), SQRT(d));
+ "select: drop %s select %.6f jitter %.6f\n",
+ ntoa(&peer_list[k]->srcadr),
+ SQRT(sys_selerr), SQRT(d));
#endif
- if (nlist <= NTP_MINCLOCK || sys_selerr <= d ||
- peer_list[k]->flags & FLAG_PREFER)
- break;
- if (!(peer_list[k]->flags & FLAG_CONFIG))
+ 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];
@@ -1788,75 +2133,62 @@ clock_select(void)
nlist--;
}
-#ifdef AUTOKEY
/*
- * In manycast client mode we may have spooked a sizeable number
- * of servers that we don't need. If there are at least
- * NTP_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 >= NTP_MINCLOCK && nlist < NTP_MINCLOCK)
- resetmanycast();
-#endif /* AUTOKEY */
- sys_survivors = nlist;
-
-#ifdef DEBUG
- if (debug > 2) {
- for (i = 0; i < nlist; i++)
- printf(
- "select: %s offset %.6f, distance %.6f poll %d\n",
- ntoa(&peer_list[i]->srcadr),
- peer_list[i]->offset, synch[i],
- peer_list[i]->pollsw);
- }
-#endif
-
- /*
- * What remains is a list of not greater than NTP_MINCLOCK
+ * 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 the peers
- * at the lowest stratum. Of these, OR the leap bits on the
- * assumption that, if some of them honk nonzero bits, they must
- * know what they are doing. Also, check for prefer and pps
- * peers. If a prefer peer is found within clock_max, update the
- * pps switch. Of the other peers not at the lowest stratum,
- * check if the system peer is among them and, if found, zap
- * him. We note that the head of the list is at the lowest
+ * 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.
*
- * Note that we go no further, unless the number of survivors is
- * a majority of the suckers that have been found reachable and
- * no prior source is available. This avoids the transient when
- * one of a flock of sources is out to lunch and just happens
- * to be the first survivor.
+ * 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.
*/
- if (osys_peer == NULL && 2 * nlist < min(nreach, NTP_MINCLOCK))
- return;
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;
- poll_update(peer, peer->hpoll);
- if (peer->stratum == peer_list[0]->stratum) {
- leap_consensus |= peer->leap;
- if (peer->refclktype == REFCLK_ATOM_PPS &&
- peer->stratum < STRATUM_UNSPEC)
- typepps = peer;
- if (peer == osys_peer)
- typesystem = peer;
- if (peer->flags & FLAG_PREFER)
- sys_prefer = peer;
- }
+ 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
@@ -1884,15 +2216,16 @@ clock_select(void)
printf("select: prefer offset %.6f\n",
sys_offset);
#endif
- } else if (typepps) {
+ }
+#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");
+ msyslog(LOG_INFO, "pps sync enabled");
pps_control = current_time;
#ifdef DEBUG
if (debug > 1)
@@ -1905,6 +2238,7 @@ clock_select(void)
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
@@ -1913,8 +2247,26 @@ clock_select(void)
sys_offset);
#endif
}
- if (osys_peer != sys_peer)
- report_event(EVNT_PEERSTCHG, (struct peer *)0);
+#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();
}
@@ -1924,11 +2276,12 @@ clock_select(void)
static double
clock_combine(
struct peer **peers,
- int npeers
+ int npeers
)
{
- int i;
- double x, y, z;
+ int i;
+ double x, y, z;
+
y = z = 0;
for (i = 0; i < npeers; i++) {
x = root_distance(peers[i]);
@@ -1965,9 +2318,9 @@ peer_xmit(
)
{
struct pkt xpkt; /* transmit packet */
- int sendlen, authlen;
- keyid_t xkeyid; /* transmit key ID */
- l_fp xmt_tx;
+ int sendlen, authlen;
+ keyid_t xkeyid = 0; /* transmit key ID */
+ l_fp xmt_tx;
/*
* Initialize transmit packet header fields.
@@ -1998,14 +2351,14 @@ peer_xmit(
if (!(peer->flags & FLAG_AUTHENABLE)) {
get_systime(&peer->xmt);
HTONL_FP(&peer->xmt, &xpkt.xmt);
- sendpkt(&peer->srcadr, peer->dstadr, peer->ttl, &xpkt,
- sendlen);
+ 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, ntoa(&peer->dstadr->sin),
- ntoa(&peer->srcadr), peer->hmode);
+ current_time, stoa(&peer->dstadr->sin),
+ stoa(&peer->srcadr), peer->hmode);
#endif
return;
}
@@ -2015,9 +2368,10 @@ peer_xmit(
* must be authenticated. If autokey is enabled, fuss with the
* various modes; otherwise, private key cryptography is used.
*/
-#ifdef AUTOKEY
- if ((peer->flags & FLAG_SKEY)) {
- u_int cmmd;
+#ifdef OPENSSL
+ if (crypto_flags && (peer->flags & FLAG_SKEY)) {
+ struct exten *exten; /* extension field */
+ u_int opcode;
/*
* The Public Key Dance (PKD): Cryptographic credentials
@@ -2077,191 +2431,214 @@ peer_xmit(
switch (peer->hmode) {
/*
- * In broadcast mode the autokey values are required.
- * Send them when a new keylist is generated; otherwise,
- * send the association ID so the client can request
- * them at other times.
+ * 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)
- cmmd = CRYPTO_AUTO | CRYPTO_RESP;
+ exten = crypto_args(peer, CRYPTO_AUTO |
+ CRYPTO_RESP, NULL);
else
- cmmd = CRYPTO_ASSOC | CRYPTO_RESP;
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, cmmd, 0, peer->associd);
+ 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 public key, leapsecond table,
- * agreement parameters and autokey values are required.
- *
- * 1. If a response is pending, always send it first.
- *
- * 2. Don't send anything except a public-key request
- * until the public key has been stored.
- *
- * 3. Once the public key has been stored, don't send
- * anything except an agreement parameter request
- * until the agreement parameters have been stored.
- *
- * 4. Once the argeement parameters have been stored,
- * don't send anything except a public value request
- * until the agreed key has been stored.
- *
- * 5. When the agreed key has been stored and the key
- * list is regenerated, send the autokey values
- * gratis unless they have already been sent.
+ * 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:
-#ifdef PUBKEY
- if (peer->cmmd != 0)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, (peer->cmmd >> 16) |
- CRYPTO_RESP, peer->hcookie,
- peer->associd);
+ 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)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_ASSOC,
- peer->hcookie, peer->assoc);
- else if (!crypto_flags &&
- peer->pcookie.tstamp == 0 && sys_leap !=
- LEAP_NOTINSYNC)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_PRIV, peer->hcookie,
- peer->assoc);
- else if (crypto_flags && peer->pubkey.ptr ==
- NULL)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_NAME, peer->hcookie,
- peer->assoc);
- else if (peer->crypto & CRYPTO_FLAG_CERT)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_CERT, peer->hcookie,
- peer->assoc);
- else if (crypto_flags && peer->crypto &
- CRYPTO_FLAG_DH && sys_leap !=
- LEAP_NOTINSYNC)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_DHPAR,
- peer->hcookie, peer->assoc);
- else if (crypto_flags && peer->pcookie.tstamp ==
- 0 && sys_leap != LEAP_NOTINSYNC)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_DH, peer->hcookie,
- peer->assoc);
-#else
- if (peer->cmmd != 0)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, (peer->cmmd >> 16) |
- CRYPTO_RESP, peer->hcookie,
- peer->associd);
- if (peer->pcookie.tstamp == 0 && sys_leap !=
- LEAP_NOTINSYNC)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_PRIV, peer->hcookie,
- peer->assoc);
-#endif /* PUBKEY */
- else if (!(peer->flags & FLAG_AUTOKEY))
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_AUTO, peer->hcookie,
- peer->assoc);
- else if ((peer->flags & FLAG_ASSOC) &&
- (peer->cmmd >> 16) != CRYPTO_AUTO)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_AUTO | CRYPTO_RESP,
- peer->hcookie, peer->associd);
-#ifdef PUBKEY
- else if (peer->crypto & CRYPTO_FLAG_TAI)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_TAI, peer->hcookie,
- peer->assoc);
-#endif /* PUBKEY */
- peer->cmmd = 0;
+ 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 public key, host cookie and
- * autokey values are required. In broadcast client
- * mode, these values must be acquired during the
+ * 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. Note that we ask
- * for the cookie at each key list regeneration anyway.
+ * 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 != 0)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, (peer->cmmd >> 16) |
- CRYPTO_RESP, peer->hcookie,
- peer->associd);
+ 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)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_ASSOC,
- peer->hcookie, peer->assoc);
-#ifdef PUBKEY
- else if (crypto_flags && peer->pubkey.ptr ==
- NULL)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_NAME, peer->hcookie,
- peer->assoc);
- else if (peer->crypto & CRYPTO_FLAG_CERT)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_CERT, peer->hcookie,
- peer->assoc);
-#endif /* PUBKEY */
- else if (peer->pcookie.tstamp == 0)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_PRIV, peer->hcookie,
- peer->assoc);
- else if (!(peer->flags & FLAG_AUTOKEY) &&
+ 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))
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_AUTO, peer->hcookie,
- peer->assoc);
-#ifdef PUBKEY
- else if (peer->crypto & CRYPTO_FLAG_TAI)
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, CRYPTO_TAI, peer->hcookie,
- peer->assoc);
-#endif /* PUBKEY */
- peer->cmmd = 0;
+ 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.
+ * 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 /* AUTOKEY */
+#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_NOTICE,
- "transmit: no encryption key found");
- peer->flash |= TEST4 | TEST5;
+ 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 AUTOKEY
+#ifdef OPENSSL
if (xkeyid > NTP_MAXKEY)
authtrust(xkeyid, 0);
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
get_systime(&xmt_tx);
if (sendlen > sizeof(xpkt)) {
msyslog(LOG_ERR, "buffer overflow %u", sendlen);
- exit(-1);
+ exit (-1);
}
- sendpkt(&peer->srcadr, peer->dstadr, peer->ttl, &xpkt, sendlen);
+ sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl], &xpkt,
+ sendlen);
/*
* Calculate the encryption delay. Keep the minimum over
@@ -2276,14 +2653,14 @@ peer_xmit(
else
sys_authdelay.l_uf = sys_authdly[1];
peer->sent++;
-#ifdef AUTOKEY
+#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, peer->keynumber);
+ ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
+ authlen, authlen, peer->keynumber);
#endif
#else
#ifdef DEBUG
@@ -2291,10 +2668,10 @@ peer_xmit(
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);
+ ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
+ authlen, authlen);
#endif
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
}
@@ -2305,16 +2682,19 @@ peer_xmit(
static void
fast_xmit(
struct recvbuf *rbufp, /* receive packet pointer */
- int xmode, /* transmit mode */
- keyid_t xkeyid, /* transmit key ID */
- int mask /* restrict mask */
+ 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; /* transmit timestamp */
- l_fp xmt_tx; /* transmit timestamp after authent */
- int sendlen, authlen;
+ 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
@@ -2327,19 +2707,35 @@ fast_xmit(
rbufp->dstadr = findinterface(&rbufp->recv_srcadr);
/*
- * If the caller is restricted, return a kiss-of-death packet;
- * otherwise, smooch politely.
+ * 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_DONTSERVE | RES_LIMITED)) {
- if (!(mask & RES_DEMOBILIZE)) {
- return;
- } else {
- xpkt.li_vn_mode =
- PKT_LI_VN_MODE(LEAP_NOTINSYNC,
- PKT_VERSION(rpkt->li_vn_mode), xmode);
- xpkt.stratum = STRATUM_UNSPEC;
- memcpy(&xpkt.refid, "DENY", 4);
+ 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);
@@ -2369,8 +2765,8 @@ fast_xmit(
#ifdef DEBUG
if (debug)
printf("transmit: at %ld %s->%s mode %d\n",
- current_time, ntoa(&rbufp->dstadr->sin),
- ntoa(&rbufp->recv_srcadr), xmode);
+ current_time, stoa(&rbufp->dstadr->sin),
+ stoa(&rbufp->recv_srcadr), xmode);
#endif
return;
}
@@ -2383,10 +2779,9 @@ fast_xmit(
* generate the cookie, which is unique for every source-
* destination-key ID combination.
*/
-#ifdef AUTOKEY
+#ifdef OPENSSL
if (xkeyid > NTP_MAXKEY) {
keyid_t cookie;
- u_int code, associd;
/*
* The only way to get here is a reply to a legitimate
@@ -2397,35 +2792,36 @@ fast_xmit(
* jerk can decode it. If no extension field is present,
* use the cookie to generate the session key.
*/
- code = (htonl(rpkt->exten[0]) >> 16) | CRYPTO_RESP;
cookie = session_key(&rbufp->recv_srcadr,
&rbufp->dstadr->sin, 0, sys_private, 0);
- associd = htonl(rpkt->exten[1]);
- if (rbufp->recv_length >= sendlen + MAX_MAC_LEN + 2 *
- sizeof(u_int32)) {
+ if (rbufp->recv_length >= (int)(sendlen + MAX_MAC_LEN + 2 *
+ sizeof(u_int32))) {
session_key(&rbufp->dstadr->sin,
&rbufp->recv_srcadr, xkeyid, 0, 2);
- sendlen += crypto_xmit((u_int32 *)&xpkt,
- sendlen, code, cookie, associd);
+ 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 /* AUTOKEY */
+#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 AUTOKEY
+#ifdef OPENSSL
if (xkeyid > NTP_MAXKEY)
authtrust(xkeyid, 0);
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
get_systime(&xmt_tx);
if (sendlen > sizeof(xpkt)) {
msyslog(LOG_ERR, "buffer overflow %u", sendlen);
- exit(-1);
+ exit (-1);
}
sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt, sendlen);
@@ -2446,13 +2842,13 @@ fast_xmit(
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);
+ ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen -
+ authlen, authlen);
#endif
}
-#ifdef AUTOKEY
+#ifdef OPENSSL
/*
* key_expire - purge the key list
*/
@@ -2463,131 +2859,128 @@ key_expire(
{
int i;
- if (peer->keylist != NULL) {
+ if (peer->keylist != NULL) {
for (i = 0; i <= peer->keynumber; i++)
authtrust(peer->keylist[i], 0);
free(peer->keylist);
peer->keylist = NULL;
}
- peer->keynumber = peer->sndauto.seq = 0;
+ value_free(&peer->sndval);
+ peer->keynumber = 0;
#ifdef DEBUG
if (debug)
printf("key_expire: at %lu\n", current_time);
#endif
}
-#endif /* AUTOKEY */
+#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 DUSECS 1000000 /* us in a s */
-#define HUSECS (1 << 20) /* approx DUSECS for shifting etc */
-#define MINSTEP 5 /* minimum clock increment (us) */
-#define MAXSTEP 20000 /* maximum clock increment (us) */
-#define MINLOOPS 5 /* minimum number of step samples */
+#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 differences between successive calls to
- * gettimeofday(). If a difference is less than zero, the us field
- * has rolled over to the next second, so we add a second in us. If
- * the difference is greater than zero and less than MINSTEP, the
- * clock has been advanced by a small amount to avoid standing still.
- * If the clock has advanced by a greater amount, then a timer interrupt
- * has occurred and this amount represents the precision of the clock.
- * In order to guard against spurious values, which could occur if we
- * happen to hit a fat interrupt, we do this for MINLOOPS times and
- * keep the minimum value obtained.
+ * 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)
{
- struct timeval tp;
-#if !defined(SYS_WINNT) && !defined(VMS) && !defined(_SEQUENT_) && \
- !defined(MPE)
- struct timezone tzp;
-#elif defined(VMS) || defined(_SEQUENT_)
- struct timezone {
- int tz_minuteswest;
- int tz_dsttime;
- } tzp;
-#endif /* defined(VMS) || defined(_SEQUENT_) */
- long last;
- int i;
- long diff;
- long val;
- long usec;
-#ifdef HAVE_GETCLOCK
- struct timespec ts;
-#endif
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
- u_long freq;
- size_t j;
-
- /* Try to see if we can find the frequency of of the counter
- * which drives our timekeeping
- */
- j = sizeof freq;
- i = sysctlbyname("kern.timecounter.frequency", &freq, &j , 0,
- 0);
- if (i)
- i = sysctlbyname("machdep.tsc_freq", &freq, &j , 0, 0);
- if (i)
- i = sysctlbyname("machdep.i586_freq", &freq, &j , 0, 0);
- if (i)
- i = sysctlbyname("machdep.i8254_freq", &freq, &j , 0,
- 0);
- if (!i) {
- for (i = 1; freq ; i--)
- freq >>= 1;
- return (i);
- }
-#endif
- usec = 0;
- val = MAXSTEP;
-#ifdef HAVE_GETCLOCK
- (void) getclock(TIMEOFDAY, &ts);
- tp.tv_sec = ts.tv_sec;
- tp.tv_usec = ts.tv_nsec / 1000;
-#else /* not HAVE_GETCLOCK */
- GETTIMEOFDAY(&tp, &tzp);
-#endif /* not HAVE_GETCLOCK */
- last = tp.tv_usec;
- for (i = 0; i < MINLOOPS && usec < HUSECS;) {
-#ifdef HAVE_GETCLOCK
- (void) getclock(TIMEOFDAY, &ts);
- tp.tv_sec = ts.tv_sec;
- tp.tv_usec = ts.tv_nsec / 1000;
-#else /* not HAVE_GETCLOCK */
- GETTIMEOFDAY(&tp, &tzp);
-#endif /* not HAVE_GETCLOCK */
- diff = tp.tv_usec - last;
- last = tp.tv_usec;
- if (diff < 0)
- diff += DUSECS;
- usec += diff;
- if (diff > MINSTEP) {
- i++;
- if (diff < val)
- val = diff;
- }
+ 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;
}
- NLOG(NLOG_SYSINFO)
- msyslog(LOG_INFO, "precision = %ld usec", val);
- if (usec >= HUSECS)
- val = MINSTEP; /* val <= MINSTEP; fast machine */
- diff = HUSECS;
- for (i = 0; diff > val; i--)
- diff >>= 1;
- return (i);
+
+ /*
+ * 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;
+ l_fp dummy;
+ int i;
/*
* Fill in the sys_* stuff. Default is don't listen to
@@ -2595,32 +2988,31 @@ init_proto(void)
*/
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;
- sys_refid = 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;
- sys_badstratum = 0;
- sys_oldversionpkt = 0;
- sys_newversionpkt = 0;
- sys_badlength = 0;
- sys_unknownversion = 0;
- sys_processed = 0;
- sys_badauth = 0;
- sys_manycastserver = 0;
-#ifdef AUTOKEY
+ 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 /* AUTOKEY */
+#endif /* OPENSSL */
/*
* Default these to enable
@@ -2631,19 +3023,6 @@ init_proto(void)
#endif
pps_enable = 0;
stats_control = 1;
-
- /*
- * Some system clocks should only be adjusted in 10ms
- * increments.
- */
-#if defined RELIANTUNIX_CLOCK
- systime_10ms_ticks = 1; /* Reliant UNIX */
-#elif defined SCO5_CLOCK
- if (sys_precision >= (s_char)-10) /* pre-SCO OpenServer 5.0.6 */
- systime_10ms_ticks = 1;
-#endif
- if (systime_10ms_ticks)
- msyslog(LOG_INFO, "using 10ms tick adjustments");
}
@@ -2652,55 +3031,52 @@ init_proto(void)
*/
void
proto_config(
- int item,
- u_long value,
- double dvalue
+ int item,
+ u_long value,
+ double dvalue,
+ struct sockaddr_storage* svalue
)
{
/*
* Figure out what he wants to change, then do it
*/
switch (item) {
- case PROTO_KERNEL:
- /*
- * Turn on/off kernel discipline
- */
+ /*
+ * Turn on/off kernel discipline.
+ */
+ case PROTO_KERNEL:
kern_enable = (int)value;
break;
+ /*
+ * Turn on/off clock discipline.
+ */
case PROTO_NTP:
-
- /*
- * Turn on/off clock discipline
- */
ntp_enable = (int)value;
break;
+ /*
+ * Turn on/off monitoring.
+ */
case PROTO_MONITOR:
-
- /*
- * Turn on/off monitoring
- */
if (value)
mon_start(MON_ON);
else
mon_stop(MON_ON);
break;
+ /*
+ * Turn on/off statistics.
+ */
case PROTO_FILEGEN:
-
- /*
- * Turn on/off statistics
- */
stats_control = (int)value;
break;
+ /*
+ * Turn on/off facility to listen to broadcasts.
+ */
case PROTO_BROADCLIENT:
-
- /*
- * Turn on/off facility to listen to broadcasts
- */
sys_bclient = (int)value;
if (value)
io_setbclient();
@@ -2708,65 +3084,107 @@ proto_config(
io_unsetbclient();
break;
+ /*
+ * Add muliticast group address.
+ */
case PROTO_MULTICAST_ADD:
-
- /*
- * Add muliticast group address
- */
- io_multicast_add(value);
+ if (svalue)
+ io_multicast_add(*svalue);
break;
+ /*
+ * Delete multicast group address.
+ */
case PROTO_MULTICAST_DEL:
-
- /*
- * Delete multicast group address
- */
- io_multicast_del(value);
+ if (svalue)
+ io_multicast_del(*svalue);
break;
+ /*
+ * Set default broadcast delay.
+ */
case PROTO_BROADDELAY:
-
- /*
- * Set default broadcast delay
- */
sys_bdelay = dvalue;
break;
- case PROTO_AUTHENTICATE:
+ /*
+ * Set modem call delay.
+ */
+ case PROTO_CALLDELAY:
+ sys_calldelay = (int)value;
+ break;
- /*
- * Specify the use of authenticated data
- */
+ /*
+ * Require authentication to mobilize ephemeral associations.
+ */
+ case PROTO_AUTHENTICATE:
sys_authenticate = (int)value;
break;
+ /*
+ * Turn on/off PPS discipline.
+ */
case PROTO_PPS:
-
- /*
- * Turn on/off PPS discipline
- */
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:
-
- /*
- * Turn on/off refclock calibrate
- */
cal_enable = (int)value;
break;
#endif
-
default:
/*
- * Log this error
+ * Log this error.
*/
- msyslog(LOG_ERR,
- "proto_config: illegal item %d, value %ld",
+ msyslog(LOG_INFO,
+ "proto_config: illegal item %d, value %ld",
item, value);
- break;
}
}
@@ -2777,13 +3195,14 @@ proto_config(
void
proto_clr_stats(void)
{
- sys_badstratum = 0;
- sys_oldversionpkt = 0;
+ 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_processed = 0;
sys_badauth = 0;
- sys_stattime = current_time;
sys_limitrejected = 0;
}
diff --git a/contrib/ntp/ntpd/ntp_refclock.c b/contrib/ntp/ntpd/ntp_refclock.c
index 2205b6c..172fbda 100644
--- a/contrib/ntp/ntpd/ntp_refclock.c
+++ b/contrib/ntp/ntpd/ntp_refclock.c
@@ -63,8 +63,9 @@
* 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, where t is the
- * clock type and u the unit. Some legacy drivers derive the
+ * 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.
@@ -107,7 +108,8 @@ refclock_report(
{
struct refclockproc *pp;
- if (!(pp = peer->procptr))
+ pp = peer->procptr;
+ if (pp == NULL)
return;
if (code == CEVNT_BADREPLY)
pp->badformat++;
@@ -116,25 +118,25 @@ refclock_report(
if (code == CEVNT_TIMEOUT)
pp->noreply++;
if (pp->currentstatus != code) {
- pp->currentstatus = code;
- pp->lastevent = 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.sin_addr.s_addr),
+ refnumtoa(&peer->srcadr),
ceventstr(code), code);
else {
NLOG(NLOG_CLOCKEVENT)
msyslog(LOG_INFO,
"clock %s event '%s' (0x%02x)",
- refnumtoa(peer->srcadr.sin_addr.s_addr),
+ refnumtoa(&peer->srcadr),
ceventstr(code), code);
}
}
#ifdef DEBUG
if (debug)
printf("clock %s event '%s' (0x%02x)\n",
- refnumtoa(peer->srcadr.sin_addr.s_addr),
+ refnumtoa(&peer->srcadr),
ceventstr(code), code);
#endif
}
@@ -186,10 +188,16 @@ refclock_newpeer(
* 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",
- ntoa(&peer->srcadr));
+ stoa(&peer->srcadr));
return (0);
}
clktype = (u_char)REFCLOCKTYPE(&peer->srcadr);
@@ -205,7 +213,8 @@ refclock_newpeer(
/*
* Allocate and initialize interface structure
*/
- if (!(pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc))))
+ pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc));
+ if (pp == NULL)
return (0);
memset((char *)pp, 0, sizeof(struct refclockproc));
typeunit[clktype][unit] = peer;
@@ -215,12 +224,10 @@ refclock_newpeer(
* Initialize structures
*/
peer->refclktype = clktype;
- peer->refclkunit = unit;
+ peer->refclkunit = (u_char)unit;
peer->flags |= FLAG_REFCLOCK;
- peer->stratum = STRATUM_REFCLOCK;
- peer->refid = peer->srcadr.sin_addr.s_addr;
peer->maxpoll = peer->minpoll;
-
+ peer->stratum = STRATUM_REFCLOCK;
pp->type = clktype;
pp->timestarted = current_time;
@@ -228,12 +235,11 @@ refclock_newpeer(
* Set peer.pmode based on the hmode. For appearances only.
*/
switch (peer->hmode) {
-
- case MODE_ACTIVE:
+ case MODE_ACTIVE:
peer->pmode = MODE_PASSIVE;
break;
- default:
+ default:
peer->pmode = MODE_SERVER;
break;
}
@@ -248,10 +254,7 @@ refclock_newpeer(
}
peer->hpoll = peer->minpoll;
peer->ppoll = peer->maxpoll;
- if (peer->stratum <= 1)
- peer->refid = pp->refid;
- else
- peer->refid = peer->srcadr.sin_addr.s_addr;
+ peer->refid = pp->refid;
return (1);
}
@@ -297,7 +300,6 @@ refclock_transmit(
{
u_char clktype;
int unit;
- int hpoll;
u_long next;
clktype = peer->refclktype;
@@ -309,14 +311,13 @@ refclock_transmit(
* specialized for reference clocks. We do a little less
* protocol here and call the driver-specific transmit routine.
*/
- hpoll = peer->hpoll;
next = peer->outdate;
if (peer->burst == 0) {
u_char oreach;
#ifdef DEBUG
if (debug)
printf("refclock_transmit: at %ld %s\n",
- current_time, ntoa(&(peer->srcadr)));
+ current_time, stoa(&(peer->srcadr)));
#endif
/*
@@ -329,17 +330,13 @@ refclock_transmit(
if (oreach) {
report_event(EVNT_UNREACH, peer);
peer->timereachable = current_time;
- peer_clear(peer);
+ peer_clear(peer, "NONE");
}
} else {
if (!(oreach & 0x03)) {
clock_filter(peer, 0., 0., MAXDISPERSE);
clock_select();
}
- if (!(oreach & 0x0f)) {
- hpoll--;
- } else if ((oreach & 0x0f) == 0x0f)
- hpoll++;
if (peer->flags & FLAG_BURST)
peer->burst = NSTAGE;
}
@@ -351,7 +348,7 @@ refclock_transmit(
peer->outdate = next;
if (peer->burst > 0)
peer->burst--;
- poll_update(peer, hpoll);
+ poll_update(peer, 0);
}
@@ -399,18 +396,19 @@ refclock_cmpl_fp(
*/
void
refclock_process_offset(
- struct refclockproc *pp,
- l_fp offset,
- l_fp lastrec,
+ 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->lastref = offset;
pp->lastrec = lastrec;
- L_SUB(&offset, &lastrec);
- LFPTOD(&offset, doffset);
+ lftemp = lasttim;
+ L_SUB(&lftemp, &lastrec);
+ LFPTOD(&lftemp, doffset);
SAMPLE(doffset + fudge);
}
@@ -425,10 +423,10 @@ refclock_process_offset(
*/
int
refclock_process(
- struct refclockproc *pp
+ struct refclockproc *pp /* refclock structure pointer */
)
{
- l_fp offset;
+ l_fp offset, ltemp;
/*
* Compute the timecode timestamp from the days, hours, minutes,
@@ -441,11 +439,9 @@ refclock_process(
if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui))
return (0);
- if (pp->usec) {
- TVUTOTSF(pp->usec, offset.l_uf);
- } else {
- MSUTOTSF(pp->msec, offset.l_uf);
- }
+ offset.l_uf = 0;
+ DTOLFP(pp->nsec / 1e9, &ltemp);
+ L_ADD(&offset, &ltemp);
refclock_process_offset(pp, offset, pp->lastrec,
pp->fudgetime1);
return (1);
@@ -463,7 +459,7 @@ refclock_process(
*/
static int
refclock_sample(
- struct refclockproc *pp
+ struct refclockproc *pp /* refclock structure pointer */
)
{
int i, j, k, m, n;
@@ -474,11 +470,14 @@ refclock_sample(
* Copy the raw offsets and sort into ascending order. Don't do
* anything if the buffer is empty.
*/
- if (pp->codeproc == pp->coderecv)
- return (0);
n = 0;
- while (pp->codeproc != pp->coderecv)
- off[n++] = pp->filter[pp->codeproc++ % MAXSTAGE];
+ 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);
@@ -536,7 +535,7 @@ refclock_receive(
#ifdef DEBUG
if (debug)
printf("refclock_receive: at %lu %s\n",
- current_time, ntoa(&peer->srcadr));
+ current_time, stoa(&peer->srcadr));
#endif
/*
@@ -556,8 +555,9 @@ refclock_receive(
if (!peer->reach)
report_event(EVNT_REACH, peer);
peer->reach |= 1;
- peer->reftime = peer->org = pp->lastrec;
- peer->rootdispersion = pp->disp + SQRT(pp->jitter);
+ peer->reftime = pp->lastref;
+ peer->org = pp->lastrec;
+ peer->rootdispersion = pp->disp;
get_systime(&peer->rec);
if (!refclock_sample(pp))
return;
@@ -608,7 +608,7 @@ refclock_gtlin(
* timestamp by noting its value is earlier than the buffer
* timestamp, but not more than one second earlier.
*/
- dpt = (char *)&rbufp->recv_space;
+ dpt = (char *)rbufp->recv_buffer;
dpend = dpt + rbufp->recv_length;
trtmp = rbufp->recv_time;
@@ -641,7 +641,7 @@ refclock_gtlin(
if (dpend - dpt > bmax - 1)
dpend = dpt + bmax - 1;
for (dp = lineptr; dpt < dpend; dpt++) {
- c = *dpt & 0x7f;
+ c = (char) (*dpt & 0x7f);
if (c >= ' ')
*dp++ = c;
}
@@ -649,9 +649,14 @@ refclock_gtlin(
if (i > 0)
*dp = '\0';
#ifdef DEBUG
- if (debug > 1 && i > 0)
- printf("refclock_gtlin: fd %d time %s timecode %d %s\n",
- rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
+ 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);
@@ -961,7 +966,7 @@ refclock_ioctl(
*/
void
refclock_control(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct refclockstat *in,
struct refclockstat *out
)
@@ -974,13 +979,16 @@ refclock_control(
/*
* 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;
- if (!(peer = typeunit[clktype][unit]))
+ peer = typeunit[clktype][unit];
+ if (peer == NULL)
return;
if (peer->procptr == NULL)
return;
@@ -995,13 +1003,16 @@ refclock_control(
if (in->haveflags & CLK_HAVETIME2)
pp->fudgetime2 = in->fudgetime2;
if (in->haveflags & CLK_HAVEVAL1)
- peer->stratum = (u_char) in->fudgeval1;
+ pp->stratum = (u_char) in->fudgeval1;
if (in->haveflags & CLK_HAVEVAL2)
pp->refid = in->fudgeval2;
- if (peer->stratum <= 1)
+ peer->stratum = pp->stratum;
+ if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
+ STRATUM_UNSPEC)
peer->refid = pp->refid;
else
- peer->refid = peer->srcadr.sin_addr.s_addr;
+ 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;
@@ -1028,7 +1039,7 @@ refclock_control(
CLK_HAVEVAL2 | CLK_HAVEFLAG4;
out->fudgetime1 = pp->fudgetime1;
out->fudgetime2 = pp->fudgetime2;
- out->fudgeval1 = peer->stratum;
+ out->fudgeval1 = pp->stratum;
out->fudgeval2 = pp->refid;
out->flags = (u_char) pp->sloppyclockflag;
@@ -1063,7 +1074,7 @@ refclock_control(
*/
void
refclock_buginfo(
- struct sockaddr_in *srcadr, /* clock address */
+ struct sockaddr_storage *srcadr, /* clock address */
struct refclockbug *bug /* output structure */
)
{
@@ -1076,13 +1087,16 @@ refclock_buginfo(
/*
* 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;
- if (!(peer = typeunit[clktype][unit]))
+ peer = typeunit[clktype][unit];
+ if (peer == NULL)
return;
pp = peer->procptr;
@@ -1096,7 +1110,7 @@ refclock_buginfo(
bug->values[2] = pp->hour;
bug->values[3] = pp->minute;
bug->values[4] = pp->second;
- bug->values[5] = pp->msec;
+ bug->values[5] = pp->nsec;
bug->values[6] = pp->yearstart;
bug->values[7] = pp->coderecv;
bug->stimes = 0xfffffffc;
diff --git a/contrib/ntp/ntpd/ntp_request.c b/contrib/ntp/ntpd/ntp_request.c
index 260b48b..eacba28 100644
--- a/contrib/ntp/ntpd/ntp_request.c
+++ b/contrib/ntp/ntpd/ntp_request.c
@@ -1,6 +1,7 @@
/*
* ntp_request.c - respond to information requests
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -14,6 +15,7 @@
#include "ntp_stdlib.h"
#include <stdio.h>
+#include <stddef.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -31,12 +33,21 @@
#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 */
- void (*handler) P((struct sockaddr_in *, struct interface *,
+ 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 */
};
@@ -47,105 +58,120 @@ static struct req_proc univ_codes[] = {
{ NO_REQUEST, NOAUTH, 0, 0 }
};
-static void req_ack P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
-static char * prepare_pkt P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_int));
+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_in *, struct interface *, struct req_pkt *));
-static void peer_list_sum P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void peer_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void peer_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void sys_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void sys_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void mem_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void io_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void timer_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void loop_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void dns_a P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_conf P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_unconf P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void set_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void clr_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void setclr_flags P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_long));
-static void list_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_resaddflags P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_ressubflags P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_unrestrict P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_restrict P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
-static void mon_getlist_0 P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void mon_getlist_1 P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void reset_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void reset_peer P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_key_reread P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void trust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void untrust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_trustkey P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_long));
-static void get_auth_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+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_in *, struct interface *, struct req_pkt *));
-static void req_set_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void req_clr_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_setclr_trap P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
-static void set_request_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void set_control_keyid P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void get_ctl_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+static void 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_in *, struct interface *, struct req_pkt *));
+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_in *, struct interface *, struct req_pkt *));
-static void set_clock_fudge P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+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_in *, struct interface *, struct req_pkt *));
+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, peer_list },
- { REQ_PEER_LIST_SUM, NOAUTH, 0, peer_list_sum },
- { REQ_PEER_INFO, NOAUTH, sizeof(struct info_peer_list), peer_info },
- { REQ_PEER_STATS, NOAUTH, sizeof(struct info_peer_list), peer_stats },
- { REQ_SYS_INFO, NOAUTH, 0, sys_info },
- { REQ_SYS_STATS, NOAUTH, 0, sys_stats },
- { REQ_IO_STATS, NOAUTH, 0, io_stats },
- { REQ_MEM_STATS, NOAUTH, 0, mem_stats },
- { REQ_LOOP_INFO, NOAUTH, 0, loop_info },
- { REQ_TIMER_STATS, NOAUTH, 0, timer_stats },
- { REQ_HOSTNAME_ASSOCID, AUTH, sizeof(struct info_dns_assoc), dns_a },
- { REQ_CONFIG, AUTH, sizeof(struct conf_peer), do_conf },
- { REQ_UNCONFIG, AUTH, sizeof(struct conf_unpeer), do_unconf },
- { REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), set_sys_flag },
- { REQ_CLR_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), clr_sys_flag },
- { REQ_GET_RESTRICT, NOAUTH, 0, list_restrict },
- { REQ_RESADDFLAGS, AUTH, sizeof(struct conf_restrict), do_resaddflags },
- { REQ_RESSUBFLAGS, AUTH, sizeof(struct conf_restrict), do_ressubflags },
- { REQ_UNRESTRICT, AUTH, sizeof(struct conf_restrict), do_unrestrict },
- { REQ_MON_GETLIST, NOAUTH, 0, mon_getlist_0 },
- { REQ_MON_GETLIST_1, NOAUTH, 0, mon_getlist_1 },
- { REQ_RESET_STATS, AUTH, sizeof(struct reset_flags), reset_stats },
- { REQ_RESET_PEER, AUTH, sizeof(struct conf_unpeer), reset_peer },
- { REQ_REREAD_KEYS, AUTH, 0, do_key_reread },
- { REQ_TRUSTKEY, AUTH, sizeof(u_long), trust_key },
- { REQ_UNTRUSTKEY, AUTH, sizeof(u_long), untrust_key },
- { REQ_AUTHINFO, NOAUTH, 0, get_auth_info },
- { REQ_TRAPS, NOAUTH, 0, req_get_traps },
- { REQ_ADD_TRAP, AUTH, sizeof(struct conf_trap), req_set_trap },
- { REQ_CLR_TRAP, AUTH, sizeof(struct conf_trap), req_clr_trap },
- { REQ_REQUEST_KEY, AUTH, sizeof(u_long), set_request_keyid },
- { REQ_CONTROL_KEY, AUTH, sizeof(u_long), set_control_keyid },
- { REQ_GET_CTLSTATS, NOAUTH, 0, get_ctl_stats },
+ { 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, get_kernel_info },
+ { REQ_GET_KERNEL, NOAUTH, 0, 0, get_kernel_info },
#endif
#ifdef REFCLOCK
- { REQ_GET_CLOCKINFO, NOAUTH, sizeof(u_int32), get_clock_info },
- { REQ_SET_CLKFUDGE, AUTH, sizeof(struct conf_fudge), set_clock_fudge },
- { REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), get_clkbug_info },
+ { 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 }
+ { NO_REQUEST, NOAUTH, 0, 0, 0 }
};
@@ -185,7 +211,7 @@ static int itemsize;
static int databytes;
static char exbuf[RESP_DATA_SIZE];
static int usingexbuf;
-static struct sockaddr_in *toaddr;
+static struct sockaddr_storage *toaddr;
static struct interface *frominter;
/*
@@ -211,7 +237,7 @@ init_request (void)
*/
static void
req_ack(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
int errcode
@@ -241,7 +267,7 @@ req_ack(
*/
static char *
prepare_pkt(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *pkt,
u_int structsize
@@ -253,7 +279,7 @@ prepare_pkt(
#endif
/*
- * Fill in the implementation, reqest and itemsize fields
+ * Fill in the implementation, request and itemsize fields
* since these won't change.
*/
rpkt.implementation = pkt->implementation;
@@ -380,10 +406,11 @@ process_private(
{
struct req_pkt *inpkt;
struct req_pkt_tail *tailinpkt;
- struct sockaddr_in *srcadr;
+ struct sockaddr_storage *srcadr;
struct interface *inter;
struct req_proc *proc;
int ec;
+ short temp_size;
/*
* Initialize pointers, for convenience
@@ -410,10 +437,9 @@ process_private(
|| (++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_MAC)
|| (++ec, rbufp->recv_length < REQ_LEN_HDR)
) {
- msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d failed", ec);
+ 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;
}
@@ -425,7 +451,8 @@ process_private(
*/
if (inpkt->implementation == IMPL_UNIV)
proc = univ_codes;
- else if (inpkt->implementation == IMPL_XNTPD)
+ else if ((inpkt->implementation == IMPL_XNTPD) ||
+ (inpkt->implementation == IMPL_XNTPD_OLD))
proc = ntp_codes;
else {
req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL);
@@ -452,6 +479,50 @@ process_private(
#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
@@ -463,10 +534,10 @@ process_private(
l_fp ftmp;
double dtemp;
- if (rbufp->recv_length < (REQ_LEN_HDR +
+ if (rbufp->recv_length < (int)((REQ_LEN_HDR +
(INFO_ITEMSIZE(inpkt->mbz_itemsize) *
INFO_NITEMS(inpkt->err_nitems))
- + sizeof(struct req_pkt_tail))) {
+ + sizeof(struct req_pkt_tail)))) {
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
}
tailinpkt = (struct req_pkt_tail *)((char *)&rbufp->recv_pkt +
@@ -481,9 +552,14 @@ process_private(
#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));
+ 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;
@@ -494,8 +570,8 @@ process_private(
printf("bad pkt length %d\n",
rbufp->recv_length);
#endif
- msyslog(LOG_ERR, "process_private: bad pkt length %d",
- rbufp->recv_length);
+ msyslog(LOG_ERR, "process_private: bad pkt length %d",
+ rbufp->recv_length);
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -503,6 +579,9 @@ process_private(
#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;
@@ -519,6 +598,10 @@ process_private(
/*
* 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;
}
@@ -529,36 +612,15 @@ process_private(
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;
}
}
- /*
- * If we need data, check to see if we have some. If we
- * don't, check to see that there is none (picky, picky).
- *
- * Handle the exception of REQ_CONFIG. It can have two data sizes.
- */
- if (INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem &&
- !(inpkt->implementation == IMPL_XNTPD &&
- inpkt->request == REQ_CONFIG &&
- INFO_ITEMSIZE(inpkt->mbz_itemsize) == sizeof(struct old_conf_peer))) {
- msyslog(LOG_ERR, "INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem: %d != %d",
- INFO_ITEMSIZE(inpkt->mbz_itemsize), proc->sizeofitem);
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
- if (proc->sizeofitem != 0)
- if (proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems)
- > sizeof(inpkt->data)) {
- msyslog(LOG_ERR, "sizeofitem(%d)*NITEMS(%d) > data: %d > %ld",
- proc->sizeofitem, INFO_NITEMS(inpkt->err_nitems),
- proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems),
- (long)sizeof(inpkt->data));
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
#ifdef DEBUG
if (debug > 3)
printf("process_private: all okay, into handler\n");
@@ -576,7 +638,7 @@ process_private(
*/
static void
peer_list(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -584,26 +646,44 @@ peer_list(
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,
- sizeof(struct info_peer_list));
+ v6sizeof(struct info_peer_list));
for (i = 0; i < HASH_SIZE && ip != 0; i++) {
pp = peer_hash[i];
while (pp != 0 && ip != 0) {
- ip->address = pp->srcadr.sin_addr.s_addr;
- ip->port = pp->srcadr.sin_port;
- 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;
+ 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();
@@ -615,7 +695,7 @@ peer_list(
*/
static void
peer_list_sum(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -624,14 +704,14 @@ peer_list_sum(
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,
- sizeof(struct info_peer_summary));
+ v6sizeof(struct info_peer_summary));
for (i = 0; i < HASH_SIZE && ips != 0; i++) {
pp = peer_hash[i];
while (pp != 0 && ips != 0) {
@@ -639,46 +719,66 @@ peer_list_sum(
if (debug > 3)
printf("sum: got one\n");
#endif
- ips->dstadr =
- (pp->processed)
- ? pp->cast_flags == MDF_BCAST
- ? pp->dstadr->bcast.sin_addr.s_addr
- : pp->cast_flags
- ? pp->dstadr->sin.sin_addr.s_addr
- ? pp->dstadr->sin.sin_addr.s_addr
- : pp->dstadr->bcast.sin_addr.s_addr
- : 1
- : 5;
- ips->srcadr = pp->srcadr.sin_addr.s_addr;
- ips->srcport = pp->srcadr.sin_port;
- ips->stratum = pp->stratum;
- 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;
+ /*
+ * 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();
}
}
@@ -691,7 +791,7 @@ peer_list_sum(
*/
static void
peer_info (
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -701,33 +801,53 @@ peer_info (
register struct info_peer *ip;
register int items;
register int i, j;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
extern struct peer *sys_peer;
l_fp ltmp;
memset((char *)&addr, 0, sizeof addr);
- addr.sin_family = AF_INET;
items = INFO_NITEMS(inpkt->err_nitems);
ipl = (struct info_peer_list *) inpkt->data;
+
ip = (struct info_peer *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_peer));
+ v6sizeof(struct info_peer));
while (items-- > 0 && ip != 0) {
- addr.sin_port = ipl->port;
- addr.sin_addr.s_addr = ipl->address;
+ 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;
- ip->dstadr =
- (pp->processed)
- ? pp->cast_flags == MDF_BCAST
- ? pp->dstadr->bcast.sin_addr.s_addr
- : pp->cast_flags
- ? pp->dstadr->sin.sin_addr.s_addr
- ? pp->dstadr->sin.sin_addr.s_addr
- : pp->dstadr->bcast.sin_addr.s_addr
- : 2
- : 6;
- ip->srcadr = NSRCADR(&pp->srcadr);
+ 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)
@@ -755,9 +875,9 @@ peer_info (
ip->precision = pp->precision;
ip->version = pp->version;
ip->reach = pp->reach;
- ip->unreach = pp->unreach;
+ ip->unreach = (u_char) pp->unreach;
ip->flash = (u_char)pp->flash;
- ip->flash2 = pp->flash;
+ ip->flash2 = (u_short) pp->flash;
ip->estbdelay = HTONS_FP(DTOFP(pp->estbdelay));
ip->ttl = pp->ttl;
ip->associd = htons(pp->associd);
@@ -775,8 +895,8 @@ peer_info (
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] = (pp->filter_nextpt+NTP_SHIFT-1)
- - pp->filter_order[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;
}
@@ -796,7 +916,7 @@ peer_info (
*/
static void
peer_stats (
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -805,32 +925,54 @@ peer_stats (
register struct peer *pp;
register struct info_peer_stats *ip;
register int items;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
extern struct peer *sys_peer;
- memset((char *)&addr, 0, sizeof addr);
- addr.sin_family = AF_INET;
+ 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,
- sizeof(struct info_peer_stats));
+ v6sizeof(struct info_peer_stats));
while (items-- > 0 && ip != 0) {
- addr.sin_port = ipl->port;
- addr.sin_addr.s_addr = ipl->address;
- ipl++;
+ 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;
- ip->dstadr =
- (pp->processed)
- ? pp->cast_flags == MDF_BCAST
- ? pp->dstadr->bcast.sin_addr.s_addr
- : pp->cast_flags
- ? pp->dstadr->sin.sin_addr.s_addr
- ? pp->dstadr->sin.sin_addr.s_addr
- : pp->dstadr->bcast.sin_addr.s_addr
- : 3
- : 7;
- ip->srcadr = NSRCADR(&pp->srcadr);
+ 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)
@@ -871,7 +1013,7 @@ peer_stats (
*/
static void
sys_info(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -897,15 +1039,26 @@ sys_info(
extern double sys_jitter;
is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_sys));
+ v6sizeof(struct info_sys));
if (sys_peer != 0) {
- is->peer = NSRCADR(&sys_peer->srcadr);
+ 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;
@@ -950,7 +1103,7 @@ sys_info(
*/
static void
sys_stats(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -960,22 +1113,11 @@ sys_stats(
/*
* Importations from the protocol module
*/
- extern u_long sys_stattime;
- extern u_long sys_badstratum;
- extern u_long sys_oldversionpkt;
- extern u_long sys_newversionpkt;
- extern u_long sys_unknownversion;
- extern u_long sys_badlength;
- extern u_long sys_processed;
- extern u_long sys_badauth;
- extern u_long sys_limitrejected;
-
ss = (struct info_sys_stats *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_sys_stats));
-
+ sizeof(struct info_sys_stats));
ss->timeup = htonl((u_int32)current_time);
ss->timereset = htonl((u_int32)(current_time - sys_stattime));
- ss->badstratum = htonl((u_int32)sys_badstratum);
+ 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);
@@ -983,6 +1125,7 @@ sys_stats(
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();
}
@@ -993,7 +1136,7 @@ sys_stats(
*/
static void
mem_stats(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1039,7 +1182,7 @@ mem_stats(
*/
static void
io_stats(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1077,7 +1220,7 @@ io_stats(
*/
static void
timer_stats(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1109,7 +1252,7 @@ timer_stats(
*/
static void
loop_info(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1145,50 +1288,44 @@ loop_info(
*/
static void
do_conf(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
{
- u_int fl;
- struct conf_peer *cp;
- struct old_conf_peer *ocp;
int items;
- struct sockaddr_in peeraddr;
+ 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.
*/
- ocp = NULL;
- if (INFO_ITEMSIZE(inpkt->mbz_itemsize) == sizeof(struct old_conf_peer))
- ocp = (struct old_conf_peer *)inpkt->data;
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 (((cp->version) > NTP_VERSION)
- || ((cp->version) < NTP_OLDVERSION))
+ if (((temp_cp.version) > NTP_VERSION)
+ || ((temp_cp.version) < NTP_OLDVERSION))
fl = 1;
- if (cp->hmode != MODE_ACTIVE
- && cp->hmode != MODE_CLIENT
- && cp->hmode != MODE_BROADCAST)
+ if (temp_cp.hmode != MODE_ACTIVE
+ && temp_cp.hmode != MODE_CLIENT
+ && temp_cp.hmode != MODE_BROADCAST)
fl = 1;
- if (cp->flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER |
- CONF_FLAG_NOSELECT | CONF_FLAG_BURST | CONF_FLAG_IBURST |
- CONF_FLAG_SKEY))
+ if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
+ | CONF_FLAG_BURST | CONF_FLAG_SKEY))
fl = 1;
- if (ocp) {
- ocp++;
- cp = (struct conf_peer *)ocp;
- } else
- cp++;
+ cp = (struct conf_peer *)
+ ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
if (fl) {
- msyslog(LOG_ERR, "do_conf: fl is nonzero!");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1197,69 +1334,70 @@ do_conf(
* Looks okay, try it out
*/
items = INFO_NITEMS(inpkt->err_nitems);
- cp = (struct conf_peer *)inpkt->data;
- if (ocp)
- ocp = (struct old_conf_peer *)inpkt->data;
- memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
- peeraddr.sin_family = AF_INET;
- peeraddr.sin_port = htons(NTP_PORT);
+ cp = (struct conf_peer *)inpkt->data;
- /*
- * Make sure the address is valid
- */
- if (
+ 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(&peeraddr) &&
+ !ISREFCLOCKADR(&tmp_clock) &&
#endif
- ISBADADR(&peeraddr)) {
-#ifdef REFCLOCK
- msyslog(LOG_ERR, "do_conf: !ISREFCLOCK && ISBADADR");
-#else
- msyslog(LOG_ERR, "do_conf: ISBADADR");
+ 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
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
- return;
- }
- while (items-- > 0) {
- fl = 0;
- if (cp->flags & CONF_FLAG_AUTHENABLE)
- fl |= FLAG_AUTHENABLE;
- if (cp->flags & CONF_FLAG_PREFER)
- fl |= FLAG_PREFER;
- if (cp->flags & CONF_FLAG_NOSELECT)
- fl |= FLAG_NOSELECT;
- if (cp->flags & CONF_FLAG_BURST)
- fl |= FLAG_BURST;
- if (cp->flags & CONF_FLAG_IBURST)
- fl |= FLAG_IBURST;
- if (cp->flags & CONF_FLAG_SKEY)
- fl |= FLAG_SKEY;
- peeraddr.sin_addr.s_addr = cp->peeraddr;
/* XXX W2DO? minpoll/maxpoll arguments ??? */
- if (peer_config(&peeraddr, any_interface, cp->hmode,
- cp->version, cp->minpoll, cp->maxpoll, fl, cp->ttl,
- cp->keyid, NULL) == 0) {
+ 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;
}
- if (ocp) {
- ocp++;
- cp = (struct conf_peer *)ocp;
- } else
- cp++;
+ 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_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1326,9 +1464,10 @@ dns_a(
}
msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
- dp->hostname, inet_ntoa(peeraddr.sin_addr), associd,
+ dp->hostname,
+ stoa((struct sockaddr_storage *)&peeraddr), associd,
bogon);
-
+
if (bogon) {
/* If it didn't work */
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
@@ -1340,28 +1479,29 @@ dns_a(
#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_in *srcadr,
+ 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_in peeraddr;
+ struct sockaddr_storage peeraddr;
int bad, found;
/*
@@ -1370,17 +1510,28 @@ do_unconf(
* configured. If so, we remove them. If not, we return
* an error.
*/
- peeraddr.sin_family = AF_INET;
- peeraddr.sin_port = htons(NTP_PORT);
-
items = INFO_NITEMS(inpkt->err_nitems);
cp = (struct conf_unpeer *)inpkt->data;
bad = 0;
while (items-- > 0 && !bad) {
- peeraddr.sin_addr.s_addr = cp->peeraddr;
+ 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)
@@ -1390,7 +1541,8 @@ do_unconf(
}
if (!found)
bad = 1;
- cp++;
+ cp = (struct conf_unpeer *)
+ ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
if (bad) {
@@ -1405,9 +1557,23 @@ do_unconf(
items = INFO_NITEMS(inpkt->err_nitems);
cp = (struct conf_unpeer *)inpkt->data;
while (items-- > 0) {
- peeraddr.sin_addr.s_addr = cp->peeraddr;
+ 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++;
+ cp = (struct conf_unpeer *)
+ ((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
req_ack(srcadr, inter, inpkt, INFO_OKAY);
@@ -1419,7 +1585,7 @@ do_unconf(
*/
static void
set_sys_flag(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1433,7 +1599,7 @@ set_sys_flag(
*/
static void
clr_sys_flag(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1447,7 +1613,7 @@ clr_sys_flag(
*/
static void
setclr_flags(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
u_long set
@@ -1467,7 +1633,7 @@ setclr_flags(
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 |
+ 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));
@@ -1476,21 +1642,21 @@ setclr_flags(
}
if (flags & SYS_FLAG_BCLIENT)
- proto_config(PROTO_BROADCLIENT, set, 0.);
+ proto_config(PROTO_BROADCLIENT, set, 0., NULL);
if (flags & SYS_FLAG_PPS)
- proto_config(PROTO_PPS, set, 0.);
+ proto_config(PROTO_PPS, set, 0., NULL);
if (flags & SYS_FLAG_NTP)
- proto_config(PROTO_NTP, set, 0.);
+ proto_config(PROTO_NTP, set, 0., NULL);
if (flags & SYS_FLAG_KERNEL)
- proto_config(PROTO_KERNEL, set, 0.);
+ proto_config(PROTO_KERNEL, set, 0., NULL);
if (flags & SYS_FLAG_MONITOR)
- proto_config(PROTO_MONITOR, set, 0.);
+ proto_config(PROTO_MONITOR, set, 0., NULL);
if (flags & SYS_FLAG_FILEGEN)
- proto_config(PROTO_FILEGEN, set, 0.);
+ proto_config(PROTO_FILEGEN, set, 0., NULL);
if (flags & SYS_FLAG_AUTH)
- proto_config(PROTO_AUTHENTICATE, set, 0.);
+ proto_config(PROTO_AUTHENTICATE, set, 0., NULL);
if (flags & SYS_FLAG_CAL)
- proto_config(PROTO_CAL, set, 0.);
+ proto_config(PROTO_CAL, set, 0., NULL);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
}
@@ -1500,30 +1666,43 @@ setclr_flags(
*/
static void
list_restrict(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
{
register struct info_restrict *ir;
register struct restrictlist *rl;
- extern struct restrictlist *restrictlist;
+ register struct restrictlist6 *rl6;
#ifdef DEBUG
if (debug > 2)
- printf("wants peer list summary\n");
+ printf("wants restrict list summary\n");
#endif
ir = (struct info_restrict *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_restrict));
+ 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();
}
@@ -1534,7 +1713,7 @@ list_restrict(
*/
static void
do_resaddflags(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1549,7 +1728,7 @@ do_resaddflags(
*/
static void
do_ressubflags(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1563,7 +1742,7 @@ do_ressubflags(
*/
static void
do_unrestrict(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1580,7 +1759,7 @@ do_unrestrict(
*/
static void
do_restrict(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
int op
@@ -1588,8 +1767,8 @@ do_restrict(
{
register struct conf_restrict *cr;
register int items;
- struct sockaddr_in matchaddr;
- struct sockaddr_in matchmask;
+ struct sockaddr_storage matchaddr;
+ struct sockaddr_storage matchmask;
int bad;
/*
@@ -1606,9 +1785,16 @@ do_restrict(
bad |= 1;
if (cr->flags & ~(RES_ALLFLAGS))
bad |= 2;
- if (cr->addr == htonl(INADDR_ANY) && cr->mask != htonl(INADDR_ANY))
- bad |= 4;
- cr++;
+ 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) {
@@ -1622,14 +1808,21 @@ do_restrict(
*/
items = INFO_NITEMS(inpkt->err_nitems);
cr = (struct conf_restrict *)inpkt->data;
- memset((char *)&matchaddr, 0, sizeof(struct sockaddr_in));
- memset((char *)&matchmask, 0, sizeof(struct sockaddr_in));
- matchaddr.sin_family = AF_INET;
- matchmask.sin_family = AF_INET;
+ memset((char *)&matchaddr, 0, sizeof(struct sockaddr_storage));
+ memset((char *)&matchmask, 0, sizeof(struct sockaddr_storage));
while (items-- > 0) {
- matchaddr.sin_addr.s_addr = cr->addr;
- matchmask.sin_addr.s_addr = cr->mask;
+ 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++;
@@ -1644,7 +1837,7 @@ do_restrict(
*/
static void
mon_getlist_0(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1662,19 +1855,24 @@ mon_getlist_0(
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
-
im = (struct info_monitor *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_monitor));
+ 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)(current_time - md->lasttime));
- im->firsttime = htonl((u_int32)(current_time - md->firsttime));
- if (md->lastdrop)
- im->lastdrop = htonl((u_int32)(current_time - md->lastdrop));
- else
- im->lastdrop = 0;
+ 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));
- im->addr = md->rmtadr;
+ 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;
@@ -1688,7 +1886,7 @@ mon_getlist_0(
*/
static void
mon_getlist_1(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1698,36 +1896,36 @@ mon_getlist_1(
extern struct mon_data mon_mru_list;
extern int mon_enabled;
-#ifdef DEBUG
- if (debug > 2)
- printf("wants monitor 1 list\n");
-#endif
if (!mon_enabled) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
-
im = (struct info_monitor_1 *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_monitor_1));
+ 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)(current_time - md->lasttime));
- im->firsttime = htonl((u_int32)(current_time - md->firsttime));
- if (md->lastdrop)
- im->lastdrop = htonl((u_int32)(current_time - md->lastdrop));
- else
- im->lastdrop = 0;
+ 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);
- im->addr = md->rmtadr;
- im->daddr =
- (md->cast_flags == MDF_BCAST)
- ? md->interface->bcast.sin_addr.s_addr
- : (md->cast_flags
- ? (md->interface->sin.sin_addr.s_addr
- ? md->interface->sin.sin_addr.s_addr
- : md->interface->bcast.sin_addr.s_addr
- )
- : 4);
+ 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;
@@ -1761,7 +1959,7 @@ struct reset_entry reset_entries[] = {
*/
static void
reset_stats(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1797,7 +1995,7 @@ reset_stats(
*/
static void
reset_peer(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1805,26 +2003,36 @@ reset_peer(
register struct conf_unpeer *cp;
register int items;
register struct peer *peer;
- struct sockaddr_in peeraddr;
+ struct sockaddr_storage peeraddr;
int bad;
/*
* We check first to see that every peer exists. If not,
* we return an error.
*/
- peeraddr.sin_family = AF_INET;
- peeraddr.sin_port = htons(NTP_PORT);
items = INFO_NITEMS(inpkt->err_nitems);
cp = (struct conf_unpeer *)inpkt->data;
bad = 0;
while (items-- > 0 && !bad) {
- peeraddr.sin_addr.s_addr = cp->peeraddr;
+ 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++;
+ cp = (struct conf_unpeer *)((char *)cp +
+ INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
if (bad) {
@@ -1839,13 +2047,24 @@ reset_peer(
items = INFO_NITEMS(inpkt->err_nitems);
cp = (struct conf_unpeer *)inpkt->data;
while (items-- > 0) {
- peeraddr.sin_addr.s_addr = cp->peeraddr;
+ 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++;
+ cp = (struct conf_unpeer *)((char *)cp +
+ INFO_ITEMSIZE(inpkt->mbz_itemsize));
}
req_ack(srcadr, inter, inpkt, INFO_OKAY);
@@ -1857,7 +2076,7 @@ reset_peer(
*/
static void
do_key_reread(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1872,7 +2091,7 @@ do_key_reread(
*/
static void
trust_key(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1886,7 +2105,7 @@ trust_key(
*/
static void
untrust_key(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1900,7 +2119,7 @@ untrust_key(
*/
static void
do_trustkey(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
u_long trust
@@ -1925,7 +2144,7 @@ do_trustkey(
*/
static void
get_auth_info(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -1993,7 +2212,7 @@ reset_auth_stats(void)
*/
static void
req_get_traps(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2014,16 +2233,27 @@ req_get_traps(
}
it = (struct info_trap *)prepare_pkt(srcadr, inter, inpkt,
- sizeof(struct info_trap));
+ v6sizeof(struct info_trap));
for (i = 0, tr = ctl_trap; i < CTL_MAXTRAPS; i++, tr++) {
if (tr->tr_flags & TRAP_INUSE) {
- if (tr->tr_localaddr == any_interface)
- it->local_address = 0;
- else
- it->local_address
- = NSRCADR(&tr->tr_localaddr->sin);
- it->trap_address = NSRCADR(&tr->tr_addr);
+ 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));
@@ -2042,7 +2272,7 @@ req_get_traps(
*/
static void
req_set_trap(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2057,7 +2287,7 @@ req_set_trap(
*/
static void
req_clr_trap(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2072,7 +2302,7 @@ req_clr_trap(
*/
static void
do_setclr_trap(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
int set
@@ -2081,14 +2311,14 @@ do_setclr_trap(
register struct conf_trap *ct;
register struct interface *linter;
int res;
- struct sockaddr_in laddr;
+ struct sockaddr_storage laddr;
/*
- * Prepare sockaddr_in structure
+ * Prepare sockaddr_storage structure
*/
memset((char *)&laddr, 0, sizeof laddr);
- laddr.sin_family = AF_INET;
- laddr.sin_port = ntohs(NTP_PORT);
+ laddr.ss_family = srcadr->ss_family;
+ NSRCPORT(&laddr) = ntohs(NTP_PORT);
/*
* Restrict ourselves to one item only. This eliminates
@@ -2107,7 +2337,10 @@ do_setclr_trap(
if (ct->local_address == 0) {
linter = any_interface;
} else {
- laddr.sin_addr.s_addr = ct->local_address;
+ 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);
@@ -2115,11 +2348,14 @@ do_setclr_trap(
}
}
- laddr.sin_addr.s_addr = ct->trap_address;
+ if (laddr.ss_family == AF_INET)
+ GET_INADDR(laddr) = ct->trap_address;
+ else
+ GET_INADDR6(laddr) = ct->trap_address6;
if (ct->trap_port != 0)
- laddr.sin_port = ct->trap_port;
+ NSRCPORT(&laddr) = ct->trap_port;
else
- laddr.sin_port = htons(TRAPPORT);
+ NSRCPORT(&laddr) = htons(TRAPPORT);
if (set) {
res = ctlsettrap(&laddr, linter, 0,
@@ -2143,7 +2379,7 @@ do_setclr_trap(
*/
static void
set_request_keyid(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2171,7 +2407,7 @@ set_request_keyid(
*/
static void
set_control_keyid(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2200,7 +2436,7 @@ set_control_keyid(
*/
static void
get_ctl_stats(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2256,7 +2492,7 @@ get_ctl_stats(
*/
static void
get_kernel_info(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2311,7 +2547,7 @@ get_kernel_info(
*/
static void
get_clock_info(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2320,12 +2556,16 @@ get_clock_info(
register u_int32 *clkaddr;
register int items;
struct refclockstat clock_stat;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
+ struct sockaddr_in tmp_clock;
l_fp ltmp;
memset((char *)&addr, 0, sizeof addr);
- addr.sin_family = AF_INET;
- addr.sin_port = htons(NTP_PORT);
+ 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;
@@ -2333,8 +2573,9 @@ get_clock_info(
sizeof(struct info_clock));
while (items-- > 0) {
- addr.sin_addr.s_addr = *clkaddr++;
- if (!ISREFCLOCKADR(&addr) ||
+ 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;
@@ -2344,7 +2585,7 @@ get_clock_info(
refclock_control(&addr, (struct refclockstat *)0, &clock_stat);
- ic->clockadr = addr.sin_addr.s_addr;
+ ic->clockadr = tmp_clock.sin_addr.s_addr;
ic->type = clock_stat.type;
ic->flags = clock_stat.flags;
ic->lastevent = clock_stat.lastevent;
@@ -2356,7 +2597,7 @@ get_clock_info(
ic->timestarted = htonl((u_int32)clock_stat.timereset);
DTOLFP(clock_stat.fudgetime1, &ltmp);
HTONL_FP(&ltmp, &ic->fudgetime1);
- DTOLFP(clock_stat.fudgetime1, &ltmp);
+ 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);
@@ -2375,7 +2616,7 @@ get_clock_info(
*/
static void
set_clock_fudge(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2383,19 +2624,24 @@ set_clock_fudge(
register struct conf_fudge *cf;
register int items;
struct refclockstat clock_stat;
- struct sockaddr_in addr;
+ 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);
- addr.sin_family = AF_INET;
- addr.sin_port = htons(NTP_PORT);
items = INFO_NITEMS(inpkt->err_nitems);
cf = (struct conf_fudge *) inpkt->data;
while (items-- > 0) {
- addr.sin_addr.s_addr = cf->clockadr;
- if (!ISREFCLOCKADR(&addr) ||
+ 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;
@@ -2421,7 +2667,7 @@ set_clock_fudge(
clock_stat.haveflags = CLK_HAVEVAL2;
break;
case FUDGE_FLAGS:
- clock_stat.flags = (u_char) ntohl(cf->fudgeval_flags) & 0xf;
+ clock_stat.flags = (u_char) (ntohl(cf->fudgeval_flags) & 0xf);
clock_stat.haveflags =
(CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
break;
@@ -2444,7 +2690,7 @@ set_clock_fudge(
*/
static void
get_clkbug_info(
- struct sockaddr_in *srcadr,
+ struct sockaddr_storage *srcadr,
struct interface *inter,
struct req_pkt *inpkt
)
@@ -2454,11 +2700,15 @@ get_clkbug_info(
register u_int32 *clkaddr;
register int items;
struct refclockbug bug;
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
+ struct sockaddr_in tmp_clock;
memset((char *)&addr, 0, sizeof addr);
- addr.sin_family = AF_INET;
- addr.sin_port = htons(NTP_PORT);
+ 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;
@@ -2466,8 +2716,9 @@ get_clkbug_info(
sizeof(struct info_clkbug));
while (items-- > 0) {
- addr.sin_addr.s_addr = *clkaddr++;
- if (!ISREFCLOCKADR(&addr) ||
+ 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;
@@ -2480,7 +2731,7 @@ get_clkbug_info(
return;
}
- ic->clockadr = addr.sin_addr.s_addr;
+ ic->clockadr = tmp_clock.sin_addr.s_addr;
i = bug.nvalues;
if (i > NUMCBUGVALUES)
i = NUMCBUGVALUES;
diff --git a/contrib/ntp/ntpd/ntp_restrict.c b/contrib/ntp/ntpd/ntp_restrict.c
index 0e5b9dc..ede4225 100644
--- a/contrib/ntp/ntpd/ntp_restrict.c
+++ b/contrib/ntp/ntpd/ntp_restrict.c
@@ -1,5 +1,5 @@
/*
- * ntp_restrict.c - find out what restrictions this host is running under
+ * ntp_restrict.c - determine host restrictions
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -14,28 +14,41 @@
/*
* This code keeps a simple address-and-mask list of hosts we want
- * to place restrictions on (or remove them from). The restrictions
+ * 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
+ * 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.
+ * 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.
+ * 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
@@ -45,43 +58,48 @@
#define INITRESLIST 10
#define INCRESLIST 5
+#define RES_AVG 8. /* interpacket averaging factor */
+
/*
* The restriction list
*/
struct restrictlist *restrictlist;
-static int restrictcount; /* count of entries in the restriction list */
+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;
-/* static u_long res_timereset; */
/*
* Parameters of the RES_LIMITED restriction option.
- * client_limit is the number of hosts allowed per source net
- * client_limit_period is the number of seconds after which an entry
- * is no longer considered for client limit determination
*/
-u_long client_limit;
-u_long client_limit_period;
+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)
+ * 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 list entries.
+ * Our initial allocation of lists entries.
*/
static struct restrictlist resinit[INITRESLIST];
+static struct restrictlist6 resinit6[INITRESLIST];
/*
* init_restrict - initialize the restriction data structures
@@ -90,31 +108,35 @@ void
init_restrict(void)
{
register int i;
- char bp[80];
/*
* 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.
+ * 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
@@ -122,19 +144,12 @@ init_restrict(void)
res_calls = 0;
res_found = 0;
res_not_found = 0;
- /* res_timereset = 0; */
/*
* set default values for RES_LIMIT functionality
*/
- client_limit = 3;
- client_limit_period = 3600;
res_limited_refcnt = 0;
-
- sprintf(bp, "client_limit=%ld", client_limit);
- set_sys_var(bp, strlen(bp)+1, RO);
- sprintf(bp, "client_limit_period=%ld", client_limit_period);
- set_sys_var(bp, strlen(bp)+1, RO);
+ res_limited_refcnt6 = 0;
}
@@ -143,161 +158,131 @@ init_restrict(void)
*/
int
restrictions(
- struct sockaddr_in *srcadr
+ struct sockaddr_storage *srcadr
)
{
- register struct restrictlist *rl;
- register struct restrictlist *match;
- register u_int32 hostaddr;
- register int isntpport;
+ 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++;
- /*
- * 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(ntohl(srcadr->sin_addr.s_addr)))
- return (int)RES_IGNORE;
+ 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);
- /*
- * 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++;
-
- /*
- * The following implements limiting the number of clients
- * accepted from a given network. The notion of "same network"
- * is determined by the mask and addr fields of the restrict
- * list entry. The monitor mechanism has to be enabled for
- * collecting info on current clients.
- *
- * The policy is as follows:
- * - take the list of clients recorded
- * from the given "network" seen within the last
- * client_limit_period seconds
- * - if there are at most client_limit entries:
- * --> access allowed
- * - otherwise sort by time first seen
- * - current client among the first client_limit seen
- * hosts?
- * if yes: access allowed
- * else: eccess denied
- */
- if (match->flags & RES_LIMITED) {
- int lcnt;
- struct mon_data *md, *this_client;
-
-#ifdef DEBUG
- if (debug > 2)
- printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n",
- client_limit, client_limit_period,
- (u_long)netof(hostaddr));
-#endif /*DEBUG*/
- if (mon_enabled == MON_OFF) {
-#ifdef DEBUG
- if (debug > 4)
- printf("no limit - monitoring is off\n");
-#endif
- return (int)(match->flags & ~RES_LIMITED);
- }
+ /*
+ * 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;
/*
- * How nice, MRU list provides our current client as the
- * first entry in the list.
- * Monitoring was verified to be active above, thus we
- * know an entry for our client must exist, or some
- * brain dead set the memory limit for mon entries to ZERO!!!
+ * Set match to first entry, which is default entry.
+ * Work our way down from there.
*/
- this_client = mon_mru_list.mru_next;
-
- for (md = mon_fifo_list.fifo_next,lcnt = 0;
- md != &mon_fifo_list;
- md = md->fifo_next) {
- if ((current_time - md->lasttime)
- > client_limit_period) {
-#ifdef DEBUG
- if (debug > 5)
- printf("checking: %s: ignore: too old: %ld\n",
- numtoa(md->rmtadr),
- current_time - md->lasttime);
-#endif
- continue;
- }
- if (md->mode == MODE_BROADCAST ||
- md->mode == MODE_CONTROL ||
- md->mode == MODE_PRIVATE) {
-#ifdef DEBUG
- if (debug > 5)
- printf("checking: %s: ignore mode %d\n",
- numtoa(md->rmtadr),
- md->mode);
-#endif
- continue;
+ 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;
}
- if (netof(md->rmtadr) !=
- netof(hostaddr)) {
-#ifdef DEBUG
- if (debug > 5)
- printf("checking: %s: different net 0x%lX\n",
- numtoa(md->rmtadr),
- (u_long)netof(md->rmtadr));
-#endif
- continue;
- }
- lcnt++;
- if (lcnt > (int) client_limit ||
- md->rmtadr == hostaddr) {
-#ifdef DEBUG
- if (debug > 5)
- printf("considering %s: found host\n",
- numtoa(md->rmtadr));
-#endif
- break;
- }
-#ifdef DEBUG
- else {
- if (debug > 5)
- printf("considering %s: same net\n",
- numtoa(md->rmtadr));
- }
-#endif
+ 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;
+ }
}
-#ifdef DEBUG
- if (debug > 4)
- printf("this one is rank %d in list, limit is %lu: %s\n",
- lcnt, client_limit,
- (lcnt <= (int) client_limit) ? "ALLOW" : "REJECT");
-#endif
- if (lcnt <= (int) client_limit) {
- this_client->lastdrop = 0;
- return (int)(match->flags & ~RES_LIMITED);
- } else {
- this_client->lastdrop = current_time;
- }
+ 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 (int)match->flags;
+ return (flags);
}
@@ -307,61 +292,112 @@ restrictions(
void
hack_restrict(
int op,
- struct sockaddr_in *resaddr,
- struct sockaddr_in *resmask,
+ struct sockaddr_storage *resaddr,
+ struct sockaddr_storage *resmask,
int mflags,
int flags
)
{
- register u_int32 addr;
- register u_int32 mask;
- register struct restrictlist *rl;
- register struct restrictlist *rlprev;
- int i;
-
- /*
- * Get address and mask in host byte order
- */
- addr = SRCADR(resaddr);
- mask = SRCADR(resmask);
- addr &= mask; /* make sure low bits are zero */
+ 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 == htonl(INADDR_ANY)) {
- 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; /* exact match */
- if (!(mflags & RESM_NTPONLY)) {
- /*
- * No flag fits before flag
- */
+ /*
+ * 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;
}
- /* continue on */
- } else if (rl->mask > mask) {
- rl = 0;
+ }
+ 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;
}
- rlprev = rl;
- rl = rl->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
@@ -372,89 +408,179 @@ hack_restrict(
/*
* Switch based on operation
*/
- 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++;
+ 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;
}
- numresfree = INCRESLIST;
- }
- rl = resfree;
- resfree = rl->next;
- numresfree--;
+ rl = resfree;
+ resfree = rl->next;
+ numresfree--;
- rl->addr = addr;
- rl->mask = mask;
- rl->mflags = (u_short)mflags;
+ 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); /* ensure data gets collected */
- }
- 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->next = rlprev->next;
+ rlprev->next = rl;
+ restrictcount++;
}
- rl->flags &= (u_short)~flags;
- }
- break;
+ 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);
+ 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++;
}
- memset((char *)rl, 0, sizeof(struct restrictlist));
+ break;
- rl->next = resfree;
- resfree = rl;
- numresfree++;
+ default:
+ break;
}
- 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:
- /* Oh, well */
- break;
+ default:
+ break;
+ }
}
-
- /* done! */
}
diff --git a/contrib/ntp/ntpd/ntp_timer.c b/contrib/ntp/ntpd/ntp_timer.c
index c2b1d72..6f0f18b 100644
--- a/contrib/ntp/ntpd/ntp_timer.c
+++ b/contrib/ntp/ntpd/ntp_timer.c
@@ -23,10 +23,6 @@
# include "ntp_timer.h"
#endif
-#ifdef PUBKEY
-#include "ntp_crypto.h"
-#endif /* PUBKEY */
-
/*
* These routines provide support for the event timer. The timer is
* implemented by an interrupt routine which sets a flag once every
@@ -50,10 +46,10 @@ 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 AUTOKEY
+#ifdef OPENSSL
static u_long revoke_timer; /* keys revoke timer */
-u_long sys_revoke = 1 << KEY_REVOKE; /* keys revoke timeout */
-#endif /* AUTOKEY */
+u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
+#endif /* OPENSSL */
/*
* Statistics counter for the interested.
@@ -83,6 +79,57 @@ static HANDLE WaitableTimerHandle = NULL;
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
@@ -90,20 +137,10 @@ static RETSIGTYPE alarming P((int));
void
init_timer(void)
{
-#if !defined(VMS)
-# if !defined SYS_WINNT || defined(SYS_CYGWIN32)
-# ifndef HAVE_TIMER_SETTIME
- struct itimerval itimer;
-# else
- static timer_t ntpd_timerid; /* should be global if we ever want */
- /* to kill timer without rebooting ... */
- struct itimerspec itimer;
-# endif /* HAVE_TIMER_SETTIME */
-# else /* SYS_WINNT */
+# if defined SYS_WINNT & !defined(SYS_CYGWIN32)
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
# endif /* SYS_WINNT */
-#endif /* !VMS */
/*
* Initialize...
@@ -218,6 +255,9 @@ 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);
@@ -228,6 +268,7 @@ timer(void)
if (adjust_timer <= current_time) {
adjust_timer += 1;
adj_host_clock();
+ kod_proto();
}
/*
@@ -269,20 +310,21 @@ timer(void)
huffpuff();
}
-#ifdef AUTOKEY
+#ifdef OPENSSL
/*
* Garbage collect old keys and generate new private value
*/
if (revoke_timer <= current_time) {
- revoke_timer += sys_revoke;
+ 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("key expire: at %lu next %lu\n",
- current_time, revoke_timer);
+ printf("timer: %s\n", statstr);
#endif
}
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
/*
* Finally, call the hourly routine.
diff --git a/contrib/ntp/ntpd/ntp_util.c b/contrib/ntp/ntpd/ntp_util.c
index f86e930..135f9b3 100644
--- a/contrib/ntp/ntpd/ntp_util.c
+++ b/contrib/ntp/ntpd/ntp_util.c
@@ -39,11 +39,10 @@
/*
* 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.
+ * 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
*/
@@ -76,6 +75,10 @@ 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
@@ -97,6 +100,11 @@ init_util(void)
#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);
@@ -133,11 +141,34 @@ init_util(void)
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 */
}
@@ -183,27 +214,27 @@ hourly_stats(void)
#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.
+ * 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
+ /*
+ * (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.
+ * 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 */
+ prio_set = 1; /* overdrive */
#endif /* VMS */
#ifdef HAVE_GETCLOCK
(void) getclock(TIMEOFDAY, &ts);
@@ -212,22 +243,23 @@ hourly_stats(void)
#else /* not HAVE_GETCLOCK */
GETTIMEOFDAY(&tv,(struct timezone *)NULL);
#endif /* not HAVE_GETCLOCK */
- if (ntp_set_tod(&tv,(struct timezone *)NULL) != 0)
- {
+ 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 */
+ 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);
+ 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",
@@ -238,7 +270,7 @@ hourly_stats(void)
(void)fclose(fp);
/* atomic */
#ifdef SYS_WINNT
- (void) unlink(stats_drift_file); /* rename semantics differ under NT */
+ (void) _unlink(stats_drift_file); /* rename semantics differ under NT */
#endif /* SYS_WINNT */
#ifndef NO_RENAME
@@ -281,14 +313,14 @@ stats_config(
double old_drift;
int len;
- /* Expand environment strings under Windows NT, since the command
- * interpreter doesn't do this, the program must.
+ /*
+ * 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))
- {
+ if (!ExpandEnvironmentStrings(invalue, newvalue, MAX_PATH)) {
switch(item) {
case STATS_FREQ_FILE:
strcpy(parameter,"STATS_FREQ_FILE");
@@ -307,15 +339,13 @@ stats_config(
msyslog(LOG_ERR,
"ExpandEnvironmentStrings(%s) failed: %m\n", parameter);
- }
- else
+ } else {
value = newvalue;
+ }
#else
value = invalue;
#endif /* SYS_WINNT */
-
-
switch(item) {
case STATS_FREQ_FILE:
if (stats_drift_file != 0) {
@@ -330,48 +360,41 @@ stats_config(
stats_drift_file = (char*)emalloc((u_int)(len + 1));
#if !defined(VMS)
- stats_temp_file = (char*)emalloc((u_int)(len + sizeof(".TEMP")));
+ stats_temp_file = (char*)emalloc((u_int)(len +
+ sizeof(".TEMP")));
#else
- stats_temp_file = (char*)emalloc((u_int)(len + sizeof("-TEMP")));
+ 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"));
+ memmove(stats_temp_file + len, ".TEMP",
+ sizeof(".TEMP"));
#else
- memmove(stats_temp_file + len, "-TEMP", sizeof("-TEMP"));
+ memmove(stats_temp_file + len, "-TEMP",
+ sizeof("-TEMP"));
#endif /* VMS */
/*
- * Open drift file and read frequency
+ * 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, "Un-parsable frequency in %s",
+ msyslog(LOG_ERR, "Frequency format error in %s",
stats_drift_file);
- (void) fclose(fp);
+ loop_config(LOOP_DRIFTCOMP, 1e9);
+ fclose(fp);
break;
}
- (void) fclose(fp);
- if (
-#ifdef HAVE_FINITE
- !finite(old_drift)
-#else /* not HAVE_FINITE */
-# ifdef HAVE_ISFINITE
- !isfinite(old_drift)
-# else /* not HAVE_ISFINITE */
- 0
-# endif /* not HAVE_ISFINITE */
-#endif /* not HAVE_FINITE */
- || (fabs(old_drift) > (NTP_MAXFREQ * 1e6))) {
- msyslog(LOG_ERR, "invalid frequency (%f) in %s",
- old_drift, stats_drift_file);
- old_drift = 0.0;
- }
- msyslog(LOG_INFO, "frequency initialized %.3f from %s",
- old_drift, stats_drift_file);
+ fclose(fp);
+ msyslog(LOG_INFO,
+ "frequency initialized %.3f PPM from %s",
+ old_drift, stats_drift_file);
loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
break;
@@ -409,6 +432,20 @@ stats_config(
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;
@@ -442,38 +479,28 @@ stats_config(
*/
void
record_peer_stats(
- struct sockaddr_in *addr,
- int status,
- double offset,
- double delay,
- double dispersion,
- double skew
+ struct sockaddr_storage *addr,
+ int status,
+ double offset,
+ double delay,
+ double dispersion,
+ double skew
)
{
- struct timeval tv;
-#ifdef HAVE_GETCLOCK
- struct timespec ts;
-#endif
- u_long day, sec, msec;
+ l_fp now;
+ u_long day;
if (!stats_control)
return;
-#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 */
- day = tv.tv_sec / 86400 + MJD_1970;
- sec = tv.tv_sec % 86400;
- msec = tv.tv_usec / 1000;
- filegen_setup(&peerstats, (u_long)(tv.tv_sec + JAN_1970));
+ 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 %lu.%03lu %s %x %.9f %.9f %.9f %.9f\n",
- day, sec, msec, ntoa(addr), status, offset,
+ "%lu %s %s %x %.9f %.9f %.9f %.9f\n",
+ day, ulfptoa(&now, 3), stoa(addr), status, offset,
delay, dispersion, skew);
fflush(peerstats.fp);
}
@@ -490,37 +517,27 @@ record_peer_stats(
*/
void
record_loop_stats(
- double offset,
- double freq,
- double jitter,
- double stability,
- int poll
+ double offset,
+ double freq,
+ double jitter,
+ double stability,
+ int spoll
)
{
- struct timeval tv;
-#ifdef HAVE_GETCLOCK
- struct timespec ts;
-#endif
- u_long day, sec, msec;
+ l_fp now;
+ u_long day;
if (!stats_control)
return;
-#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 */
- day = tv.tv_sec / 86400 + MJD_1970;
- sec = tv.tv_sec % 86400;
- msec = tv.tv_usec / 1000;
- filegen_setup(&loopstats, (u_long)(tv.tv_sec + JAN_1970));
+ 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 %lu.%03lu %.9f %.6f %.9f %.6f %d\n",
- day, sec, msec, offset, freq * 1e6, jitter,
- stability * 1e6, poll);
+ 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);
}
}
@@ -536,33 +553,23 @@ record_loop_stats(
*/
void
record_clock_stats(
- struct sockaddr_in *addr,
+ struct sockaddr_storage *addr,
const char *text
)
{
- struct timeval tv;
-#ifdef HAVE_GETCLOCK
- struct timespec ts;
-#endif
- u_long day, sec, msec;
+ l_fp now;
+ u_long day;
if (!stats_control)
return;
-#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 */
- day = tv.tv_sec / 86400 + MJD_1970;
- sec = tv.tv_sec % 86400;
- msec = tv.tv_usec / 1000;
- filegen_setup(&clockstats, (u_long)(tv.tv_sec + JAN_1970));
+ 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 %lu.%03lu %s %s\n",
- day, sec, msec, ntoa(addr), text);
+ fprintf(clockstats.fp, "%lu %s %s %s\n",
+ day, ulfptoa(&now, 3), stoa(addr), text);
fflush(clockstats.fp);
}
}
@@ -579,43 +586,116 @@ record_clock_stats(
*/
void
record_raw_stats(
- struct sockaddr_in *srcadr,
- struct sockaddr_in *dstadr,
- l_fp *t1,
- l_fp *t2,
- l_fp *t3,
- l_fp *t4
+ struct sockaddr_storage *srcadr,
+ struct sockaddr_storage *dstadr,
+ l_fp *t1,
+ l_fp *t2,
+ l_fp *t3,
+ l_fp *t4
)
{
- struct timeval tv;
-#ifdef HAVE_GETCLOCK
- struct timespec ts;
-#endif
- u_long day, sec, msec;
+ l_fp now;
+ u_long day;
if (!stats_control)
return;
-#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 */
- day = tv.tv_sec / 86400 + MJD_1970;
- sec = tv.tv_sec % 86400;
- msec = tv.tv_usec / 1000;
- filegen_setup(&rawstats, (u_long)(tv.tv_sec + JAN_1970));
+ 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 %lu.%03lu %s %s %s %s %s %s\n",
- day, sec, msec, ntoa(srcadr), ntoa(dstadr),
+ 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
*/
@@ -667,3 +747,51 @@ 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
index 1b80560..0b05253 100644
--- a/contrib/ntp/ntpd/ntpd.c
+++ b/contrib/ntp/ntpd/ntpd.c
@@ -11,6 +11,10 @@
#include "ntp_io.h"
#include "ntp_stdlib.h"
+#ifdef SIM
+#include "ntpsim.h"
+#endif
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -40,6 +44,7 @@
# include <process.h>
# include <io.h>
# include "../libntp/log.h"
+# include <clockstuff.h>
# include <crtdbg.h>
#endif /* SYS_WINNT */
#if defined(HAVE_RTPRIO)
@@ -99,9 +104,11 @@
# include <sys/ci/ciioctl.h>
#endif
-#ifdef PUBKEY
-#include "ntp_crypto.h"
-#endif /* PUBKEY */
+#ifdef HAVE_CLOCKCTL
+# include <ctype.h>
+# include <grp.h>
+# include <pwd.h>
+#endif
/*
* Signals we catch for debugging. If not debugging we ignore them.
@@ -123,11 +130,13 @@
/* 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 */
/*
@@ -146,10 +155,26 @@ int priority_done = 2; /* 0 - Set priority */
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.
@@ -176,8 +201,10 @@ 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 */
@@ -185,7 +212,16 @@ static RETSIGTYPE no_debug P((int));
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
@@ -198,6 +234,7 @@ main(
return ntpdmain(argc, argv);
}
#endif
+#endif /* SIM */
#ifdef _AIX
/*
@@ -335,10 +372,6 @@ ntpdmain(
{
l_fp now;
char *cp;
-#ifdef AUTOKEY
- u_int n;
- char hostname[MAXFILENAME];
-#endif /* AUTOKEY */
struct recvbuf *rbuflist;
struct recvbuf *rbuf;
#ifdef _AIX /* HMS: ifdef SIGDANGER? */
@@ -384,9 +417,17 @@ ntpdmain(
#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));
@@ -414,12 +455,12 @@ ntpdmain(
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 defined(F_CLOSEM)
if (fcntl(0, F_CLOSEM, 0) == -1)
msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
#else /* not F_CLOSEM */
@@ -484,16 +525,22 @@ ntpdmain(
# else /* SYS_WINNT */
{
- SERVICE_TABLE_ENTRY dispatchTable[] = {
+ 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);
+ /* daemonize */
+ if (!StartServiceCtrlDispatcher(dispatchTable))
+ {
+ msyslog(LOG_ERR, "StartServiceCtrlDispatcher: %m");
+ ExitProcess(2);
+ }
+ }
+ else {
+ service_main(argc, argv);
+ return 0;
}
}
# endif /* SYS_WINNT */
@@ -520,15 +567,13 @@ service_main(
char *cp;
struct recvbuf *rbuflist;
struct recvbuf *rbuf;
-#ifdef AUTOKEY
- u_int n;
- char hostname[MAXFILENAME];
-#endif /* AUTOKEY */
- if(!debug)
+
+ if(!debug && NoWinService == FALSE)
{
/* register our service control handler */
- if (!(sshStatusHandle = RegisterServiceCtrlHandler( TEXT("NetworkTimeProtocol"),
- (LPHANDLER_FUNCTION)service_ctrl)))
+ sshStatusHandle = RegisterServiceCtrlHandler( TEXT("NetworkTimeProtocol"),
+ (LPHANDLER_FUNCTION)service_ctrl);
+ if(sshStatusHandle == 0)
{
msyslog(LOG_ERR, "RegisterServiceCtrlHandler failed: %m");
return;
@@ -567,7 +612,7 @@ service_main(
debug = 0; /* will be immediately re-initialized 8-( */
getstartup(argc, argv); /* startup configuration, catch logfile this time */
-#if !defined(SYS_WINNT) && !defined(VMS)
+#if !defined(VMS)
# ifndef LOG_DAEMON
openlog(cp, LOG_PID);
@@ -624,6 +669,25 @@ service_main(
#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
*/
@@ -741,15 +805,9 @@ service_main(
debug = 0;
#endif
getconfig(argc, argv);
-#ifdef AUTOKEY
- gethostname(hostname, MAXFILENAME);
- n = strlen(hostname) + 1;
- sys_hostname = emalloc(n);
- memcpy(sys_hostname, hostname, n);
-#ifdef PUBKEY
+#ifdef OPENSSL
crypto_setup();
-#endif /* PUBKEY */
-#endif /* AUTOKEY */
+#endif /* OPENSSL */
initializing = 0;
#if defined(SYS_WINNT) && !defined(NODETACH)
@@ -757,23 +815,83 @@ service_main(
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;
+ 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
*/
@@ -797,10 +915,10 @@ service_main(
#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();
+ WaitHandles[2] = get_io_event();
for (;;) {
- DWORD Index = WaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, FALSE, 1000, MWMO_ALERTABLE);
+ DWORD Index = WaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, FALSE, 1000, TRUE);
switch (Index) {
case WAIT_OBJECT_0 + 0 : /* exit request */
exit(0);
@@ -819,30 +937,16 @@ service_main(
# endif
break;
-# if 1
- /*
- * FIXME: According to the documentation for WaitForMultipleObjectsEx
- * this is not possible. This may be a vestigial from when this was
- * MsgWaitForMultipleObjects, maybe it should be removed?
- */
- case WAIT_OBJECT_0 + 3 : /* windows message */
- {
- MSG msg;
- while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
- {
- if ( msg.message == WM_QUIT )
- {
- exit( 0 );
- }
- DispatchMessage( &msg );
- }
- }
- break;
-# endif
-
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 */
@@ -900,9 +1004,10 @@ service_main(
}
else if (nfound == -1 && errno != EINTR)
msyslog(LOG_ERR, "select() error: %m");
- else if (debug > 2) {
+# ifdef DEBUG
+ else if (debug > 2)
msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
- }
+# endif /* DEBUG */
# else /* HAVE_SIGNALED_IO */
wait_for_signal();
@@ -950,8 +1055,12 @@ service_main(
* Go around again
*/
}
+#ifndef SYS_WINNT
exit(1); /* unreachable */
+#endif
+#ifndef SYS_WINNT
return 1; /* DEC OSF cc braindamage */
+#endif
}
@@ -984,6 +1093,7 @@ finish(
#ifdef DEBUG
+#ifndef SYS_WINNT
/*
* moredebug - increase debugging verbosity
*/
@@ -1019,8 +1129,9 @@ lessdebug(
}
errno = saved_errno;
}
+#endif
#else /* not DEBUG */
-/*
+#ifndef SYS_WINNT/*
* no_debug - We don't do the debug here.
*/
static RETSIGTYPE
@@ -1033,6 +1144,7 @@ no_debug(
msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig);
errno = saved_errno;
}
+#endif /* not SYS_WINNT */
#endif /* not DEBUG */
#ifdef SYS_WINNT
diff --git a/contrib/ntp/ntpd/ntpsim.c b/contrib/ntp/ntpd/ntpsim.c
new file mode 100644
index 0000000..3fbae17
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpsim.c
@@ -0,0 +1,368 @@
+/*
+ * 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
index efdf536..d26ceed 100644
--- a/contrib/ntp/ntpd/refclock_acts.c
+++ b/contrib/ntp/ntpd/refclock_acts.c
@@ -733,8 +733,9 @@ acts_receive (
* waiting for carrier loss or long-space disconnect, but we do
* these clumsy things anyway.
*/
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ 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);
@@ -800,7 +801,7 @@ acts_timeout (
acts_disc(peer);
return;
}
- switch (peer->ttlmax) {
+ switch (peer->ttl) {
/*
* In manual mode the ACTS calling program is activated
diff --git a/contrib/ntp/ntpd/refclock_arbiter.c b/contrib/ntp/ntpd/refclock_arbiter.c
index cdbe2ee..cf5f92f 100644
--- a/contrib/ntp/ntpd/refclock_arbiter.c
+++ b/contrib/ntp/ntpd/refclock_arbiter.c
@@ -419,8 +419,9 @@ arb_poll(
refclock_report(peer, CEVNT_TIMEOUT);
return;
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
}
#else
diff --git a/contrib/ntp/ntpd/refclock_arc.c b/contrib/ntp/ntpd/refclock_arc.c
index c771f47..f556da6 100644
--- a/contrib/ntp/ntpd/refclock_arc.c
+++ b/contrib/ntp/ntpd/refclock_arc.c
@@ -1,5 +1,5 @@
/*
- * refclock_arc - clock driver for ARCRON MSF receivers
+ * refclock_arc - clock driver for ARCRON MSF/DCF/WWVB receivers
*/
#ifdef HAVE_CONFIG_H
@@ -7,9 +7,11 @@
#endif
#if defined(REFCLOCK) && defined(CLOCK_ARCRON_MSF)
-static const char arc_version[] = { "V1.1 1997/06/23" };
+static const char arc_version[] = { "V1.3 2003/02/21" };
-#undef ARCRON_DEBUG /* Define only while in development... */
+/* 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. */
@@ -28,6 +30,9 @@ static const char arc_version[] = { "V1.1 1997/06/23" };
/*
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.
@@ -42,6 +47,33 @@ 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.
@@ -306,6 +338,7 @@ 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>
@@ -324,7 +357,7 @@ Also note h<cr> command which starts a resync to MSF signal.
#endif
/*
- * This driver supports the ARCRON MSF Radio Controlled Clock
+ * This driver supports the ARCRON MSF/DCF/WWVB Radio Controlled Clock
*/
/*
@@ -335,9 +368,16 @@ Also note h<cr> command which starts a resync to MSF signal.
#define PRECISION (-4) /* Precision (~63 ms). */
#define HIGHPRECISION (-5) /* If things are going well... */
#define REFID "MSFa" /* Reference ID. */
-#define DESCRIPTION "ARCRON MSF Receiver"
+#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"
-#define NSAMPLESLONG 8 /* Stages of long filter. */
+#ifdef PRE_NTP420
+#define MODE ttlmax
+#else
+#define MODE ttl
+#endif
#define LENARC 16 /* Format `o' timecode length. */
@@ -405,22 +445,6 @@ Also note h<cr> command which starts a resync to MSF signal.
#endif
};
-/* Chose filter length dependent on fudge flag 4. */
-#define CHOSENSAMPLES(pp) \
-(((pp)->sloppyclockflag & CLK_FLAG4) ? NSAMPLESLONG : NSAMPLES)
- /*
-Chose how many filter samples to keep. Several factors are in play.
-
- 1) Discard at least one sample to allow a spike value to be
- discarded.
-
- 2) Discard about 1-in-8 to 1-in-30 samples to handle spikes.
-
- 3) Keep an odd number of samples to avoid median value being biased
- high or low.
-*/
-#define NKEEP(pp) ((CHOSENSAMPLES(pp) - 1 - (CHOSENSAMPLES(pp)>>3)) | 1)
-
#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
@@ -454,6 +478,7 @@ struct arcunit {
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. */
@@ -463,6 +488,7 @@ struct arcunit {
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.
@@ -522,18 +548,16 @@ struct refclock refclock_arc = {
/* Queue us up for the next tick. */
#define ENQUEUE(up) \
do { \
- if((up)->ev.next != 0) { break; } /* WHOOPS! */ \
- peer->nextdate = current_time + QUEUETICK; \
+ peer->nextaction = current_time + QUEUETICK; \
} while(0)
-#if 0
-/* Placeholder event handler---does nothing safely---soaks up lose tick. */
+/* Placeholder event handler---does nothing safely---soaks up loose tick. */
static void
dummy_event_handler(
struct peer *peer
)
{
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug) { printf("arc: dummy_event_handler() called.\n"); }
#endif
}
@@ -558,7 +582,7 @@ arc_event_handler(
register struct arcunit *up = (struct arcunit *)pp->unitptr;
int i;
char c;
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug > 2) { printf("arc: arc_event_handler() called.\n"); }
#endif
@@ -572,12 +596,13 @@ arc_event_handler(
if(write(pp->io.fd, &c, 1) != 1) {
msyslog(LOG_NOTICE, "ARCRON: write to fd %d failed", pp->io.fd);
}
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
else if(debug) { printf("arc: sent `%2.2x', fd %d.\n", c, pp->io.fd); }
#endif
}
+
+ ENQUEUE(up);
}
-#endif /* 0 */
/*
* arc_start - open the devices and initialize data for processing
@@ -597,7 +622,7 @@ arc_start(
#endif
msyslog(LOG_NOTICE, "ARCRON: %s: opening unit %d", arc_version, unit);
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug) {
printf("arc: %s: attempt to open unit %d.\n", arc_version, unit);
}
@@ -612,7 +637,7 @@ arc_start(
(void)sprintf(device, DEVICE, unit);
if (!(fd = refclock_open(device, SPEED, LDISC_CLK)))
return(0);
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug) { printf("arc: unit %d using open().\n", unit); }
#endif
fd = open(device, OPEN_FLAGS);
@@ -624,9 +649,9 @@ arc_start(
}
fcntl(fd, F_SETFL, 0); /* clear the descriptor flags */
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug)
- { printf("Opened RS232 port with file descriptor %d.\n", fd); }
+ { printf("arc: opened RS232 port with file descriptor %d.\n", fd); }
#endif
#ifdef HAVE_TERMIOS
@@ -667,7 +692,27 @@ arc_start(
peer->precision = PRECISION;
peer->stratum = 2; /* Default to stratum 2 not 0. */
pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
+ 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;
@@ -686,6 +731,11 @@ arc_start(
#else
up->quality = MIN_CLOCK_QUALITY;/* Don't trust the clock yet. */
#endif
+
+ peer->action = arc_event_handler;
+
+ ENQUEUE(up);
+
return(1);
}
@@ -702,6 +752,8 @@ arc_shutdown(
register struct arcunit *up;
struct refclockproc *pp;
+ peer->action = dummy_event_handler;
+
pp = peer->procptr;
up = (struct arcunit *)pp->unitptr;
io_closeclock(&pp->io);
@@ -740,11 +792,11 @@ send_slow(
int sl = strlen(s);
int spaceleft = space_left(up);
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug > 1) { printf("arc: spaceleft = %d.\n", spaceleft); }
#endif
if(spaceleft < sl) { /* Should not normally happen... */
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)",
sl, spaceleft);
#endif
@@ -776,8 +828,11 @@ arc_receive(
struct refclockproc *pp;
struct peer *peer;
char c;
- int i, n, wday, month, bst, status;
+ 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
@@ -857,7 +912,7 @@ arc_receive(
handle for tty_clk or somesuch kernel timestamper.
*/
if(arc_last_offset > LENARC) {
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug) {
printf("arc: input code too long (%d cf %d); rejected.\n",
arc_last_offset, LENARC);
@@ -869,7 +924,7 @@ arc_receive(
}
L_SUBUF(&timestamp, charoffsets[arc_last_offset]);
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug > 1) {
printf(
"arc: %s%d char(s) rcvd, the last for lastcode[%d]; -%sms offset applied.\n",
@@ -898,7 +953,7 @@ arc_receive(
L_ISGEQ(&(up->lastrec), &timestamp))
#endif
{
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug > 1) {
printf("arc: system timestamp captured.\n");
#ifdef ARCRON_MULTIPLE_SAMPLES
@@ -922,7 +977,7 @@ arc_receive(
/* eg on receipt of the \r coming in on its own after the */
/* timecode. */
if(pp->lencode >= LENARC) {
-#ifdef ARCRON_DEBUG
+#ifdef DEBUG
if(debug && (rbufp->recv_buffer[0] != '\r'))
{ printf("arc: rubbish in pp->a_lastcode[].\n"); }
#endif
@@ -947,11 +1002,12 @@ arc_receive(
*/
if((c == 'o') && (pp->lencode == 1)) {
L_CLR(&(up->lastrec));
-#ifdef ARCRON_DEBUG
+#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') {
@@ -963,17 +1019,31 @@ arc_receive(
if(((q & 0x70) != 0x30) || ((q & 0xf) > MAX_CLOCK_QUALITY) ||
((r & 0x70) != 0x30)) {
/* Badly formatted response. */
-#ifdef ARCRON_DEBUG
+#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. */
- up->quality = (q & 0xf);
+ 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.\n", up->quality); }
+ 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)
{
@@ -987,6 +1057,9 @@ arc_receive(
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. */
@@ -1011,13 +1084,13 @@ arc_receive(
/* WE HAVE NOW COLLECTED ONE TIMESTAMP (phew)... */
-#ifdef ARCRON_DEBUG
+#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 ARCRON_DEBUG
+#ifdef DEBUG
if(debug) { printf("arc: FAILED TO GET SYSTEM TIMESTAMP\n"); }
#endif
pp->lencode = 0;
@@ -1033,22 +1106,26 @@ arc_receive(
pp->a_lastcode[pp->lencode] = ((up->quality == QUALITY_UNKNOWN) ?
'6' : ('0' + up->quality));
pp->a_lastcode[pp->lencode + 1] = '\0'; /* Terminate for printf(). */
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+#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, &bst, &status);
+ &wday, &pp->day, &month, &pp->year, &flags, &status);
/* Validate format and numbers. */
if(n != 9) {
-#ifdef ARCRON_DEBUG
+#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;
}
@@ -1064,15 +1141,21 @@ arc_receive(
(month < 1) || (month > 12) ||
(pp->year < 0) || (pp->year > 99)) {
/* Data out of range. */
+ pp->lencode = 0;
refclock_report(peer, CEVNT_BADREPLY);
return;
}
- /* Check that BST/UTC bits are the complement of one another. */
- if(!(bst & 2) == !(bst & 4)) {
- 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! */
@@ -1094,7 +1177,7 @@ arc_receive(
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, bst, status);
+ pp->day, month, pp->year, flags, status);
}
#endif
@@ -1114,41 +1197,159 @@ arc_receive(
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;
- pp->day += moff[month - 1];
-
- if(isleap_4(pp->year) && month > 2) { pp->day++; } /* Y2KFixes */
+ 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;
+ }
+ }
+ }
+ }
- /* 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) {
- refclock_report(peer, CEVNT_BADTIME);
+ 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 clock signal quality is unknown, revert to default PRECISION...*/
- if(up->quality == QUALITY_UNKNOWN) { peer->precision = PRECISION; }
- /* ...else improve precision if flag3 is set... */
- else {
- peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ?
- HIGHPRECISION : PRECISION);
+ 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 ARCRON_DEBUG
+#ifdef DEBUG
msyslog(LOG_NOTICE, "ARCRON: flags enabled: %s%s%s%s",
((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."),
((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."),
@@ -1156,8 +1357,6 @@ arc_receive(
((pp->sloppyclockflag & CLK_FLAG4) ? "4" : "."));
/* Note effects of flags changing... */
if(debug) {
- printf("arc: CHOSENSAMPLES(pp) = %d.\n", CHOSENSAMPLES(pp));
- printf("arc: NKEEP(pp) = %d.\n", NKEEP(pp));
printf("arc: PRECISION = %d.\n", peer->precision);
}
#endif
@@ -1185,9 +1384,11 @@ arc_receive(
#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);
}
@@ -1208,9 +1409,12 @@ request_time(
if(debug) { printf("arc: unit %d: requesting time.\n", unit); }
#endif
if (!send_slow(up, pp->io.fd, "o\r")) {
-#ifdef ARCRON_DEBUG
- msyslog(LOG_NOTICE, "ARCRON: unit %d: problem sending", unit);
+#ifdef DEBUG
+ if (debug) {
+ printf("arc: unit %d: problem sending", unit);
+ }
#endif
+ pp->lencode = 0;
refclock_report(peer, CEVNT_FAULT);
return;
}
@@ -1232,8 +1436,10 @@ arc_poll(
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. */
@@ -1241,7 +1447,8 @@ arc_poll(
#endif
/* Resync if our next scheduled resync time is here or has passed. */
- resync_needed = (up->next_resync <= current_time);
+ resync_needed = ( !(pp->sloppyclockflag & CLK_FLAG2) &&
+ (up->next_resync <= current_time) );
#ifdef ARCRON_LEAPSECOND_KEEN
/*
@@ -1309,6 +1516,7 @@ arc_poll(
printf("arc: clock quality %d too poor.\n", up->quality);
}
#endif
+ pp->lencode = 0;
refclock_report(peer, CEVNT_FAULT);
return;
}
diff --git a/contrib/ntp/ntpd/refclock_as2201.c b/contrib/ntp/ntpd/refclock_as2201.c
index 516f7ad..f04d417b 100644
--- a/contrib/ntp/ntpd/refclock_as2201.c
+++ b/contrib/ntp/ntpd/refclock_as2201.c
@@ -299,12 +299,13 @@ as2201_receive(
/*
* Timecode format: "yy:ddd:hh:mm:ss.mmm"
*/
- if (sscanf(pp->a_lastcode, "%2d:%3d:%2d:%2d:%2d.%3d", &pp->year,
- &pp->day, &pp->hour, &pp->minute, &pp->second, &pp->msec)
+ 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).
diff --git a/contrib/ntp/ntpd/refclock_atom.c b/contrib/ntp/ntpd/refclock_atom.c
index 56f86b3..51153ae 100644
--- a/contrib/ntp/ntpd/refclock_atom.c
+++ b/contrib/ntp/ntpd/refclock_atom.c
@@ -1,3 +1,4 @@
+
/*
* refclock_atom - clock driver for 1-pps signals
*/
@@ -75,8 +76,6 @@
* Interface definitions
*/
#ifdef HAVE_PPSAPI
-extern int pps_assert; /* selects rising or falling edge */
-extern int pps_hardpps; /* enables the kernel PPS interface */
#define DEVICE "/dev/pps%d" /* device name and unit */
#endif /* HAVE_PPSAPI */
@@ -159,9 +158,9 @@ atom_start(
pp = peer->procptr;
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
+ pp->stratum = STRATUM_UNSPEC;
memcpy((char *)&pp->refid, REFID, 4);
peer->burst = ASTAGE;
- peer->stratum = STRATUM_UNSPEC;
#ifdef HAVE_PPSAPI
up = emalloc(sizeof(struct ppsunit));
memset(up, 0, sizeof(struct ppsunit));
@@ -194,7 +193,7 @@ atom_start(
"refclock_atom: time_pps_create failed: %m");
return (0);
}
- return (atom_ppsapi(peer, pps_assert, pps_hardpps));
+ return (atom_ppsapi(peer, 0, 0));
#else /* HAVE_PPSAPI */
return (1);
#endif /* HAVE_PPSAPI */
@@ -250,7 +249,7 @@ atom_ppsapi(
if (!up->pps_params.mode) {
msyslog(LOG_ERR,
"refclock_atom: invalid capture edge %d",
- pps_assert);
+ enb_clear);
return (0);
}
up->pps_params.mode |= PPS_TSFMT_TSPEC;
@@ -459,17 +458,17 @@ atom_poll(
* +-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.
+ * peer, unless overriden by a fudge command.
*/
if (peer->burst > 0)
return;
- peer->stratum = STRATUM_UNSPEC;
+ peer->leap = LEAP_NOTINSYNC;
if (pp->codeproc == pp->coderecv) {
refclock_report(peer, CEVNT_TIMEOUT);
peer->burst = ASTAGE;
return;
- } else if (!sys_prefer) {
+ } else if (sys_prefer == NULL) {
pp->codeproc = pp->coderecv;
peer->burst = ASTAGE;
return;
@@ -479,12 +478,17 @@ atom_poll(
peer->burst = ASTAGE;
return;
}
- peer->stratum = sys_prefer->stratum;
- if (peer->stratum <= 1)
+ 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 = peer->srcadr.sin_addr.s_addr;
- pp->leap = LEAP_NOWARNING;
+ peer->refid = addr2refid(&sys_prefer->srcadr);
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
peer->burst = ASTAGE;
}
diff --git a/contrib/ntp/ntpd/refclock_bancomm.c b/contrib/ntp/ntpd/refclock_bancomm.c
index a3debcb..a63be44 100644
--- a/contrib/ntp/ntpd/refclock_bancomm.c
+++ b/contrib/ntp/ntpd/refclock_bancomm.c
@@ -317,8 +317,9 @@ vme_poll(
refclock_report(peer, CEVNT_BADTIME);
return;
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
}
struct vmedate *
diff --git a/contrib/ntp/ntpd/refclock_chronolog.c b/contrib/ntp/ntpd/refclock_chronolog.c
index 9273a84..a1d131e 100644
--- a/contrib/ntp/ntpd/refclock_chronolog.c
+++ b/contrib/ntp/ntpd/refclock_chronolog.c
@@ -215,7 +215,6 @@ chronolog_receive(
* calls since it is transmitted a few seconds ahead of the
* timestamp.
*/
- pp->msec = 0;
got_good=0;
if (sscanf(pp->a_lastcode, "Y %d/%d/%d", &up->year,&up->month,&up->day))
{
@@ -293,8 +292,9 @@ chronolog_receive(
refclock_report(peer, CEVNT_BADTIME);
return;
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
up->lasthour = pp->hour;
}
diff --git a/contrib/ntp/ntpd/refclock_chu.c b/contrib/ntp/ntpd/refclock_chu.c
index b239ad6..e0c79e2 100644
--- a/contrib/ntp/ntpd/refclock_chu.c
+++ b/contrib/ntp/ntpd/refclock_chu.c
@@ -40,10 +40,10 @@
* change throughout the day and night.
*
* The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a Sun workstation running SunOS or
- * Solaris, 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.
+ * 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.
@@ -105,8 +105,8 @@
*
* 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 -d -d on the ntpd command
- * line), the driver produces one line for each burst in two formats
+ * 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
@@ -161,22 +161,22 @@
*
* 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. When the modem driver
- * is compiled, fudge flag3 enables the ppsclock line discipline. Fudge
- * flag4 causes the dubugging output described above to be recorded in
- * the clockstats file.
+ * be done conviently using the minimuf program.
*
- * 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 speaker volume must be set before the driver is started.
+ * 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 alwasy 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.
+ * 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
@@ -194,11 +194,13 @@
#define DEVICE "/dev/chu%d" /* device name and unit */
#define SPEED232 B300 /* UART speed (300 baud) */
#ifdef ICOM
-#define DWELL 5 /* minutes before qsy */
+#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
+#ifdef HAVE_AUDIO
/*
* Audio demodulator definitions
*/
@@ -207,11 +209,13 @@
#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 */
@@ -224,16 +228,19 @@
#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 PANIC (4 * 1440) /* panic restart */
+#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 */
+#define HEX_MISS 16 /* miss _ */
+#define HEX_SOFT 17 /* soft error * */
+#define HEX_HARD 18 /* hard error = */
/*
* Status bits (status)
@@ -246,8 +253,9 @@
#define AFORMAT 0x0020 /* invalid format A data */
#define DECODE 0x0040 /* invalid data decode */
#define STAMP 0x0080 /* too few timestamps */
-#define INYEAR 0x0100 /* valid B frame */
-#define INSYNC 0x0200 /* clock synchronized */
+#define AVALID 0x0100 /* valid A frame */
+#define BVALID 0x0200 /* valid B frame */
+#define INSYNC 0x0400 /* clock synchronized */
/*
* Alarm status bits (alarm)
@@ -264,6 +272,10 @@
#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 */
@@ -272,6 +284,19 @@ struct surv {
};
#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
*/
@@ -284,12 +309,13 @@ struct chuunit {
l_fp charstamp; /* character time as a l_fp */
int errflg; /* error flags */
int status; /* status bits */
- int bufptr; /* buffer index pointer */
- char ident[10]; /* transmitter frequency */
+ char ident[5]; /* station ID and channel */
#ifdef ICOM
int fd_icom; /* ICOM file descriptor */
- int chan; /* frequency identifier */
- int dwell; /* dwell minutes at current frequency */
+ int chan; /* data channel */
+ int achan; /* active channel */
+ int dwell; /* dwell cycle */
+ struct xmtr xmtr[NCHAN]; /* station metric */
#endif /* ICOM */
/*
@@ -300,7 +326,6 @@ struct chuunit {
int ndx; /* buffer start index */
int prevsec; /* previous burst second */
int burdist; /* burst distance */
- int mindist; /* minimum distance */
int syndist; /* sync distance */
int burstcnt; /* format A bursts this minute */
@@ -320,7 +345,7 @@ struct chuunit {
double comp[SIZE]; /* decompanding table */
int port; /* codec port */
int gain; /* codec gain */
- int bufcnt; /* samples in buffer */
+ int mongain; /* codec monitor gain */
int clipcnt; /* sample clip count */
int seccnt; /* second interval counter */
@@ -362,21 +387,30 @@ 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 int chu_major P((struct peer *));
+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_-=";
+static char hexchar[] = "0123456789abcdef_*=";
+
#ifdef ICOM
-static double qsy[NCHAN] = {3.33, 7.335, 14.67}; /* frequencies (MHz) */
+/*
+ * 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 */
/*
@@ -407,7 +441,6 @@ chu_start(
char device[20]; /* device name */
int fd; /* file descriptor */
#ifdef ICOM
- char tbuf[80]; /* trace buffer */
int temp;
#endif /* ICOM */
#ifdef HAVE_AUDIO
@@ -418,7 +451,7 @@ chu_start(
/*
* Open audio device.
*/
- fd_audio = audio_init(DEVICE_AUDIO);
+ fd_audio = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
#ifdef DEBUG
if (fd_audio > 0 && debug)
audio_show();
@@ -470,7 +503,8 @@ chu_start(
*/
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
+ strcpy(up->ident, "CHU");
+ memcpy(&peer->refid, up->ident, 4);
DTOLFP(CHAR, &up->charstamp);
#ifdef HAVE_AUDIO
@@ -493,15 +527,14 @@ chu_start(
}
DTOLFP(1. / SECOND, &up->tick);
#endif /* HAVE_AUDIO */
- strcpy(up->ident, "X");
#ifdef ICOM
temp = 0;
#ifdef DEBUG
if (debug > 1)
temp = P_TRACE;
#endif
- if (peer->ttlmax > 0) {
- if (peer->ttlmax & 0x80)
+ if (peer->ttl > 0) {
+ if (peer->ttl & 0x80)
up->fd_icom = icom_init("/dev/icom", B1200,
temp);
else
@@ -509,22 +542,17 @@ chu_start(
temp);
}
if (up->fd_icom > 0) {
- if (icom_freq(up->fd_icom, peer->ttlmax & 0x7f,
- qsy[up->chan]) < 0) {
+ if (chu_newchan(peer, 0) != 0) {
NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_ERR,
- "ICOM bus error; autotune disabled");
+ msyslog(LOG_NOTICE,
+ "icom: radio not found");
up->errflg = CEVNT_FAULT;
close(up->fd_icom);
up->fd_icom = 0;
} else {
- sprintf(up->ident, "%.1f", qsy[up->chan]);
- sprintf(tbuf, "chu: QSY to %s MHz", up->ident);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif
+ NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
+ msyslog(LOG_NOTICE,
+ "icom: autotune enabled");
}
}
#endif /* ICOM */
@@ -548,12 +576,16 @@ chu_shutdown(
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
*/
@@ -588,8 +620,8 @@ chu_receive(
#endif /* HAVE_AUDIO */
}
-#ifdef HAVE_AUDIO
+#ifdef HAVE_AUDIO
/*
* chu_audio_receive - receive data from the audio device
*/
@@ -604,10 +636,8 @@ chu_audio_receive(
double sample; /* codec sample */
u_char *dpt; /* buffer pointer */
+ int bufcnt; /* buffer counter */
l_fp ltemp; /* l_fp temp */
- int isneg; /* parity flag */
- double dtemp;
- int i, j;
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
@@ -617,13 +647,12 @@ chu_audio_receive(
* 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;
- up->bufcnt = rbufp->recv_length;
- DTOLFP(up->bufcnt * 1. / SECOND, &ltemp);
- L_SUB(&up->timestamp, &ltemp);
- dpt = (u_char *)&rbufp->recv_space;
- for (up->bufptr = 0; up->bufptr < up->bufcnt; up->bufptr++) {
- sample = up->comp[~*dpt & 0xff];
+ 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,
@@ -637,56 +666,30 @@ chu_audio_receive(
sample = -MAXSIG;
up->clipcnt++;
}
- up->seccnt = (up->seccnt + 1) % SECOND;
- if (up->seccnt == 0) {
- if (pp->sloppyclockflag & CLK_FLAG2)
- up->port = 2;
- else
- up->port = 1;
- chu_gain(peer);
- }
chu_rf(peer, sample);
+ L_ADD(&up->timestamp, &up->tick);
/*
- * During development, it is handy to have an audio
- * monitor that can be switched to various signals. This
- * code converts the linear signal left in up->monitor
- * to codec format. If we can get the grass out of this
- * thing and improve modem performance, this expensive
- * code will be permanently nixed.
+ * Once each second ride gain.
*/
- isneg = 0;
- dtemp = up->monitor;
- if (sample < 0) {
- isneg = 1;
- dtemp-= dtemp;
- }
- i = 0;
- j = OFFSET >> 1;
- while (j != 0) {
- if (dtemp > up->comp[i])
- i += j;
- else if (dtemp < up->comp[i])
- i -= j;
- else
- break;
- j >>= 1;
+ up->seccnt = (up->seccnt + 1) % SECOND;
+ if (up->seccnt == 0) {
+ pp->second = (pp->second + 1) % 60;
+ chu_gain(peer);
}
- if (isneg)
- *dpt = ~(i + OFFSET);
- else
- *dpt = ~i;
- dpt++;
- L_ADD(&up->timestamp, &up->tick);
}
-
+
/*
- * Squawk to the monitor speaker if enabled.
+ * 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)
- if (write(pp->io.fd, (u_char *)&rbufp->recv_space,
- (u_int)up->bufcnt) < 0)
- perror("chu:");
+ up->mongain = MONGAIN;
+ else
+ up->mongain = 0;
}
@@ -1068,13 +1071,13 @@ chu_b(
* 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.
+ * 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]);
+ sprintf(&tbuf[strlen(tbuf)], "%02x", up->cbuf[i]);
if (pp->sloppyclockflag & CLK_FLAG4)
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
@@ -1085,7 +1088,7 @@ chu_b(
up->status |= BFRAME;
return;
}
- up->status |= INYEAR;
+ up->status |= BVALID;
/*
* Convert the burst data to internal format. If this succeeds,
@@ -1201,6 +1204,7 @@ chu_a(
* 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;
@@ -1236,6 +1240,7 @@ chu_a(
up->decode[i][(up->cbuf[j] >> 4) & 0xf]++;
i++;
}
+ up->status |= AVALID;
up->burstcnt++;
}
@@ -1251,54 +1256,48 @@ chu_poll(
{
struct refclockproc *pp;
struct chuunit *up;
+ l_fp offset;
char synchar, qual, leapchar;
- int minset;
- int temp;
-#ifdef ICOM
- char tbuf[80]; /* trace buffer */
-#endif /* ICOM */
+ 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
+ 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.
+ * 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
- if (up->burstcnt > 2) {
- up->dwell = 0;
- } else if (up->dwell < DWELL) {
- up->dwell++;
- } else if (up->fd_icom > 0) {
- up->dwell = 0;
- up->chan = (up->chan + 1) % NCHAN;
- icom_freq(up->fd_icom, peer->ttlmax & 0x7f, qsy[up->chan]);
- sprintf(up->ident, "%.3f", qsy[up->chan]);
- sprintf(tbuf, "chu: QSY to %s MHz", up->ident);
- record_clock_stats(&peer->srcadr, tbuf);
-#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
-#endif
- }
+ chu_newchan(peer, 0);
#endif /* ICOM */
- if (up->burstcnt == 0)
return;
- temp = chu_major(peer);
- if (up->status & INYEAR)
- up->status |= INSYNC;
+ }
+ dtemp = chu_major(peer);
qual = 0;
if (up->status & (BFRAME | AFRAME))
qual |= SYNERR;
@@ -1308,6 +1307,8 @@ chu_poll(
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;
@@ -1324,34 +1325,45 @@ chu_poll(
#ifdef HAVE_AUDIO
if (up->fd_audio)
sprintf(pp->a_lastcode,
- "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %d %s %d %d %d %d",
+ "%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, up->tai, up->burstcnt,
- up->mindist, up->ntstamp);
+ minset, up->gain, up->ident, dtemp, up->ntstamp);
else
sprintf(pp->a_lastcode,
- "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %s %d %d %d %d",
+ "%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, up->tai, up->burstcnt,
- up->mindist, up->ntstamp);
+ minset, up->ident, dtemp, up->ntstamp);
#else
sprintf(pp->a_lastcode,
- "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %s %d %d %d %d",
+ "%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, up->tai, up->burstcnt, up->mindist, up->ntstamp);
+ pp->second, leapchar, up->dst, up->dut, minset, up->ident,
+ dtemp, up->ntstamp);
#endif /* HAVE_AUDIO */
pp->lencode = strlen(pp->a_lastcode);
/*
- * If timestamps have been stuffed, the timecode is ipso fatso
- * correct and can be selected to discipline the clock.
+ * 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 (temp > 0) {
+ 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);
- refclock_receive(peer);
} else if (pp->sloppyclockflag & CLK_FLAG4) {
record_clock_stats(&peer->srcadr, pp->a_lastcode);
}
@@ -1360,6 +1372,9 @@ chu_poll(
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);
@@ -1370,7 +1385,7 @@ chu_poll(
/*
* chu_major - majority decoder
*/
-static int
+static double
chu_major(
struct peer *peer /* peer structure pointer */
)
@@ -1379,10 +1394,9 @@ chu_major(
struct chuunit *up;
u_char code[11]; /* decoded timecode */
- l_fp toffset, offset; /* l_fp temps */
+ int mindist; /* minimum distance */
int val1, val2; /* maximum distance */
int synchar; /* stray cat */
- double dtemp;
int temp;
int i, j, k;
@@ -1392,20 +1406,20 @@ chu_major(
/*
* Majority decoder. Each burst encodes two replications at each
* digit position in the timecode. Each row of the decoding
- * matrix encodes the number of occurences of each digit found
+ * matrix encodes the number of occurrences of each digit found
* at the corresponding position. The maximum over all
- * occurences at each position is the distance for this position
- * and the corresponding digit is the maximumn likelihood
- * candidate. If the distance is zero, assume a miss '_'; if the
- * distance is not more than half the total number of
- * occurences, 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.
+ * 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.
*/
- up->mindist = 16;
+ mindist = 16;
for (i = 0; i < 9; i++) {
val1 = val2 = 0;
k = 0;
@@ -1425,19 +1439,18 @@ chu_major(
code[i] = HEX_SOFT;
else
code[i] = k;
- if (val1 < up->mindist)
- up->mindist = val1;
+ if (val1 < mindist)
+ mindist = val1;
code[i] = hexchar[code[i]];
}
code[i] = 0;
/*
- * A valid timecode requires at least three bursts and a
- * decoding distance greater than half the total number of
- * occurences. A valid timecode also requires at least 20 valid
- * timestamps.
+ * 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 < 3 || up->mindist <= up->burstcnt)
+ if (up->burstcnt < MINBURST || mindist < up->burstcnt)
up->status |= DECODE;
if (up->ntstamp < MINSTAMP)
up->status |= STAMP;
@@ -1458,20 +1471,7 @@ chu_major(
up->errflg = CEVNT_BADREPLY;
return (0);
}
- L_CLR(&offset);
- if (!clocktime(pp->day, pp->hour, pp->minute, 0, GMT,
- up->tstamp[0].l_ui, &pp->yearstart, &offset.l_ui)) {
- up->errflg = CEVNT_BADTIME;
- return (0);
- }
- pp->lastref = offset;
- for (i = 0; i < up->ntstamp; i++) {
- toffset = offset;
- L_SUB(&toffset, &up->tstamp[i]);
- LFPTOD(&toffset, dtemp);
- SAMPLE(dtemp + FUDGE + pp->fudgetime1);
- }
- return (i);
+ return (mindist * 100. / (2. * up->burstcnt));
}
@@ -1494,15 +1494,120 @@ chu_clear(
* Clear stuff for the minute.
*/
up->ndx = up->prevsec = 0;
- up->burstcnt = up->mindist = up->ntstamp = 0;
- up->status &= INSYNC | INYEAR;
- up->burstcnt = 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
@@ -1564,14 +1669,14 @@ chu_gain(
*/
if (up->clipcnt == 0) {
up->gain += 4;
- if (up->gain > 255)
- up->gain = 255;
- } else if (up->clipcnt > SECOND / 100) {
+ 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->port);
+ audio_gain(up->gain, up->mongain, up->port);
up->clipcnt = 0;
}
#endif /* HAVE_AUDIO */
diff --git a/contrib/ntp/ntpd/refclock_conf.c b/contrib/ntp/ntpd/refclock_conf.c
index 04166d9..8a424f0 100644
--- a/contrib/ntp/ntpd/refclock_conf.c
+++ b/contrib/ntp/ntpd/refclock_conf.c
@@ -192,7 +192,7 @@ extern struct refclock refclock_oncore;
#define refclock_oncore refclock_none
#endif
-#if defined(CLOCK_JUPITER) && defined(PPS)
+#if defined(CLOCK_JUPITER) && defined(HAVE_PPSAPI)
extern struct refclock refclock_jupiter;
#else
#define refclock_jupiter refclock_none
diff --git a/contrib/ntp/ntpd/refclock_datum.c b/contrib/ntp/ntpd/refclock_datum.c
index db03c95..82b7369 100644
--- a/contrib/ntp/ntpd/refclock_datum.c
+++ b/contrib/ntp/ntpd/refclock_datum.c
@@ -712,6 +712,7 @@ datum_pts_receive(
&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
@@ -813,6 +814,7 @@ datum_pts_receive(
** 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);
/*
diff --git a/contrib/ntp/ntpd/refclock_dumbclock.c b/contrib/ntp/ntpd/refclock_dumbclock.c
index c439646..2788649 100644
--- a/contrib/ntp/ntpd/refclock_dumbclock.c
+++ b/contrib/ntp/ntpd/refclock_dumbclock.c
@@ -12,6 +12,11 @@
#include <config.h>
#endif
+#if defined(SYS_WINNT)
+#undef close
+#define close closesocket
+#endif
+
#if defined(REFCLOCK) && defined(CLOCK_DUMBCLOCK)
#include "ntpd.h"
@@ -114,14 +119,15 @@ dumbclock_start(
if (debug)
printf ("starting Dumbclock with device %s\n",device);
#endif
- if (!(fd = refclock_open(device, SPEED232, 0)))
+ fd = refclock_open(device, SPEED232, 0);
+ if (fd < 0)
return (0);
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct dumbclock_unit *)
- emalloc(sizeof(struct dumbclock_unit)))) {
+ up = (struct dumbclock_unit *)emalloc(sizeof(struct dumbclock_unit));
+ if (up == NULL) {
(void) close(fd);
return (0);
}
@@ -218,7 +224,7 @@ dumbclock_receive(
up->tcswitch = 0;
return;
}
- pp->lencode = temp;
+ pp->lencode = (u_short)temp;
pp->lastrec = up->laststamp;
up->laststamp = trtmp;
up->tcswitch = 1;
@@ -232,7 +238,6 @@ dumbclock_receive(
/*
* We get down to business. Check the timecode format...
*/
- pp->msec = 0;
got_good=0;
if (sscanf(pp->a_lastcode,"%02d:%02d:%02d",
&hours,&minutes,&seconds) == 3)
@@ -330,9 +335,10 @@ dumbclock_receive(
refclock_report(peer, CEVNT_BADTIME);
return;
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
- up->lasthour = pp->hour;
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ up->lasthour = (u_char)pp->hour;
}
#if 0
diff --git a/contrib/ntp/ntpd/refclock_fg.c b/contrib/ntp/ntpd/refclock_fg.c
index 655b6bc..ebcf1b5 100644
--- a/contrib/ntp/ntpd/refclock_fg.c
+++ b/contrib/ntp/ntpd/refclock_fg.c
@@ -299,14 +299,14 @@ fg_receive(
{
pp->minute = BP1(7)*10 + BP2(7);
pp->second = BP1(8)*10 + BP2(8);
- pp->msec = BP1(9)*10 + BP2(9);
- pp->usec = BP1(10);
+ 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->msec = BP1(8)*10 + BP2(8);
- pp->usec = BP1(9);
+ pp->nsec = (BP1(8)*10 + BP2(8)) * 1000000;
+ pp->nsec += BP1(9) * 1000;
}
if((pp->hour == 10) && (pp->minute == 10))
@@ -327,7 +327,7 @@ fg_receive(
if (peer->stratum <= 1)
peer->refid = pp->refid;
pp->disp = (10e-6);
- pp->lastrec = rbufp->recv_time; /* Is it better then get_systime()? */
+ pp->lastrec = rbufp->recv_time; /* Is it better than get_systime()? */
/* pp->leap = LEAP_NOWARNING; */
/*
@@ -337,7 +337,7 @@ fg_receive(
if (!refclock_process(pp))
refclock_report(peer, CEVNT_BADTIME);
-
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
return;
}
diff --git a/contrib/ntp/ntpd/refclock_gpsvme.c b/contrib/ntp/ntpd/refclock_gpsvme.c
index 42eb2f9..a7fcf5f 100644
--- a/contrib/ntp/ntpd/refclock_gpsvme.c
+++ b/contrib/ntp/ntpd/refclock_gpsvme.c
@@ -349,6 +349,7 @@ vme_poll(
l_fp tstmp;
time_t tloc;
struct tm *tadr;
+ long ltemp;
@@ -395,13 +396,13 @@ vme_poll(
vme->hour = tptr->hr;
vme->minute = tptr->mn;
vme->second = tptr->sec;
- vme->usec = tptr->frac;
+ 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->usec, tptr->status);
+ vme->nsec, tptr->status);
#endif
if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */
vme_report_event(vme, CEVNT_BADREPLY);
@@ -424,14 +425,16 @@ vme_poll(
msyslog(LOG_ERR, "refclock_gpsvme: bad data!!");
return;
}
- TVUTOTSF(vme->usec, vme->lastref.l_uf);
+ 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);
}
@@ -548,7 +551,7 @@ vme_buginfo(
bug->values[4] = (u_long)vme->hour;
bug->values[5] = (u_long)vme->minute;
bug->values[6] = (u_long)vme->second;
- bug->values[7] = (u_long)vme->usec;
+ bug->values[7] = (u_long)vme->nsec;
bug->values[9] = vme->yearstart;
bug->stimes = 0x1c;
bug->times[0] = vme->lastref;
diff --git a/contrib/ntp/ntpd/refclock_heath.c b/contrib/ntp/ntpd/refclock_heath.c
index ef4db5a..c16cef3 100644
--- a/contrib/ntp/ntpd/refclock_heath.c
+++ b/contrib/ntp/ntpd/refclock_heath.c
@@ -177,14 +177,6 @@ static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int speed[] = {B1200, B2400, B4800, B9600};
/*
- * Unit control structure
- */
-struct heathunit {
- int pollcnt; /* poll message counter */
- l_fp tstamp; /* timestamp of last poll */
-};
-
-/*
* Function prototypes
*/
static int heath_start P((int, struct peer *));
@@ -215,7 +207,6 @@ heath_start(
struct peer *peer
)
{
- register struct heathunit *up;
struct refclockproc *pp;
int fd;
char device[20];
@@ -224,18 +215,8 @@ heath_start(
* Open serial port
*/
(void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, speed[peer->ttlmax & 0x3], 0)))
+ if (!(fd = refclock_open(device, speed[peer->ttl & 0x3], 0)))
return (0);
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct heathunit *)
- emalloc(sizeof(struct heathunit)))) {
- (void) close(fd);
- return (0);
- }
- memset((char *)up, 0, sizeof(struct heathunit));
pp = peer->procptr;
pp->io.clock_recv = heath_receive;
pp->io.srcclock = (caddr_t)peer;
@@ -243,10 +224,8 @@ heath_start(
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
(void) close(fd);
- free(up);
return (0);
}
- pp->unitptr = (caddr_t)up;
/*
* Initialize miscellaneous variables
@@ -255,7 +234,6 @@ heath_start(
peer->burst = NSTAGE;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
- up->pollcnt = 2;
return (1);
}
@@ -269,13 +247,10 @@ heath_shutdown(
struct peer *peer
)
{
- register struct heathunit *up;
struct refclockproc *pp;
pp = peer->procptr;
- up = (struct heathunit *)pp->unitptr;
io_closeclock(&pp->io);
- free(up);
}
@@ -287,7 +262,6 @@ heath_receive(
struct recvbuf *rbufp
)
{
- register struct heathunit *up;
struct refclockproc *pp;
struct peer *peer;
l_fp trtmp;
@@ -300,27 +274,10 @@ heath_receive(
*/
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
- up = (struct heathunit *)pp->unitptr;
pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
&trtmp);
/*
- * We get a buffer and timestamp for each <cr>; however, we use
- * the timestamp captured at the RTS modem control line toggle
- * on the assumption that's what the radio bases the timecode
- * on. Apparently, the radio takes about a second to make up its
- * mind to send a timecode, so the receive timestamp is
- * worthless.
- */
- pp->lastrec = up->tstamp;
- up->pollcnt = 2;
-#ifdef DEBUG
- if (debug)
- printf("heath: 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.
@@ -396,7 +353,7 @@ heath_receive(
if (!isdigit((int)dsec))
pp->leap = LEAP_NOTINSYNC;
else {
- pp->msec = (dsec - '0') * 100;
+ pp->nsec = (dsec - '0') * 100000000;
pp->leap = LEAP_NOWARNING;
}
if (!refclock_process(pp))
@@ -413,7 +370,6 @@ heath_poll(
struct peer *peer
)
{
- register struct heathunit *up;
struct refclockproc *pp;
int bits = TIOCM_RTS;
@@ -421,10 +377,11 @@ heath_poll(
* 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;
- up = (struct heathunit *)pp->unitptr;
- pp->polls++;
/*
* We toggle the RTS modem control lead (GC-1000) and sent a T
@@ -437,19 +394,26 @@ heath_poll(
*/
if (ioctl(pp->io.fd, TIOCMBIC, (char *)&bits) < 0)
refclock_report(peer, CEVNT_FAULT);
- get_systime(&up->tstamp);
- ioctl(pp->io.fd, TIOCMBIS, (char *)&bits);
+ 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;
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
- peer->burst = NSTAGE;
+ 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
diff --git a/contrib/ntp/ntpd/refclock_hopfpci.c b/contrib/ntp/ntpd/refclock_hopfpci.c
index a9deb21..1b02319 100644
--- a/contrib/ntp/ntpd/refclock_hopfpci.c
+++ b/contrib/ntp/ntpd/refclock_hopfpci.c
@@ -48,6 +48,7 @@
#ifndef SYS_WINNT
# include <sys/ipc.h>
+# include <sys/ioctl.h>
# include <assert.h>
# include <unistd.h>
# include <stdio.h>
@@ -149,7 +150,7 @@ hopfpci_start(
pp->io.clock_recv = noentry;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
- pp->io.fd = -1;
+ pp->io.fd = INVALID_SOCKET;
pp->unitptr = (caddr_t)up;
get_systime(&pp->lastrec);
@@ -190,7 +191,7 @@ hopfpci_shutdown(
close(fd);
#else
CloseHopfDevice();
-// UnmapViewOfFile (up);
+/* UnmapViewOfFile (up); */
#endif
}
@@ -212,7 +213,7 @@ hopfpci_poll(
up = (struct hopfpciTime *)pp->unitptr;
#ifndef SYS_WINNT
- ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
+ ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
#else
GetHopfSystemTime(&m_time);
#endif
@@ -222,17 +223,16 @@ hopfpci_poll(
pp->hour = m_time.wHour;
pp->minute = m_time.wMinute;
pp->second = m_time.wSecond;
- pp->msec=m_time.wMilliseconds;
- pp->usec=0;
+ 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.%03d D: %02d.%02d.%04d",
- m_time.wStatus, pp->hour, pp->minute, pp->second, pp->msec,
- m_time.wDay, m_time.wMonth, m_time.wYear);
- pp->lencode = strlen(pp->a_lastcode);
+ 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);
@@ -262,10 +262,9 @@ hopfpci_poll(
refclock_report(peer, CEVNT_BADTIME);
return;
}
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
-
record_clock_stats(&peer->srcadr, pp->a_lastcode);
-
return;
}
diff --git a/contrib/ntp/ntpd/refclock_hopfser.c b/contrib/ntp/ntpd/refclock_hopfser.c
index a9d74dd..1d27333 100644
--- a/contrib/ntp/ntpd/refclock_hopfser.c
+++ b/contrib/ntp/ntpd/refclock_hopfser.c
@@ -14,6 +14,11 @@
# include "config.h"
#endif
+#if defined(SYS_WINNT)
+#undef close
+#define close closesocket
+#endif
+
#if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
#include "ntpd.h"
@@ -216,7 +221,7 @@ hopfserial_receive (
struct refclockproc *pp;
struct peer *peer;
- int sync; /* synchronization indicator */
+ int synch; /* synchhronization indicator */
int DoW; /* Dow */
int day, month; /* ddd conversion */
@@ -234,7 +239,7 @@ hopfserial_receive (
up->rpt_next = 0; /* wait until next poll interval occur */
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
+ pp->lencode = (u_short)refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
if (pp->lencode == 0)
return;
@@ -245,7 +250,7 @@ hopfserial_receive (
#else
"%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
#endif
- &sync,
+ &synch,
&DoW,
&pp->hour,
&pp->minute,
@@ -286,7 +291,7 @@ hopfserial_receive (
#if 0
wsprintf(pp->a_lastcode,
"STATUS: %1X%1X, DATE: %02d.%02d.%04d TIME: %02d:%02d:%02d",
- sync,
+ synch,
DoW,
day,
month,
@@ -296,7 +301,7 @@ hopfserial_receive (
pp->second);
pp->lencode = strlen(pp->a_lastcode);
- if ((sync && 0xc) == 0 ){ /* time ok? */
+ if ((synch && 0xc) == 0 ){ /* time ok? */
refclock_report(peer, CEVNT_BADTIME);
pp->leap = LEAP_NOTINSYNC;
return;
@@ -305,7 +310,7 @@ hopfserial_receive (
/*
* If clock has no valid status then report error and exit
*/
- if ((sync & HOPF_OPMODE) == HOPF_INVALID ){ /* time ok? */
+ if ((synch & HOPF_OPMODE) == HOPF_INVALID ){ /* time ok? */
refclock_report(peer, CEVNT_BADTIME);
pp->leap = LEAP_NOTINSYNC;
return;
@@ -316,7 +321,7 @@ hopfserial_receive (
* if CLK_FLAG1 is set, sychronize even if no radio operation
*/
- if ((sync & HOPF_OPMODE) == HOPF_INTERNAL){
+ if ((synch & HOPF_OPMODE) == HOPF_INTERNAL){
if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
refclock_report(peer, CEVNT_BADTIME);
pp->leap = LEAP_NOTINSYNC;
@@ -329,10 +334,11 @@ hopfserial_receive (
refclock_report(peer, CEVNT_BADTIME);
return;
}
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
#if 0
- msyslog(LOG_ERR, " D:%x D:%d D:%d",sync,pp->minute,pp->second);
+ msyslog(LOG_ERR, " D:%x D:%d D:%d",synch,pp->minute,pp->second);
#endif
record_clock_stats(&peer->srcadr, pp->a_lastcode);
diff --git a/contrib/ntp/ntpd/refclock_hpgps.c b/contrib/ntp/ntpd/refclock_hpgps.c
index 7a506cf..7c801bb 100644
--- a/contrib/ntp/ntpd/refclock_hpgps.c
+++ b/contrib/ntp/ntpd/refclock_hpgps.c
@@ -554,6 +554,7 @@ hpgps_receive(
refclock_report(peer, CEVNT_BADTIME);
return;
}
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
/*
diff --git a/contrib/ntp/ntpd/refclock_irig.c b/contrib/ntp/ntpd/refclock_irig.c
index 7efd57e..0b35368 100644
--- a/contrib/ntp/ntpd/refclock_irig.c
+++ b/contrib/ntp/ntpd/refclock_irig.c
@@ -75,8 +75,8 @@
* 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
+ * 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
@@ -97,11 +97,11 @@
*
* 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 -d -d on the ntpd command
- * line), the driver produces one line for each timecode in the
- * following format:
+ * 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 47 20 0.083 66.5 3094572411.00027
+ * 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.
@@ -111,14 +111,18 @@
* 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),
- * field phase (0-79), time constant (2-20), modulation index (0-1),
- * carrier phase error (0+-0.5) and carrier frequency error (PPM). The
- * last field is the on-time timestamp in NTP format.
+ * 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, 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.
+ * 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
@@ -127,16 +131,15 @@
*
* Fudge factors
*
- * Fudge flag2 selects the audio input port, where 0 is the mike port
+ * 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 speaker volume
- * must be set before the driver is started. Fudge flag4 causes the
- * debugging output described above to be recorded in the clockstats
- * file. Any of these flags can be changed during operation with the
- * ntpdc program.
+ * 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
*/
@@ -144,7 +147,7 @@
#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 */
@@ -155,16 +158,20 @@
#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 fudge factors
+ * Experimentally determined filter delays
*/
-#define IRIG_B .0019 /* IRIG-B phase delay */
-#define IRIG_E .0019 /* IRIG-E phase delay */
+#define IRIG_B .0019 /* IRIG-B filter delay */
+#define IRIG_E .0019 /* IRIG-E filter delay */
/*
* Data bit definitions
@@ -183,6 +190,7 @@
#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
@@ -191,23 +199,24 @@ struct irigunit {
u_char timecode[21]; /* timecode string */
l_fp timestamp; /* audio sample timestamp */
l_fp tick; /* audio sample increment */
- double comp[SIZE]; /* decompanding table */
double integ[BAUD]; /* baud integrator */
double phase, freq; /* logical clock phase and frequency */
double zxing; /* phase detector integrator */
- double yxing; /* phase detector display */
+ 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 */
- int bufcnt; /* samples in buffer */
- int bufptr; /* buffer index pointer */
- int pollcnt; /* poll counter */
+ /*
+ * 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 */
- int decim; /* sample decimation factor */
/*
* RF variables
@@ -222,8 +231,8 @@ struct irigunit {
double lastenv[CYCLE]; /* last cycle amplitudes */
double lastint[CYCLE]; /* last integrated cycle amplitudes */
double lastsig; /* last carrier sample */
- double xxing; /* phase detector interpolated output */
double fdelay; /* filter delay */
+ int decim; /* sample decimation factor */
int envphase; /* envelope phase */
int envptr; /* envelope phase pointer */
int carphase; /* carrier phase */
@@ -236,8 +245,6 @@ struct irigunit {
/*
* Decoder variables
*/
- l_fp montime; /* reference timestamp for eyeball */
- int timecnt; /* timecode counter */
int pulse; /* cycle counter */
int cycles; /* carrier cycles */
int dcycles; /* data cycles */
@@ -247,6 +254,13 @@ struct irigunit {
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;
};
/*
@@ -282,10 +296,10 @@ struct refclock refclock_irig = {
* 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 */
+ '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 */
};
@@ -294,7 +308,7 @@ static char hexchar[] = { /* really quick decoding table */
*/
static int
irig_start(
- int unit, /* instance number (not used) */
+ int unit, /* instance number (used for PCM) */
struct peer *peer /* peer structure pointer */
)
{
@@ -311,7 +325,7 @@ irig_start(
/*
* Open audio device
*/
- fd = audio_init(DEVICE_AUDIO);
+ fd = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
if (fd < 0)
return (0);
#ifdef DEBUG
@@ -350,7 +364,6 @@ irig_start(
up->decim = 1;
up->fdelay = IRIG_B;
up->gain = 127;
- up->pollcnt = 2;
/*
* The companded samples are encoded sign-magnitude. The table
@@ -364,7 +377,7 @@ irig_start(
up->comp[i] = up->comp[i - 1] + step;
up->comp[OFFSET + i] = -up->comp[i];
if (i % 16 == 0)
- step *= 2.;
+ step *= 2.;
}
DTOLFP(1. / SECOND, &up->tick);
return (1);
@@ -410,6 +423,7 @@ irig_receive(
*/
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;
@@ -420,20 +434,17 @@ irig_receive(
* 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;
- up->bufcnt = rbufp->recv_length;
- DTOLFP((double)up->bufcnt / SECOND, &ltemp);
- L_SUB(&up->timestamp, &ltemp);
dpt = rbufp->recv_buffer;
- for (up->bufptr = 0; up->bufptr < up->bufcnt; up->bufptr++) {
+ 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. Choose either IRIG-B or IRIG-E
- * according to the energy at the respective filter
- * output.
+ * decrease a tad.
*/
if (sample > MAXSIG) {
sample = MAXSIG;
@@ -444,11 +455,15 @@ irig_receive(
}
/*
- * Variable frequency oscillator. A phase change of one
- * unit produces a change of 360 degrees; a frequency
- * change of one unit produces a change of 1 Hz.
+ * 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) {
@@ -461,8 +476,7 @@ irig_receive(
L_ADD(&up->timestamp, &up->tick);
/*
- * Once each second, determine the IRIG format, codec
- * port and gain.
+ * Once each second, determine the IRIG format and gain.
*/
up->seccnt = (up->seccnt + 1) % SECOND;
if (up->seccnt == 0) {
@@ -473,22 +487,22 @@ irig_receive(
up->decim = 10;
up->fdelay = IRIG_E;
}
- if (pp->sloppyclockflag & CLK_FLAG2)
- up->port = 2;
- else
- up->port = 1;
irig_gain(peer);
up->irig_b = up->irig_e = 0;
}
}
/*
- * Squawk to the monitor speaker if enabled.
+ * 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)
- if (write(pp->io.fd, (u_char *)&rbufp->recv_space,
- (u_int)up->bufcnt) < 0)
- perror("irig:");
+ up->mongain = MONGAIN;
+ else
+ up->mongain = 0;
}
/*
@@ -521,7 +535,7 @@ irig_rf(
/*
* IRIG-B filter. 4th-order elliptic, 800-Hz highpass, 0.3 dB
- * passband ripple, -50 dB stopband ripple, phase delay -.0022
+ * passband ripple, -50 dB stopband ripple, phase delay .0022
* s)
*/
irig_b = (up->hpf[4] = up->hpf[3]) * 2.322484e-01;
@@ -558,9 +572,9 @@ irig_rf(
up->badcnt = (up->badcnt + 1) % up->decim;
if (up->badcnt == 0) {
if (up->decim == 1)
- irig_base(peer, irig_b);
+ irig_base(peer, irig_b);
else
- irig_base(peer, irig_e);
+ irig_base(peer, irig_e);
}
}
@@ -583,10 +597,10 @@ irig_base(
/*
* Local variables
*/
+ double xxing; /* phase detector interpolated output */
double lope; /* integrator output */
double env; /* envelope detector output */
double dtemp; /* double temp */
- int i; /* index temp */
pp = peer->procptr;
up = (struct irigunit *)pp->unitptr;
@@ -612,8 +626,8 @@ irig_base(
* change of 360 degrees produces an output change of one unit.
*/
if (up->lastsig > 0 && lope <= 0) {
- up->xxing = lope / (up->lastsig - lope);
- up->zxing += (up->carphase - 4 + up->xxing) / 8.;
+ xxing = lope / (up->lastsig - lope);
+ up->zxing += (up->carphase - 4 + xxing) / CYCLE;
}
up->lastsig = lope;
@@ -629,16 +643,17 @@ irig_base(
up->maxsignal = up->intmax;
up->noise = up->intmin;
if (up->maxsignal < DRPOUT)
- up->errflg |= IRIG_ERR_AMP;
- if (up->intmax > 0)
- up->modndx = (up->intmax - up->intmin) / up->intmax;
+ up->errflg |= IRIG_ERR_AMP;
+ if (up->maxsignal > 0)
+ up->modndx = (up->intmax - up->intmin) /
+ up->intmax;
else
- up->modndx = 0;
+ up->modndx = 0;
if (up->modndx < MODMIN)
- up->errflg |= IRIG_ERR_MOD;
+ 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)) {
+ IRIG_ERR_MOD | IRIG_ERR_SYNCH)) {
up->tc = MINTC;
up->tcount = 0;
}
@@ -674,13 +689,13 @@ irig_base(
* the slice level and left-shifted in the decoding register.
*/
if (up->carphase != 7)
- return;
+ return;
env = (up->lastenv[2] - up->lastenv[6]) / 2.;
lope = (up->lastint[2] - up->lastint[6]) / 2.;
if (lope > up->intmax)
- up->intmax = lope;
+ up->intmax = lope;
if (lope < up->intmin)
- up->intmin = lope;
+ up->intmin = lope;
/*
* Pulse code demodulator and reference timestamp. The decoder
@@ -690,15 +705,15 @@ irig_base(
*/
up->pulse = (up->pulse + 1) % 10;
if (up->pulse == 1)
- up->envmax = env;
+ up->envmax = env;
else if (up->pulse == 9)
- up->envmin = env;
+ up->envmin = env;
up->dcycles <<= 1;
if (env >= (up->envmax + up->envmin) / 2.)
- up->dcycles |= 1;
+ up->dcycles |= 1;
up->cycles <<= 1;
if (lope >= (up->maxsignal + up->noise) / 2.)
- up->cycles |= 1;
+ up->cycles |= 1;
if ((up->cycles & 0x303c0f03) == 0x300c0300) {
l_fp ltemp;
int bitz;
@@ -711,22 +726,19 @@ irig_base(
* persist for lots of samples.
*/
if (up->pulse != 9)
- up->errflg |= IRIG_ERR_SYNCH;
+ up->errflg |= IRIG_ERR_SYNCH;
up->pulse = 9;
- dtemp = BAUD - up->zxing;
- i = up->envxing - up->envphase;
- if (i < 0)
- i -= i;
- if (i <= 1) {
+ 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->tc = MAXTC;
up->tcount = 0;
up->envxing = up->envphase;
} else {
- dtemp -= up->envxing - up->envphase;
+ up->exing -= up->envxing - up->envphase;
}
} else {
up->tcount = 0;
@@ -740,8 +752,9 @@ irig_base(
* this plus the delay since the last carrier positive
* zero crossing.
*/
- DTOLFP(up->decim * (dtemp / SECOND + 1.) + up->fdelay,
- &ltemp);
+ dtemp = up->decim * ((up->exing + BAUD) / SECOND + 1.) +
+ up->fdelay;
+ DTOLFP(dtemp, &ltemp);
pp->lastrec = up->timestamp;
L_SUB(&pp->lastrec, &ltemp);
@@ -756,23 +769,23 @@ irig_base(
bitz = up->dcycles & 0xfc;
switch(bitz) {
- case 0x00:
- case 0x80:
+ case 0x00:
+ case 0x80:
irig_decode(peer, BIT0);
break;
- case 0xc0:
- case 0xe0:
- case 0xf0:
+ case 0xc0:
+ case 0xe0:
+ case 0xf0:
irig_decode(peer, BIT1);
break;
- case 0xf8:
- case 0xfc:
+ case 0xf8:
+ case 0xfc:
irig_decode(peer, BITP);
break;
- default:
+ default:
irig_decode(peer, 0);
up->errflg |= IRIG_ERR_DECODE;
}
@@ -797,11 +810,14 @@ irig_decode(
{
struct refclockproc *pp;
struct irigunit *up;
+#ifdef IRIG_SUCKS
+ int i;
+#endif /* IRIG_SUCKS */
/*
* Local variables
*/
- char syncchar; /* sync character (Spectracom only) */
+ char syncchar; /* sync character (Spectracom) */
char sbs[6]; /* binary seconds since 0h */
char spare[2]; /* mulligan digits */
@@ -824,15 +840,63 @@ irig_decode(
up->bitcnt = 1;
up->fieldcnt = 0;
up->lastbit = 0;
- up->montime = pp->lastrec;
if (up->errflg == 0) {
- up->timecnt++;
+#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);
- }
- if (up->timecnt >= MAXSTAGE) {
- refclock_receive(peer);
- up->timecnt = 0;
- up->pollcnt = 2;
+#else /* IRIG_SUCKS */
+ pp->lastref = pp->lastrec;
+ up->wuggle = pp->lastrec;
+ refclock_process(pp);
+#endif /* IRIG_SUCKS */
}
up->errflg = 0;
}
@@ -848,45 +912,58 @@ irig_decode(
if (up->xptr < 2)
up->xptr = 2 * FIELD;
up->timecode[--up->xptr] = hexchar[(up->bits >> 5) &
- 0xf];
+ 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, adjust the
- * gain and set the input port. Set the port
- * here on the assumption somebody might even
- * change it on-wing.
+ * 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;
+ "%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;
+ 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->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 %2d %6.3f %6.1f %s",
- up->errflg, syncchar, pp->year, pp->day,
- pp->hour, pp->minute, pp->second,
- up->maxsignal, up->gain, up->modndx,
- up->envxing, up->tc, up->yxing, up->freq *
- 1e6 / SECOND, ulfptoa(&up->montime, 6));
+ "%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 (up->timecnt == 0 || pp->sloppyclockflag &
- CLK_FLAG4)
- record_clock_stats(&peer->srcadr,
- pp->a_lastcode);
+ if (pp->sloppyclockflag & CLK_FLAG4) {
+ record_clock_stats(&peer->srcadr,
+ pp->a_lastcode);
#ifdef DEBUG
- if (debug > 2)
- printf("irig: %s\n", pp->a_lastcode);
+ if (debug)
+ printf("irig: %s\n",
+ pp->a_lastcode);
#endif /* DEBUG */
+ }
}
}
up->lastbit = bit;
@@ -896,9 +973,10 @@ irig_decode(
/*
* irig_poll - called by the transmit procedure
*
- * This routine keeps track of status. If nothing is heard for two
- * successive poll intervals, a timeout event is declared and any
- * orphaned timecode updates are sent to foster care.
+ * 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(
@@ -912,15 +990,17 @@ irig_poll(
pp = peer->procptr;
up = (struct irigunit *)pp->unitptr;
- /*
- * Keep book for tattletales
- */
- if (up->pollcnt == 0) {
+ if (pp->coderecv == pp->codeproc) {
refclock_report(peer, CEVNT_TIMEOUT);
- up->timecnt = 0;
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 */
}
- up->pollcnt--;
pp->polls++;
}
@@ -953,18 +1033,17 @@ irig_gain(
*/
if (up->clipcnt == 0) {
up->gain += 4;
- if (up->gain > 255)
- up->gain = 255;
- } else if (up->clipcnt > SECOND / 100) {
+ 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->port);
+ 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
index dba6070..2aa9d6a 100644
--- a/contrib/ntp/ntpd/refclock_jjy.c
+++ b/contrib/ntp/ntpd/refclock_jjy.c
@@ -188,7 +188,7 @@ jjy_start ( int unit, struct peer *peer )
#ifdef DEBUG
if ( debug ) {
- printf ( "jjy_start (refclock_jjy.c) : %s mode=%d ", ntoa(&peer->srcadr), peer->ttlmax ) ;
+ printf ( "jjy_start (refclock_jjy.c) : %s mode=%d ", ntoa(&peer->srcadr), peer->ttl ) ;
printf ( DEVICE, unit ) ;
printf ( "\n" ) ;
}
@@ -202,15 +202,15 @@ jjy_start ( int unit, struct peer *peer )
sprintf ( pDeviceName, DEVICE, unit ) ;
/*
- * peer->ttlmax is a mode number specified by "127.127.40.X mode N" in the ntp.conf
+ * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
*/
- switch ( peer->ttlmax ) {
+ 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->ttlmax ) ;
+ ntoa(&peer->srcadr), peer->ttl ) ;
free ( (void*) pDeviceName ) ;
return RC_START_ERROR ;
}
@@ -233,9 +233,9 @@ jjy_start ( int unit, struct peer *peer )
up->linediscipline = iDiscipline ;
/*
- * peer->ttlmax is a mode number specified by "127.127.40.X mode N" in the ntp.conf
+ * peer->ttl is a mode number specified by "127.127.40.X mode N" in the ntp.conf
*/
- switch ( peer->ttlmax ) {
+ switch ( peer->ttl ) {
case 0 :
/*
* The mode 0 is a default clock type at this time.
@@ -255,7 +255,7 @@ jjy_start ( int unit, struct peer *peer )
break ;
default :
msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
- ntoa(&peer->srcadr), peer->ttlmax ) ;
+ ntoa(&peer->srcadr), peer->ttl ) ;
close ( fd ) ;
free ( (void*) up ) ;
return RC_START_ERROR ;
@@ -422,8 +422,7 @@ jjy_receive ( struct recvbuf *rbufp )
pp->hour = up->hour ;
pp->minute = up->minute ;
pp->second = up->second ;
- pp->msec = up->msecond ;
- pp->usec = 0;
+ pp->nsec = up->msecond * 1000000;
/*
* JST to UTC
@@ -460,10 +459,9 @@ jjy_receive ( struct recvbuf *rbufp )
sprintf ( sLogText, "%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 ) ;
-
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
-
+ record_clock_stats ( &peer->srcadr, sLogText ) ;
}
/**************************************************************************************************/
diff --git a/contrib/ntp/ntpd/refclock_jupiter.c b/contrib/ntp/ntpd/refclock_jupiter.c
index 4d1d4c2..eff088b 100644
--- a/contrib/ntp/ntpd/refclock_jupiter.c
+++ b/contrib/ntp/ntpd/refclock_jupiter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 1998
+ * 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
@@ -35,21 +35,28 @@
# include <config.h>
#endif
-#if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(PPS)
+#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 "ntp_calendar.h"
#include <stdio.h>
#include <ctype.h>
#include "jupiter.h"
-#include <sys/ppsclock.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))
@@ -83,15 +90,6 @@ char *strerror(int);
#define SPEED232 B9600 /* baud */
/*
- * The number of raw samples which we acquire to derive a single estimate.
- * NSAMPLES ideally should not exceed the default poll interval 64.
- * NKEEP must be a power of 2 to simplify the averaging process.
- */
-#define NSAMPLES 64
-#define NKEEP 8
-#define REFCLOCKMAXDISPERSE .25 /* max sample dispersion */
-
-/*
* Radio interface parameters
*/
#define PRECISION (-18) /* precision assumed (about 4 us) */
@@ -114,24 +112,27 @@ char *strerror(int);
/*
* Jupiter unit control structure.
*/
-struct jupiterunit {
+struct instance {
+ struct peer *peer; /* peer */
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 */
+#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 */
- u_int32 timecode; /* current ntp timecode */
+ 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_long sloppyclockflag; /* fudge flags */
- u_int known; /* position known yet? */
- int coderecv; /* total received samples */
- int nkeep; /* number of samples to preserve */
- int rshift; /* number of rshifts for division */
- l_fp filter[NSAMPLES]; /* offset filter */
- l_fp lastref; /* last reference timestamp */
+ u_char sloppyclockflag; /* fudge flags */
u_short sbuf[512]; /* local input buffer */
int ssize; /* space used in sbuf */
};
@@ -139,30 +140,28 @@ struct jupiterunit {
/*
* Function prototypes
*/
-static void jupiter_canmsg P((struct peer *, u_int));
+static void jupiter_canmsg P((struct instance *, u_int));
static u_short jupiter_cksum P((u_short *, u_int));
-#ifdef QSORT_USES_VOID_P
- int jupiter_cmpl_fp P((const void *, const void *));
-#else
- int jupiter_cmpl_fp P((const l_fp *, const l_fp *));
-#endif /* not QSORT_USES_VOID_P */
-static void jupiter_config P((struct peer *));
-static void jupiter_debug P((struct peer *, char *, ...))
- __attribute__ ((format (printf, 2, 3)));
-static char * jupiter_offset P((struct peer *));
-static char * jupiter_parse_t P((struct peer *, u_short *));
-static void jupiter_platform P((struct peer *, 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 int jupiter_pps P((struct peer *));
-static char * jupiter_process P((struct peer *));
-static int jupiter_recv P((struct peer *));
-static void jupiter_receive P((register struct recvbuf *rbufp));
-static void jupiter_reqmsg P((struct peer *, u_int, u_int));
-static void jupiter_reqonemsg P((struct peer *, u_int));
-static char * jupiter_send P((struct peer *, struct jheader *));
+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 *));
-static int jupiter_ttyinit P((struct peer *, int));
/*
* Transfer vector
@@ -171,7 +170,7 @@ struct refclock refclock_jupiter = {
jupiter_start, /* start up driver */
jupiter_shutdown, /* shut down driver */
jupiter_poll, /* transmit poll message */
- noentry, /* (clock control) */
+ jupiter_control, /* (clock control) */
noentry, /* (clock init) */
noentry, /* (clock buginfo) */
NOFLAGS /* not used */
@@ -182,39 +181,34 @@ struct refclock refclock_jupiter = {
*/
static int
jupiter_start(
- register int unit,
- register struct peer *peer
+ int unit,
+ struct peer *peer
)
{
struct refclockproc *pp;
- register struct jupiterunit *up;
- register int fd;
+ struct instance *instance;
+ int fd = -1;
char gpsdev[20];
/*
* Open serial port
*/
(void)sprintf(gpsdev, DEVICE, unit);
- fd = open(gpsdev, O_RDWR
-#ifdef O_NONBLOCK
- | O_NONBLOCK
-#endif
- , 0);
- if (fd < 0) {
- jupiter_debug(peer, "jupiter_start: open %s: %s\n",
+ fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
+ if (fd == 0) {
+ jupiter_debug(peer, "jupiter_start", "open %s: %s",
gpsdev, strerror(errno));
return (0);
}
- if (!jupiter_ttyinit(peer, fd))
- return (0);
/* Allocate unit structure */
- if ((up = (struct jupiterunit *)
- emalloc(sizeof(struct jupiterunit))) == NULL) {
+ if ((instance = (struct instance *)
+ emalloc(sizeof(struct instance))) == NULL) {
(void) close(fd);
return (0);
}
- memset((char *)up, 0, sizeof(struct jupiterunit));
+ 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;
@@ -222,10 +216,10 @@ jupiter_start(
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
(void) close(fd);
- free(up);
+ free(instance);
return (0);
}
- pp->unitptr = (caddr_t)up;
+ pp->unitptr = (caddr_t)instance;
/*
* Initialize miscellaneous variables
@@ -234,145 +228,228 @@ jupiter_start(
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 */
- jupiter_config(peer);
+ if (!jupiter_config(instance))
+ goto clean_up;
- /* Turn on pulse gathering by requesting the first sample */
- if (ioctl(fd, CIOGETEV, (caddr_t)&up->ppsev) < 0) {
- jupiter_debug(peer, "jupiter_ttyinit: CIOGETEV: %s\n",
- strerror(errno));
- (void) close(fd);
- free(up);
- return (0);
- }
- up->lastserial = up->ppsev.serial;
- memset(&up->ppsev, 0, sizeof(up->ppsev));
return (1);
+
+clean_up:
+ jupiter_shutdown(unit, peer);
+ pp->unitptr = 0;
+ return (0);
}
/*
* jupiter_shutdown - shut down the clock
*/
static void
-jupiter_shutdown(register int unit, register struct peer *peer)
+jupiter_shutdown(int unit, struct peer *peer)
{
- register struct jupiterunit *up;
+ struct instance *instance;
struct refclockproc *pp;
pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
+ 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(up);
+ free(instance);
}
/*
* jupiter_config - Configure the receiver
*/
-static void
-jupiter_config(register struct peer *peer)
+static int
+jupiter_config(struct instance *instance)
{
- register int i;
- register struct jupiterunit *up;
- register struct refclockproc *pp;
-
- pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
+ jupiter_debug(instance->peer, "jupiter_config", "init receiver");
/*
* Initialize the unit variables
- *
- * STRANGE BEHAVIOUR WARNING: The fudge flags are not available
- * at the time jupiter_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, "jupiter_config: mobile platform");
- } else {
- up->moving = 0; /* Static Installation */
- }
-
- /* XXX fludge flags don't make the trip from the config to here... */
-#ifdef notdef
- /* Configure for trailing edge triggers */
-#ifdef CIOSETTET
- i = ((pp->sloppyclockflag & CLK_FLAG3) != 0);
- jupiter_debug(peer, "jupiter_configure: (sloppyclockflag 0x%lx)\n",
- pp->sloppyclockflag);
- if (ioctl(pp->io.fd, CIOSETTET, (char *)&i) < 0)
- msyslog(LOG_DEBUG, "jupiter_configure: CIOSETTET %d: %m", i);
-#else
- if (pp->sloppyclockflag & CLK_FLAG3)
- msyslog(LOG_DEBUG, "jupiter_configure: \
-No kernel support for trailing edge trigger");
-#endif
-#endif
-
- up->pollcnt = 2;
- up->polled = 0;
- up->known = 0;
- up->gweek = 0;
- up->lastsweek = 2 * WEEKSECS;
- up->timecode = 0;
- up->stime = 0;
- up->ssize = 0;
- up->coderecv = 0;
- up->nkeep = NKEEP;
- if (up->nkeep > NSAMPLES)
- up->nkeep = NSAMPLES;
- if (up->nkeep >= 1)
- up->rshift = 0;
- if (up->nkeep >= 2)
- up->rshift = 1;
- if (up->nkeep >= 4)
- up->rshift = 2;
- if (up->nkeep >= 8)
- up->rshift = 3;
- if (up->nkeep >= 16)
- up->rshift = 4;
- if (up->nkeep >= 32)
- up->rshift = 5;
- if (up->nkeep >= 64)
- up->rshift = 6;
- up->nkeep = 1;
- i = up->rshift;
- while (i > 0) {
- up->nkeep *= 2;
- i--;
- }
+ 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(peer, JUPITER_ALL);
+ jupiter_canmsg(instance, JUPITER_ALL);
/* Request the receiver id so we can syslog the firmware version */
- jupiter_reqonemsg(peer, JUPITER_O_ID);
+ jupiter_reqonemsg(instance, JUPITER_O_ID);
/* Flag that this the id was requested (so we don't get called again) */
- up->wantid = 1;
+ instance->wantid = 1;
/* Request perodic time mark pulse messages */
- jupiter_reqmsg(peer, JUPITER_O_PULSE, 1);
+ jupiter_reqmsg(instance, JUPITER_O_PULSE, 1);
+
+ /* Request perodic geodetic position status */
+ jupiter_reqmsg(instance, JUPITER_O_GPOS, 1);
/* Set application platform type */
- if (up->moving)
- jupiter_platform(peer, JUPITER_I_PLAT_MED);
+ 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
- jupiter_platform(peer, JUPITER_I_PLAT_LOW);
+ 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(register int unit, register struct peer *peer)
+jupiter_poll(int unit, struct peer *peer)
{
- register struct jupiterunit *up;
- register struct refclockproc *pp;
+ struct instance *instance;
+ struct refclockproc *pp;
pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
+ instance = (struct instance *)pp->unitptr;
/*
* You don't need to poll this clock. It puts out timecodes
@@ -383,79 +460,106 @@ jupiter_poll(register int unit, register struct peer *peer)
/*
* If we haven't had a response in a while, reset the receiver.
*/
- if (up->pollcnt > 0) {
- up->pollcnt--;
+ if (instance->pollcnt > 0) {
+ instance->pollcnt--;
} else {
refclock_report(peer, CEVNT_TIMEOUT);
/* Request the receiver id to trigger a reconfig */
- jupiter_reqonemsg(peer, JUPITER_O_ID);
- up->wantid = 0;
+ jupiter_reqonemsg(instance, JUPITER_O_ID);
+ instance->wantid = 0;
}
/*
* polled every 64 seconds. Ask jupiter_receive to hand in
* a timestamp.
*/
- up->polled = 1;
+ instance->polled = 1;
pp->polls++;
}
/*
- * jupiter_receive - receive gps data
- * Gag me!
+ * jupiter_control - fudge control
*/
static void
-jupiter_receive(register struct recvbuf *rbufp)
+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 */
+ )
{
- register int bpcnt, cc, size, ppsret;
- register u_int32 last_timecode, laststime;
- register char *cp;
- register u_char *bp;
- register u_short *sp;
- register u_long sloppyclockflag;
- register struct jupiterunit *up;
- register struct jid *ip;
- register struct jheader *hp;
- register struct refclockproc *pp;
- register struct peer *peer;
+ struct refclockproc *pp;
+ struct instance *instance;
+ u_char sloppyclockflag;
- /* Initialize pointers and read the timecode and timestamp */
- peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
+ instance = (struct instance *)pp->unitptr;
- /*
- * If operating mode has been changed, then reinitialize the receiver
- * before doing anything else.
- */
-/* XXX Sloppy clock flags are broken!! */
- sloppyclockflag = up->sloppyclockflag;
- up->sloppyclockflag = pp->sloppyclockflag;
- if ((pp->sloppyclockflag & CLK_FLAG2) !=
+ 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_receive: mode switch: reset receiver\n");
- jupiter_config(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;
- up->pollcnt = 2;
+ /* 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(up->sbuf) - up->ssize)
- bpcnt = sizeof(up->sbuf) - up->ssize;
+ if (bpcnt > sizeof(instance->sbuf) - instance->ssize)
+ bpcnt = sizeof(instance->sbuf) - instance->ssize;
/* Append to input buffer */
- memcpy((u_char *)up->sbuf + up->ssize, bp, bpcnt);
- up->ssize += bpcnt;
+ 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;
- /* While there's at least a header and we parse a intact message */
- while (up->ssize > sizeof(*hp) && (cc = jupiter_recv(peer)) > 0) {
- hp = (struct jheader *)up->sbuf;
+ tstamp = rbufp->recv_time;
+ hp = (struct jheader *)instance->sbuf;
sp = (u_short *)(hp + 1);
size = cc - sizeof(*hp);
switch (getshort(hp->id)) {
@@ -463,7 +567,7 @@ jupiter_receive(register struct recvbuf *rbufp)
case JUPITER_O_PULSE:
if (size != sizeof(struct jpulse)) {
jupiter_debug(peer,
- "jupiter_receive: pulse: len %d != %u\n",
+ "jupiter_receive", "pulse: len %d != %u",
size, (int)sizeof(struct jpulse));
refclock_report(peer, CEVNT_BADREPLY);
break;
@@ -479,23 +583,32 @@ jupiter_receive(register struct recvbuf *rbufp)
* pulse message in the last 210 ms, we skip
* this one.
*/
- laststime = up->stime;
- up->stime = DS2UI(((struct jpulse *)sp)->stime);
- if (laststime != 0 && up->stime - laststime <= 21) {
- jupiter_debug(peer, "jupiter_receive: \
-avoided firmware bug (stime %.2f, laststime %.2f)\n",
- (double)up->stime * 0.01, (double)laststime * 0.01);
+ 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(peer);
+ 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 = up->timecode;
- if ((cp = jupiter_parse_t(peer, sp)) != NULL) {
+ last_timecode = instance->timecode;
+ if ((cp = jupiter_parse_t(instance, sp)) != NULL) {
jupiter_debug(peer,
- "jupiter_receive: pulse: %s\n", cp);
+ "jupiter_receive", "pulse: %s", cp);
break;
}
@@ -508,300 +621,118 @@ avoided firmware bug (stime %.2f, laststime %.2f)\n",
break;
/* Add the new sample to a median filter */
- if ((cp = jupiter_offset(peer)) != NULL) {
- jupiter_debug(peer,
- "jupiter_receive: offset: %s\n", cp);
- refclock_report(peer, CEVNT_BADTIME);
- break;
- }
+ 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 (!up->polled)
+ if (!instance->polled)
break;
+ instance->polled = 0;
/*
* It's a live one! Remember this time.
*/
- pp->lasttime = current_time;
+
+ pp->lastref = pp->lastrec;
+ refclock_receive(peer);
/*
- * Determine the reference clock offset and
- * dispersion. NKEEP of NSAMPLE offsets are
- * passed through a median filter.
- * Save the (filtered) offset and dispersion in
- * pp->offset and pp->disp.
- */
- if ((cp = jupiter_process(peer)) != NULL) {
- jupiter_debug(peer,
- "jupiter_receive: process: %s\n", cp);
- refclock_report(peer, CEVNT_BADTIME);
- break;
- }
- /*
- * 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.
+ * If we get here - what we got from the clock is
+ * OK, so say so
*/
- jupiter_debug(peer,
- "jupiter_receive: process time: \
-%4d-%03d %02d:%02d:%02d at %s, %s\n",
- pp->year, pp->day,
- pp->hour, pp->minute, pp->second,
- prettydate(&pp->lastrec), lfptoa(&pp->offset, 6));
-
- refclock_receive(peer);
+ refclock_report(peer, CEVNT_NOMINAL);
/*
* We have succeeded in answering the poll.
* Turn off the flag and return
*/
- up->polled = 0;
+ 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\n",
+ "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 up, it needs to be reconfigured.
+ * just powered instance, it needs to be reconfigured.
*/
ip = (struct jid *)sp;
jupiter_debug(peer,
- "jupiter_receive: >> %s chan ver %s, %s (%s)\n",
+ "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 (up->wantid)
- up->wantid = 0;
+ if (instance->wantid)
+ instance->wantid = 0;
else {
jupiter_debug(peer,
- "jupiter_receive: reset receiver\n");
- jupiter_config(peer);
- /* Rese since jupiter_config() just zeroed it */
- up->ssize = cc;
+ "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\n",
+ "jupiter_receive", "unknown message id %d",
getshort(hp->id));
break;
}
- up->ssize -= cc;
- if (up->ssize < 0) {
+ instance->ssize -= cc;
+ if (instance->ssize < 0) {
fprintf(stderr, "jupiter_recv: negative ssize!\n");
abort();
- } else if (up->ssize > 0)
- memcpy(up->sbuf, (u_char *)up->sbuf + cc, up->ssize);
+ } else if (instance->ssize > 0)
+ memcpy(instance->sbuf, (u_char *)instance->sbuf + cc, instance->ssize);
}
- record_clock_stats(&peer->srcadr, "<timecode is binary>");
}
-/*
- * jupiter_offset - Calculate the offset, and add to the rolling filter.
- */
static char *
-jupiter_offset(register struct peer *peer)
+jupiter_parse_t(struct instance *instance, u_short *sp)
{
- register struct jupiterunit *up;
- register struct refclockproc *pp;
- register int i;
- l_fp offset;
-
- pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
+ struct tm *tm;
+ char *cp;
+ struct jpulse *jp;
+ u_int32 sweek;
+ time_t last_timecode;
+ u_short flags;
- /*
- * Calculate the offset
- */
- if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
- pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) {
- return ("jupiter_process: clocktime failed");
- }
- if (pp->usec) {
- TVUTOTSF(pp->usec, offset.l_uf);
- } else {
- MSUTOTSF(pp->msec, offset.l_uf);
- }
- L_ADD(&offset, &pp->fudgetime1);
- up->lastref = offset; /* save last reference time */
- L_SUB(&offset, &pp->lastrec); /* form true offset */
-
- /*
- * A rolling filter. Initialize first time around.
- */
- i = ((up->coderecv)) % NSAMPLES;
-
- up->filter[i] = offset;
- if (up->coderecv == 0)
- for (i = 1; (u_int) i < NSAMPLES; i++)
- up->filter[i] = up->filter[0];
- up->coderecv++;
-
- return (NULL);
-}
-
-/*
- * jupiter_process - process the sample from the clock,
- * passing it through a median filter and optionally averaging
- * the samples. Returns offset and dispersion in "up" structure.
- */
-static char *
-jupiter_process(register struct peer *peer)
-{
- register struct jupiterunit *up;
- register struct refclockproc *pp;
- register int i, n;
- register int j, k;
- l_fp offset, median, lftmp;
- u_fp disp;
- l_fp off[NSAMPLES];
-
- pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
-
- /*
- * Copy the raw offsets and sort into ascending order
- */
- for (i = 0; i < NSAMPLES; i++)
- off[i] = up->filter[i];
- qsort((char *)off, (size_t)NSAMPLES, sizeof(l_fp), jupiter_cmpl_fp);
-
- /*
- * Reject the furthest from the median of NSAMPLES samples until
- * NKEEP samples remain.
- */
- i = 0;
- n = NSAMPLES;
- while ((n - i) > up->nkeep) {
- lftmp = off[n - 1];
- median = off[(n + i) / 2];
- L_SUB(&lftmp, &median);
- L_SUB(&median, &off[i]);
- if (L_ISHIS(&median, &lftmp)) {
- /* reject low end */
- i++;
- } else {
- /* reject high end */
- n--;
- }
- }
-
- /*
- * Copy key values to the billboard to measure performance.
- */
- pp->lastref = up->lastref;
- pp->coderecv = up->coderecv;
- pp->filter[0] = off[0]; /* smallest offset */
- pp->filter[1] = off[NSAMPLES-1]; /* largest offset */
- for (j = 2, k = i; k < n; j++, k++)
- pp->filter[j] = off[k]; /* offsets actually examined */
-
- /*
- * Compute the dispersion based on the difference between the
- * extremes of the remaining offsets. Add to this the time since
- * the last clock update, which represents the dispersion
- * increase with time. We know that NTP_MAXSKEW is 16. If the
- * sum is greater than the allowed sample dispersion, bail out.
- * If the loop is unlocked, return the most recent offset;
- * otherwise, return the median offset.
- */
- lftmp = off[n - 1];
- L_SUB(&lftmp, &off[i]);
- disp = LFPTOFP(&lftmp);
- if (disp > REFCLOCKMAXDISPERSE)
- return ("Maximum dispersion exceeded");
-
- /*
- * Now compute the offset estimate. If fudge flag 1
- * is set, average the remainder, otherwise pick the
- * median.
- */
- if (pp->sloppyclockflag & CLK_FLAG1) {
- L_CLR(&lftmp);
- while (i < n) {
- L_ADD(&lftmp, &off[i]);
- i++;
- }
- i = up->rshift;
- while (i > 0) {
- L_RSHIFT(&lftmp);
- i--;
- }
- offset = lftmp;
- } else {
- i = (n + i) / 2;
- offset = off[i];
- }
-
- /*
- * The payload: filtered offset and dispersion.
- */
-
- pp->offset = offset;
- pp->disp = disp;
-
- return (NULL);
-
-}
-
-/* Compare two l_fp's, used with qsort() */
-#ifdef QSORT_USES_VOID_P
-int
-jupiter_cmpl_fp(register const void *p1, register const void *p2)
-#else
-int
-jupiter_cmpl_fp(register const l_fp *fp1, register const l_fp *fp2)
-#endif
-{
-#ifdef QSORT_USES_VOID_P
- register const l_fp *fp1 = (const l_fp *)p1;
- register const l_fp *fp2 = (const l_fp *)p2;
-#endif
-
- if (!L_ISGEQ(fp1, fp2))
- return (-1);
- if (L_ISEQU(fp1, fp2))
- return (0);
- return (1);
-}
-
-static char *
-jupiter_parse_t(register struct peer *peer, register u_short *sp)
-{
- register struct refclockproc *pp;
- register struct jupiterunit *up;
- register struct tm *tm;
- register char *cp;
- register struct jpulse *jp;
- register struct calendar *jt;
- register u_int32 sweek;
- register u_int32 last_timecode;
- register u_short flags;
- time_t t;
- struct calendar cal;
-
- pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
jp = (struct jpulse *)sp;
/* The timecode is presented as seconds into the current GPS week */
- sweek = DS2UI(jp->sweek);
+ sweek = DS2UI(jp->sweek) % WEEKSECS;
/*
* If we don't know the current GPS week, calculate it from the
@@ -815,12 +746,31 @@ jupiter_parse_t(register struct peer *peer, register u_short *sp)
* If we already know the current GPS week, increment it when
* we wrap into a new week.
*/
- if (up->gweek == 0)
- up->gweek = (time(NULL) - GPS_EPOCH) / WEEKSECS;
- else if (sweek == 0 && up->lastsweek == WEEKSECS - 1) {
- ++up->gweek;
- jupiter_debug(peer,
- "jupiter_parse_t: NEW gps week %u\n", up->gweek);
+ 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);
}
/*
@@ -835,167 +785,145 @@ jupiter_parse_t(register struct peer *peer, register u_short *sp)
*
* Then we warped.
*/
- if (up->lastsweek == sweek)
- jupiter_debug(peer,
- "jupiter_parse_t: gps sweek not incrementing (%d)\n",
+ if (instance->lastsweek == sweek)
+ jupiter_debug(instance->peer,
+ "jupiter_parse_t", "gps sweek not incrementing (%d)",
sweek);
- else if (up->lastsweek != 2 * WEEKSECS &&
- up->lastsweek + 1 != sweek &&
- !(sweek == 0 && up->lastsweek == WEEKSECS - 1))
- jupiter_debug(peer,
- "jupiter_parse_t: gps sweek jumped (was %d, now %d)\n",
- up->lastsweek, sweek);
- up->lastsweek = 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 = up->timecode;
- up->timecode = (u_int32)JAN_1970 +
- GPS_EPOCH + (up->gweek * WEEKSECS) + sweek;
+ last_timecode = instance->timecode;
+ instance->timecode =
+ GPS_EPOCH + (instance->gweek * WEEKSECS) + sweek;
if (last_timecode == 0)
/* XXX debugging */
- jupiter_debug(peer,
- "jupiter_parse_t: UTC <none> (gweek/sweek %u/%u)\n",
- up->gweek, sweek);
+ jupiter_debug(instance->peer,
+ "jupiter_parse_t", "UTC <none> (gweek/sweek %u/%u)",
+ instance->gweek, sweek);
else {
/* XXX debugging */
- t = last_timecode - (u_int32)JAN_1970;
- tm = gmtime(&t);
+ tm = gmtime(&last_timecode);
cp = asctime(tm);
- jupiter_debug(peer,
- "jupiter_parse_t: UTC %.24s (gweek/sweek %u/%u)\n",
- cp, up->gweek, sweek);
+ 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) */
- jt = &cal;
- caljulian(last_timecode, jt);
- pp = peer->procptr;
- pp->year = jt->year;
- pp->day = jt->yearday;
- pp->hour = jt->hour;
- pp->minute = jt->minute;
- pp->second = jt->second;
- pp->msec = 0;
- pp->usec = 0;
+ 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;
}
- /* XXX debugging */
- tm = gmtime(&up->ppsev.tv.tv_sec);
- cp = asctime(tm);
flags = getshort(jp->flags);
- jupiter_debug(peer,
- "jupiter_parse_t: PPS %.19s.%06lu %.4s (serial %u)%s\n",
- cp, up->ppsev.tv.tv_usec, cp + 20, up->ppsev.serial,
- (flags & JUPITER_O_PULSE_VALID) == 0 ?
- " NOT VALID" : "");
/* Toss if not designated "valid" by the gps */
if ((flags & JUPITER_O_PULSE_VALID) == 0) {
- refclock_report(peer, CEVNT_BADTIME);
+ 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(peer, CEVNT_BADTIME);
+ refclock_report(instance->peer, CEVNT_BADTIME);
return ("time mark not sync'ed to UTC");
}
return (NULL);
}
-/*
- * Process a PPS signal, returning a timestamp.
- */
-static int
-jupiter_pps(register struct peer *peer)
+static char *
+jupiter_parse_gpos(struct instance *instance, u_short *sp)
{
- register struct refclockproc *pp;
- register struct jupiterunit *up;
- register int firsttime;
- struct timeval ntp_tv;
+ struct jgpos *jg;
+ time_t t;
+ struct tm *tm;
+ char *cp;
- pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
+ jg = (struct jgpos *)sp;
- /*
- * Grab the timestamp of the PPS signal.
- */
- firsttime = (up->ppsev.tv.tv_sec == 0);
- if (ioctl(pp->io.fd, CIOGETEV, (caddr_t)&up->ppsev) < 0) {
- /* XXX Actually, if this fails, we're pretty much screwed */
- jupiter_debug(peer, "jupiter_pps: CIOGETEV: %s\n",
- strerror(errno));
- refclock_report(peer, CEVNT_FAULT);
- return (1);
+ 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");
}
- /*
- * Check pps serial number against last one
- */
- if (!firsttime && up->lastserial + 1 != up->ppsev.serial) {
- if (up->ppsev.serial == up->lastserial)
- jupiter_debug(peer, "jupiter_pps: no new pps event\n");
- else
- jupiter_debug(peer,
- "jupiter_pps: missed %d pps events\n",
- up->ppsev.serial - up->lastserial - 1);
- up->lastserial = up->ppsev.serial;
- refclock_report(peer, CEVNT_FAULT);
- return (1);
+ instance->gpos_gweek = jg->gweek;
+ instance->gpos_sweek = DS2UI(jg->sweek);
+ while(instance->gpos_sweek >= WEEKSECS) {
+ instance->gpos_sweek -= WEEKSECS;
+ ++instance->gpos_gweek;
}
- up->lastserial = up->ppsev.serial;
+ instance->gweek = 0;
- /*
- * Return the timestamp in pp->lastrec
- */
- ntp_tv = up->ppsev.tv;
- ntp_tv.tv_sec += (u_int32)JAN_1970;
- TVTOTS(&ntp_tv, &pp->lastrec);
+ t = GPS_EPOCH + (instance->gpos_gweek * WEEKSECS) + instance->gpos_sweek;
+ tm = gmtime(&t);
+ cp = asctime(tm);
- return (0);
+ 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__)
+#if defined(__STDC__) || defined(SYS_WINNT)
static void
-jupiter_debug(struct peer *peer, char *fmt, ...)
+jupiter_debug(struct peer *peer, char *function, char *fmt, ...)
#else
static void
-jupiter_debug(peer, fmt, va_alist)
+jupiter_debug(peer, function, fmt, va_alist)
struct peer *peer;
+ char *function;
char *fmt;
#endif /* __STDC__ */
{
+ char buffer[200];
va_list ap;
- if (debug) {
-
-#if defined(__STDC__)
- va_start(ap, fmt);
+#if defined(__STDC__) || defined(SYS_WINNT)
+ va_start(ap, fmt);
#else
- va_start(ap);
+ va_start(ap);
#endif /* __STDC__ */
- /*
- * Print debug message to stdout
- * In the future, we may want to get get more creative...
- */
- vfprintf(stderr, fmt, ap);
-
- va_end(ap);
+ /*
+ * 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(register struct peer *peer, register struct jheader *hp)
+jupiter_send(struct instance *instance, struct jheader *hp)
{
- register u_int len, size;
- register int cc;
- register u_short *sp;
+ u_int len, size;
+ int cc;
+ u_short *sp;
static char errstr[132];
size = sizeof(*hp);
@@ -1008,7 +936,7 @@ jupiter_send(register struct peer *peer, register struct jheader *hp)
size += (len + 1) * sizeof(u_short);
}
- if ((cc = write(peer->procptr->io.fd, (char *)hp, size)) < 0) {
+ 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) {
@@ -1025,65 +953,65 @@ static struct {
} reqmsg = {
{ putshort(JUPITER_SYNC), 0,
putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
- 0, putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
+ 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(register struct peer *peer, register u_int id,
- register u_int interval)
+jupiter_reqmsg(struct instance *instance, u_int id,
+ u_int interval)
{
- register struct jheader *hp;
- register struct jrequest *rp;
- register char *cp;
+ 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(peer, hp)) != NULL)
- jupiter_debug(peer, "jupiter_reqmsg: %u: %s\n", id, cp);
+ 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,
- putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC),
+ (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC),
0
};
static void
-jupiter_canmsg(register struct peer *peer, register u_int id)
+jupiter_canmsg(struct instance *instance, u_int id)
{
- register struct jheader *hp;
- register char *cp;
+ struct jheader *hp;
+ char *cp;
hp = &canmsg;
hp->id = putshort(id);
- if ((cp = jupiter_send(peer, hp)) != NULL)
- jupiter_debug(peer, "jupiter_canmsg: %u: %s\n", id, cp);
+ 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,
- putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY),
+ (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY),
0
};
static void
-jupiter_reqonemsg(register struct peer *peer, register u_int id)
+jupiter_reqonemsg(struct instance *instance, u_int id)
{
- register struct jheader *hp;
- register char *cp;
+ struct jheader *hp;
+ char *cp;
hp = &reqonemsg;
hp->id = putshort(id);
- if ((cp = jupiter_send(peer, hp)) != NULL)
- jupiter_debug(peer, "jupiter_reqonemsg: %u: %s\n", id, cp);
+ if ((cp = jupiter_send(instance, hp)) != NULL)
+ jupiter_debug(instance->peer, "jupiter_reqonemsg", "%u: %s", id, cp);
}
/* Set the platform dynamics */
@@ -1093,29 +1021,29 @@ static struct {
} platmsg = {
{ putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
- putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK), 0 },
+ (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK), 0 },
{ 0, 0, 0 }
};
static void
-jupiter_platform(register struct peer *peer, register u_int platform)
+jupiter_platform(struct instance *instance, u_int platform)
{
- register struct jheader *hp;
- register struct jplat *pp;
- register char *cp;
+ struct jheader *hp;
+ struct jplat *pp;
+ char *cp;
hp = &platmsg.jheader;
pp = &platmsg.jplat;
pp->platform = putshort(platform);
- if ((cp = jupiter_send(peer, hp)) != NULL)
- jupiter_debug(peer, "jupiter_platform: %u: %s\n", platform, cp);
+ 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(register u_short *sp, register u_int len)
+jupiter_cksum(u_short *sp, u_int len)
{
- register u_short sum, x;
+ u_short sum, x;
sum = 0;
while (len-- > 0) {
@@ -1127,60 +1055,61 @@ jupiter_cksum(register u_short *sp, register u_int len)
/* Return the size of the next message (or zero if we don't have it all yet) */
static int
-jupiter_recv(register struct peer *peer)
+jupiter_recv(struct instance *instance)
{
- register int n, len, size, cc;
- register struct refclockproc *pp;
- register struct jupiterunit *up;
- register struct jheader *hp;
- register u_char *bp;
- register u_short *sp;
-
- pp = peer->procptr;
- up = (struct jupiterunit *)pp->unitptr;
+ 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 = up->ssize;
+ size = instance->ssize;
if (size < cc)
return (0);
/* Search for the sync short if missing */
- sp = up->sbuf;
+ sp = instance->sbuf;
hp = (struct jheader *)sp;
if (getshort(hp->sync) != JUPITER_SYNC) {
/* Wasn't at the front, sync up */
- jupiter_debug(peer, "syncing");
+ jupiter_debug(instance->peer, "jupiter_recv", "syncing");
bp = (u_char *)sp;
n = size;
while (n >= 2) {
if (bp[0] != (JUPITER_SYNC & 0xff)) {
- jupiter_debug(peer, "{0x%x}", bp[0]);
+ /*
+ jupiter_debug(instance->peer, "{0x%x}", bp[0]);
+ */
++bp;
--n;
continue;
}
if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))
break;
- jupiter_debug(peer, "{0x%x 0x%x}", bp[0], bp[1]);
+ /*
+ jupiter_debug(instance->peer, "{0x%x 0x%x}", bp[0], bp[1]);
+ */
bp += 2;
n -= 2;
}
- jupiter_debug(peer, "\n");
+ /*
+ jupiter_debug(instance->peer, "\n");
+ */
/* Shuffle data to front of input buffer */
if (n > 0)
memcpy(sp, bp, n);
size = n;
- up->ssize = size;
+ 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(peer, "jupiter_recv: bad header checksum!\n");
+ jupiter_debug(instance->peer, "jupiter_recv", "bad header checksum!");
/* This is drastic but checksum errors should be rare */
- up->ssize = 0;
+ instance->ssize = 0;
return (0);
}
@@ -1195,10 +1124,10 @@ jupiter_recv(register struct peer *peer)
/* Check payload checksum */
sp = (u_short *)(hp + 1);
if (jupiter_cksum(sp, len) != getshort(sp[len])) {
- jupiter_debug(peer,
- "jupiter_recv: bad payload checksum!\n");
+ jupiter_debug(instance->peer,
+ "jupiter_recv", "bad payload checksum!");
/* This is drastic but checksum errors should be rare */
- up->ssize = 0;
+ instance->ssize = 0;
return (0);
}
cc += n;
@@ -1206,57 +1135,6 @@ jupiter_recv(register struct peer *peer)
return (cc);
}
-static int
-jupiter_ttyinit(register struct peer *peer, register int fd)
-{
- struct termios termios;
-
- memset((char *)&termios, 0, sizeof(termios));
- if (cfsetispeed(&termios, B9600) < 0 ||
- cfsetospeed(&termios, B9600) < 0) {
- jupiter_debug(peer,
- "jupiter_ttyinit: cfsetispeed/cfgetospeed: %s\n",
- strerror(errno));
- return (0);
- }
-#ifdef HAVE_CFMAKERAW
- cfmakeraw(&termios);
-#else
- termios.c_iflag &= ~(IMAXBEL | IXOFF | INPCK | BRKINT | PARMRK |
- ISTRIP | INLCR | IGNCR | ICRNL | IXON | IGNPAR);
- termios.c_iflag |= IGNBRK;
- termios.c_oflag &= ~OPOST;
- termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | ISIG |
- IEXTEN | NOFLSH | TOSTOP | PENDIN);
- termios.c_cflag &= ~(CSIZE | PARENB);
- termios.c_cflag |= CS8 | CREAD;
- termios.c_cc[VMIN] = 1;
-#endif
- termios.c_cflag |= CLOCAL;
- if (tcsetattr(fd, TCSANOW, &termios) < 0) {
- jupiter_debug(peer, "jupiter_ttyinit: tcsetattr: %s\n",
- strerror(errno));
- return (0);
- }
-
-#ifdef TIOCSPPS
- if (ioctl(fd, TIOCSPPS, (char *)&fdpps) < 0) {
- jupiter_debug(peer, "jupiter_ttyinit: TIOCSPPS: %s\n",
- strerror(errno));
- return (0);
- }
-#endif
-#ifdef I_PUSH
- if (ioctl(fd, I_PUSH, "ppsclock") < 0) {
- jupiter_debug(peer, "jupiter_ttyinit: push ppsclock: %s\n",
- strerror(errno));
- return (0);
- }
-#endif
-
- return (1);
-}
-
-#else /* not (REFCLOCK && CLOCK_JUPITER && PPS) */
+#else /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
int refclock_jupiter_bs;
-#endif /* not (REFCLOCK && CLOCK_JUPITER && PPS) */
+#endif /* not (REFCLOCK && CLOCK_JUPITER && HAVE_PPSAPI) */
diff --git a/contrib/ntp/ntpd/refclock_leitch.c b/contrib/ntp/ntpd/refclock_leitch.c
index 42b02fc..d7cd9bb 100644
--- a/contrib/ntp/ntpd/refclock_leitch.c
+++ b/contrib/ntp/ntpd/refclock_leitch.c
@@ -446,6 +446,7 @@ leitch_receive(
leitch->state = STATE_IDLE;
break;
}
+ leitch->reftime1.l_uf = 0;
#ifdef DEBUG
if (debug)
fprintf(stderr, "%lu\n", (u_long)leitch->reftime1.l_ui);
diff --git a/contrib/ntp/ntpd/refclock_local.c b/contrib/ntp/ntpd/refclock_local.c
index 0a0ecc0..3478f43 100644
--- a/contrib/ntp/ntpd/refclock_local.c
+++ b/contrib/ntp/ntpd/refclock_local.c
@@ -1,7 +1,8 @@
-/* wjm 17-aug-1995: add a hook for special treatment of VMS_LOCALUNIT */
/*
* 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>
@@ -69,31 +70,34 @@
*
* 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.
+ * 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.
+ * 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 */
-#define REFID "LCL\0" /* reference ID */
+#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 */
@@ -160,14 +164,11 @@ local_start(
* Initialize miscellaneous variables
*/
peer->precision = sys_precision;
+ pp->leap = LEAP_NOTINSYNC;
peer->stratum = STRATUM;
+ pp->stratum = STRATUM;
pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
-#if defined(VMS) && defined(VMS_LOCALUNIT)
- /* provide a non-standard REFID */
- if(unit == VMS_LOCALUNIT)
- memcpy((char *)&pp->refid,"LCLv",4);
-#endif /* VMS && VMS_LOCALUNIT */
+ memcpy(&pp->refid, "INIT", 4);
poll_time = current_time;
return (1);
}
@@ -175,6 +176,15 @@ local_start(
/*
* 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(
@@ -182,20 +192,19 @@ local_poll(
struct peer *peer
)
{
- struct refclockproc *pp;
-#if defined(KERNEL_PLL) && defined(STA_CLK)
+#if defined(KERNEL_PLL) && defined(LOCKCLOCK)
struct timex ntv;
- int retval;
-#endif /* KERNEL_PLL STA_CLK */
+#endif /* KERNEL_PLL LOCKCLOCK */
+ struct refclockproc *pp;
#if defined(VMS) && defined(VMS_LOCALUNIT)
- if(unit == VMS_LOCALUNIT) {
+ if (unit == VMS_LOCALUNIT) {
extern void vms_local_poll(struct peer *);
vms_local_poll(peer);
return;
}
-#endif /* VMS && VMS_LOCALUNIT */
+#endif /* VMS && VMS_LOCALUNIT */
pp = peer->procptr;
pp->polls++;
@@ -210,48 +219,42 @@ local_poll(
pp->fudgetime1 += pp->fudgetime2 * 1e-6 * (current_time -
poll_time);
poll_time = current_time;
- refclock_process_offset(pp, pp->lastrec, pp->lastrec, pp->fudgetime1);
- pp->leap = LEAP_NOWARNING;
- pp->disp = DISPERSION;
- pp->jitter = 0;
-#if defined(KERNEL_PLL) && defined(STA_CLK)
+ refclock_process_offset(pp, pp->lastrec, pp->lastrec,
+ pp->fudgetime1);
/*
- * If the kernel pll code is up and running, somebody else
- * may come diddle the clock. If so, they better use ntp_adjtime(),
- * and set the STA_CLK bit in the status word. In this case, the
- * performance information is read from the kernel and becomes the
- * variables presented to the clock mitigation process.
+ * If another process is disciplining the system clock, we set
+ * the leap bits and quality indicators from the kernel.
*/
- if (pll_control && kern_enable && (peer->flags & FLAG_PREFER)) {
- memset((char *)&ntv, 0, sizeof ntv);
- retval = ntp_adjtime(&ntv);
- if (ntv.status & STA_CLK) {
- ext_enable = 1;
- switch(retval) {
+#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_OK:
- pp->leap = LEAP_NOWARNING;
- break;
+ case TIME_INS:
+ pp->leap = LEAP_ADDSECOND;
+ peer->stratum = pp->stratum;
+ break;
- case TIME_INS:
- pp->leap = LEAP_ADDSECOND;
- break;
+ case TIME_DEL:
+ pp->leap = LEAP_DELSECOND;
+ peer->stratum = pp->stratum;
+ break;
- case TIME_DEL:
- pp->leap = LEAP_DELSECOND;
- break;
-
- case TIME_ERROR:
- pp->leap = LEAP_NOTINSYNC;
- }
- pp->disp = ntv.maxerror / 1e6;
- pp->jitter = SQUARE(ntv.esterror / 1e6);
- }
- } else {
- ext_enable = 0;
+ default:
+ pp->leap = LEAP_NOTINSYNC;
+ peer->stratum = STRATUM_UNSPEC;
}
-#endif /* KERNEL_PLL STA_CLK */
+ 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;
diff --git a/contrib/ntp/ntpd/refclock_msfees.c b/contrib/ntp/ntpd/refclock_msfees.c
index b1aaa56..ebfb983 100644
--- a/contrib/ntp/ntpd/refclock_msfees.c
+++ b/contrib/ntp/ntpd/refclock_msfees.c
@@ -99,7 +99,7 @@
* On the next minute it steps forward again :-(
* This is typically 16.5uS/S then 3975uS at the 4min re-sync,
* or 9.5uS/S then 3990.5uS at a 7min re-sync,
- * at which point it may loose the "00" second time stamp.
+ * 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,
*
@@ -720,7 +720,7 @@ ees_receive(
/* Incomplete. Wait for more. */
if (debug & DB_LOG_AWAITMORE)
msyslog(LOG_INFO,
- "I: ees clock %d: %x == %x: await more",
+ "I: ees clock %d: %p == %p: await more",
ees->unit, dpt, dpend);
return;
}
diff --git a/contrib/ntp/ntpd/refclock_mx4200.c b/contrib/ntp/ntpd/refclock_mx4200.c
index 3c520b0..bc694ad 100644
--- a/contrib/ntp/ntpd/refclock_mx4200.c
+++ b/contrib/ntp/ntpd/refclock_mx4200.c
@@ -67,6 +67,8 @@
# include <sys/ppsclock.h>
#endif
+#include "ntp_sprintf.h"
+
#ifndef HAVE_STRUCT_PPSCLOCKEV
struct ppsclockev {
# ifdef HAVE_STRUCT_TIMESPEC
@@ -892,7 +894,7 @@ mx4200_receive(
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);
/*
@@ -947,7 +949,7 @@ mx4200_receive(
* 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 occurence, when
+ * 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.
@@ -1103,8 +1105,6 @@ mx4200_parse_t(
pp->hour = hour;
pp->minute = minute;
pp->second = second;
- pp->msec = 0;
- pp->usec = 0;
/*
* Toss if sentence is marked invalid
@@ -1636,25 +1636,11 @@ mx4200_send(peer, fmt, va_alist)
cp = buf;
*cp++ = '$';
-#ifdef notdef
- /* BSD is rational */
- n = vsnprintf(cp, sizeof(buf) - 1, fmt, ap);
-#else
- /* SunOS sucks */
- (void)vsprintf(cp, fmt, ap);
- n = strlen(cp);
-#endif /* notdef */
+ n = VSNPRINTF((cp, sizeof(buf) - 1, fmt, ap));
ck = mx4200_cksum(cp, n);
cp += n;
++n;
-#ifdef notdef
- /* BSD is rational */
- n += snprintf(cp, sizeof(buf) - n - 5, "*%02X\r\n", ck);
-#else
- /* SunOS sucks */
- sprintf(cp, "*%02X\r\n", ck);
- n += strlen(cp);
-#endif /* notdef */
+ n += SNPRINTF((cp, sizeof(buf) - n - 5, "*%02X\r\n", ck));
m = write(pp->io.fd, buf, (unsigned)n);
if (m < 0)
diff --git a/contrib/ntp/ntpd/refclock_neoclock4x.c b/contrib/ntp/ntpd/refclock_neoclock4x.c
index 3b64017..082b1cf 100644
--- a/contrib/ntp/ntpd/refclock_neoclock4x.c
+++ b/contrib/ntp/ntpd/refclock_neoclock4x.c
@@ -1,15 +1,15 @@
/*
*
- * refclock_neoclock4x.c
+ * Refclock_neoclock4x.c
* - NeoClock4X driver for DCF77 or FIA Timecode
*
- * Date: 2002-04-27 1.0
+ * 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 by Linum Software GmbH <support@linum.com>
- *
+ * 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.
@@ -58,6 +58,24 @@
# 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
@@ -77,14 +95,17 @@
#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 */
+ 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;
@@ -112,8 +133,13 @@ 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 */
@@ -134,11 +160,15 @@ neoclock4x_start(int unit,
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);
- (void) sprintf(dev, "/dev/neoclock4x-%d", unit);
-
/* LDISC_STD, LDISC_RAW
* Open serial port. Use CLK line discipline, if available.
*/
@@ -147,13 +177,61 @@ neoclock4x_start(int unit,
{
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 */
@@ -163,28 +241,16 @@ neoclock4x_start(int unit,
if(ioctl(fd, TIOCMSET, (caddr_t)&sl232) == -1)
{
msyslog(LOG_CRIT, "NeoClock4X(%d): can't set RTS/DTR to power neoclock4x: %m", unit);
- }
-
- if(ioctl(fd, TCGETS, (caddr_t)&termsettings) == -1)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): can't query serial port settings: %m", unit);
- }
-
- /* 2400 Baud mit 8N2 */
- termsettings.c_cflag &= ~PARENB;
- termsettings.c_cflag |= CSTOPB;
- termsettings.c_cflag &= ~CSIZE;
- termsettings.c_cflag |= CS8;
-
- if(ioctl(fd, TCSETS, &termsettings) == -1)
- {
- msyslog(LOG_CRIT, "NeoClock4X(%d): can't set serial port to 2400 8N2: %m", unit);
+ (void) close(fd);
+ return (0);
}
#else
- msyslog(LOG_EMERG, "NeoClock4X(%d): OS interface is incapable of setting DTR/RTS to power NeoClock4X",
+ 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))
{
@@ -201,31 +267,26 @@ neoclock4x_start(int unit,
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
pp->io.fd = fd;
- /* no time is given by user! use 169.583333 ms to compensate the serial line delay
+ /*
+ * 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;
- if (!io_addclock(&pp->io))
- {
- msyslog(LOG_ERR, "NeoClock4X(%d): error add peer to ntpd: %m",unit);
- (void) close(fd);
- free(up);
- return (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 = '?';
@@ -241,13 +302,25 @@ neoclock4x_start(int unit,
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++)
{
- /*
- * Wait 3 second for receiver to power up
- */
NLOG(NLOG_CLOCKINFO)
- msyslog(LOG_INFO, "NeoClock4X(%d): try query NeoClock4X firmware version (%d/5)", unit, tries);
+ 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)))
{
@@ -255,9 +328,30 @@ neoclock4x_start(int unit,
}
}
+ /* 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);
}
@@ -269,30 +363,47 @@ neoclock4x_shutdown(int unit,
struct refclockproc *pp;
int sl232;
- pp = peer->procptr;
- up = (struct neoclock4x_unit *)pp->unitptr;
-
-#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)
+ if(NULL != peer)
{
- msyslog(LOG_CRIT, "NeoClock4X(%d): can't query RTS/DTR state: %m", unit);
- }
+ 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
- sl232 &= ~(TIOCM_DTR | TIOCM_RTS); /* turn on RTS, and DTR for power supply */
+ /* turn on RTS, and DTR for power supply */
+ sl232 &= ~(TIOCM_DTR | TIOCM_RTS);
#else
- sl232 &= ~(CIOCM_DTR | CIOCM_RTS); /* turn on RTS, and DTR for power supply */
+ /* 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);
- }
+ 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);
- io_closeclock(&pp->io);
- free(up);
NLOG(NLOG_CLOCKINFO)
msyslog(LOG_INFO, "NeoClock4X(%d): receiver shutdown done", unit);
}
@@ -307,23 +418,25 @@ neoclock4x_receive(struct recvbuf *rbufp)
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)
@@ -353,7 +466,7 @@ neoclock4x_receive(struct recvbuf *rbufp)
/* 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))
{
@@ -373,9 +486,9 @@ neoclock4x_receive(struct recvbuf *rbufp)
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
+ * If NeoClock4X is not synchronized to a radio clock
* check if we're allowed to synchronize with the quartz
* clock.
*/
@@ -410,9 +523,9 @@ neoclock4x_receive(struct recvbuf *rbufp)
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], &pp->msec, 2);
- pp->msec *= 10; /* convert 1/100s from neoclock to real miliseconds */
-
+ 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);
@@ -438,18 +551,23 @@ neoclock4x_receive(struct recvbuf *rbufp)
refclock_report(peer, CEVNT_BADDATE);
return;
}
-
- /* Year-2000 check! */
- /* wrap 2-digit date into 4-digit */
-
- if(pp->year < YEAR_PIVOT) /* < 98 */
- {
- pp->year += 100;
- }
- pp->year += 1900;
-
+
+ /* 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);
@@ -457,16 +575,15 @@ neoclock4x_receive(struct recvbuf *rbufp)
/*
some preparations
*/
- pp->day = ymd2yd(pp->year,month,day);
+ 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.%03d",
+ 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->msec);
+ pp->hour, pp->minute, pp->second, pp->nsec/1000);
}
up->utc_year = pp->year;
@@ -475,8 +592,8 @@ neoclock4x_receive(struct recvbuf *rbufp)
up->utc_hour = pp->hour;
up->utc_minute = pp->minute;
up->utc_second = pp->second;
- up->utc_msec = pp->msec;
-
+ up->utc_msec = pp->nsec/1000;
+
if(!refclock_process(pp))
{
NLOG(NLOG_CLOCKEVENT)
@@ -485,7 +602,10 @@ neoclock4x_receive(struct recvbuf *rbufp)
return;
}
refclock_receive(peer);
-
+
+ /* report good status */
+ refclock_report(peer, CEVNT_NOMINAL);
+
record_clock_stats(&peer->srcadr, pp->a_lastcode);
}
@@ -511,7 +631,7 @@ neoclock4x_control(int unit,
{
struct neoclock4x_unit *up;
struct refclockproc *pp;
-
+
if(NULL == peer)
{
msyslog(LOG_ERR, "NeoClock4X(%d): control: unit invalid/inactive", unit);
@@ -542,7 +662,7 @@ neoclock4x_control(int unit,
msyslog(LOG_NOTICE, "NeoClock4X(%d): using fudgetime1 with %0.5fs from ntp.conf.",
unit, pp->fudgetime1);
}
-
+
/* notify */
if(pp->sloppyclockflag & CLK_FLAG1)
{
@@ -561,61 +681,66 @@ neoclock4x_control(int unit,
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;
-
- sprintf(tmpbuf, "%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, 512, RO|DEF);
- tt += sprintf(tt, "calc_utc=\"%s\"", tmpbuf);
- tt = add_var(&out->kv_list, 512, RO|DEF);
- tt += sprintf(tt, "radiosignal=\"%s\"", up->radiosignal);
- tt = add_var(&out->kv_list, 512, RO|DEF);
- tt += sprintf(tt, "antenna1=\"%d\"", up->antenna1);
- tt = add_var(&out->kv_list, 512, RO|DEF);
- tt += sprintf(tt, "antenna2=\"%d\"", up->antenna2);
- tt = add_var(&out->kv_list, 512, RO|DEF);
+
+ 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)
- tt += sprintf(tt, "timesource=\"radio\"");
+ snprintf(tt, 39, "timesource=\"radio\"");
else if('C' == up->timesource)
- tt += sprintf(tt, "timesource=\"quartz\"");
+ snprintf(tt, 39, "timesource=\"quartz\"");
else
- tt += sprintf(tt, "timesource=\"unknown\"");
- tt = add_var(&out->kv_list, 512, RO|DEF);
+ snprintf(tt, 39, "timesource=\"unknown\"");
+ tt = add_var(&out->kv_list, 40, RO|DEF);
if('I' == up->quarzstatus)
- tt += sprintf(tt, "quartzstatus=\"synchronized\"");
+ snprintf(tt, 39, "quartzstatus=\"synchronized\"");
else if('X' == up->quarzstatus)
- tt += sprintf(tt, "quartzstatus=\"not synchronized\"");
+ snprintf(tt, 39, "quartzstatus=\"not synchronized\"");
else
- tt += sprintf(tt, "quartzstatus=\"unknown\"");
- tt = add_var(&out->kv_list, 512, RO|DEF);
+ snprintf(tt, 39, "quartzstatus=\"unknown\"");
+ tt = add_var(&out->kv_list, 40, RO|DEF);
if('S' == up->dststatus)
- tt += sprintf(tt, "dststatus=\"summer\"");
+ snprintf(tt, 39, "dststatus=\"summer\"");
else if('W' == up->dststatus)
- tt += sprintf(tt, "dststatus=\"winter\"");
+ snprintf(tt, 39, "dststatus=\"winter\"");
else
- tt += sprintf(tt, "dststatus=\"unknown\"");
- tt = add_var(&out->kv_list, 512, RO|DEF);
- tt += sprintf(tt, "firmware=\"%s\"", up->firmware);
- tt = add_var(&out->kv_list, 512, RO|DEF);
- tt += sprintf(tt, "serialnumber=\"%s\"", up->serial);
- tt = add_var(&out->kv_list, 512, RO|DEF);
+ 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)
+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;
@@ -625,14 +750,15 @@ static int neol_hexatoi_len(const char str[],
return (n);
}
-int neol_atoi_len(const char str[],
+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';
@@ -657,12 +783,13 @@ int neol_atoi_len(const char str[],
* 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)
+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 */
@@ -676,41 +803,36 @@ static unsigned long neol_mktime(int year,
)*60 + sec; /* finally seconds */
}
-static void neol_localtime(unsigned long utc,
- int* year,
- int* month,
- int* day,
- int* hour,
- int* minute,
- int* second)
+static void
+neol_localtime(unsigned long utc,
+ int* year,
+ int* month,
+ int* day,
+ int* hour,
+ int* min,
+ int* sec)
{
- ldiv_t d;
-
- /* Sekunden */
- d = ldiv(utc, 60);
- *second = d.rem;
-
- /* Minute */
- d = ldiv(d.quot, 60);
- *minute = d.rem;
-
- /* Stunden */
- d = ldiv(d.quot, 24);
- *hour = d.rem;
-
+ *sec = utc % 60;
+ utc /= 60;
+ *min = utc % 60;
+ utc /= 60;
+ *hour = utc % 24;
+ utc /= 24;
+
/* JDN Date 1/1/1970 */
- neol_jdn_to_ymd(d.quot + 2440588L, year, month, day);
+ neol_jdn_to_ymd(utc + 2440588L, year, month, day);
}
-static void neol_jdn_to_ymd(unsigned long jdn,
- int *yy,
- int *mm,
- int *dd)
+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;
@@ -721,83 +843,110 @@ static void neol_jdn_to_ymd(unsigned long jdn,
x = m / 11UL;
m = m + 2UL - 12UL * x;
y = 100UL * (z - 49UL) + y + x;
-
+
*yy = (int)y;
*mm = (int)m;
*dd = (int)d;
}
-/*
- * 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);
- }
+#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)
{
- unsigned char tmpbuf[256];
+ char tmpbuf[256];
int len;
int lastsearch;
unsigned char c;
int last_c_was_crlf;
int last_crlf_conv_len;
int init;
- int read_tries;
+ int read_errors;
int flag = 0;
+ int chars_read;
/* wait a little bit */
- neol_mdelay(250);
+ sleep(1);
if(-1 != write(fd, "V", 1))
{
/* wait a little bit */
- neol_mdelay(250);
+ sleep(1);
memset(tmpbuf, 0x00, sizeof(tmpbuf));
-
+
len = 0;
lastsearch = 0;
last_c_was_crlf = 0;
last_crlf_conv_len = 0;
init = 1;
- read_tries = 0;
+ read_errors = 0;
+ chars_read = 0;
for(;;)
{
- if(read_tries++ > 500)
+ 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))
{
- neol_mdelay(25);
+ 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;
}
-
- //msyslog(LOG_NOTICE, "NeoClock4X(%d): firmware %c = %02Xh", unit, c, c);
+
+#if 0
+ msyslog(LOG_NOTICE, "NeoClock4X(%d): firmware %c = %02Xh", unit, c, c);
+#endif
+
if(0x0A == c || 0x0D == c)
{
if(last_c_was_crlf)
@@ -823,7 +972,7 @@ neol_query_firmware(int fd,
{
last_c_was_crlf = 0;
if(0x00 != c)
- tmpbuf[len++] = c;
+ tmpbuf[len++] = (char) c;
}
tmpbuf[len] = '\0';
if(len > sizeof(tmpbuf)-5)
@@ -846,7 +995,35 @@ neol_query_firmware(int fd,
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 */
@@ -858,7 +1035,34 @@ int refclock_neoclock4x_bs;
* 2002/04/27 cjh
* Revision 1.0 first release
*
- * 2002/0715 cjh
+ * 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
index e9304ee..28d6263 100644
--- a/contrib/ntp/ntpd/refclock_nmea.c
+++ b/contrib/ntp/ntpd/refclock_nmea.c
@@ -7,6 +7,11 @@
#include <config.h>
#endif
+#if defined(SYS_WINNT)
+#undef close
+#define close closesocket
+#endif
+
#if defined(REFCLOCK) && defined(CLOCK_NMEA)
#include "ntpd.h"
@@ -147,14 +152,15 @@ nmea_start(
*/
(void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
+ fd = refclock_open(device, SPEED232, LDISC_CLK);
+ if (fd < 0)
return (0);
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct nmeaunit *)
- emalloc(sizeof(struct nmeaunit)))) {
+ up = (struct nmeaunit *)emalloc(sizeof(struct nmeaunit));
+ if (up == NULL) {
(void) close(fd);
return (0);
}
@@ -380,7 +386,7 @@ nmea_receive(
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct nmeaunit *)pp->unitptr;
- rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
+ 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
@@ -433,8 +439,8 @@ nmea_receive(
/* See if I want to process this message type */
- if ( ((peer->ttlmax == 0) && (cmdtype != GPRMC))
- || ((peer->ttlmax != 0) && !(cmdtype & peer->ttlmax)) )
+ if ( ((peer->ttl == 0) && (cmdtype != GPRMC))
+ || ((peer->ttl != 0) && !(cmdtype & peer->ttl)) )
return;
pp->lencode = rd_lencode;
@@ -530,21 +536,21 @@ nmea_receive(
/* Default to 0 milliseconds, if decimal convert milliseconds in
one, two or three digits
*/
- pp->msec = 0;
+ pp->nsec = 0;
if (dp[6] == '.') {
if (isdigit((int)dp[7])) {
- pp->msec = (dp[7] - '0') * 100;
+ pp->nsec = (dp[7] - '0') * 100000000;
if (isdigit((int)dp[8])) {
- pp->msec += (dp[8] - '0') * 10;
+ pp->nsec += (dp[8] - '0') * 10000000;
if (isdigit((int)dp[9])) {
- pp->msec += (dp[9] - '0');
+ pp->nsec += (dp[9] - '0') * 1000000;
}
}
}
}
if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
- || pp->msec > 1000) {
+ || pp->nsec > 1000000000) {
refclock_report(peer, CEVNT_BADTIME);
return;
}
@@ -604,7 +610,7 @@ nmea_receive(
*/
if (nmea_pps(up, &rd_tmp) == 1) {
pp->lastrec = up->tstamp = rd_tmp;
- pp->msec = 0;
+ pp->nsec = 0;
}
#endif /* HAVE_PPSAPI */
@@ -630,7 +636,7 @@ nmea_receive(
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 */
diff --git a/contrib/ntp/ntpd/refclock_oncore.c b/contrib/ntp/ntpd/refclock_oncore.c
index 43a38fb..14db92f 100644
--- a/contrib/ntp/ntpd/refclock_oncore.c
+++ b/contrib/ntp/ntpd/refclock_oncore.c
@@ -9,8 +9,9 @@
* 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.
- * The receivers with TRAIM (VP, UT, UT+), will be more accurate than the others.
+ * 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:
@@ -28,16 +29,16 @@
* OPTIONS LIST IB
*
* (Basic) (M12)
- * COPYRIGHT 1991-1996 MOTOROLA INC. COPYRIGHT 1991-2000 MOTOROLA INC.
- * SFTW P/N # 98-P36830P SFTW P/N # 61-G10002A
- * SOFTWARE VER # 8 SOFTWARE VER # 1
- * SOFTWARE REV # 8 SOFTWARE REV # 3
- * SOFTWARE DATE 06 Aug 1996 SOFTWARE DATE Mar 13 2000
- * MODEL # B4121P1155 MODEL # P143T12NR1
+ * 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 # SSG0226478 SERIAL # P003UD
- * MANUFACTUR DATE 7E02 MANUFACTUR DATE 0C27
- * OPTIONS LIST IB
+ * SERIAL # SSG0049809 SERIAL # P003UD
+ * MANUFACTUR DATE 417AMA199 MANUFACTUR DATE 0C27
+ * OPTIONS LIST AB
*
* --------------------------------------------------------------------------
* This code uses the two devices
@@ -138,7 +139,9 @@ struct ppsclockev {
enum receive_state {
ONCORE_NO_IDEA,
- ONCORE_ID_SENT,
+ ONCORE_CHECK_ID,
+ ONCORE_CHECK_CHAN,
+ ONCORE_HAVE_CHAN,
ONCORE_RESET_SENT,
ONCORE_TEST_SENT,
ONCORE_INIT,
@@ -154,6 +157,14 @@ enum site_survey_state {
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.
*/
@@ -204,7 +215,7 @@ struct instance {
int ttyfd; /* TTY file descriptor */
int ppsfd; /* PPS file descriptor */
- int statusfd; /* Status shm descriptor */
+ int shmemfd; /* Status shm descriptor */
#ifdef HAVE_PPSAPI
pps_handle_t pps_h;
pps_params_t pps_p;
@@ -212,6 +223,7 @@ struct instance {
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;
@@ -224,9 +236,10 @@ struct instance {
u_int shmem_Ba;
u_int shmem_Ea;
u_int shmem_Ha;
- u_char shmem_first;
u_char shmem_reset;
u_char shmem_Posn;
+ u_char shmem_bad_Ea;
+ u_char almanac_from_shmem;
double ss_lat;
double ss_long;
@@ -240,59 +253,98 @@ struct instance {
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, -1 unknown, 0 no, +1 yes */
+ 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;
- int pollcnt;
- u_int ev_serial;
+ u_long ev_serial;
int Rcvptr;
u_char Rcvbuf[500];
- u_char Ea[160]; /* Ba, Ea or Ha */
- u_char En[70]; /* Bn or En */
+ u_char BEHa[160]; /* Ba, Ea or Ha */
+ u_char BEHn[80]; /* Bn , En , or Hn */
u_char Cj[300];
- u_char As;
- u_char Ay;
- u_char Az;
+ 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;
- u_int timeout; /* count to retry Cj after Fa self-test */
- u_char count; /* cycles thru Ea before starting */
+ 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_int saw_At;
+ u_char hardpps;
};
#define rcvbuf instance->Rcvbuf
#define rcvptr instance->Rcvptr
-static void oncore_consume P((struct instance *));
-static void oncore_poll P((int, struct peer *));
-static void oncore_read_config P((struct instance *));
-static void oncore_receive P((struct recvbuf *));
-static void oncore_sendmsg P((int fd, u_char *, size_t));
-static void oncore_shutdown P((int, struct peer *));
-static int oncore_start P((int, struct peer *));
-static void oncore_get_timestamp P((struct instance *, long, long));
-static void oncore_init_shmem P((struct instance *));
-static void oncore_print_As P((struct instance *));
+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_BnEn 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));
@@ -300,7 +352,7 @@ struct refclock refclock_oncore = {
oncore_start, /* start up driver */
oncore_shutdown, /* shut down driver */
oncore_poll, /* transmit poll message */
- noentry, /* not used */
+ oncore_control, /* fudge (flag) control messages */
noentry, /* not used */
noentry, /* not used */
NOFLAGS /* not used */
@@ -322,13 +374,15 @@ static struct msg_desc {
{ "Ea", 76, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" },
{ "Ba", 68, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdsC" },
{ "Ha", 154, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmaaaaoooohhhhmmmmVVvvhhddntimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddssrrccooooTTushmvvvvvvC" },
- { "En", 69, oncore_msg_BnEn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC" },
- { "Bn", 59, oncore_msg_BnEn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffC" },
+ { "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, 0, "" },
- { "Ae", 11, 0, "" },
- { "Af", 15, 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, "" },
@@ -338,6 +392,7 @@ static struct msg_desc {
{ "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, "" },
@@ -347,132 +402,92 @@ static struct msg_desc {
{ "Cj", 294, oncore_msg_Cj, "" },
{ "Ek", 71, 0, "" },
{ "Fa", 9, oncore_msg_CaFaIa, "" },
- { "Gd", 8, 0, "" },
+ { "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, "" }
};
-/*
- * Position Set.
- */
-u_char oncore_cmd_Ad[] = { 'A', 'd', 0,0,0,0 };
-u_char oncore_cmd_Ae[] = { 'A', 'e', 0,0,0,0 };
-u_char oncore_cmd_Af[] = { 'A', 'f', 0,0,0,0, 0 };
-u_char oncore_cmd_Ga[] = { 'G', 'a', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
-
-/*
- * Position-Hold Mode
- * Start automatic site survey
- */
-static u_char oncore_cmd_At0[] = { 'A', 't', 0 }; /* Posn Hold off */
-static u_char oncore_cmd_At1[] = { 'A', 't', 1 }; /* Posn Hold on */
-static u_char oncore_cmd_At2[] = { 'A', 't', 2 }; /* Start Site Survey */
-
-/*
- * 0D/2D Position and Set.
- */
-u_char oncore_cmd_As[] = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
-u_char oncore_cmd_Asx[]= { 'A', 's', 0x7f, 0xff, 0xff, 0xff,
- 0x7f, 0xff, 0xff, 0xff,
- 0x7f, 0xff, 0xff, 0xff, 0xff };
-u_char oncore_cmd_Au[] = { 'A', 'u', 0,0,0,0,0 };
-
-u_char oncore_cmd_Av0[] = { 'A', 'v', 0 };
-u_char oncore_cmd_Av1[] = { 'A', 'v', 1 };
-
-u_char oncore_cmd_Gd0[] = { 'G', 'd', 0 }; /* 3D */
-u_char oncore_cmd_Gd1[] = { 'G', 'd', 1 }; /* 0D */
-u_char oncore_cmd_Gd2[] = { 'G', 'd', 2 }; /* 2D */
-
-/*
- * Set to UTC time (not GPS).
- */
-u_char oncore_cmd_Aw[] = { 'A', 'w', 1 };
-
-/*
- * Output Almanac when it changes
- */
-u_char oncore_cmd_Be[] = { 'B', 'e', 1 };
-/*
- * Read back PPS Offset for Output
- */
-u_char oncore_cmd_Ay[] = { 'A', 'y', 0, 0, 0, 0 };
-u_char oncore_cmd_Ayx[] = { 'A', 'y', 0xff, 0xff, 0xff, 0xff };
-
-/*
- * Read back Cable Delay for Output
+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
*/
-u_char oncore_cmd_Az[] = { 'A', 'z', 0, 0, 0, 0 };
-u_char oncore_cmd_Azx[] = { 'A', 'z', 0xff, 0xff, 0xff, 0xff };
-/*
- * Application type = static.
- */
-u_char oncore_cmd_AB[] = { 'A', 'B', 4 };
-
-/*
- * Visible Satellite Status Msg.
- */
-u_char oncore_cmd_Bb[] = { 'B', 'b', 1 };
-
-/*
- * Leap Second Pending Message
- * Request message once
- */
-u_char oncore_cmd_Bj[] = { 'B', 'j', 0 };
-u_char oncore_cmd_Gj[] = { 'G', 'j' };
-
-/*
- * Set to Defaults
- */
-static u_char oncore_cmd_Cf[] = { 'C', 'f' };
-
-/*
- * Set to Position Fix mode (only needed on VP).
- */
-u_char oncore_cmd_Cg[] = { 'C', 'g', 1 };
-
-/*
- * Receiver Id
- */
-static u_char oncore_cmd_Cj[] = { 'C', 'j' };
-
-/*
- * Position/Status/Data message
- * Send once per second
- */
-static u_char oncore_cmd_Ea[] = { 'E', 'a', 1 };
-static u_char oncore_cmd_Ba[] = { 'B', 'a', 1 };
-static u_char oncore_cmd_Ha[] = { 'H', 'a', 1 };
-static u_char oncore_cmd_Ea0[] = { 'E', 'a', 0 };
-static u_char oncore_cmd_Ba0[] = { 'B', 'a', 0 };
-
-/*
- * Position/Status Extension Msg
- */
-u_char oncore_cmd_Ek[] = { 'E', 'k', 0 }; /* just turn off */
-
-/*
- * Time Raim Setup & Status Message
- * Send once per second
- * Time-RAIM on
- * Alarm limit 1us
- * PPS on when we have the first sat
- */
-static u_char oncore_cmd_En[] = { 'E', 'n', 1, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static u_char oncore_cmd_En0[] = { 'E', 'n', 0, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static u_char oncore_cmd_Bn[] = { 'B', 'n', 1, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-static u_char oncore_cmd_Bn0[] = { 'B', 'n', 0, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-/*
- * Self-test
- */
-static u_char oncore_cmd_Ca[] = { 'C', 'a' }; /* 6 Chan */
-static u_char oncore_cmd_Fa[] = { 'F', 'a' }; /* 8 Chan */
-static u_char oncore_cmd_Ia[] = { 'I', 'a' }; /* 12 Chan */
+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 */
@@ -502,10 +517,6 @@ static u_char oncore_cmd_Ia[] = { 'I', 'a' }; /* 12 Chan */
/* from buffer, char *buf, result to an int */
#define buf_w32(buf) (((buf)[0]&0200) ? (-(~w32(buf)+1)) : w32(buf))
-extern int pps_assert;
-extern int pps_hardpps;
-
-
/*
* oncore_start - initialize data for processing
@@ -519,7 +530,7 @@ oncore_start(
{
register struct instance *instance;
struct refclockproc *pp;
- int fd1, fd2, mode;
+ int fd1, fd2;
char device1[30], device2[30];
const char *cp;
struct stat stat1, stat2;
@@ -548,6 +559,14 @@ oncore_start(
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
@@ -559,7 +578,7 @@ oncore_start(
exit(1);
}
fd2 = fd1;
- } else { /* different devices here */
+ } else { /* different devices here */
if (!(fd1=refclock_open(device1, SPEED, LDISC_RAW))) {
perror("ONCORE: fd1");
exit(1);
@@ -570,24 +589,18 @@ oncore_start(
}
}
- /* Devices now open, create instance structure for this unit */
-
- if (!(instance = (struct instance *) malloc(sizeof *instance))) {
- perror("malloc");
- close(fd1);
- return (0);
- }
- memset((char *) instance, 0, sizeof *instance);
-
- /* link instance up and down */
+ /* 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;
- /* initialize miscellaneous variables */
+ cp = "ONCORE DRIVER -- CONFIGURING";
+ record_clock_stats(&(instance->peer->srcadr), cp);
instance->o_state = ONCORE_NO_IDEA;
cp = "state = ONCORE_NO_IDEA";
@@ -597,11 +610,14 @@ oncore_start(
instance->ppsfd = fd2;
instance->Bj_day = -1;
- instance->assert = pps_assert;
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;
@@ -609,7 +625,7 @@ oncore_start(
pp->clockdesc = "Motorola Oncore GPS Receiver";
memcpy((char *)&pp->refid, "GPS\0", (size_t) 4);
- /* go read any input data in /etc/ntp.oncoreX */
+ /* go read any input data in /etc/ntp.oncoreX or /etc/ntp/oncore.X */
oncore_read_config(instance);
@@ -619,15 +635,183 @@ oncore_start(
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");
+ 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");
+ msyslog(LOG_ERR, "refclock_ioctl: time_pps_getparams failed: %m");
return (0);
}
@@ -652,59 +836,183 @@ oncore_start(
exit(1);
}
- if (pps_device && pps_device[0]) {
- if (stat(pps_device, &stat1)) {
- perror("ONCORE: stat pps_device");
- return(0);
- }
+ /* If HARDPPS is on, we tell kernel */
- /* must have hardpps ON, and fd2 must be the same device as on the pps line */
+ if (instance->hardpps) {
+ int i;
- if (pps_hardpps && ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino))) {
- int i;
+ if (instance->assert)
+ i = PPS_CAPTUREASSERT;
+ else
+ i = PPS_CAPTURECLEAR;
- 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;
+ 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
- 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
+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);
}
- /*
- * This will return the Model Number of the Oncore receiver.
+ /* 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.
*/
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
- instance->o_state = ONCORE_ID_SENT;
- cp = "state = ONCORE_ID SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->timeout = 4;
+ 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;
- instance->pollcnt = 2;
- return (1);
+ 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 */
@@ -751,8 +1059,8 @@ oncore_read_config(
* -------------------------------------------------------------------------------
*
* 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, STATUS,
- * POSN3D, POSN2D, CHAN, TRAIM
+ * 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).
*
@@ -773,7 +1081,7 @@ oncore_read_config(
* 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 reciever reports height in both GPS and MSL, then we will report
+ * 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
@@ -793,24 +1101,36 @@ oncore_read_config(
* 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 opition.
- * First, to enable the option there must be an ASSERT line with a file name.
+ * 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 the shared memory there are three 'records' containing the @@Ea (or equivalent)
- * data, and this contains the position data. There will always be data in the
- * record cooresponding to the '0D' @@Ea record, and the user has a choice of
- * filling the '3D' @@Ea record by specifying POSN3D, or the '2D' record by
- * specifying POSN2D. In either case the '2D' or '3D' record is filled once
- * every 15s.
+ * 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 existance of TRAIM.
+ * 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
@@ -821,7 +1141,7 @@ oncore_read_config(
FILE *fd;
char *cp, *cc, *ca, line[100], units[2], device[20], Msg[160];
- int i, sign, lat_flg, long_flg, ht_flg, mode;
+ 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 */
@@ -835,7 +1155,7 @@ oncore_read_config(
}
}
- mode = 0;
+ mode = mask = 0;
lat_flg = long_flg = ht_flg = 0;
while (fgets(line, 100, fd)) {
@@ -871,12 +1191,6 @@ oncore_read_config(
for (; *ca && isascii((int)*ca) && (isspace((int)*ca) || (*ca == '=')); ca++)
continue;
- /*
- * move call to oncore_shmem_init() from here to after
- * we have determined Oncore Model, so we can ignore
- * request if model doesnt 'support' it
- */
-
if (!strncmp(cc, "STATUS", (size_t) 6) || !strncmp(cc, "SHMEM", (size_t) 5)) {
i = strlen(ca);
instance->shmem_fname = (char *) malloc((unsigned) (i+1));
@@ -963,6 +1277,8 @@ oncore_read_config(
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)) {
@@ -970,11 +1286,15 @@ oncore_read_config(
} else if (!strncmp(cc, "CHAN", (size_t) 4)) {
sscanf(ca, "%d", &i);
if ((i == 6) || (i == 8) || (i == 12))
- instance->chan = i;
+ instance->chan_in = i;
} else if (!strncmp(cc, "TRAIM", (size_t) 5)) {
- instance->traim = 1; /* so TRAIM alone is YES */
+ instance->traim_in = 1; /* so TRAIM alone is YES */
if (!strcmp(ca, "NO") || !strcmp(ca, "OFF")) /* Yes/No, On/Off */
- instance->traim = 0;
+ 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);
@@ -985,7 +1305,7 @@ oncore_read_config(
*/
instance->posn_set = 1;
- if ((lat_flg || long_flg || ht_flg) && !(lat_flg * long_flg * ht_flg)) {
+ 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) {
@@ -1002,170 +1322,8 @@ oncore_read_config(
-static void
-oncore_init_shmem(
- struct instance *instance
- )
-{
-#ifdef ONCORE_SHMEM_STATUS
- int i, l, n;
- char *buf;
- struct msg_desc *mp;
- size_t oncore_shmem_length;
-
- if (instance->shmem_first)
- return;
-
- instance->shmem_first++;
-
- if ((instance->statusfd = open(instance->shmem_fname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
- perror(instance->shmem_fname);
- return;
- }
-
- 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);
- }
- oncore_shmem_length = n + 2;
- fprintf(stderr, "ONCORE: SHMEM length: %d bytes\n", (int) oncore_shmem_length);
-
- buf = malloc(oncore_shmem_length);
- if (buf == NULL) {
- perror("malloc");
- return;
- }
- memset(buf, 0, sizeof(buf));
- i = write(instance->statusfd, buf, oncore_shmem_length);
- if (i != oncore_shmem_length) {
- perror(instance->shmem_fname);
- return;
- }
- free(buf);
- instance->shmem = (u_char *) mmap(0, oncore_shmem_length,
- PROT_READ | PROT_WRITE,
-#ifdef MAP_HASSEMAPHORE
- MAP_HASSEMAPHORE |
-#endif
- MAP_SHARED,
- instance->statusfd, (off_t)0);
- if (instance->shmem == (u_char *)MAP_FAILED) {
- instance->shmem = 0;
- close (instance->statusfd);
- return;
- }
- for (mp = oncore_messages; mp->flag[0]; mp++) {
- l = mp->shmem;
- instance->shmem[l + 0] = mp->len >> 8;
- instance->shmem[l + 1] = mp->len & 0xff;
- instance->shmem[l + 2] = 0;
- instance->shmem[l + 3] = '@';
- instance->shmem[l + 4] = '@';
- instance->shmem[l + 5] = mp->flag[0];
- instance->shmem[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++) {
- instance->shmem[l + i * (mp->len+3) + 0] = mp->len >> 8;
- instance->shmem[l + i * (mp->len+3) + 1] = mp->len & 0xff;
- instance->shmem[l + i * (mp->len+3) + 2] = 0;
- instance->shmem[l + i * (mp->len+3) + 3] = '@';
- instance->shmem[l + i * (mp->len+3) + 4] = '@';
- instance->shmem[l + i * (mp->len+3) + 5] = mp->flag[0];
- instance->shmem[l + i * (mp->len+3) + 6] = mp->flag[1];
- }
- }
- }
-#endif /* ONCORE_SHMEM_STATUS */
-}
-
-
-
/*
- * 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);
-
- 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;
-}
-
-
-
-/*
- * move data from NTP to buffer (toss in unlikely case it wont fit)
+ * move data from NTP to buffer (toss the extra in the unlikely case it won't fit)
*/
static void
@@ -1215,7 +1373,7 @@ oncore_consume(
struct instance *instance
)
{
- int i, j, m;
+ int i, m;
unsigned l;
while (rcvptr >= 7) {
@@ -1261,10 +1419,7 @@ oncore_consume(
if (debug)
printf("ONCORE[%d]: NO <CR><LF> at end of message\n", instance->unit);
} else { /* check the CheckSum */
- j = 0;
- for (i = 2; i < l-3; i++)
- j ^= rcvbuf[i];
- if (j == rcvbuf[l-3]) {
+ 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,
@@ -1274,7 +1429,7 @@ oncore_consume(
if (oncore_messages[m].handler)
oncore_messages[m].handler(instance, rcvbuf, (size_t) (l-3));
} else if (debug) {
- printf("ONCORE[%d]: Checksum mismatch! calc %o is %o\n", instance->unit, j, rcvbuf[l-3]);
+ 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]);
@@ -1290,29 +1445,317 @@ oncore_consume(
-/*
- * write message to Oncore.
- */
-
static void
-oncore_sendmsg(
- int fd,
- u_char *ptr,
- size_t len
+oncore_get_timestamp(
+ struct instance *instance,
+ long dt1, /* tick offset THIS time step */
+ long dt2 /* tick offset NEXT time step */
)
{
- u_char cs = 0;
+ 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 */
- 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);
+#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.
@@ -1336,9 +1779,9 @@ oncore_msg_any(
if (debug > 3) {
#ifdef HAVE_GETCLOCK
- (void) getclock(TIMEOFDAY, &ts);
- tv.tv_sec = ts.tv_sec;
- tv.tv_usec = ts.tv_nsec / 1000;
+ (void) getclock(TIMEOFDAY, &ts);
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000;
#else
GETTIMEOFDAY(&tv, 0);
#endif
@@ -1368,542 +1811,344 @@ oncore_msg_any(
-/*
- * Demultiplex the almanac into shmem
- */
+/* Latitude, Longitude, Height */
static void
-oncore_msg_Cb(
+oncore_msg_Adef(
struct instance *instance,
u_char *buf,
size_t len
)
{
- int i;
+}
- if (instance->shmem == NULL)
- return;
- if (buf[4] == 5)
- 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
- i = 34;
- i *= 36;
- instance->shmem[instance->shmem_Cb + i + 2]++;
- memcpy(instance->shmem + instance->shmem_Cb + i + 3, buf, (size_t) (len + 3));
-}
+/* 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);
+}
-/*
- * We do an @@Cj twice in the initialization sequence.
- * o Once at the very beginning to get the Model number so we know what commands
- * we can issue,
- * 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.
- */
/*
- * Determine the Type from the Model #, this determines #chan and if TRAIM is
- * available. We use ONLY the #chans, and determint TRAIM by trying it.
+ * get Position hold position
*/
static void
-oncore_msg_Cj(
+oncore_msg_As(
struct instance *instance,
u_char *buf,
size_t len
)
{
- memcpy(instance->Cj, buf, len);
+ instance->ss_lat = buf_w32(&buf[4]);
+ instance->ss_long = buf_w32(&buf[8]);
+ instance->ss_ht = buf_w32(&buf[12]);
- instance->timeout = 0;
- if (instance->o_state == ONCORE_ID_SENT)
- oncore_msg_Cj_id(instance, buf, len);
- else if (instance->o_state == ONCORE_INIT)
- oncore_msg_Cj_init(instance, buf, len);
+ /* Print out Position */
+ oncore_print_posn(instance);
}
-/* The information on determing 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 didnt give the information out.
+/*
+ * Try to use Oncore UT+ Auto Survey Feature
+ * If its not there (VP), set flag to do it ourselves.
*/
static void
-oncore_msg_Cj_id(
+oncore_msg_At(
struct instance *instance,
u_char *buf,
size_t len
)
{
- char *cp, *cp1, *cp2, Model[21], Msg[160];
- int mode;
+ char *cp;
- /* Write Receiver ID message to clockstats file */
+ 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");
- 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;
+ cp = "SSstate = ONCORE_SS_HW";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ instance->site_survey = ONCORE_SS_HW;
+ }
}
+}
- /* 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';
+/*
+ * get PPS Offset
+ * Nb. @@Ay is not supported for early UT (no plus) model
+ */
- 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 (!strncmp(Model, "P1", (size_t) 2)) {
- cp = "M12";
- instance->model = ONCORE_M12;
- } else if (Model[0] == 'R') {
- 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;
- }
+static void
+oncore_msg_Ay(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ char Msg[120];
- 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);
+ if (instance->saw_Ay)
+ return;
- if (instance->chan == 0) { /* dont reset if set in input data */
- instance->chan = 8; /* default */
- if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
- instance->chan = 6;
- else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
- instance->chan = 8;
- else if (instance->model == ONCORE_M12)
- instance->chan = 12;
- }
+ instance->saw_Ay = 1;
- if (instance->traim == -1) { /* dont reset if set in input data */
- instance->traim = 0; /* default */
- if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
- instance->traim = 0;
- else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
- instance->traim = 1;
- else if (instance->model == ONCORE_M12)
- instance->traim = 0;
- }
+ instance->offset = buf_w32(&buf[4]);
- sprintf(Msg, "Channels = %d, TRAIM = %s", instance->chan,
- ((instance->traim < 0) ? "UNKNOWN" : ((instance->traim > 0) ? "ON" : "OFF")));
+ sprintf(Msg, "PPS Offset is set to %ld ns", instance->offset);
record_clock_stats(&(instance->peer->srcadr), Msg);
+}
- /* The M12 with 1.3 Firmware, looses track of all Satellites and has to
- * start again if we go from 0D -> 3D, then looses them again when we
- * go from 3D -> 0D. We do this to get a @@Ea message for SHMEM.
- * For NOW we have SHMEM turned off for the M12, v1.3
- */
-/*BAD M12*/ if (instance->model == ONCORE_M12 && instance->version == 1 && instance->revision <= 3) {
- instance->shmem_fname = 0;
- cp = "*** SHMEM turned off for ONCORE M12 ***";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
- /*
- * we now know model number and have zeroed
- * instance->shmem_fname if SHMEM is not supported
- */
+/*
+ * get Cable Delay
+ */
- if (instance->shmem_fname);
- oncore_init_shmem(instance);
+static void
+oncore_msg_Az(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ char Msg[120];
- if (instance->shmem)
- cp = "SHMEM is available";
- else
- cp = "SHMEM is NOT available";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ if (instance->saw_Az)
+ return;
-#ifdef HAVE_PPSAPI
- if (instance->assert)
- cp = "Timing on Assert.";
- else
- cp = "Timing on Clear.";
- record_clock_stats(&(instance->peer->srcadr), cp);
-#endif
+ instance->saw_Az = 1;
- mode = instance->init_type;
- if (mode == 3 || mode == 4) { /* Cf will call Fa */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cf, sizeof(oncore_cmd_Cf));
- instance->o_state = ONCORE_RESET_SENT;
- cp = "state = ONCORE_RESET_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- } else {
- 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));
+ instance->delay = buf_w32(&buf[4]);
- instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->timeout = 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_Cj_init(
+oncore_msg_BaEaHa(
struct instance *instance,
u_char *buf,
size_t len
)
{
- char *cp, Cmd[20], Msg[160];
- int mode;
-
- /* OK, know type of Oncore, have possibly reset, and have tested.
- * If we have or don't have TRAIM and position hold may still be unknown.
- * Now initialize.
- */
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Set Posn Fix mode (not Idle (VP)) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bb, sizeof(oncore_cmd_Bb)); /* turn on for shmem */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ek, sizeof(oncore_cmd_Ek)); /* turn off */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Aw, sizeof(oncore_cmd_Aw)); /* UTC time */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_AB, sizeof(oncore_cmd_AB)); /* Appl type static */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Be, sizeof(oncore_cmd_Be)); /* Tell us the Almanac for shmem */
-
- /* 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));
- else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
- }
-
- mode = instance->init_type;
- if (debug) {
- printf("ONCORE[%d]: INIT mode = %d\n", instance->unit, mode);
- printf("ONCORE[%d]: chan = %d\n", instance->unit, instance->chan);
- }
+ const char *cp;
+ char Msg[160];
+ int mode;
- /* 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.
+ /* 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->posn_set) {
- switch (mode) { /* if we have a position, put it in as posn and posn-hold posn */
- case 0:
- break;
- case 1:
- case 2:
- case 3:
- case 4:
- memcpy(Cmd, oncore_cmd_As, sizeof(oncore_cmd_As)); /* dont modify static variables */
- w32_buf(&Cmd[2], (int) instance->ss_lat);
- w32_buf(&Cmd[6], (int) instance->ss_long);
- w32_buf(&Cmd[10], (int) instance->ss_ht);
- Cmd[14] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_As));
-
- memcpy(Cmd, oncore_cmd_Au, sizeof(oncore_cmd_Au));
- w32_buf(&Cmd[2], (int) instance->ss_ht);
- Cmd[6] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Au));
-
- if (instance->chan == 12) {
- memcpy(Cmd, oncore_cmd_Ga, sizeof(oncore_cmd_Ga));
- w32_buf(&Cmd[2], (int) instance->ss_lat);
- w32_buf(&Cmd[6], (int) instance->ss_long);
- w32_buf(&Cmd[10], (int) instance->ss_ht);
- Cmd[14] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ga));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
- } else {
- memcpy(Cmd, oncore_cmd_Ad, sizeof(oncore_cmd_Ad));
- w32_buf(&Cmd[2], (int) instance->ss_lat);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ad));
-
- memcpy(Cmd, oncore_cmd_Ae, sizeof(oncore_cmd_Ae));
- w32_buf(&Cmd[2], (int) instance->ss_long);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ae));
-
- memcpy(Cmd, oncore_cmd_Af, sizeof(oncore_cmd_Af));
- w32_buf(&Cmd[2], (int) instance->ss_ht);
- Cmd[6] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Af));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1));
- }
- break;
+ 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;
- switch (mode) {
- case 0: /* NO initialization, don't change anything */
- instance->site_survey = ONCORE_SS_DONE;
- break;
+ instance->count3 = 0;
- case 1:
- case 3: /* Use given Position */
- instance->site_survey = ONCORE_SS_DONE;
- break;
+ if (instance->chan_in != -1) /* set in Input */
+ instance->chan = instance->chan_in;
+ else /* set from test */
+ instance->chan = instance->chan_ck;
- case 2:
- case 4: /* Site Survey */
- if (instance->chan == 12) { /* no 12chan site survey command */
- instance->site_survey = ONCORE_SS_SW;
- sprintf(Msg, "Initiating software 3D site survey (%d samples)", POS_HOLD_AVERAGE);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- } else {
- instance->site_survey = ONCORE_SS_TESTING;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At2, sizeof(oncore_cmd_At2));
- }
- break;
- }
+ 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);
- if (mode != 0) {
- /* cable delay in ns */
- memcpy(Cmd, oncore_cmd_Az, sizeof(oncore_cmd_Az));
- w32_buf(&Cmd[2], instance->delay);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Az));
+ instance->o_state = ONCORE_HAVE_CHAN;
+ cp = "state = ONCORE_HAVE_CHAN";
+ record_clock_stats(&(instance->peer->srcadr), cp);
- /* PPS offset in ns */
- if (instance->offset) {
- if (instance->model == ONCORE_VP || instance->model == ONCORE_UT ||
- instance->model == ONCORE_UTPLUS) {
- memcpy(Cmd, oncore_cmd_Ay, sizeof(oncore_cmd_Ay));
- w32_buf(&Cmd[2], instance->offset);
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ay));
- } else {
- cp = "Can only set PPS OFFSET for VP/UT/UT+, offset ignored";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->offset = 0;
- }
- }
+ instance->timeout = 4;
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ return;
}
- /* 6, 8 12 chan - Position/Status/Data Output Message, 1/s */
- /* now we're really running */
-
- if (instance->chan == 6) { /* kill 8 chan commands, possibly testing VP in 6chan mode */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba, sizeof(oncore_cmd_Ba));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En0, sizeof(oncore_cmd_En0));
- } else if (instance->chan == 8) { /* kill 6chan commands */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof(oncore_cmd_Ea));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
- } else if (instance->chan == 12)
- 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);
-}
-
-
-
-/*
- * 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_ALMANAC && instance->o_state != ONCORE_RUN)
+ return;
- if (instance->o_state == ONCORE_RESET_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));
+ /* PAUSE 5sec */
- instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ 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 */
-/* Here for @@Ca, @@Fa and @@Ia messages */
+ /* check the antenna and almanac for changes (did it get unplugged, is it ready?) */
-/* There are good reasons NOT to do a @@Ca or @@Fa command with the ONCORE.
- * Doing it, 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 wastefull, and may cause trouble for some OS's, repeating
- * itimer, we set a flag, and test it at the next POLL. If it hasnt
- * 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).
- */
+ oncore_check_almanac(instance);
+ oncore_check_antenna(instance);
-static void
-oncore_msg_CaFaIa(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char *cp;
+ /* 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_TEST_SENT) {
- int antenna;
+ if (instance->o_state == ONCORE_ALMANAC)
+ if (oncore_wait_almanac(instance))
+ return;
- instance->timeout = 0;
+ /* do some things once when we get this far in BaEaHa */
- 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]);
- }
+ if (instance->once) {
+ instance->once = 0;
+ instance->count2 = 1;
- antenna = buf[4] & 0xc0;
- antenna >>= 6;
- buf[4] &= ~0xc0;
+ /* Have we seen an @@At (position hold) command response */
+ /* if not, message out */
- if (buf[4] || buf[5] || ((buf[2] == 'I') && buf[6])) {
- cp = "ONCORE: Self Test Failed, shutting down driver";
+ 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_shutdown(instance->unit, instance->peer);
- return;
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
}
- if (antenna) {
- char *cp1, Msg[160];
- cp1 = (antenna == 0x1) ? "(Over Current)" :
- ((antenna == 0x2) ? "(Under Current)" : "(No Voltage)");
+ /* 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
+ */
- cp = "ONCORE: Self Test, NonFatal Antenna Problems ";
- strcpy(Msg, cp);
- strcat(Msg, cp1);
- record_clock_stats(&(instance->peer->srcadr), Msg);
+ 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;
}
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
- instance->o_state = ONCORE_INIT;
- cp = "state = ONCORE_INIT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
-}
+ /* 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 */
-/* Ba, Ea and Ha come here */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Azx, sizeof(oncore_cmd_Azx));
-static void
-oncore_msg_BaEaHa(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- const char *cp;
- char Msg[160], Cmd[20];
- u_char *vp; /* pointer to start of shared mem for Ba/Ea/Ha */
- size_t Len;
+ /* 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);
- /* At the beginning of Ea here there are various 'timers'.
- * We enter Ea 1/sec, and since the upper levels of NTP have usurped
- * the use of timers, we use the 1/sec entry to Ea to do things that
- * we would normally do with timers...
- */
+ record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_SW");
+ instance->site_survey = ONCORE_SS_SW;
- if (instance->count) {
- if (instance->count++ < 5) /* make sure results are stable, using position */
- return;
- instance->count = 0;
+ 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 */
+ }
+ }
+ }
}
- if (instance->o_state != ONCORE_ALMANAC && instance->o_state != ONCORE_RUN)
- return;
-
- Len = len+3; /* message length @@ -> CR,LF */
- memcpy(instance->Ea, buf, Len); /* Ba, Ea or Ha */
+ /* check the mode we are in 0/2/3D */
- if (buf[2] == 'B') { /* 6chan */
- if (instance->Ea[64]&0x8)
+ if (instance->chan == 6) {
+ if (instance->BEHa[64]&0x8)
instance->mode = MODE_0D;
- else if (instance->Ea[64]&0x10)
+ else if (instance->BEHa[64]&0x10)
instance->mode = MODE_2D;
- else if (instance->Ea[64]&0x20)
+ else if (instance->BEHa[64]&0x20)
instance->mode = MODE_3D;
- } else if (buf[2] == 'E') { /* 8chan */
- if (instance->Ea[72]&0x8)
+ } else if (instance->chan == 8) {
+ if (instance->BEHa[72]&0x8)
instance->mode = MODE_0D;
- else if (instance->Ea[72]&0x10)
+ else if (instance->BEHa[72]&0x10)
instance->mode = MODE_2D;
- else if (instance->Ea[72]&0x20)
+ else if (instance->BEHa[72]&0x20)
instance->mode = MODE_3D;
- } else if (buf[2] == 'H') { /* 12chan */
+ } else if (instance->chan == 12) {
int bits;
- bits = (instance->Ea[129]>>5) & 0x7; /* actually Ha */
+ bits = (instance->BEHa[129]>>5) & 0x7; /* actually Ha */
if (bits == 0x4)
instance->mode = MODE_0D;
else if (bits == 0x6)
@@ -1912,131 +2157,36 @@ oncore_msg_BaEaHa(
instance->mode = MODE_3D;
}
- vp = (u_char) 0; /* just to keep compiler happy */
- if (instance->chan == 6) {
- instance->rsm.bad_almanac = instance->Ea[64]&0x1;
- instance->rsm.bad_fix = instance->Ea[64]&0x52;
- vp = &instance->shmem[instance->shmem_Ba];
- } else if (instance->chan == 8) {
- instance->rsm.bad_almanac = instance->Ea[72]&0x1;
- instance->rsm.bad_fix = instance->Ea[72]&0x52;
- vp = &instance->shmem[instance->shmem_Ea];
- } else if (instance->chan == 12) {
- int bits1, bits2;
-
- bits1 = (instance->Ea[129]>>5) & 0x7; /* actually Ha */
- bits2 = instance->Ea[130];
- instance->rsm.bad_almanac = (bits2 & 0x80);
- instance->rsm.bad_fix = (bits2 & 0x8) || (bits1 == 0x2);
- /* too few sat Bad Geom */
- vp = &instance->shmem[instance->shmem_Ha];
-#if 0
-fprintf(stderr, "ONCORE: DEBUG BITS: (%x %x), (%x %x), %x %x %x %x %x\n",
- instance->Ea[129], instance->Ea[130], bits1, bits2, instance->mode == MODE_0D, instance->mode == MODE_2D,
- instance->mode == MODE_3D, instance->rsm.bad_almanac, instance->rsm.bad_fix);
-#endif
- }
-
- /* Here calculate dH = GPS - MSL for output message */
- /* also set Altitude Hold mode if GT */
-
- if (!instance->have_dH) {
- int GPS, MSL;
-
- instance->have_dH++;
- if (instance->chan == 12) {
- GPS = buf_w32(&instance->Ea[39]);
- MSL = buf_w32(&instance->Ea[43]);
- } else {
- GPS = buf_w32(&instance->Ea[23]);
- MSL = buf_w32(&instance->Ea[27]);
- }
- instance->dH = GPS - MSL;
- instance->dH /= 100.;
-
- if (MSL) { /* not set ! */
- sprintf(Msg, "dH = (GPS - MSL) = %.2fm", instance->dH);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- }
-
- /* stuck in here as it only gets done once */
-
- if (instance->chan != 12 && !instance->saw_At) {
- cp = "Not Good, no @@At command, must be a GT/GT+";
- record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
- }
- }
-
- /*
- * For instance->site_survey to be ONCORE_SS_TESTING, this must be the first
- * time thru @@Ea. There are two choices
- * (a) We did not get a response to the @@At0 or @@At2 commands,
- * must be a GT/GT+/SL with no position hold mode.
- * (b) Saw the @@At0, @@At2 commands, but @@At2 failed,
- * must be a VP or older UT which doesnt have Site Survey mode.
- * We will have to do it ourselves.
- */
-
- if (instance->site_survey == ONCORE_SS_TESTING) { /* first time thru Ea */
- sprintf(Msg, "Initiating software 3D site survey (%d samples)",
- POS_HOLD_AVERAGE);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- instance->site_survey = ONCORE_SS_SW;
-
- instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* disable */
- }
+ /* 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 */
- i = 0;
- if (instance->mode == MODE_0D) /* 0D, Position Hold */
- i = 1;
- else if (instance->mode == MODE_2D) /* 2D, Altitude Hold */
- i = 2;
- else if (instance->mode == MODE_3D) /* 3D fix */
- i = 3;
- if (i) {
- i *= (Len+3);
- vp[i + 2]++;
- memcpy(&vp[i+3], buf, Len);
+ 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;
}
- }
- /* Almanac mode, waiting for Almanac, cant do anything till we have it */
- /* When we have an almanac, start the En/Bn messages */
+ 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 (instance->o_state == ONCORE_ALMANAC) {
- if (instance->rsm.bad_almanac) {
- if (debug)
- printf("ONCORE: waiting for almanac\n");
- return;
- } else { /* Here we have almanac.
- Start TRAIM (@@En/@@Bn) dependant on TRAIM flag.
- If flag == -1, then we dont know if this unit supports
- traim, and we issue the command and then wait up to
- 5sec to see if we get a reply */
-
- if (instance->traim != 0) { /* either yes or unknown */
- 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));
-
- if (instance->traim == -1)
- instance->traim_delay = 1;
- }
- instance->o_state = ONCORE_RUN;
- cp = "state = ONCORE_RUN";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ if (i) {
+ i *= (len+6);
+ smp[i + 2]++;
+ memcpy(&smp[i+3], buf, (size_t) (len+3));
}
}
/*
* check if timer active
- * if it hasnt been cleared, then @@En/@@Bn did not respond
+ * if it hasn't been cleared, then @@Bn/@@En/@@Hn did not respond
*/
if (instance->traim_delay) {
@@ -2045,175 +2195,135 @@ fprintf(stderr, "ONCORE: DEBUG BITS: (%x %x), (%x %x), %x %x %x %x %x\n",
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->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];
/*
- * Check to see if Hardware SiteSurvey has Finished.
+ * Are we doing a Hardware or Software Site Survey?
*/
- if ((instance->site_survey == ONCORE_SS_HW) && !(instance->Ea[37] & 0x20)) {
- record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
- instance->site_survey = ONCORE_SS_DONE;
- }
+ if (instance->site_survey == ONCORE_SS_HW || instance->site_survey == ONCORE_SS_SW)
+ oncore_ss(instance);
- if (!instance->printed && instance->site_survey == ONCORE_SS_DONE) {
- instance->printed = 1;
- /* Read back Position Hold Params (cant for GT) */
- if (instance->saw_At)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Asx, sizeof(oncore_cmd_Asx));
- else
- oncore_print_As(instance);
+ /* see if we ever saw a response from the @@Ayx above */
- /* 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));
+ if (instance->count2) {
+ if (instance->count2++ > 5) { /* this delay to check on @@Ay command */
+ instance->count2 = 0;
- /* Read back Cable Delay for Output */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Azx, sizeof(oncore_cmd_Azx));
+ /* 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.
*/
- if (instance->Bj_day != buf[5]) { /* do this 1/day */
- instance->Bj_day = buf[5];
-
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gj, sizeof(oncore_cmd_Gj));
- else {
- /*
- * The following additional check, checking for June/December, is a
- * workaround for incorrect ONCORE firmware. The oncore starts
- * reporting the leap second when the GPS satellite data message
- * (page 18, subframe 4) is updated to a date in the future, which
- * can be several months before the leap second. WWV and other
- * services seem to wait until the month of the event to turn
- * on their indicators (which is usually a single bit).
- */
-
- if ((buf[4] == 6) || (buf[4] == 12))
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
- }
- }
+ oncore_check_leap_sec(instance);
/*
* if SHMEM active, every 15s, steal one 'tick' to get 2D or 3D posn.
*/
- if (instance->shmem && instance->shmem_Posn && (instance->site_survey == ONCORE_SS_DONE)) { /* dont screw up the SS by changing mode */
- if (instance->pp->second%15 == 3) { /* start the sequence */
- 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) {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* out of 0D to 3D mode */
- if (instance->shmem_Posn == 2)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1)); /* 3D to 2D mode */
- } 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)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* 2D -> 3D or 0D */
- 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));
- }
- }
- }
+ if (instance->shmem && !instance->shmem_bad_Ea && instance->shmem_Posn && (instance->site_survey == ONCORE_SS_DONE))
+ oncore_shmem_get_3D(instance);
- if (instance->traim == 0) /* NO traim, go get tick */
+ if (!instance->traim) /* NO traim, no BnEnHn, go get tick */
oncore_get_timestamp(instance, instance->offset, instance->offset);
+}
- if (instance->site_survey != ONCORE_SS_SW)
- return;
-
- /*
- * We have to average our own position for the Position Hold Mode
- * We use Heights from the GPS ellipsoid.
- */
-
- if (instance->rsm.bad_fix) /* Not if poor geometry or less than 3 sats */
- return;
- if (instance->mode != MODE_3D) /* Only 3D Fix */
- return;
- instance->ss_lat += buf_w32(&instance->Ea[15]);
- instance->ss_long += buf_w32(&instance->Ea[19]);
- instance->ss_ht += buf_w32(&instance->Ea[23]); /* GPS ellipsoid */
- instance->ss_count++;
+/* Almanac Status */
- 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;
+static void
+oncore_msg_Bd(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ char Msg[160];
- sprintf(Msg, "Surveyed posn: lat %.3f long %.3f ht %.3f",
- instance->ss_lat, instance->ss_long, instance->ss_ht);
+ 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);
+}
- /* set newly determined position as 3D Position hold position */
- memcpy(Cmd, oncore_cmd_As, sizeof(oncore_cmd_As));
- w32_buf(&Cmd[2], (int) instance->ss_lat);
- w32_buf(&Cmd[6], (int) instance->ss_long);
- w32_buf(&Cmd[10], (int) instance->ss_ht);
- Cmd[14] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_As));
- /* set height seperately for 2D */
+/* get leap-second warning message */
- memcpy(Cmd, oncore_cmd_Au, sizeof(oncore_cmd_Au));
- w32_buf(&Cmd[2], (int) instance->ss_ht);
- Cmd[6] = 0;
- oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Au));
+/*
+ * @@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.
+ */
- /* and set Position Hold */
+static void
+oncore_msg_Bj(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ const char *cp;
- if (instance->chan == 12)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
- else {
- if (instance->saw_At)
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1));
- else
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
+ 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), "Now in 0D mode");
- instance->site_survey = ONCORE_SS_DONE;
+ record_clock_stats(&(instance->peer->srcadr), cp);
}
static void
-oncore_msg_BnEn(
+oncore_msg_BnEnHn(
struct instance *instance,
u_char *buf,
- size_t len
+ size_t len
)
{
long dt1, dt2;
@@ -2222,385 +2332,570 @@ oncore_msg_BnEn(
if (instance->o_state != ONCORE_RUN)
return;
- if (instance->traim_delay) { /* flag that @@En/@@Bn returned */
- instance->traim = 1;
+ 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->En, buf, len); /* En or Bn */
+ memcpy(instance->BEHn, buf, (size_t) len); /* Bn or En or Hn */
/* If Time RAIM doesn't like it, don't trust it */
- if (instance->En[21])
- return;
+ 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->En[25]; /* update for next time */
- dt2 = instance->saw_tooth + instance->offset; /* dt next time step */
+ 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_get_timestamp(
+oncore_msg_CaFaIa(
struct instance *instance,
- long dt1, /* tick offset THIS time step */
- long dt2 /* tick offset NEXT time step */
+ u_char *buf,
+ size_t len
)
{
- 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 ((instance->site_survey == ONCORE_SS_DONE) && (instance->mode != MODE_0D))
- return;
-
- /* Don't do anything without an almanac to define the GPS->UTC delta */
-
- if (instance->rsm.bad_almanac)
- return;
+ char *cp;
+ int i;
-#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->o_state == ONCORE_TEST_SENT) {
+ enum antenna_state antenna;
- if (instance->assert) {
- tsp = &pps_i.assert_timestamp;
+ instance->timeout = 0;
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 (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]);
}
- 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;
+ antenna = (buf[4] & 0xc0) >> 6;
+ buf[4] &= ~0xc0;
- 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
- }
+ 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);
- if (pps_i.clear_sequence == j) {
- printf("ONCORE: oncore_get_timestamp, error serial pps\n");
+ refclock_report(instance->peer, CEVNT_FAULT);
+ oncore_shutdown(instance->unit, instance->peer);
return;
}
- instance->ev_serial = pps_i.clear_sequence;
- }
- /* convert timespec -> ntp l_fp */
+ /* report the current antenna state */
- 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;
+ 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));
}
+}
- 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");
+/*
+ * 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;
- }
- instance->ev_serial = ev.serial;
- /* convert timeval -> ntp l_fp */
+ 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;
- TVTOTS(tsp, &ts);
-# else
-# if defined(TIOCDCDTIMESTAMP)
- if(ioctl(instance->ppsfd, TIOCDCDTIMESTAMP, &tv) < 0) {
- perror("ONCORE: ioctl(TIOCDCDTIMESTAMP)");
+ cp = "Cb: Response is NO ALMANAC";
+ record_clock_stats(&(instance->peer->srcadr), cp);
return;
}
- tsp = &tv;
- TVTOTS(tsp, &ts);
-# else
-#error "Cannot compile -- no PPS mechanism configured!"
-# endif
-# endif
+
+ 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
- /* 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 */
+/*
+ * Set to Factory Defaults (Reasonable for UT w/ no Battery Backup
+ * not so for VP (eeprom) or any unit with a battery
+ */
- if (instance->assert)
- instance->pps_p.assert_offset.tv_nsec = -dt2;
- else
- instance->pps_p.clear_offset.tv_nsec = -dt2;
+static void
+oncore_msg_Cf(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ const char *cp;
- /* 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 (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);
- if (time_pps_getcap(instance->pps_h, &current_mode) < 0) {
- msyslog(LOG_ERR,
- "refclock_ioctl: time_pps_getcap failed: %m");
- return;
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
}
+}
- 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;
+/*
+ * 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.
+ */
- 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 */
+static void
+oncore_msg_Cj(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ int mode;
+ char *cp;
- dmy = -1.0e-9*dt1;
- DTOLFP(dmy, &ts_tmp);
- L_ADD(&ts, &ts_tmp);
-#endif
- /* have time from UNIX origin, convert to NTP origin. */
+ memcpy(instance->Cj, buf, len);
- ts.l_ui += JAN_1970;
- instance->pp->lastrec = ts;
- instance->pp->msec = 0;
+ 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);
+ }
+ }
- 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 */
+ 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);
+}
- Rsm = 0;
- if (instance->chan == 6)
- Rsm = instance->Ea[64];
- else if (instance->chan == 8)
- Rsm = instance->Ea[72];
- else if (instance->chan == 12)
- Rsm = ((instance->Ea[129]<<8) | instance->Ea[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 %d 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->Ea[35]+instance->Ea[36]),
- /*rsat dop */
- instance->Ea[38], instance->Ea[39], instance->En[21],
- /* nsat visible, nsat tracked, traim */
- instance->En[23]*256+instance->En[24], (s_char) instance->En[25],
- /* sigma neg-sawtooth */
- /*sat*/ instance->Ea[41], instance->Ea[45], instance->Ea[49], instance->Ea[53],
- instance->Ea[57], instance->Ea[61], instance->Ea[65], instance->Ea[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 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->Ea[53]+instance->Ea[54]),
- /*rsat dop */
- instance->Ea[55], instance->Ea[56],
- /* nsat visible, nsat tracked */
- /*sat*/ instance->Ea[58], instance->Ea[64], instance->Ea[70], instance->Ea[76],
- instance->Ea[82], instance->Ea[88], instance->Ea[94], instance->Ea[100],
- instance->Ea[106], instance->Ea[112], instance->Ea[118], instance->Ea[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);
- }
+/* 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
+ */
- if (!refclock_process(instance->pp)) {
- refclock_report(instance->peer, CEVNT_BADTIME);
- return;
+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;
}
- record_clock_stats(&(instance->peer->srcadr), instance->pp->a_lastcode);
- instance->pollcnt = 2;
+ /* next, the Firmware Version and Revision numbers */
- if (instance->polled) {
- instance->polled = 0;
-/*
- instance->pp->dispersion = instance->pp->skew = 0;
-*/
- refclock_receive(instance->peer);
+ 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);
}
-/*
- * Try to use Oncore UT+ Auto Survey Feature
- * If its not there (VP), set flag to do it ourselves.
+/* 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_At(
+oncore_msg_Cj_init(
struct instance *instance,
u_char *buf,
size_t len
)
{
- 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");
- instance->site_survey = ONCORE_SS_HW;
+ 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);
}
-/* get leap-second warning message */
+/* 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);
+}
+
+
/*
- * @@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.
- * Until this firmware bug is fixed, @@Bj is only called in June/December.
+ * Try to use Oncore M12+Timing Auto Survey Feature
+ * If its not there (M12), set flag to do it ourselves.
*/
static void
-oncore_msg_Bj(
+oncore_msg_Gd(
struct instance *instance,
u_char *buf,
size_t len
)
{
- const char *cp;
+ 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;
+ 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;
+ }
}
- record_clock_stats(&(instance->peer->srcadr), cp);
}
+
+
/* Leap Second for M12, gives all info from satellite message */
+/* also in UT v3.0 */
static void
oncore_msg_Gj(
@@ -2611,8 +2906,8 @@ oncore_msg_Gj(
{
int dt;
char Msg[160], *cp;
- static char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly",
- "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ instance->saw_Gj = 1; /* flag, saw_Gj, dont need to try Bj in check_leap */
/* print the message to verify whats there */
@@ -2639,8 +2934,8 @@ oncore_msg_Gj(
instance->peer->leap = LEAP_NOWARNING;
cp = "Set peer.leap to LEAP_NOWARNING";
- if (buf[6] == instance->Ea[6] && buf[7] == instance->Ea[7] && /* year */
- buf[8] == instance->Ea[4]) { /* month */
+ 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;
@@ -2656,34 +2951,426 @@ oncore_msg_Gj(
-/*
- * get Position hold position
- */
+/* Power on failure */
static void
-oncore_msg_As(
+oncore_msg_Sz(
struct instance *instance,
u_char *buf,
size_t len
)
{
- if (!instance->printed || instance->As)
+ 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;
- instance->As = 1;
+ 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->ss_lat = buf_w32(&buf[4]);
- instance->ss_long = buf_w32(&buf[8]);
- instance->ss_ht = buf_w32(&buf[12]);
+ instance->ant_state = new_state;
+ record_clock_stats(&instance->peer->srcadr, cp);
+}
- /* Print out Position */
- oncore_print_As(instance);
+
+
+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_As(
+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
)
{
@@ -2721,7 +3408,8 @@ oncore_print_As(
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);
+ 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;
@@ -2730,79 +3418,306 @@ oncore_print_As(
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);
+ 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);
}
/*
- * get PPS Offset
- * Nb. @@Ay is not supported for early UT (no plus) model
+ * write message to Oncore.
*/
static void
-oncore_msg_Ay(
- struct instance *instance,
- u_char *buf,
+oncore_sendmsg(
+ int fd,
+ u_char *ptr,
size_t len
)
{
- char Msg[120];
+ u_char cs = 0;
- if (!instance->printed || instance->Ay)
- return;
+ 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);
+}
- instance->Ay = 1;
- instance->offset = buf_w32(&buf[4]);
- sprintf(Msg, "PPS Offset is set to %ld ns", instance->offset);
+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));
+ }
}
/*
- * get Cable Delay
+ * if SHMEM active, every 15s, steal one 'tick' to get 2D or 3D posn.
*/
static void
-oncore_msg_Az(
- struct instance *instance,
- u_char *buf,
- size_t len
+oncore_shmem_get_3D(
+ struct instance *instance
)
{
- char Msg[120];
-
- if (!instance->printed || instance->Az)
- return;
+ 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));
+ }
+ }
+}
- instance->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);
-}
+/*
+ * 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_msg_Sz(
- struct instance *instance,
- u_char *buf,
- size_t len
+oncore_ss(
+ struct instance *instance
)
{
- const char *cp;
+ char *cp, Msg[160];
+ double lat, lon, ht;
- cp = "Oncore: System Failure at Power On";
- if (instance && instance->peer) {
+
+ 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);
- oncore_shutdown(instance->unit, instance->peer);
+ 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
index 4b36b78..897221b 100644
--- a/contrib/ntp/ntpd/refclock_palisade.c
+++ b/contrib/ntp/ntpd/refclock_palisade.c
@@ -56,6 +56,11 @@
#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"
@@ -88,6 +93,16 @@ struct refclock refclock_palisade = {
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
*/
@@ -195,6 +210,19 @@ palisade_start (
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;
@@ -335,7 +363,10 @@ TSIP_decode (
return 0;
}
- if (up->rpt_buf[0] == (char) 0x8f) {
+ /*
+ * 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
*/
@@ -385,7 +416,7 @@ if (debug > 1) {
secint = (long) secs;
secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
- pp->usec = (long) (secfrac * 1000000);
+ pp->nsec = (long) (secfrac * 1000000000);
secint %= 86400; /* Only care about today */
pp->hour = secint / 3600;
@@ -402,7 +433,7 @@ if (debug > 1) {
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->usec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
+ 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
@@ -463,7 +494,7 @@ if (debug > 1) {
return 0;
}
- pp->usec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
+ pp->nsec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
if ((pp->day = day_of_year(&mb(14))) < 0)
break;
@@ -476,7 +507,7 @@ if (debug > 1) {
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->usec, mb(15), mb(14), pp->year,
+ pp->second, pp->nsec, mb(15), mb(14), pp->year,
mb(19), *Tracking_Status[st]);
#endif
return 1;
@@ -534,7 +565,7 @@ palisade_receive (
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->usec);
+ pp->second, pp->nsec);
#endif
/*
@@ -544,7 +575,7 @@ palisade_receive (
*/
(void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld",
- pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->usec);
+ pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->nsec);
pp->lencode = 24;
#ifdef PALISADE
@@ -571,7 +602,7 @@ palisade_receive (
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,
@@ -620,10 +651,43 @@ palisade_poll (
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 (
@@ -649,6 +713,13 @@ palisade_io (
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;
diff --git a/contrib/ntp/ntpd/refclock_palisade.h b/contrib/ntp/ntpd/refclock_palisade.h
index cc37716..7e1ed49 100644
--- a/contrib/ntp/ntpd/refclock_palisade.h
+++ b/contrib/ntp/ntpd/refclock_palisade.h
@@ -146,6 +146,7 @@ struct palisade_unit {
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 */
};
/*
diff --git a/contrib/ntp/ntpd/refclock_parse.c b/contrib/ntp/ntpd/refclock_parse.c
index cfb9904..52fadaa 100644
--- a/contrib/ntp/ntpd/refclock_parse.c
+++ b/contrib/ntp/ntpd/refclock_parse.c
@@ -802,7 +802,7 @@ static struct parse_clockinfo
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 loosing synch */
+ 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 */
@@ -1181,7 +1181,7 @@ static struct parse_clockinfo
"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 loosing synch */
+ (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 */
@@ -1240,10 +1240,10 @@ static struct parse_clockinfo
static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
-#define CLK_REALTYPE(x) ((int)(((x)->ttlmax) & 0x7F))
+#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)->ttlmax) & 0x80)
+#define CLK_PPS(x) (((x)->ttl) & 0x80)
/*
* Other constant stuff
@@ -3095,7 +3095,7 @@ parse_event(
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.sin_addr.s_addr), ceventstr(event),
+ "clock %s fault '%s' (0x%02x)", refnumtoa(&parse->peer->srcadr), ceventstr(event),
(u_int)event);
}
else
@@ -3103,7 +3103,7 @@ parse_event(
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.sin_addr.s_addr), ceventstr(event),
+ "clock %s event '%s' (0x%02x)", refnumtoa(&parse->peer->srcadr), ceventstr(event),
(u_int)event);
}
@@ -3728,11 +3728,11 @@ gps16x_message(
case GPS_ANT_INFO:
{
ANT_INFO antinfo;
- char buffer[512];
- char *p;
+ u_char buffer[512];
+ u_char *p;
get_mbg_antinfo(&bufp, &antinfo);
- sprintf((char *)buffer, "meinberg_antenna_status=\"");
+ sprintf(buffer, "meinberg_antenna_status=\"");
p = buffer + strlen(buffer);
switch (antinfo.status)
@@ -3750,20 +3750,20 @@ gps16x_message(
CLK_UNIT(parse->peer), p);
p += strlen(p);
- mbg_tm_str((unsigned char **)&p, &antinfo.tm_disconn);
+ mbg_tm_str(&p, &antinfo.tm_disconn);
*p = '\0';
break;
case ANT_RECONN:
strcat(p, "RECONNECTED on ");
p += strlen(p);
- mbg_tm_str((unsigned char **)&p, &antinfo.tm_reconn);
+ 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((unsigned char **)&p, &antinfo.tm_disconn);
+ mbg_tm_str(&p, &antinfo.tm_disconn);
*p = '\0';
break;
@@ -3786,8 +3786,8 @@ gps16x_message(
case GPS_CFGH:
{
CFGH cfgh;
- char buffer[512];
- char *p;
+ u_char buffer[512];
+ u_char *p;
get_mbg_cfgh(&bufp, &cfgh);
if (cfgh.valid)
@@ -3797,7 +3797,7 @@ gps16x_message(
p = buffer;
strcpy(buffer, "gps_tot_51=\"");
p += strlen(p);
- mbg_tgps_str((unsigned char **)&p, &cfgh.tot_51);
+ mbg_tgps_str(&p, &cfgh.tot_51);
*p++ = '"';
*p = '\0';
set_var(&parse->kv, buffer, sizeof(buffer), RO);
@@ -3805,7 +3805,7 @@ gps16x_message(
p = buffer;
strcpy(buffer, "gps_tot_63=\"");
p += strlen(p);
- mbg_tgps_str((unsigned char **)&p, &cfgh.tot_63);
+ mbg_tgps_str(&p, &cfgh.tot_63);
*p++ = '"';
*p = '\0';
set_var(&parse->kv, buffer, sizeof(buffer), RO);
@@ -3813,7 +3813,7 @@ gps16x_message(
p = buffer;
strcpy(buffer, "gps_t0a=\"");
p += strlen(p);
- mbg_tgps_str((unsigned char **)&p, &cfgh.t0a);
+ mbg_tgps_str(&p, &cfgh.t0a);
*p++ = '"';
*p = '\0';
set_var(&parse->kv, buffer, sizeof(buffer), RO);
@@ -5176,7 +5176,7 @@ rawdcf_init_1(
}
#else
static int
-rawdcfdtr_init(
+rawdcfdtr_init_1(
struct parseunit *parse
)
{
diff --git a/contrib/ntp/ntpd/refclock_pcf.c b/contrib/ntp/ntpd/refclock_pcf.c
index ff2b28e..d4e9fd1 100644
--- a/contrib/ntp/ntpd/refclock_pcf.c
+++ b/contrib/ntp/ntpd/refclock_pcf.c
@@ -196,9 +196,9 @@ pcf_poll(
pp->hour = tp->tm_hour;
pp->minute = tp->tm_min;
pp->second = tp->tm_sec;
- pp->usec = buf[16] * 31250;
+ pp->nsec = buf[16] * 31250000;
if (buf[17] & 1)
- pp->usec += 500000;
+ pp->nsec += 500000000;
#ifdef DEBUG
if (debug)
@@ -216,6 +216,7 @@ pcf_poll(
pp->leap = LEAP_NOTINSYNC;
else
pp->leap = LEAP_NOWARNING;
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
}
#else
diff --git a/contrib/ntp/ntpd/refclock_pst.c b/contrib/ntp/ntpd/refclock_pst.c
index b92a2e0..2443b2c 100644
--- a/contrib/ntp/ntpd/refclock_pst.c
+++ b/contrib/ntp/ntpd/refclock_pst.c
@@ -71,7 +71,7 @@
/*
* Interface definitions
*/
-#define DEVICE "/dev/pst%d" /* device name and unit */
+#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 */
@@ -84,7 +84,7 @@
* Unit control structure
*/
struct pstunit {
- u_char tcswitch; /* timecode switch */
+ int tcswitch; /* timecode switch */
char *lastptr; /* pointer to timecode data */
};
@@ -155,9 +155,9 @@ pst_start(
* Initialize miscellaneous variables
*/
peer->precision = PRECISION;
- peer->burst = NSTAGE;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, WWVREFID, 4);
+ peer->burst = MAXSTAGE;
return (1);
}
@@ -214,17 +214,12 @@ pst_receive(
* Note we get a buffer and timestamp for each <cr>, but only
* the first timestamp is retained.
*/
- if (!up->tcswitch)
+ if (up->tcswitch == 0)
pp->lastrec = trtmp;
up->tcswitch++;
pp->lencode = up->lastptr - pp->a_lastcode;
if (up->tcswitch < 3)
return;
-#ifdef DEBUG
- if (debug)
- printf("pst: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
/*
* We get down to business, check the timecode format and decode
@@ -240,13 +235,14 @@ pst_receive(
* Timecode format:
* "ahh:mm:ss.fffs yy/dd/mm/ddd frdzycchhSSFTttttuuxx"
*/
- if (sscanf(pp->a_lastcode, "%c%2d:%2d:%2d.%3d%c %9s%3d%13s%4ld",
- &ampmchar, &pp->hour, &pp->minute, &pp->second,
- &pp->msec, &daychar, junque, &pp->day,
- info, &ltemp) != 10) {
+ 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
@@ -263,7 +259,9 @@ pst_receive(
memcpy((char *)&pp->refid, WWVREFID, 4);
if (peer->stratum <= 1)
peer->refid = pp->refid;
- pp->disp = PST_PHI * ltemp;
+ if (ltemp == 0)
+ pp->lastref = pp->lastrec;
+ pp->disp = PST_PHI * ltemp * 60;
/*
* Process the new sample in the median filter and determine the
@@ -290,8 +288,10 @@ pst_poll(
/*
* Time to poll the clock. The PSTI/Traconex clock responds to a
* "QTQDQMT" by returning a timecode in the format specified
- * above. If nothing is heard from the clock for two polls,
- * declare a timeout and keep going.
+ * 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;
@@ -299,17 +299,21 @@ pst_poll(
up->lastptr = pp->a_lastcode;
if (write(pp->io.fd, "QTQDQMT", 6) != 6)
refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
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;
+ 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
diff --git a/contrib/ntp/ntpd/refclock_ripencc.c b/contrib/ntp/ntpd/refclock_ripencc.c
index f18270e..6337f63 100644
--- a/contrib/ntp/ntpd/refclock_ripencc.c
+++ b/contrib/ntp/ntpd/refclock_ripencc.c
@@ -461,8 +461,6 @@ struct refclock refclock_ripencc = {
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};
-extern int pps_hardpps;
-extern int pps_assert;
/*
* ripencc_start - open the GPS devices and initialize data for processing
@@ -612,7 +610,7 @@ ripencc_start(int unit, struct peer *peer)
return (1);
}
- return(ripencc_ppsapi(peer, pps_assert, pps_hardpps));
+ return(ripencc_ppsapi(peer, 0, 0));
}
/*
@@ -988,7 +986,7 @@ ripencc_receive(struct recvbuf *rbufp)
*/
if (ripencc_get_pps_ts(up, &rd_tmp) == 1) {
pp->lastrec = up->tstamp = rd_tmp;
- pp->msec = 0;
+ pp->nsec = 0;
}
else
msyslog(LOG_INFO, "%s(): ripencc_get_pps_ts returns failure\n",__FUNCTION__);
@@ -1479,7 +1477,7 @@ parse0x8FAD(rpt, peer)
pp->hour = hour;
pp->minute = minute;
pp-> second = second;
- pp->msec = 0;
+ pp->nsec = 0;
if ((utcflags&UTCF_LEAP_PNDG) && up->leapdelta != 0)
pp-> leap = (up->leapdelta > 0 ? LEAP_ADDSECOND : LEAP_DELSECOND);
@@ -4706,7 +4704,7 @@ 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 occurence of a series of reports */
+ /* for the first occurrence of a series of reports */
static int
last_rptcode = 0;
int
diff --git a/contrib/ntp/ntpd/refclock_shm.c b/contrib/ntp/ntpd/refclock_shm.c
index 3747ce0..4ab0ede 100644
--- a/contrib/ntp/ntpd/refclock_shm.c
+++ b/contrib/ntp/ntpd/refclock_shm.c
@@ -87,6 +87,9 @@ struct shmTime {
int valid;
int dummy[10];
};
+
+struct shmTime *getShmTime(int);
+
struct shmTime *getShmTime (int unit) {
#ifndef SYS_WINNT
int shmid=0;
@@ -149,7 +152,6 @@ struct shmTime *getShmTime (int unit) {
return p;
}
#endif
- return 0;
}
/*
* shm_start - attach to shared memory
@@ -201,7 +203,8 @@ shm_shutdown(
pp = peer->procptr;
up = (struct shmTime *)pp->unitptr;
#ifndef SYS_WINNT
- shmdt (up);
+ /* HMS: shmdt()wants char* or const void * */
+ (void) shmdt (up);
#else
UnmapViewOfFile (up);
#endif
@@ -272,8 +275,7 @@ shm_poll(
pp->hour=t->tm_hour;
pp->minute=t->tm_min;
pp->second=t->tm_sec;
- pp->msec=0;
- pp->usec=tvt.tv_usec;
+ pp->nsec=tvt.tv_usec * 1000;
peer->precision=up->precision;
pp->leap=up->leap;
}
@@ -285,13 +287,16 @@ shm_poll(
}
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);
}
diff --git a/contrib/ntp/ntpd/refclock_tpro.c b/contrib/ntp/ntpd/refclock_tpro.c
index 159f817..3c42568 100644
--- a/contrib/ntp/ntpd/refclock_tpro.c
+++ b/contrib/ntp/ntpd/refclock_tpro.c
@@ -164,6 +164,11 @@ tpro_poll(
* 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",
@@ -179,11 +184,12 @@ tpro_poll(
pp->a_lastcode);
#endif
if (sscanf(pp->a_lastcode, "%3d %2d:%2d:%2d.%6ld", &pp->day,
- &pp->hour, &pp->minute, &pp->second, &pp->usec)
+ &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
@@ -198,6 +204,8 @@ tpro_poll(
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;
diff --git a/contrib/ntp/ntpd/refclock_trak.c b/contrib/ntp/ntpd/refclock_trak.c
index 326a8e9..3a4a54e 100644
--- a/contrib/ntp/ntpd/refclock_trak.c
+++ b/contrib/ntp/ntpd/refclock_trak.c
@@ -325,6 +325,7 @@ trak_receive(
refclock_report(peer, CEVNT_BADTIME);
return;
}
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
}
diff --git a/contrib/ntp/ntpd/refclock_true.c b/contrib/ntp/ntpd/refclock_true.c
index 986031d..dd355d9 100644
--- a/contrib/ntp/ntpd/refclock_true.c
+++ b/contrib/ntp/ntpd/refclock_true.c
@@ -503,6 +503,7 @@ true_receive(
refclock_report(peer, CEVNT_BADTIME);
return;
}
+ off.l_uf = 0;
#endif
pp->usec = true_sample720();
@@ -545,8 +546,9 @@ true_receive(
* If clock is good we send a NOMINAL message so that
* any previous BAD messages are nullified
*/
- refclock_report(peer, CEVNT_NOMINAL);
+ pp->lastref = pp->lastrec;
refclock_receive(peer);
+ refclock_report(peer, CEVNT_NOMINAL);
/*
* We have succedded in answering the poll.
diff --git a/contrib/ntp/ntpd/refclock_ulink.c b/contrib/ntp/ntpd/refclock_ulink.c
index 5bf569a..1f5e78a 100644
--- a/contrib/ntp/ntpd/refclock_ulink.c
+++ b/contrib/ntp/ntpd/refclock_ulink.c
@@ -248,8 +248,6 @@ ulink_receive(
* proper format, we declare bad format and exit.
*/
syncchar = leapchar = modechar = ' ';
- pp->msec = 0;
-
switch (pp->lencode ) {
case LEN33X:
/*
@@ -347,11 +345,11 @@ ulink_receive(
* T = DST <-> STD transition indicators
*
*/
- if (sscanf(pp->a_lastcode, "%c%1d%c%4d%3d%*c%2d:%2d:%2d.%2d%c",
+ 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->msec,&leapchar) == 10) {
- pp->msec *= 10; /* M320 returns 10's of msecs */
+ &pp->nsec, &leapchar) == 10) {
+ pp->nsec *= 10000000; /* M320 returns 10's of msecs */
if (leapchar == 'I' ) leapchar = '+';
if (leapchar == 'D' ) leapchar = '-';
if (syncchar != '?' ) syncchar = ':';
@@ -487,8 +485,9 @@ ulink_poll(
refclock_report(peer, CEVNT_TIMEOUT);
return;
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- refclock_receive(peer);
+ pp->lastref = pp->lastrec;
+ refclock_receive(peer);
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
peer->burst = NSTAGE;
}
diff --git a/contrib/ntp/ntpd/refclock_usno.c b/contrib/ntp/ntpd/refclock_usno.c
index 30a1330..057eef9 100644
--- a/contrib/ntp/ntpd/refclock_usno.c
+++ b/contrib/ntp/ntpd/refclock_usno.c
@@ -344,8 +344,9 @@ usno_receive(
* protocol module to chuck out the data. Finaly, we unhook the
* timeout, arm for the next call, fold the tent and go home.
*/
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ 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;
@@ -437,7 +438,7 @@ usno_timeout(
peer->nextdate = current_time + ANSWER;
return;
}
- switch (peer->ttlmax) {
+ switch (peer->ttl) {
/*
* In manual mode the calling program is activated
diff --git a/contrib/ntp/ntpd/refclock_wwv.c b/contrib/ntp/ntpd/refclock_wwv.c
index b1d05c7..11aae7f 100644
--- a/contrib/ntp/ntpd/refclock_wwv.c
+++ b/contrib/ntp/ntpd/refclock_wwv.c
@@ -21,7 +21,7 @@
# include <sys/ioctl.h>
#endif /* HAVE_SYS_IOCTL_H */
-#define ICOM 1 /* undefine to suppress ICOM code */
+#define ICOM 1
#ifdef ICOM
#include "icom.h"
@@ -32,7 +32,7 @@
*
* 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. Transmikssions are made continuously on
+ * 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
@@ -40,16 +40,16 @@
* night.
*
* The driver receives, demodulates and decodes the radio signals when
- * connected to the audio codec of a Sun workstation running SunOS or
- * Solaris, 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.
+ * 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
+ * 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
@@ -64,66 +64,69 @@
* 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 REFID "NONE" /* reference ID */
#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. /* maximum signal level reference */
+#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 (125e-6 * SECOND) /* freq tolerance (.0125%) */
+#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 UTCYEAR 72 /* the first UTC year */
#define MAXERR 30 /* max data bit errors in minute */
-#define NCHAN 5 /* number of channels */
-
-/*
- * Macroni
- */
-#define MOD(x, y) ((x) < 0 ? -(-(x) % (y)) : (x) % (y))
+#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)
*
- * Notes: SELV and/or SELH are set when the minute sync pulse from
- * either or both WWV and/or WWVH stations has been heard. MSYNC is set
- * when the minute sync pulse has been acquired and never reset. SSYNC
- * is set when the second sync pulse has been acquired and cleared by
- * watchdog or signal loss. DSYNC is set when the minutes unit digit has
- * reached the threshold and INSYNC is set when if all nine digits have
- * reached the threshold and never cleared.
+ * 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, BGATE is set if a BCD digit
+ * 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 for alternate frequencies. LEPSEC is set when the SECWAR of
- * the timecode is set on the last second of 30 June or 31 December. At
- * the end of this minute both the receiver and transmitter insert
- * second 60 in the minute and the minute sync slips a second.
+ * 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 DGATE 0x0010 /* data bit error */
-#define BGATE 0x0020 /* BCD digit bit error */
+#define FGATE 0x0010 /* frequency gate */
+#define DGATE 0x0020 /* data bit error */
+#define BGATE 0x0040 /* BCD digit bit error */
#define SFLAG 0x1000 /* probe flag */
-#define LEPSEC 0x2000 /* leap second in progress */
+#define LEPDAY 0x2000 /* leap second day */
+#define LEPSEC 0x4000 /* leap second minute */
/*
- * Station scoreboard bits (select)
+ * Station scoreboard bits
*
* These are used to establish the signal quality for each of the five
* frequencies and two stations.
*/
-#define JITRNG 0x0001 /* jitter above threshold */
-#define SYNCNG 0x0002 /* sync below threshold or SNR */
-#define DATANG 0x0004 /* data below threshold or SNR */
+#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 */
@@ -131,75 +134,72 @@
* Alarm status bits (alarm)
*
* These bits indicate various alarm conditions, which are decoded to
- * form the quality character included in the timecode. There are four
- * four-bit nibble fields in the word, each corresponding to a specific
- * alarm condition. At the end of each second, the word is shifted left
- * one position and the least significant bit of each nibble cleared.
- * This bit can be set during the next minute if the associated alarm
- * condition is raised. This provides a way to remember alarm conditions
- * up to four minutes.
- *
- * If not tracking both minute sync and 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.
+ * 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 0 /* BCD digit compare error */
-#define SYMERR 4 /* low bit or digit probability */
-#define MODERR 8 /* too many data bit errors */
-#define SYNERR 12 /* not synchronized to station */
+#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 */
/*
- * Watchdog timeouts (watch)
+ * 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 /* acquisition timeout */
-#define HSPEC 15 /* second sync timeout */
+#define ACQSN 5 /* station acquisition timeout */
#define DIGIT 30 /* minute unit digit timeout */
-#define PANIC (4 * 1440) /* panic 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 receiver. The values defined here may be on the
+ * rates of the driver. The values defined here may be on the
* adventurous side in the interest of the highest sensitivity.
*/
-#define ATHR 2000 /* acquisition amplitude threshold */
-#define ASNR 6.0 /* acquisition SNR threshold (dB) */
-#define AWND 50 /* acquisition window threshold (ms) */
-#define AMIN 3 /* acquisition min compare count */
-#define AMAX 6 /* max compare count */
-#define QTHR 2000 /* QSY amplitude threshold */
-#define QSNR 20.0 /* QSY SNR threshold (dB) */
+#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.0 /* bit SNR threshold (dB) */
-#define BTHR 1000 /* digit probability threshold */
-#define BSNR 3.0 /* digit likelihood threshold (dB) */
-#define BCMP 5 /* digit compare threshold (dB) */
+#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.
+ * Tone frequency definitions. The increments are for 4.5-deg sine
+ * table.
*/
-#define MS 8 /* samples per millisecond */
-#define IN100 1 /* 100 Hz 4.5-deg sin table */
-#define IN1000 10 /* 1000 Hz 4.5-deg sin table */
-#define IN1200 12 /* 1200 Hz 4.5-deg sin 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 (s) */
-#define MAXAVG 7 /* max time constant (log2 s) */
-#define TCONST 16 /* minute time constant (s) */
-#define SYNCTC (1024 / (1 << MAXAVG)) /* FLL constant (s) */
+#define MINAVG 8 /* min time constant */
+#define MAXAVG 1024 /* max time constant */
+#define TCONST 16 /* data bit/digit time constant */
/*
* Miscellaneous status bits (misc)
@@ -212,30 +212,20 @@
#define DUT2 0x02 /* 57 DUT .2 */
#define DUT4 0x04 /* 58 DUT .4 */
#define DUTS 0x08 /* 50 DUT sign */
-#define DST1 0x10 /* 55 DST1 DST in progress */
-#define DST2 0x20 /* 2 DST2 DST change warning */
+#define DST1 0x10 /* 55 DST1 leap warning */
+#define DST2 0x20 /* 2 DST2 DST1 delayed one day */
#define SECWAR 0x40 /* 3 leap second warning */
/*
- * The total system delay with the DSP93 program is at 22.5 ms,
- * including the propagation delay from Ft. Collins, CO, to Newark, DE
- * (8.9 ms), the communications receiver delay and the delay of the
- * DSP93 program itself. The DSP93 program delay is due mainly to the
- * 400-Hz FIR bandpass filter (5 ms) and second sync matched filter (5
- * ms), leaving about 3.6 ms for the receiver delay and strays.
- *
- * The total system delay with this program is estimated at 27.1 ms by
- * comparison with another PPS-synchronized NTP server over a 10-Mb/s
- * Ethernet. The propagation and receiver delays are the same as with
- * the DSP93 program. The program delay is due only to the 600-Hz
- * IIR bandpass filter (1.1 ms), since other delays have been removed.
- * Assuming 4.7 ms for the receiver, program and strays, this leaves
- * 13.5 ms for the audio codec and operating system latencies for a
- * total of 18.2 ms. as the systematic delay. The additional propagation
- * delay specific to each receiver location can be programmed in the
- * fudge time1 and time2 values for WWV and WWVH, respectively.
+ * 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 (.0036 + .0011 + .0135) /* net system delay (s) */
+#define PDELAY (.0011 + .0047 + .0002) /* net system delay (s) */
/*
* Table of sine values at 4.5-degree increments. This is used by the
@@ -280,20 +270,19 @@ struct progx {
* Case switch numbers
*/
#define IDLE 0 /* no operation */
-#define COEF 1 /* BCD bit conditioned on DSYNC */
-#define COEF1 2 /* BCD bit */
-#define COEF2 3 /* BCD bit ignored */
-#define DECIM9 4 /* BCD digit 0-9 */
-#define DECIM6 5 /* BCD digit 0-6 */
-#define DECIM3 6 /* BCD digit 0-3 */
-#define DECIM2 7 /* BCD digit 0-2 */
-#define MSCBIT 8 /* miscellaneous bit */
-#define MSC20 9 /* miscellaneous bit */
-#define MSC21 10 /* QSY probe channel */
-#define MIN1 11 /* minute */
-#define MIN2 12 /* leap second */
-#define SYNC2 13 /* QSY data channel */
-#define SYNC3 14 /* QSY data channel */
+#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
@@ -314,10 +303,10 @@ struct progx progx[] = {
{COEF, 3}, /* 7 8 */
{DECIM9, YR}, /* 8 */
{IDLE, 0}, /* 9 p1 */
- {COEF1, 0}, /* 10 1 minute units */
- {COEF1, 1}, /* 11 2 */
- {COEF1, 2}, /* 12 4 */
- {COEF1, 3}, /* 13 8 */
+ {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 */
@@ -442,8 +431,8 @@ double bcd2[][4] = {
*/
char dstcod[] = {
'S', /* 00 standard time */
- 'I', /* 01 daylight warning */
- 'O', /* 10 standard warning */
+ 'I', /* 01 set clock ahead at 0200 local */
+ 'O', /* 10 set clock back at 0200 local */
'D' /* 11 daylight time */
};
@@ -472,32 +461,32 @@ struct decvec {
* for WWVH. Other than frequency, the format is the same.
*/
struct sync {
- double amp; /* sync amplitude (I, Q square) */
- double synamp; /* sync envelope at 800 ms */
+ 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; /* avg sync envelope at 59 s, 1 s */
+ double synmin; /* sync envelope at 59, 1 s */
double synsnr; /* sync signal SNR */
- double noise; /* max amplitude off pulse */
- double sigmax; /* max amplitude on pulse */
- double lastmax; /* last max amplitude on pulse */
- long pos; /* position at maximum amplitude */
- long lastpos; /* last position at maximum amplitude */
- long jitter; /* shake, wiggle and waggle */
- long mepoch; /* minute synch epoch */
- int count; /* compare counter */
+ int count; /* bit counter */
char refid[5]; /* reference identifier */
- char ident[4]; /* station identifier */
int select; /* select bits */
+ int reach; /* reachability register */
};
/*
- * The channel structure is used to mitigate between channels. At this
- * point we have already decided which station to use.
+ * The channel structure is used to mitigate between channels.
*/
struct chan {
int gain; /* audio gain */
- int errcnt; /* data bit error counter */
- double noiamp; /* I-channel average noise amplitude */
+ 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 */
};
@@ -508,37 +497,42 @@ struct chan {
struct wwvunit {
l_fp timestamp; /* audio sample timestamp */
l_fp tick; /* audio sample increment */
- double comp[SIZE]; /* decompanding table */
double phase, freq; /* logical clock phase and frequency */
double monitor; /* audio monitor point */
int fd_icom; /* ICOM file descriptor */
int errflg; /* error flags */
- int bufcnt; /* samples in buffer */
- int bufptr; /* buffer index pointer */
+ 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 */
- int seccnt; /* second countdown */
- int minset; /* minutes since last clock set */
- int watch; /* watchcat */
- int swatch; /* second sync watchcat */
+#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; /* log2 master time constant (s) */
- int epoch; /* second epoch ramp */
- int repoch; /* receiver sync epoch */
- int yepoch; /* transmitter sync epoch */
+ 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; /* receiver sample counter */
- int rsec; /* receiver seconds counter */
+ int rphase; /* second sample counter */
long mphase; /* minute sample counter */
- long nepoch; /* minute epoch index */
/*
* Variables used to mitigate which channel to use
@@ -553,19 +547,16 @@ struct wwvunit {
* Variables used by the clock state machine
*/
struct decvec decvec[9]; /* decoding matrix */
- int cdelay; /* WWV propagation delay (samples) */
- int hdelay; /* WVVH propagation delay (samples) */
- int pdelay; /* propagation delay (samples) */
- int tphase; /* transmitter sample counter */
- int tsec; /* transmitter seconds counter */
+ int rsec; /* seconds counter */
int digcnt; /* count of digits synchronized */
/*
* Variables used to estimate signal levels and bit/digit
* probabilities
*/
- double sigamp; /* I-channel peak signal amplitude */
- double noiamp; /* I-channel average noise amplitude */
+ double sigsig; /* data max signal */
+ double sigamp; /* data max envelope (square) */
+ double noiamp; /* data noise envelope (square) */
double datsnr; /* data SNR (dB) */
/*
@@ -575,6 +566,7 @@ struct wwvunit {
int alarm; /* alarm flashers */
int misc; /* miscellaneous timecode bits */
int errcnt; /* data bit error counter */
+ int errbit; /* data bit errors in minute */
};
/*
@@ -590,10 +582,10 @@ static void wwv_poll P((int, struct peer *));
*/
static void wwv_epoch P((struct peer *));
static void wwv_rf P((struct peer *, double));
-static void wwv_endpoc P((struct peer *, double, int));
+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));
+ double, int));
static void wwv_corr4 P((struct peer *, struct decvec *,
double [], double [][4]));
static void wwv_gain P((struct peer *));
@@ -603,7 +595,12 @@ 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) */
/*
@@ -625,13 +622,12 @@ struct refclock refclock_wwv = {
*/
static int
wwv_start(
- int unit, /* instance number (not used) */
+ int unit, /* instance number (used by PCM) */
struct peer *peer /* peer structure pointer */
)
{
struct refclockproc *pp;
struct wwvunit *up;
- struct chan *cp;
#ifdef ICOM
int temp;
#endif /* ICOM */
@@ -646,7 +642,7 @@ wwv_start(
/*
* Open audio device
*/
- fd = audio_init(DEVICE_AUDIO);
+ fd = audio_init(DEVICE_AUDIO, AUDIO_BUFSIZ, unit);
if (fd < 0)
return (0);
#ifdef DEBUG
@@ -657,12 +653,11 @@ wwv_start(
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct wwvunit *)
- emalloc(sizeof(struct wwvunit)))) {
- (void) close(fd);
+ if (!(up = (struct wwvunit *)emalloc(sizeof(struct wwvunit)))) {
+ close(fd);
return (0);
}
- memset((char *)up, 0, sizeof(struct wwvunit));
+ memset(up, 0, sizeof(struct wwvunit));
pp = peer->procptr;
pp->unitptr = (caddr_t)up;
pp->io.clock_recv = wwv_receive;
@@ -670,7 +665,7 @@ wwv_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void)close(fd);
+ close(fd);
free(up);
return (0);
}
@@ -680,8 +675,6 @@ wwv_start(
*/
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- DTOLFP(1. / SECOND, &up->tick);
/*
* The companded samples are encoded sign-magnitude. The table
@@ -697,6 +690,7 @@ wwv_start(
if (i % 16 == 0)
step *= 2.;
}
+ DTOLFP(1. / SECOND, &up->tick);
/*
* Initialize the decoding matrix with the radix for each digit
@@ -711,22 +705,8 @@ wwv_start(
up->decvec[DA + 2].radix = 4;
up->decvec[YR].radix = 10; /* years */
up->decvec[YR + 1].radix = 10;
-
- /*
- * Initialize the station processes for audio gain, select bit,
- * station/frequency identifier and reference identifier.
- */
- up->gain = 127;
- for (i = 0; i < NCHAN; i++) {
- cp = &up->mitig[i];
- cp->gain = up->gain;
- cp->wwv.select = SELV;
- strcpy(cp->wwv.refid, "WWV ");
- sprintf(cp->wwv.ident,"C%.0f", floor(qsy[i]));
- cp->wwvh.select = SELH;
- strcpy(cp->wwvh.refid, "WWVH");
- sprintf(cp->wwvh.ident, "H%.0f", floor(qsy[i]));
- }
+ wwv_newgame(peer);
+ up->schan = up->achan = 3;
/*
* Initialize autotune if available. Start out at 15 MHz. Note
@@ -739,8 +719,8 @@ wwv_start(
if (debug > 1)
temp = P_TRACE;
#endif
- if (peer->ttlmax != 0) {
- if (peer->ttlmax & 0x80)
+ if (peer->ttl != 0) {
+ if (peer->ttl & 0x80)
up->fd_icom = icom_init("/dev/icom", B1200,
temp);
else
@@ -748,14 +728,17 @@ wwv_start(
temp);
}
if (up->fd_icom > 0) {
- up->schan = 3;
- if ((temp = wwv_qsy(peer, up->schan)) < 0) {
+ if ((temp = wwv_qsy(peer, up->schan)) != 0) {
NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_ERR,
- "ICOM bus error; autotune disabled");
+ 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 */
@@ -806,10 +789,8 @@ wwv_receive(
*/
double sample; /* codec sample */
u_char *dpt; /* buffer pointer */
+ int bufcnt; /* buffer counter */
l_fp ltemp;
- int isneg;
- double dtemp;
- int i, j;
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
@@ -819,13 +800,12 @@ wwv_receive(
* 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;
- up->bufcnt = rbufp->recv_length;
- DTOLFP((double)up->bufcnt / SECOND, &ltemp);
- L_SUB(&up->timestamp, &ltemp);
dpt = rbufp->recv_buffer;
- for (up->bufptr = 0; up->bufptr < up->bufcnt; up->bufptr++) {
- sample = up->comp[~*dpt & 0xff];
+ for (bufcnt = 0; bufcnt < rbufp->recv_length; bufcnt++) {
+ sample = up->comp[~*dpt++ & 0xff];
/*
* Clip noise spikes greater than MAXSIG. If no clips,
@@ -841,14 +821,17 @@ wwv_receive(
}
/*
- * Variable frequency oscillator. A phase change of one
- * unit produces a change of 360 degrees; a frequency
- * change of one unit produces a change of 1 Hz.
+ * 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) {
+ } else if (up->phase < -.5) {
up->phase += 1.;
wwv_rf(peer, sample);
wwv_rf(peer, sample);
@@ -856,71 +839,30 @@ wwv_receive(
wwv_rf(peer, sample);
}
L_ADD(&up->timestamp, &up->tick);
-
- /*
- * Once each second adjust the codec port and gain.
- * While at it, initialize the propagation delay for
- * both WWV and WWVH. Don't forget to correct for the
- * receiver phase delay, mostly due to the 600-Hz
- * IIR bandpass filter used for the sync signals.
- */
- up->cdelay = (int)(SECOND * (pp->fudgetime1 + PDELAY));
- up->hdelay = (int)(SECOND * (pp->fudgetime2 + PDELAY));
- up->seccnt = (up->seccnt + 1) % SECOND;
- if (up->seccnt == 0) {
- if (pp->sloppyclockflag & CLK_FLAG2)
- up->port = 2;
- else
- up->port = 1;
- }
-
- /*
- * During development, it is handy to have an audio
- * monitor that can be switched to various signals. This
- * code converts the linear signal left in up->monitor
- * to codec format.
- */
- isneg = 0;
- dtemp = up->monitor;
- if (sample < 0) {
- isneg = 1;
- dtemp -= dtemp;
- }
- i = 0;
- j = OFFSET >> 1;
- while (j != 0) {
- if (dtemp > up->comp[i])
- i += j;
- else if (dtemp < up->comp[i])
- i -= j;
- else
- break;
- j >>= 1;
- }
- if (isneg)
- *dpt = ~(i + OFFSET);
- else
- *dpt = ~i;
- dpt++;
}
/*
- * Squawk to the monitor speaker if enabled.
+ * 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)
- if (write(pp->io.fd, (u_char *)&rbufp->recv_space,
- (u_int)up->bufcnt) < 0)
- perror("wwv:");
+ up->mongain = MONGAIN;
+ else
+ up->mongain = 0;
}
/*
* wwv_poll - called by the transmit procedure
*
- * This routine keeps track of status. If nothing is heard for two
- * successive poll intervals, a timeout event is declared and any
- * orphaned timecode updates are sent to foster care. Once the clock is
- * set, it always appears reachable, unless reset by watchdog timeout.
+ * 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(
@@ -935,13 +877,10 @@ wwv_poll(
up = (struct wwvunit *)pp->unitptr;
if (pp->coderecv == pp->codeproc)
up->errflg = CEVNT_TIMEOUT;
- else
- pp->polls++;
- if (up->status & INSYNC)
- peer->reach |= 1;
if (up->errflg)
refclock_report(peer, up->errflg);
up->errflg = 0;
+ pp->polls++;
}
@@ -953,36 +892,27 @@ wwv_poll(
* form, plus the epoch index of the second sync signal and the second
* index of the minute sync signal.
*
- * There are three 1-s ramps used by this program, all spanning the
- * range 0-7999 logical samples for exactly one second, as determined by
- * the logical clock. The first drives the second epoch and runs
- * continuously. The second determines the receiver phase and the third
- * the transmitter phase within the second. The receiver second begins
- * upon arrival of the 5-ms second sync pulse which begins the second;
- * while the transmitter second begins before it by the specified
- * propagation delay.
- *
- * There are three 1-m ramps spanning the range 0-59 seconds. The first
- * drives the minute epoch in samples and runs continuously. The second
- * determines the receiver second and the third the transmitter second.
- * The receiver second begins upon arrival of the 800-ms sync pulse sent
- * during the first second of the minute; while the transmitter second
- * begins before it by the specified propagation delay.
+ * 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.
*
- * The output signals include the epoch maximum and phase and second
- * maximum and index. The epoch phase provides the master reference for
- * all signal and timing functions, while the second index identifies
- * the first second of the minute. The epoch and second maxima are used
- * to calculate SNR for gating functions.
+ * 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 subcarrier, 1000 Hz for the WWV sync
- * signals and 1200 Hz for the WWVH sync signal. These drive synchronous
- * matched filters for the data subcarrier (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 seconds sync signal (5 ms at 1000 Hz) and
- * WWVH seconds sync signal (5 ms at 1200 Hz).
+ * 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(
@@ -992,6 +922,7 @@ wwv_rf(
{
struct refclockproc *pp;
struct wwvunit *up;
+ struct sync *sp;
static double lpf[5]; /* 150-Hz lpf delay line */
double data; /* lpf output */
@@ -1021,13 +952,14 @@ wwv_rf(
static int epopos; /* epoch sync position buffer */
static int iniflg; /* initialization flag */
- struct sync *sp;
- double dtemp;
- long ltemp;
- int i;
+ 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));
@@ -1041,7 +973,6 @@ wwv_rf(
memset((char *)hqbuf, 0, sizeof(hqbuf));
memset((char *)epobuf, 0, sizeof(epobuf));
}
- up->monitor = isig; /* change for debug */
/*
* Baseband data demodulation. The 100-Hz subcarrier is
@@ -1069,13 +1000,9 @@ wwv_rf(
* 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. Note the correction
- * due to the propagation delay is necessary for seamless
- * handover between WWV and WWVH.
+ * and phase signals used by the decoder.
*/
- i = up->datapt - up->pdelay % 80;
- if (i < 0)
- i += 80;
+ i = up->datapt;
up->datapt = (up->datapt + IN100) % 80;
dtemp = sintab[i] * data / DATSIZ * DGAIN;
up->irig -= ibuf[iptr];
@@ -1123,9 +1050,14 @@ wwv_rf(
* 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;
@@ -1135,9 +1067,12 @@ wwv_rf(
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;
- wwv_qrz(peer, &up->mitig[up->schan].wwv, dtemp);
-
+ 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;
@@ -1147,98 +1082,95 @@ wwv_rf(
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;
- wwv_qrz(peer, &up->mitig[up->schan].wwvh, dtemp);
-
+ 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) {
-
- /*
- * This section is called once per minute at the minute
- * epoch independently of the transmitter or receiver
- * minute. If the leap bit is set, set the minute epoch
- * back one second so the station processes don't miss a
- * beat. Then, increment the watchdog counter and test
- * for two sets of conditions depending on whether
- * minute sync has been acquired or not.
- */
up->watch++;
- if (up->rsec == 60) {
- up->mphase -= SECOND;
- if (up->mphase < 0)
- up->mphase += MINUTE;
- } else if (!(up->status & MSYNC)) {
-
- /*
- * If minute sync has not been acquired, the
- * program listens for minute sync pulses from
- * both WWV and WWVH. The station with the
- * greater compare count is selected, with ties
- * broken by WWV, but only if the count is at
- * least three. Once a station has been
- * acquired, it is initialized and begins
- * tracking the signal.
+ 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.
*/
- if (up->mitig[up->achan].wwv.count >=
- up->mitig[up->achan].wwvh.count)
- sp = &up->mitig[up->achan].wwv;
- else
- sp = &up->mitig[up->achan].wwvh;
- if (sp->count >= AMIN) {
- up->watch = up->swatch = 0;
- up->status |= MSYNC;
- ltemp = sp->mepoch - SYNSIZ;
- if (ltemp < 0)
- ltemp += MINUTE;
- up->rsec = (MINUTE - ltemp) / SECOND;
- if (!(up->status & SSYNC)) {
- up->repoch = ltemp % SECOND;
- up->yepoch = up->repoch -
- up->pdelay;
- if (up->yepoch < 0)
- up->yepoch += SECOND;
+ 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);
}
- wwv_newchan(peer);
- } else if (sp->count == 0 || up->watch >= ACQSN)
- {
- up->watch = sp->count = 0;
- up->schan = (up->schan + 1) % NCHAN;
- wwv_qsy(peer, up->schan);
+#endif /* ICOM */
}
} else {
/*
- * If minute sync has been acquired, the program
- * watches for timeout. The timeout is reset
- * when the clock is set or verified. If a
- * timeout occurs and the minute units digit has
- * not synchronized, reset the program and start
- * over.
+ * If the leap bit is set, set the minute epoch
+ * back one second so the station processes
+ * don't miss a beat.
*/
- if (up->watch > DIGIT && !(up->status & DSYNC))
- up->watch = up->status = 0;
+ if (up->status & LEPSEC) {
+ up->mphase -= SECOND;
+ if (up->mphase < 0)
+ up->mphase += MINUTE;
+ }
+ }
+ }
- /*
- * If the second sync times out, dim the sync
- * lamp and raise an alarm.
- */
- up->swatch++;
- if (up->swatch > HSPEC)
- up->status &= ~SSYNC;
+ /*
+ * 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->alarm |= 1 << SYNERR;
+ 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 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 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) {
- up->pdelay = up->cdelay;
+ pdelay = (int)(pp->fudgetime1 * SECOND);
/*
* WWV FIR matched filter, five cycles of 1000-Hz
@@ -1286,7 +1218,7 @@ wwv_rf(
mfsync += (mf[1] = mf[0]) * -4.224514e-02;
mf[0] = syncx;
} else if (up->status & SELH) {
- up->pdelay = up->hdelay;
+ pdelay = (int)(pp->fudgetime2 * SECOND);
/*
* WWVH FIR matched filter, six cycles of 1200-Hz
@@ -1335,32 +1267,47 @@ wwv_rf(
mf[0] = syncx;
} else {
mfsync = 0;
+ pdelay = 0;
}
/*
- * Extract the seconds sync pulse using a 1-s comb filter at
- * baseband. Correct for the FIR matched filter delay, which is
- * 5 ms for both the WWV and WWVH filters. Blank the signal when
- * probing.
+ * 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.
*/
- up->epoch = (up->epoch + 1) % SECOND;
- if (up->epoch == 0) {
- wwv_endpoc(peer, epomax, epopos);
- up->epomax = epomax;
- epomax = 0;
- if (!(up->status & MSYNC))
- wwv_gain(peer);
- }
- dtemp = (epobuf[up->epoch] += (mfsync - epobuf[up->epoch]) /
- (MINAVG << up->avgint));
+ dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) /
+ up->avgint);
if (dtemp > epomax) {
epomax = dtemp;
- epopos = up->epoch - up->pdelay - 5 * MS;
+ 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);
}
- if (up->status & MSYNC)
- wwv_epoch(peer);
}
@@ -1369,39 +1316,41 @@ wwv_rf(
*
* 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
+ * 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 epoch minute of samples. After
- * minute sync acquisition, the process searches only during the probe
- * window, which occupies seconds 59, 0 and 1, to construct a metric
- * used to determine which frequency and station provides the best
- * signal.
- *
- * The pulse discriminator requires that (a) the peak on-pulse sample
- * amplitude must be above 2000, (b) the SNR relative to the peak
- * off-pulse sample amplitude must be reduced 6 dB or more below the
- * peak and (c) the maximum difference between the current and previous
- * epoch indices must be less than 50 ms. A compare counter keeps track
- * of the number of successive intervals which satisfy these criteria.
+ * 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. In practice, the performance
- * of this gadget is amazing. Once setting teeth in a station, it hangs
- * on until the minute beep can barely be heard and long after the
- * second tick and comb filter have given up.
+ * 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, /* peerstructure pointer */
+ struct peer *peer, /* peer structure pointer */
struct sync *sp, /* sync channel structure */
- double syncx /* bandpass filtered sync signal */
+ 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;
+ long epoch, fpoch;
int isgood;
pp = peer->procptr;
@@ -1409,171 +1358,147 @@ wwv_qrz(
/*
* Find the sample with peak energy, which defines the minute
- * epoch. If minute sync has been acquired, search only the
- * probe window; otherwise, search the entire minute. If a
- * maximum has been found with good amplitude, search only the
- * second before and after that position for the next maximum
- * and the rest of the window for the noise.
- */
- if (!(up->status & MSYNC) || up->status & SFLAG) {
- sp->amp = syncx;
- if (up->status & MSYNC)
- epoch = up->nepoch;
- else if (sp->count > 1)
- epoch = sp->mepoch;
- else
- epoch = sp->lastpos;
- if (syncx > sp->sigmax) {
- sp->sigmax = syncx;
- sp->pos = up->mphase;
- }
- if (abs(MOD(up->mphase - epoch, MINUTE)) > SYNSIZ &&
- syncx > sp->noise) {
- sp->noise = syncx;
- }
+ * 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;
/*
- * 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 (jitter).
+ * If not yet in minute sync, we have to do a little
+ * dance to find a valid minute sync pulse, emphasis
+ * valid.
*/
- sp->jitter = MOD(sp->pos - sp->lastpos, MINUTE);
- sp->select &= ~JITRNG;
- if (abs(sp->jitter) > AWND * MS)
- sp->select |= JITRNG;
- sp->sigmax = SQRT(sp->sigmax);
- sp->noise = SQRT(sp->noise);
- if (up->status & MSYNC) {
-
- /*
- * If in minute sync, just count the runs up and
- * down.
- */
- if (sp->select & (DATANG | SYNCNG | JITRNG)) {
- if (sp->count > 0)
- sp->count--;
- } else {
- if (sp->count < AMAX)
- sp->count++;
- }
- } else {
+ snr = wwv_snr(sp->synmax, sp->synmin);
+ isgood = isgood && sp->synmax > ATHR && snr > ASNR;
+ switch (sp->count) {
- /*
- * 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->sigmax, sp->noise);
- isgood = sp->sigmax > ATHR && snr > ASNR &&
- !(sp->select & JITRNG);
- 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 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.
- * If found, bump to state 1.
- */
- case 0:
- if (sp->sigmax >= ATHR)
- sp->count++;
+ /*
+ * 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 state 1 a candidate blip has been found
- * and the next minute has been searched for
- * another blip. If none are found greater than
- * the threshold, or if the biggest blip outside
- * the candidate pulse is less than 6 dB below
- * the biggest blip, 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 (sp->sigmax < ATHR) {
- sp->count--;
- break;
- } else if (!isgood) {
- break;
- }
- /* fall through */
-
- /*
- * In states 2 and above, continue to groom
- * samples as before and drop back to the
- * previous state if the groom fails. If it
- * succeeds, bump to the next state until
- * reaching the clamp, if ever.
- */
- default:
- if (!isgood) {
- sp->count--;
- break;
- }
- sp->mepoch = sp->pos;
- if (sp->count < AMAX)
- 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 %-3s %d %5.0f %5.1f %7ld %7ld %7ld",
- up->port, up->gain, sp->ident, sp->count,
- sp->sigmax, snr, sp->pos, sp->jitter,
- MOD(sp->pos - up->nepoch - SYNSIZ, MINUTE));
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, 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->lastmax = sp->sigmax;
sp->lastpos = sp->pos;
- sp->sigmax = sp->noise = 0;
+ sp->maxamp = sp->noiamp = 0;
}
}
/*
- * wwv_endpoc - process receiver epoch
+ * wwv_endpoc - identify and acquire second sync pulse
*
- * This routine is called at the end of the receiver epoch. It
- * determines the epoch position within the second and disciplines the
- * sample clock using a frequency-lock loop (FLL).
+ * 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).
*
- * Seconds sync is determined in the RF input routine as the maximum
+ * 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 data filtering and grooming.
+ * 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 */
- double epomax, /* epoch max */
int epopos /* epoch max position */
)
{
struct refclockproc *pp;
struct wwvunit *up;
-
static int epoch_mf[3]; /* epoch median filter */
- static int tepoch; /* median filter epoch */
- static int tspan; /* median filter span */
static int xepoch; /* last second epoch */
static int zepoch; /* last averaging interval epoch */
- static int syncnt; /* second epoch run length counter */
- static int jitcnt; /* jitter holdoff counter */
+ 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, tmp3;
+ int tmp2;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
@@ -1584,86 +1509,64 @@ wwv_endpoc(
/*
* A three-stage median filter is used to help denoise the
- * seconds sync pulse. The median sample becomes the candidate
- * epoch; the difference between the other two samples becomes
- * the span, which is used currently only for debugging.
+ * 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]) {
- tepoch = epoch_mf[1]; /* 0 1 2 */
- tspan = epoch_mf[0] - epoch_mf[2];
- } else if (epoch_mf[2] > epoch_mf[0]) {
- tepoch = epoch_mf[0]; /* 2 0 1 */
- tspan = epoch_mf[2] - epoch_mf[1];
- } else {
- tepoch = epoch_mf[2]; /* 0 2 1 */
- tspan = 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]) {
- tepoch = epoch_mf[1]; /* 2 1 0 */
- tspan = epoch_mf[2] - epoch_mf[0];
- } else if (epoch_mf[2] < epoch_mf[0]) {
- tepoch = epoch_mf[0]; /* 1 0 2 */
- tspan = epoch_mf[1] - epoch_mf[2];
- } else {
- tepoch = epoch_mf[2]; /* 1 2 0 */
- tspan = epoch_mf[1] - epoch_mf[0];
- }
+ 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 epoch candidate is within 1 ms of the last one, the
- * new candidate replaces the last one and the jitter counter is
- * reset; otherwise, the candidate is ignored and the jitter
- * counter is incremented. If the jitter counter exceeds the
- * frequency averaging interval, the new candidate replaces the
- * old one anyway. The compare counter is incremented if the new
- * candidate is identical to the last one; otherwise, it is
- * forced to zero. If the compare counter increments to 10, the
- * epoch is reset and the receiver second epoch is set.
- *
- * Careful attention to detail here. If the signal amplitude
- * falls below the threshold or if no stations are heard, we
- * certainly cannot be in sync.
+ * If the signal amplitude or SNR fall below thresholds or if no
+ * stations are heard, dim the second sync lamp and start over.
*/
- tmp2 = MOD(tepoch - xepoch, SECOND);
- if (up->epomax < STHR || !(up->status & (SELV | SELH))) {
- up->status &= ~SSYNC;
- jitcnt = syncnt = avgcnt = 0;
- } else if (abs(tmp2) <= MS || jitcnt >= (MINAVG << up->avgint))
- {
- jitcnt = 0;
- if (tmp2 != 0) {
- xepoch = tepoch;
- syncnt = 0;
- } else {
- if (syncnt < SCMP) {
- syncnt++;
- } else {
- up->status |= SSYNC;
- up->swatch = 0;
- up->repoch = tepoch;
- up->yepoch = up->repoch;
- if (up->yepoch < 0)
- up->yepoch += SECOND;
- }
- }
- avgcnt++;
+ 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 {
- jitcnt++;
- syncnt = avgcnt = 0;
+ if (maxrun > 0 && mepoch == xepoch) {
+ maxrun += syncnt;
+ } else if (syncnt > maxrun) {
+ maxrun = syncnt;
+ mepoch = xepoch;
+ }
+ syncnt = 0;
}
- if (!(up->status & SSYNC) && 0) {
+ if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & (SSYNC |
+ MSYNC))) {
sprintf(tbuf,
- "wwv1 %2d %04x %5.0f %2d %5.0f %5d %5d %5d %2d %4d",
- up->rsec, up->status, up->epomax, avgcnt, epomax,
- tepoch, tspan, tmp2, syncnt, jitcnt);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, 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);
@@ -1671,72 +1574,122 @@ wwv_endpoc(
}
/*
- * The sample clock frequency is disciplined using a first-order
+ * 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 loop update is
- * calculated each averaging interval from the epoch change in
- * 125-us units and interval length in seconds. The interval is
- * doubled after four intervals where epoch change is not more
- * than one sample.
+ * 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 sample clock
+ * 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.
*/
- tmp3 = MOD(tepoch - zepoch, SECOND);
- if (avgcnt >= (MINAVG << up->avgint)) {
- if (abs(tmp3) < MS) {
- dtemp = (double)tmp3 / avgcnt;
- up->freq += dtemp / SYNCTC;
- if (up->freq > MAXFREQ)
- up->freq = MAXFREQ;
- else if (up->freq < -MAXFREQ)
- up->freq = -MAXFREQ;
- if (abs(tmp3) <= 1 && up->avgint < MAXAVG) {
- if (avginc < 4) {
+ 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;
- up->avgint++;
}
}
- if (up->avgint < MAXAVG) {
- sprintf(tbuf,
- "wwv2 %2d %04x %5.0f %5d %5d %2d %2d %6.1f %6.1f",
- up->rsec, up->status, up->epomax,
- MINAVG << up->avgint, avgcnt,
- avginc, tmp3, dtemp / SECOND * 1e6,
- up->freq / SECOND * 1e6);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(
- &peer->srcadr, tbuf);
+ }
+ }
+ 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);
+ if (debug)
+ printf("%s\n", tbuf);
#endif /* DEBUG */
- }
- }
- zepoch = tepoch;
- avgcnt = 0;
}
+ up->status |= FGATE;
+ zepoch = mepoch;
+ avgcnt = syncnt = maxrun = 0;
}
/*
- * wwv_epoch - main loop
+ * wwv_epoch - epoch scanner
*
- * This routine establishes receiver and transmitter epoch
- * synchronization and determines the data subcarrier pulse length.
- * 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. This establishes when to sample the data
- * subcarrier in-phase signal for the maximum level and noise level and
- * when to determine the pulse length. The transmitter second leads the
- * receiver second by the propagation delay, receiver delay and filter
- * delay of this program. It establishes the clock time and implements
- * the sometimes idiosyncratic conventional clock time and civil
- * calendar.
+ * 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
@@ -1750,152 +1703,96 @@ wwv_epoch(
struct peer *peer /* peer structure pointer */
)
{
- static double dpulse; /* data pulse length */
struct refclockproc *pp;
struct wwvunit *up;
struct chan *cp;
- struct sync *sp;
- l_fp offset; /* NTP format offset */
+ static double dpulse; /* data pulse length */
double dtemp;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
/*
- * Sample the minute sync pulse amplitude at epoch 800 for both
+ * Sample the minute sync pulse envelopes at epoch 800 for both
* the WWV and WWVH stations. This will be used later for
- * channel mitigation.
+ * 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.
*/
- cp = &up->mitig[up->achan];
if (up->rphase == 800 * MS) {
- sp = &cp->wwv;
- sp->synamp = SQRT(sp->amp);
- sp = &cp->wwvh;
- sp->synamp = SQRT(sp->amp);
+ up->repoch = up->yepoch;
+ cp = &up->mitig[up->achan];
+ cp->wwv.synamp = cp->wwv.amp;
+ cp->wwvh.synamp = cp->wwvh.amp;
}
- if (up->rsec == 0) {
- up->sigamp = up->datsnr = 0;
- } else {
-
- /*
- * Estimate the noise level by integrating the I-channel
- * energy at epoch 30 ms.
- */
- if (up->rphase == 30 * MS) {
- if (!(up->status & SFLAG))
- up->noiamp += (up->irig - up->noiamp) /
- (MINAVG << up->avgint);
- else
- cp->noiamp += (SQRT(up->irig *
- up->irig + up->qrig * up->qrig) -
- cp->noiamp) / 8;
-
- /*
- * Strobe the peak I-channel data signal at epoch 200
- * ms. Compute the SNR and adjust the 100-Hz reference
- * oscillator phase using the Q-channel data signal at
- * that epoch. Save the envelope amplitude for the probe
- * channel.
- */
- } else if (up->rphase == 200 * MS) {
- if (!(up->status & SFLAG)) {
- up->sigamp = up->irig;
- if (up->sigamp < 0)
- up->sigamp = 0;
- up->datsnr = wwv_snr(up->sigamp,
- up->noiamp);
- up->datpha = up->qrig / (MINAVG <<
- 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;
- }
- } else {
- up->sigamp = SQRT(up->irig * up->irig +
- up->qrig * up->qrig);
- up->datsnr = wwv_snr(up->sigamp,
- cp->noiamp);
- }
+ /*
+ * 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;
- /*
- * The slice level is set half way between the peak
- * signal and noise levels. Strobe 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->sigamp + up->noiamp) / 2;
- if (up->irig < dtemp && dpulse == 0)
- dpulse = up->rphase;
+ /*
+ * 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;
/*
- * At the end of the transmitter second, crank the clock state
- * machine. Note we have to be careful to set the transmitter
- * epoch at the same time as the receiver epoch to be sure the
- * right propagation delay is used. We don't bother the heavy
- * machinery unless the clock is set.
+ * 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.
*/
- up->tphase++;
- if (up->epoch == up->yepoch) {
- wwv_tsec(up);
- up->tphase = 0;
-
- /*
- * Determine the current offset from the time of century
- * and the sample timestamp, but only if the SYNERR
- * alarm has not been raised in the present or previous
- * minute.
- */
- if (!(up->status & SFLAG) && up->status & INSYNC &&
- (up->alarm & (3 << SYNERR)) == 0) {
- pp->second = up->tsec;
- 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;
- if (pp->year < UTCYEAR)
- pp->year += 2000;
- else
- pp->year += 1900;
-
- /*
- * We have to simulate refclock_process() here,
- * since the fudgetime gets added much earlier
- * than this.
- */
- pp->lastrec = up->timestamp;
- L_CLR(&offset);
- if (!clocktime(pp->day, pp->hour, pp->minute,
- pp->second, GMT, pp->lastrec.l_ui,
- &pp->yearstart, &offset.l_ui))
- up->errflg = CEVNT_BADTIME;
- else
- refclock_process_offset(pp, offset,
- pp->lastrec, 0.);
- }
+ } 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 receiver second, process the data bit and
- * update the decoding matrix probabilities.
+ * 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->epoch == up->repoch) {
+ 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;
@@ -1915,9 +1812,7 @@ wwv_epoch(
* 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. BTW, stations WWV/WWVH cowardly kill the
- * transmitter carrier for a few seconds around the leap to avoid icky
- * details of transmission format during the leap.
+ * machine to ignore it.
*/
static void
wwv_rsec(
@@ -1932,9 +1827,14 @@ wwv_rsec(
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;
@@ -1969,65 +1869,105 @@ wwv_rsec(
* Probe channel stuff
*
* The WWV/H format contains data pulses in second 59 (position
- * identifier) and second 1 (not used), and the minute sync
- * pulse in second 0. At the end of second 58, we QSYed to the
- * probe channel, which rotates over all WWV/H frequencies. At
- * the end of second 59, we latched the sync noise and tested
- * for data bit error. At the end of second 0, we now latch the
- * sync peak.
+ * 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];
- sp = &cp->wwv;
- sp->synmax = sp->synamp;
- sp = &cp->wwvh;
- sp->synmax = sp->synamp;
+ cp->wwv.synmax = sqrt(cp->wwv.synamp);
+ cp->wwvh.synmax = sqrt(cp->wwvh.synamp);
break;
/*
- * At the end of second 1, latch and average the sync noise and
- * test for data bit error. Set SYNCNG if the sync pulse
- * amplitude and SNR are not above thresholds. Set DATANG if
- * data error occured on both second 59 and second 1. Finally,
- * QSY back to the data channel.
+ * 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];
- if (up->sigamp < DTHR || up->datsnr < DSNR)
- cp->errcnt++;
+ 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 = (sp->synmin + sp->synamp) / 2;
+ sp->synmin = sqrt((sp->synmin + sp->synamp) / 2.);
sp->synsnr = wwv_snr(sp->synmax, sp->synmin);
- sp->select &= ~(DATANG | SYNCNG);
+ sp->select &= ~(SYNCNG | DATANG | ERRRNG);
if (sp->synmax < QTHR || sp->synsnr < QSNR)
sp->select |= SYNCNG;
- if (cp->errcnt > 1)
+ 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 = (rp->synmin + rp->synamp) / 2;
+ rp->synmin = sqrt((rp->synmin + rp->synamp) / 2.);
rp->synsnr = wwv_snr(rp->synmax, rp->synmin);
- rp->select &= ~(DATANG | SYNCNG);
+ rp->select &= ~(SYNCNG | DATANG | ERRRNG);
if (rp->synmax < QTHR || rp->synsnr < QSNR)
rp->select |= SYNCNG;
- if (cp->errcnt > 1)
+ 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++;
+ }
- cp->errcnt = 0;
- sprintf(tbuf,
- "wwv5 %d %3d %-3s %04x %d %.0f/%.1f/%ld %s %04x %d %.0f/%.1f/%ld",
- up->port, up->gain, sp->ident, sp->select,
- sp->count, sp->synmax, sp->synsnr, sp->jitter,
- rp->ident, rp->select, rp->count, rp->synmax,
- rp->synsnr, rp->jitter);
- if (pp->sloppyclockflag & CLK_FLAG4)
+ /*
+ * 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);
+ 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;
@@ -2038,7 +1978,9 @@ wwv_rsec(
* considered valid. Bits not used in the digit are forced to
* zero and not checked for errors.
*/
- case COEF1: /* 10-13 */
+ 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;
@@ -2048,13 +1990,6 @@ wwv_rsec(
bcddld[arg] = 0;
break;
- case COEF: /* 4-7, 15-17, 20-23, 25-26,
- 30-33, 35-38, 40-41, 51-54 */
- if (up->status & DGATE || !(up->status & DSYNC))
- up->status |= BGATE;
- bcddld[arg] = bit;
- break;
-
/*
* Correlate coefficient vector with each valid digit vector and
* save in decoding matrix. We step through the decoding matrix
@@ -2081,122 +2016,207 @@ wwv_rsec(
* 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.
+ * 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 */
+ 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 |= 1 << SYMERR;
+ 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 |= 1 << SYMERR;
- up->schan = (up->schan + 1) % NCHAN;
- wwv_qsy(peer, up->schan);
- up->status |= SFLAG;
+ 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
*
- * Second 59 contains the first data pulse of the probe
- * sequence. Check it for validity and establish the noise floor
- * for the minute sync SNR.
+ * 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];
- if (up->sigamp < DTHR || up->datsnr < DSNR)
- cp->errcnt++;
- sp = &cp->wwv;
- sp->synmin = sp->synamp;
- sp = &cp->wwvh;
- sp->synmin = sp->synamp;
+ cp->wwv.synmin = cp->wwv.synamp;
+ cp->wwvh.synmin = cp->wwvh.synamp;
/*
- * If SECWARN is set on the last minute of 30 June or 31
- * December, 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.
+ * 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->tsec == 60) {
- up->status &= ~LEPSEC;
- break;
- }
- /* fall through */
-
- /*
- * If all nine clock digits are valid and the SYNERR alarm is
- * not raised in the current or previous second, the clock is
- * set or validated. If at least one digit is set, which by
- * design must be the minute units digit, the clock state
- * machine begins to count the minutes.
- */
- case MIN2: /* 59/60 */
- up->minset = ((current_time - peer->update) + 30) / 60;
- if (up->digcnt > 0)
- up->status |= DSYNC;
- if (up->digcnt >= 9 && (up->alarm & (3 << SYNERR)) == 0)
- {
+ if (up->status & SSYNC && up->digcnt >= 9)
up->status |= INSYNC;
- up->watch = 0;
- }
- pp->lencode = timecode(up, pp->a_lastcode);
- if (up->misc & SECWAR)
+ if (up->status & LEPDAY) {
pp->leap = LEAP_ADDSECOND;
- else
+ } else {
pp->leap = LEAP_NOWARNING;
- refclock_receive(peer);
+ 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;
- /*
- * The ultimate watchdog is the interval since the
- * reference clock interface code last received an
- * update from this driver. If the interval is greater
- * than a couple of days, manual intervention is
- * probably required, so the program resets and tries to
- * resynchronized from scratch.
- */
- if (up->minset > PANIC)
- up->status = 0;
- up->alarm = (up->alarm & ~0x8888) << 1;
- up->nepoch = (up->mphase + SYNSIZ) % MINUTE;
- up->errcnt = up->digcnt = nsec = 0;
+ /*
+ * 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 (!(up->status & DSYNC)) {
+
+ /*
+ * 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.0f %5.0f %5.1f %5.0f %5.0f",
- up->rsec, up->status, up->epomax, up->sigamp,
- up->datpha, up->datsnr, bit, bitvec[up->rsec]);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, 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 */
- }
- up->rsec = up->tsec = nsec;
- return;
+ }
}
@@ -2209,7 +2229,12 @@ wwv_rsec(
* 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..
+ * 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(
@@ -2224,14 +2249,16 @@ wwv_data(
dpulse = pulse - DATSIZ / 2;
/*
- * If the data amplitude or SNR are below threshold or if the
- * pulse length is less than 170 ms, declare an erasure.
+ * 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->sigamp < DTHR || up->datsnr < DSNR || dpulse < DATSIZ) {
+ if (!(up->status & (SELV | SELH)) || up->sigsig < DTHR ||
+ up->datsnr < DSNR || dpulse < DATSIZ) {
up->status |= DGATE;
up->errcnt++;
if (up->errcnt > MAXERR)
- up->alarm |= 1 << MODERR;
+ up->alarm |= MODERR;
return (0);
}
@@ -2325,44 +2352,59 @@ wwv_corr4(
/*
* The maximum likelihood digit is compared with the current
* clock digit. The difference represents the decoding phase
- * error. If the digit probability and likelihood are good and
- * the difference stays the same for a number of comparisons,
- * the clock digit is reset to the maximum likelihood digit.
+ * 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->phase = diff;
vp->count = 0;
+ vp->phase = diff;
}
- if (vp->digprb < BTHR || vp->digsnr < BSNR) {
+ if (vp->digsnr < BSNR) {
vp->count = 0;
- up->alarm |= 1 << SYMERR;
- } else if (vp->count < BCMP) {
+ 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 |= 1 << DECERR;
- if (!(up->status & INSYNC)) {
+ 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,
+ up->rsec, up->status, up->epomax, vp->radix,
vp->digit, vp->mldigit, vp->phase, vp->count,
vp->digprb, vp->digsnr);
- if (pp->sloppyclockflag & CLK_FLAG4)
- record_clock_stats(&peer->srcadr, tbuf);
+ record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
+ if (debug)
+ printf("%s\n", tbuf);
#endif /* DEBUG */
}
up->status &= ~BGATE;
@@ -2370,13 +2412,11 @@ wwv_corr4(
/*
- * wwv_tsec - transmitter second processing
+ * wwv_tsec - transmitter minute processing
*
- * This routine is called at the end of the transmitter second. It
+ * 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. Note
- * that carries from the least significant (minutes) digit are inhibited
- * until that digit is synchronized.
+ * the funny rules that govern the conventional clock and calendar.
*/
static void
wwv_tsec(
@@ -2386,18 +2426,10 @@ wwv_tsec(
int minute, day, isleap;
int temp;
- up->tsec++;
- if (up->tsec < 60 || up->status & LEPSEC)
- return;
- up->tsec = 0;
-
/*
- * Advance minute unit of the day. If the minute unit is not
- * synchronized, go no further.
+ * Advance minute unit of the day.
*/
temp = carry(&up->decvec[MN]); /* minute units */
- if (!(up->status & DSYNC))
- return;
/*
* Propagate carries through the day.
@@ -2410,8 +2442,10 @@ wwv_tsec(
temp = carry(&up->decvec[HR + 1]);
/*
- * Decode the current minute and day. Set the leap second enable
- * bit on the last minute of 30 June and 31 December.
+ * 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 +
@@ -2419,9 +2453,16 @@ wwv_tsec(
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 (minute == 1439 && (day == (isleap ? 182 : 183) || day ==
- (isleap ? 365 : 366)) && up->misc & SECWAR)
+ 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
@@ -2459,8 +2500,8 @@ wwv_tsec(
* 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 -
- * zero if a carry occured. Once synchronized, the clock digit will
+ * 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
@@ -2517,19 +2558,36 @@ wwv_snr(
return (rval);
}
+
/*
* wwv_newchan - change to new data channel
*
- * Assuming the radio can be tuned by this program, it actually appears
- * as a 10-channel receiver, one channel for each of WWV and WWVH on
- * each of five frequencies. 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 channel, in order
- * to pick up minute sync and data pulses. The search for WWV and WWVH
- * stations operates simultaneously, with WWV on 1000 Hz and WWVH on
- * 1200 Hz. The probe channel rotates for each minute over the five
- * frequencies. At the end of each rotation, this routine mitigates over
- * all channels and chooses the best frequency and station.
+ * 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(
@@ -2538,61 +2596,119 @@ wwv_newchan(
{
struct refclockproc *pp;
struct wwvunit *up;
- struct chan *cp;
struct sync *sp, *rp;
- int rank;
+ double rank, dtemp;
int i, j;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
/*
- * Reset the matched filter selector and station pointer to
- * avoid fooling around should we lose this game.
- */
- up->sptr = 0;
- up->status &= ~(SELV | SELH);
-
- /*
- * Search all five station pairs looking for the station with
- * the maximum compare counter. Ties go to the highest frequency
- * and then to WWV.
+ * 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 = (struct sync *)0;
+ sp = NULL;
rank = 0;
for (i = 0; i < NCHAN; i++) {
- cp = &up->mitig[i];
- rp = &cp->wwvh;
- if (rp->count >= rank) {
+ rp = &up->mitig[i].wwvh;
+ dtemp = wwv_metric(rp);
+ if (dtemp >= rank) {
+ rank = dtemp;
sp = rp;
- rank = rp->count;
j = i;
}
- rp = &cp->wwv;
- if (rp->count >= rank) {
+ rp = &up->mitig[i].wwv;
+ dtemp = wwv_metric(rp);
+ if (dtemp >= rank) {
+ rank = dtemp;
sp = rp;
- rank = rp->count;
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;
/*
- * If we find a station, continue to track it. If not, X marks
- * the spot and we wait for better ions.
+ * Initialize strategic values. Note we set the leap bits
+ * NOTINSYNC and the refid "NONE".
*/
- if (rank > 0) {
- up->dchan = j;
- up->sptr = sp;
- up->status |= sp->select & (SELV | SELH);
- memcpy((char *)&pp->refid, sp->refid, 4);
- if (peer->stratum <= 1)
- memcpy((char *)&peer->refid, sp->refid, 4);
- wwv_qsy(peer, up->dchan);
+ 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
*
@@ -2606,22 +2722,22 @@ wwv_qsy(
int chan /* channel */
)
{
+ int rval = 0;
struct refclockproc *pp;
struct wwvunit *up;
- int rval = 0;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
- up->mitig[up->achan].gain = up->gain;
-#ifdef ICOM
- if (up->fd_icom > 0)
- rval = icom_freq(up->fd_icom, peer->ttlmax & 0x7f,
+ if (up->fd_icom > 0) {
+ up->mitig[up->achan].gain = up->gain;
+ rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
qsy[chan]);
-#endif /* ICOM */
- up->achan = chan;
- up->gain = up->mitig[up->achan].gain;
+ up->achan = chan;
+ up->gain = up->mitig[up->achan].gain;
+ }
return (rval);
}
+#endif /* ICOM */
/*
@@ -2629,23 +2745,22 @@ wwv_qsy(
*
* Prettytime format - similar to Spectracom
*
- * sq yy ddd hh:mm:ss.fff ld dut lset agc stn comp errs freq avgt
+ * sq yy ddd hh:mm:ss ld dut lset agc iden sig errs freq avgt
*
* s sync indicator ('?' or ' ')
- * q quality character (hex 0-F)
+ * q error bits (hex 0-F)
* yyyy year of century
* ddd day of year
* hh hour of day
* mm minute of hour
- * ss minute of hour
- * fff millisecond of second
- * l leap second warning ' ' or 'L'
- * d DST state 'S', 'D', 'I', or 'O'
- * dut DUT sign and magnitude in deciseconds
+ * 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 station identifier (station and frequency)
- * comp minute sync compare counter
+ * 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)
@@ -2657,8 +2772,8 @@ timecode(
)
{
struct sync *sp;
- int year, day, hour, minute, second, frac, dut;
- char synchar, qual, leapchar, dst;
+ int year, day, hour, minute, second, dut;
+ char synchar, leapchar, dst;
char cptr[50];
@@ -2666,49 +2781,30 @@ timecode(
* Common fixed-format fields
*/
synchar = (up->status & INSYNC) ? ' ' : '?';
- qual = 0;
- if (up->alarm & (3 << DECERR))
- qual |= 0x1;
- if (up->alarm & (3 << SYMERR))
- qual |= 0x2;
- if (up->alarm & (3 << MODERR))
- qual |= 0x4;
- if (up->alarm & (3 << SYNERR))
- qual |= 0x8;
- year = up->decvec[7].digit + up->decvec[7].digit * 10;
- if (year < UTCYEAR)
- year += 2000;
- else
- year += 1900;
- day = up->decvec[4].digit + up->decvec[5].digit * 10 +
- up->decvec[6].digit * 100;
- hour = up->decvec[2].digit + up->decvec[3].digit * 10;
- minute = up->decvec[0].digit + up->decvec[1].digit * 10;
- second = up->tsec;
- frac = (up->tphase * 1000) / SECOND;
+ 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, qual);
- sprintf(cptr, " %4d %03d %02d:%02d:%02d.%.03d %c%c %+d",
- year, day, hour, minute, second, frac, leapchar, dst, 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;
- if (sp != 0)
- sprintf(cptr, " %d %d %s %d %d %.1f %d", up->minset,
- up->mitig[up->dchan].gain, sp->ident, sp->count,
- up->errcnt, up->freq / SECOND * 1e6, MINAVG <<
- up->avgint);
- else
- sprintf(cptr, " %d %d X 0 %d %.1f %d", up->minset,
- up->mitig[up->dchan].gain, up->errcnt, up->freq /
- SECOND * 1e6, MINAVG << up->avgint);
+ 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));
}
@@ -2717,9 +2813,10 @@ timecode(
/*
* wwv_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
+ * 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.
*/
@@ -2741,15 +2838,19 @@ wwv_gain(
*/
if (up->clipcnt == 0) {
up->gain += 4;
- if (up->gain > 255)
- up->gain = 255;
- } else if (up->clipcnt > SECOND / 100) {
+ 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->port);
+ audio_gain(up->gain, up->mongain, up->port);
up->clipcnt = 0;
+#if DEBUG
+ if (debug > 1)
+ audio_show();
+#endif
}
diff --git a/contrib/ntp/ntpd/refclock_wwvb.c b/contrib/ntp/ntpd/refclock_wwvb.c
index 0ca9f75..c5ef9f9 100644
--- a/contrib/ntp/ntpd/refclock_wwvb.c
+++ b/contrib/ntp/ntpd/refclock_wwvb.c
@@ -103,6 +103,7 @@
#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 */
@@ -187,7 +188,7 @@ wwvb_start(
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
- peer->burst = NSTAGE;
+ peer->burst = MAXSTAGE;
return (1);
}
@@ -263,11 +264,6 @@ wwvb_receive(
pp->lastrec = up->laststamp;
up->laststamp = trtmp;
up->tcswitch = 1;
-#ifdef DEBUG
- if (debug)
- printf("wwvb: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
/*
* We get down to business, check the timecode format and decode
@@ -277,10 +273,9 @@ wwvb_receive(
*/
syncchar = qualchar = leapchar = dstchar = ' ';
tz = 0;
- pp->msec = 0;
switch (pp->lencode) {
- case LENWWVB0:
+ case LENWWVB0:
/*
* Timecode format 0: "I ddd hh:mm:ss DTZ=nn"
@@ -289,20 +284,22 @@ wwvb_receive(
"%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:
+ case LENWWVB2:
/*
* Timecode format 2: "IQyy ddd hh:mm:ss.mmm LD" */
if (sscanf(pp->a_lastcode,
- "%c%c %2d %3d %2d:%2d:%2d.%3d %c",
+ "%c%c %2d %3d %2d:%2d:%2d.%3ld %c",
&syncchar, &qualchar, &pp->year, &pp->day,
- &pp->hour, &pp->minute, &pp->second, &pp->msec,
+ &pp->hour, &pp->minute, &pp->second, &pp->nsec,
&leapchar) == 9)
+ pp->nsec *= 1000000;
break;
- case LENWWVB3:
+ case LENWWVB3:
/*
* Timecode format 3: "0003I yyyymmdd hhmmss+0000SL#"
@@ -313,10 +310,11 @@ wwvb_receive(
&pp->minute, &pp->second, &dstchar, &leapchar) == 8)
{
pp->day = ymd2yd(pp->year, month, day);
+ pp->nsec = 0;
break;
}
- default:
+ default:
/*
* Unknown format: If dumping internal table, record
@@ -343,6 +341,7 @@ wwvb_receive(
case ' ':
pp->disp = .001;
+ pp->lastref = pp->lastrec;
break;
case 'A':
@@ -411,17 +410,21 @@ wwvb_poll(
pollchar = 'T';
if (write(pp->io.fd, &pollchar, 1) != 1)
refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
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;
+ 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
OpenPOWER on IntegriCloud