summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd
diff options
context:
space:
mode:
authorroberto <roberto@FreeBSD.org>2008-08-22 15:58:00 +0000
committerroberto <roberto@FreeBSD.org>2008-08-22 15:58:00 +0000
commitb85c7169a740b2edf0106ad59fdaa1b0160f823c (patch)
tree2b9fb7f64eacb322e95695e412c923e97ba33e88 /contrib/ntp/ntpd
parent1d197cfe9feac6bc29537d8e53c30b6435937b95 (diff)
parent7a6072eb585696f8856cd498c3fd194cf49f14c6 (diff)
downloadFreeBSD-src-b85c7169a740b2edf0106ad59fdaa1b0160f823c.zip
FreeBSD-src-b85c7169a740b2edf0106ad59fdaa1b0160f823c.tar.gz
Merge ntpd & friends 4.2.4p5 from vendor/ntp/dist into head. Next commit
will update usr.sbin/ntp to match this. MFC after: 2 weeks
Diffstat (limited to 'contrib/ntp/ntpd')
-rw-r--r--contrib/ntp/ntpd/Makefile.am88
-rw-r--r--contrib/ntp/ntpd/Makefile.in827
-rw-r--r--contrib/ntp/ntpd/cmd_args.c504
-rw-r--r--contrib/ntp/ntpd/map_vme.c135
-rw-r--r--contrib/ntp/ntpd/ntp_config.c334
-rw-r--r--contrib/ntp/ntpd/ntp_control.c221
-rw-r--r--contrib/ntp/ntpd/ntp_crypto.c1009
-rw-r--r--contrib/ntp/ntpd/ntp_filegen.c33
-rw-r--r--contrib/ntp/ntpd/ntp_intres.c288
-rw-r--r--contrib/ntp/ntpd/ntp_io.c4110
-rw-r--r--contrib/ntp/ntpd/ntp_loopfilter.c708
-rw-r--r--contrib/ntp/ntpd/ntp_monitor.c35
-rw-r--r--contrib/ntp/ntpd/ntp_peer.c421
-rw-r--r--contrib/ntp/ntpd/ntp_proto.c2672
-rw-r--r--contrib/ntp/ntpd/ntp_refclock.c606
-rw-r--r--contrib/ntp/ntpd/ntp_request.c268
-rw-r--r--contrib/ntp/ntpd/ntp_restrict.c85
-rw-r--r--contrib/ntp/ntpd/ntp_timer.c48
-rw-r--r--contrib/ntp/ntpd/ntp_util.c186
-rw-r--r--contrib/ntp/ntpd/ntpd-opts.c1021
-rw-r--r--contrib/ntp/ntpd/ntpd-opts.def13
-rw-r--r--contrib/ntp/ntpd/ntpd-opts.h351
-rw-r--r--contrib/ntp/ntpd/ntpd-opts.menu1
-rw-r--r--contrib/ntp/ntpd/ntpd-opts.texi489
-rw-r--r--contrib/ntp/ntpd/ntpd.1296
-rw-r--r--contrib/ntp/ntpd/ntpd.c881
-rw-r--r--contrib/ntp/ntpd/ntpdbase-opts.def459
-rw-r--r--contrib/ntp/ntpd/ntpdsim-opts.c1262
-rw-r--r--contrib/ntp/ntpd/ntpdsim-opts.def15
-rw-r--r--contrib/ntp/ntpd/ntpdsim-opts.h422
-rw-r--r--contrib/ntp/ntpd/ntpdsim-opts.menu1
-rw-r--r--contrib/ntp/ntpd/ntpdsim-opts.texi509
-rw-r--r--contrib/ntp/ntpd/ntpdsim.1357
-rw-r--r--contrib/ntp/ntpd/ntpsim.c27
-rw-r--r--contrib/ntp/ntpd/ppsapi_timepps.h26
-rw-r--r--contrib/ntp/ntpd/refclock_acts.c1349
-rw-r--r--contrib/ntp/ntpd/refclock_arbiter.c142
-rw-r--r--contrib/ntp/ntpd/refclock_arc.c52
-rw-r--r--contrib/ntp/ntpd/refclock_atom.c313
-rw-r--r--contrib/ntp/ntpd/refclock_bancomm.c224
-rw-r--r--contrib/ntp/ntpd/refclock_chu.c20
-rw-r--r--contrib/ntp/ntpd/refclock_conf.c32
-rw-r--r--contrib/ntp/ntpd/refclock_datum.c18
-rw-r--r--contrib/ntp/ntpd/refclock_fg.c3
-rw-r--r--contrib/ntp/ntpd/refclock_gpsvme.c828
-rw-r--r--contrib/ntp/ntpd/refclock_heath.c56
-rw-r--r--contrib/ntp/ntpd/refclock_hopfpci.c8
-rw-r--r--contrib/ntp/ntpd/refclock_hopfser.c8
-rw-r--r--contrib/ntp/ntpd/refclock_hpgps.c21
-rw-r--r--contrib/ntp/ntpd/refclock_irig.c47
-rw-r--r--contrib/ntp/ntpd/refclock_jjy.c363
-rw-r--r--contrib/ntp/ntpd/refclock_jupiter.c47
-rw-r--r--contrib/ntp/ntpd/refclock_leitch.c18
-rw-r--r--contrib/ntp/ntpd/refclock_local.c10
-rw-r--r--contrib/ntp/ntpd/refclock_msfees.c63
-rw-r--r--contrib/ntp/ntpd/refclock_mx4200.c24
-rw-r--r--contrib/ntp/ntpd/refclock_neoclock4x.c119
-rw-r--r--contrib/ntp/ntpd/refclock_nmea.c63
-rw-r--r--contrib/ntp/ntpd/refclock_oncore.c827
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.c2
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.h2
-rw-r--r--contrib/ntp/ntpd/refclock_parse.c1521
-rw-r--r--contrib/ntp/ntpd/refclock_pst.c3
-rw-r--r--contrib/ntp/ntpd/refclock_ptbacts.c16
-rw-r--r--contrib/ntp/ntpd/refclock_ripencc.c10
-rw-r--r--contrib/ntp/ntpd/refclock_shm.c9
-rw-r--r--contrib/ntp/ntpd/refclock_ulink.c230
-rw-r--r--contrib/ntp/ntpd/refclock_usno.c674
-rw-r--r--contrib/ntp/ntpd/refclock_wwv.c1874
-rw-r--r--contrib/ntp/ntpd/refclock_wwvb.c96
70 files changed, 17921 insertions, 9879 deletions
diff --git a/contrib/ntp/ntpd/Makefile.am b/contrib/ntp/ntpd/Makefile.am
index 0fa4e21..6896b45 100644
--- a/contrib/ntp/ntpd/Makefile.am
+++ b/contrib/ntp/ntpd/Makefile.am
@@ -1,60 +1,108 @@
-#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
-AUTOMAKE_OPTIONS = ../util/ansi2knr
-bin_PROGRAMS = ntpd @MAKE_NTPDSIM@
-noinst_LIBRARIES = libntpd.a
-INCLUDES = -I$(top_srcdir)/include -I../include
+AUTOMAKE_OPTIONS= ../util/ansi2knr
+
+bindir= ${exec_prefix}/${BINSUBDIR}
+
+bin_PROGRAMS= ntpd @MAKE_NTPDSIM@
+
+noinst_LIBRARIES= libntpd.a
+
+AM_CPPFLAGS= -I$(top_srcdir)/include -I../include $(LIBOPTS_CFLAGS)
# LDADD might need RESLIB and ADJLIB.
-# If LIBPARSE, we need libntpd.a 2wagain afterwards...
-LDADD = version.o libntpd.a @LIBPARSE@ libntpd.a
+LDADD= version.o libntpd.a @LIBPARSE@
+
+BUILT_SOURCES= ntpd-opts.c ntpd-opts.h ntpd.1 ntpd-opts.texi ntpd-opts.menu
+man_MANS= ntpd.1
+
+BUILT_SOURCES+= ntpdsim-opts.c ntpdsim-opts.h ntpdsim.1 ntpdsim-opts.texi ntpdsim-opts.menu
+man_MANS+= ntpdsim.1
+
# ntpd may need:
# log10 refclock_wwv.o
# sqrt ntp_control.o
# floor refclock_wwv.o
# which are (usually) provided by -lm.
-ntpd_LDADD = $(LDADD) ../libntp/libntp.a -lm @LCRYPTO@
-ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@
+ntpd_LDADD = $(LDADD) -lm @LCRYPTO@ $(LIBOPTS_LDADD) ../libntp/libntp.a
+ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@ $(LIBOPTS_LDADD)
ntpdsim_CFLAGS = $(CFLAGS) -DSIM
check_y2k_LDADD = $(LDADD) ../libntp/libntp.a
DISTCLEANFILES = .version version.c
-#EXTRA_DIST = ntpd.mak
+EXTRA_DIST = ntpd-opts.def ntpdbase-opts.def ntpdsim-opts.def \
+ refclock_msfees.c \
+ refclock_trak.c \
+ $(BUILT_SOURCES)
ETAGS_ARGS = Makefile.am
### Y2Kfixes
check_PROGRAMS = @MAKE_CHECK_Y2K@
EXTRA_PROGRAMS = check_y2k ntpdsim
+run_ag = cd $(srcdir) && autogen -L ../include --writable
+std_def_list= $(top_srcdir)/include/debug-opt.def \
+ $(top_srcdir)/include/autogen-version.def \
+ $(top_srcdir)/include/copyright.def \
+ $(top_srcdir)/include/version.def
check-local: @MAKE_CHECK_Y2K@
test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
# SIM: cmd_args.c ntp_config.c ntp_io.c ntpd.c + ntpsim.c (include/ntpsim.h)
# ntp_resolver.c is presently unused...
-ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c
-ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c
-libntpd_a_SOURCES = jupiter.h map_vme.c ntp_control.c \
+ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c ntpd-opts.c ntpd-opts.h
+ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c ntpdsim-opts.c ntpdsim-opts.h
+libntpd_a_SOURCES = jupiter.h ntp_control.c \
ntp_crypto.c ntp_filegen.c \
ntp_intres.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \
ntp_proto.c ntp_refclock.c ntp_request.c \
ntp_restrict.c ntp_timer.c ntp_util.c \
+ ppsapi_timepps.h \
refclock_acts.c refclock_arbiter.c refclock_arc.c refclock_as2201.c \
refclock_atom.c refclock_bancomm.c refclock_chronolog.c \
refclock_chu.c refclock_conf.c refclock_datum.c refclock_dumbclock.c \
refclock_fg.c refclock_gpsvme.c refclock_heath.c refclock_hopfser.c \
refclock_hopfpci.c refclock_hpgps.c refclock_irig.c refclock_jjy.c \
refclock_jupiter.c refclock_leitch.c refclock_local.c \
- refclock_msfees.c refclock_mx4200.c refclock_nmea.c refclock_oncore.c \
- refclock_palisade.c refclock_palisade.h refclock_parse.c \
- refclock_pcf.c refclock_pst.c refclock_ptbacts.c refclock_shm.c \
- refclock_tpro.c refclock_trak.c refclock_true.c refclock_tt560.c \
- refclock_ulink.c refclock_usno.c refclock_wwv.c refclock_wwvb.c \
- refclock_zyfer.c refclock_ripencc.c refclock_neoclock4x.c
+ refclock_mx4200.c refclock_neoclock4x.c \
+ refclock_nmea.c refclock_oncore.c refclock_palisade.c \
+ refclock_palisade.h refclock_parse.c \
+ refclock_pcf.c refclock_pst.c refclock_ripencc.c refclock_shm.c \
+ refclock_tpro.c refclock_true.c refclock_tt560.c \
+ refclock_ulink.c refclock_wwv.c refclock_wwvb.c \
+ refclock_zyfer.c
+
+$(srcdir)/ntpd-opts.h: $(srcdir)/ntpd-opts.c
+$(srcdir)/ntpd-opts.c: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+ $(run_ag) ntpd-opts.def
+
+$(srcdir)/ntpd.1: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+ $(run_ag) -Tagman1.tpl -bntpd ntpd-opts.def
+
+$(srcdir)/ntpd-opts.texi $(srcdir)/ntpd-opts.menu: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+ $(run_ag) -Taginfo.tpl -DLEVEL=section ntpd-opts.def
+
+$(srcdir)/ntpdsim-opts.h: $(srcdir)/ntpdsim-opts.c
+$(srcdir)/ntpdsim-opts.c: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
+ $(run_ag) ntpdsim-opts.def
+
+$(srcdir)/ntpdsim.1: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
+ $(run_ag) -Tagman1.tpl -bntpdsim ntpdsim-opts.def
+
+$(srcdir)/ntpdsim-opts.texi $(srcdir)/ntpdsim-opts.menu: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
+ $(run_ag) -Taginfo.tpl -DLEVEL=section ntpdsim-opts.def
$(PROGRAMS): $(LDADD)
../libntp/libntp.a:
- cd ../libntp && $(MAKE)
+ cd ../libntp && $(MAKE) libntp.a
+
+../libntp/libntpsim.a:
+ cd ../libntp && $(MAKE) libntpsim.a
../libparse/libparse.a:
cd ../libparse && $(MAKE)
+$(top_srcdir)/version :
+ cd $(top_srcdir) && $(MAKE) version
+
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
+
+include ../bincheck.mf
diff --git a/contrib/ntp/ntpd/Makefile.in b/contrib/ntp/ntpd/Makefile.in
index eef0774..ad07930 100644
--- a/contrib/ntp/ntpd/Makefile.in
+++ b/contrib/ntp/ntpd/Makefile.in
@@ -1,8 +1,8 @@
-# Makefile.in generated by automake 1.7.7 from Makefile.am.
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
-# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-# Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -14,6 +14,11 @@
@SET_MAKE@
+# we traditionally installed software in bindir, while it should have gone
+# in sbindir. Now that we offer a choice, look in the "other" installation
+# subdir to warn folks if there is another version there.
+
+
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
@@ -21,7 +26,6 @@ pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
-
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
@@ -37,16 +41,108 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-target_triplet = @target@
+ANSI2KNR = ../util/ansi2knr
+bin_PROGRAMS = ntpd$(EXEEXT) @MAKE_NTPDSIM@
+check_PROGRAMS = @MAKE_CHECK_Y2K@
+EXTRA_PROGRAMS = check_y2k$(EXEEXT) ntpdsim$(EXEEXT)
+DIST_COMMON = $(srcdir)/../bincheck.mf $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+subdir = ntpd
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/libopts/m4/libopts.m4 \
+ $(top_srcdir)/m4/define_dir.m4 \
+ $(top_srcdir)/m4/hs_ulong_const.m4 \
+ $(top_srcdir)/m4/os_cflags.m4 $(top_srcdir)/version.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libntpd_a_AR = $(AR) $(ARFLAGS)
+libntpd_a_LIBADD =
+am_libntpd_a_OBJECTS = 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_mx4200$U.$(OBJEXT) \
+ refclock_neoclock4x$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_ripencc$U.$(OBJEXT) \
+ refclock_shm$U.$(OBJEXT) refclock_tpro$U.$(OBJEXT) \
+ refclock_true$U.$(OBJEXT) refclock_tt560$U.$(OBJEXT) \
+ refclock_ulink$U.$(OBJEXT) refclock_wwv$U.$(OBJEXT) \
+ refclock_wwvb$U.$(OBJEXT) refclock_zyfer$U.$(OBJEXT)
+libntpd_a_OBJECTS = $(am_libntpd_a_OBJECTS)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+check_y2k_SOURCES = check_y2k.c
+check_y2k_OBJECTS = check_y2k$U.$(OBJEXT)
+am__DEPENDENCIES_1 = version.o libntpd.a
+check_y2k_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libntp/libntp.a
+am_ntpd_OBJECTS = cmd_args$U.$(OBJEXT) ntp_config$U.$(OBJEXT) \
+ ntp_io$U.$(OBJEXT) ntpd$U.$(OBJEXT) ntpd-opts$U.$(OBJEXT)
+ntpd_OBJECTS = $(am_ntpd_OBJECTS)
+am__DEPENDENCIES_2 =
+ntpd_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
+ ../libntp/libntp.a
+am__objects_1 = ntpdsim-cmd_args$U.$(OBJEXT) \
+ ntpdsim-ntp_config$U.$(OBJEXT) ntpdsim-ntp_io$U.$(OBJEXT) \
+ ntpdsim-ntpd$U.$(OBJEXT) ntpdsim-ntpd-opts$U.$(OBJEXT)
+am_ntpdsim_OBJECTS = $(am__objects_1) ntpdsim-ntpsim$U.$(OBJEXT) \
+ ntpdsim-ntpdsim-opts$U.$(OBJEXT)
+ntpdsim_OBJECTS = $(am_ntpdsim_OBJECTS)
+ntpdsim_DEPENDENCIES = $(am__DEPENDENCIES_1) ../libntp/libntpsim.a \
+ $(am__DEPENDENCIES_2)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) \
+ $(ntpdsim_SOURCES)
+DIST_SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) \
+ $(ntpdsim_SOURCES)
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(man_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
+AR = @AR@
ARLIB_DIR = @ARLIB_DIR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BINSUBDIR = @BINSUBDIR@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
@@ -54,10 +150,15 @@ CHUTEST = @CHUTEST@
CLKTEST = @CLKTEST@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DCFD = @DCFD@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
+ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
@@ -65,30 +166,39 @@ EF_LIBS = @EF_LIBS@
EF_PROGS = @EF_PROGS@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
INSTALL_DATA = @INSTALL_DATA@
+INSTALL_LIBOPTS_FALSE = @INSTALL_LIBOPTS_FALSE@
+INSTALL_LIBOPTS_TRUE = @INSTALL_LIBOPTS_TRUE@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LCRYPTO = @LCRYPTO@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
+LIBOPTS_CFLAGS = @LIBOPTS_CFLAGS@
+LIBOPTS_DIR = @LIBOPTS_DIR@
+LIBOPTS_LDADD = @LIBOPTS_LDADD@
LIBPARSE = @LIBPARSE@
LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MAKE_ADJTIMED = @MAKE_ADJTIMED@
+MAKE_CHECK_LAYOUT = @MAKE_CHECK_LAYOUT@
MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@
MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@
MAKE_LIBPARSE = @MAKE_LIBPARSE@
MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
MAKE_NTPDSIM = @MAKE_NTPDSIM@
MAKE_NTPTIME = @MAKE_NTPTIME@
-MAKE_NTP_KEYGEN = @MAKE_NTP_KEYGEN@
MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
-MAKE_SNTP = @MAKE_SNTP@
MAKE_TICKADJ = @MAKE_TICKADJ@
MAKE_TIMETRIM = @MAKE_TIMETRIM@
+NEED_LIBOPTS_FALSE = @NEED_LIBOPTS_FALSE@
+NEED_LIBOPTS_TRUE = @NEED_LIBOPTS_TRUE@
OBJEXT = @OBJEXT@
OPENSSL = @OPENSSL@
OPENSSL_INC = @OPENSSL_INC@
@@ -111,15 +221,22 @@ STRIP = @STRIP@
TESTDCF = @TESTDCF@
U = @U@
VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
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__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
-bindir = @bindir@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = ${exec_prefix}/${BINSUBDIR}
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
@@ -139,6 +256,7 @@ libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
+mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
@@ -146,208 +264,98 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
-target = @target@
target_alias = @target_alias@
-target_cpu = @target_cpu@
-target_os = @target_os@
-target_vendor = @target_vendor@
-
-#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
AUTOMAKE_OPTIONS = ../util/ansi2knr
-bin_PROGRAMS = ntpd @MAKE_NTPDSIM@
noinst_LIBRARIES = libntpd.a
-INCLUDES = -I$(top_srcdir)/include -I../include
+AM_CPPFLAGS = -I$(top_srcdir)/include -I../include $(LIBOPTS_CFLAGS)
# LDADD might need RESLIB and ADJLIB.
-# If LIBPARSE, we need libntpd.a 2wagain afterwards...
-LDADD = version.o libntpd.a @LIBPARSE@ libntpd.a
+LDADD = version.o libntpd.a @LIBPARSE@
+BUILT_SOURCES = ntpd-opts.c ntpd-opts.h ntpd.1 ntpd-opts.texi \
+ ntpd-opts.menu ntpdsim-opts.c ntpdsim-opts.h ntpdsim.1 \
+ ntpdsim-opts.texi ntpdsim-opts.menu
+man_MANS = ntpd.1 ntpdsim.1
+
# ntpd may need:
# log10 refclock_wwv.o
# sqrt ntp_control.o
# floor refclock_wwv.o
# which are (usually) provided by -lm.
-ntpd_LDADD = $(LDADD) ../libntp/libntp.a -lm @LCRYPTO@
-ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@
+ntpd_LDADD = $(LDADD) -lm @LCRYPTO@ $(LIBOPTS_LDADD) ../libntp/libntp.a
+ntpdsim_LDADD = $(LDADD) ../libntp/libntpsim.a -lm @LCRYPTO@ $(LIBOPTS_LDADD)
ntpdsim_CFLAGS = $(CFLAGS) -DSIM
check_y2k_LDADD = $(LDADD) ../libntp/libntp.a
DISTCLEANFILES = .version version.c
-#EXTRA_DIST = ntpd.mak
+EXTRA_DIST = ntpd-opts.def ntpdbase-opts.def ntpdsim-opts.def \
+ refclock_msfees.c \
+ refclock_trak.c \
+ $(BUILT_SOURCES)
+
ETAGS_ARGS = Makefile.am
-### Y2Kfixes
-check_PROGRAMS = @MAKE_CHECK_Y2K@
-EXTRA_PROGRAMS = check_y2k ntpdsim
+run_ag = cd $(srcdir) && autogen -L ../include --writable
+std_def_list = $(top_srcdir)/include/debug-opt.def \
+ $(top_srcdir)/include/autogen-version.def \
+ $(top_srcdir)/include/copyright.def \
+ $(top_srcdir)/include/version.def
+
# SIM: cmd_args.c ntp_config.c ntp_io.c ntpd.c + ntpsim.c (include/ntpsim.h)
# ntp_resolver.c is presently unused...
-ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c
-ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c
-libntpd_a_SOURCES = jupiter.h map_vme.c ntp_control.c \
+ntpd_SOURCES = cmd_args.c ntp_config.c ntp_io.c ntpd.c ntpd-opts.c ntpd-opts.h
+ntpdsim_SOURCES = $(ntpd_SOURCES) ntpsim.c ntpdsim-opts.c ntpdsim-opts.h
+libntpd_a_SOURCES = jupiter.h ntp_control.c \
ntp_crypto.c ntp_filegen.c \
ntp_intres.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \
ntp_proto.c ntp_refclock.c ntp_request.c \
ntp_restrict.c ntp_timer.c ntp_util.c \
+ ppsapi_timepps.h \
refclock_acts.c refclock_arbiter.c refclock_arc.c refclock_as2201.c \
refclock_atom.c refclock_bancomm.c refclock_chronolog.c \
refclock_chu.c refclock_conf.c refclock_datum.c refclock_dumbclock.c \
refclock_fg.c refclock_gpsvme.c refclock_heath.c refclock_hopfser.c \
refclock_hopfpci.c refclock_hpgps.c refclock_irig.c refclock_jjy.c \
refclock_jupiter.c refclock_leitch.c refclock_local.c \
- refclock_msfees.c refclock_mx4200.c refclock_nmea.c refclock_oncore.c \
- refclock_palisade.c refclock_palisade.h refclock_parse.c \
- refclock_pcf.c refclock_pst.c refclock_ptbacts.c refclock_shm.c \
- refclock_tpro.c refclock_trak.c refclock_true.c refclock_tt560.c \
- refclock_ulink.c refclock_usno.c refclock_wwv.c refclock_wwvb.c \
- refclock_zyfer.c refclock_ripencc.c refclock_neoclock4x.c
-
-subdir = ntpd
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-LIBRARIES = $(noinst_LIBRARIES)
+ refclock_mx4200.c refclock_neoclock4x.c \
+ refclock_nmea.c refclock_oncore.c refclock_palisade.c \
+ refclock_palisade.h refclock_parse.c \
+ refclock_pcf.c refclock_pst.c refclock_ripencc.c refclock_shm.c \
+ refclock_tpro.c refclock_true.c refclock_tt560.c \
+ refclock_ulink.c refclock_wwv.c refclock_wwvb.c \
+ refclock_zyfer.c
-libntpd_a_AR = $(AR) cru
-libntpd_a_LIBADD =
-am_libntpd_a_OBJECTS = map_vme$U.$(OBJEXT) ntp_control$U.$(OBJEXT) \
- ntp_crypto$U.$(OBJEXT) ntp_filegen$U.$(OBJEXT) \
- ntp_intres$U.$(OBJEXT) ntp_loopfilter$U.$(OBJEXT) \
- ntp_monitor$U.$(OBJEXT) ntp_peer$U.$(OBJEXT) \
- ntp_proto$U.$(OBJEXT) ntp_refclock$U.$(OBJEXT) \
- ntp_request$U.$(OBJEXT) ntp_restrict$U.$(OBJEXT) \
- ntp_timer$U.$(OBJEXT) ntp_util$U.$(OBJEXT) \
- refclock_acts$U.$(OBJEXT) refclock_arbiter$U.$(OBJEXT) \
- refclock_arc$U.$(OBJEXT) refclock_as2201$U.$(OBJEXT) \
- refclock_atom$U.$(OBJEXT) refclock_bancomm$U.$(OBJEXT) \
- refclock_chronolog$U.$(OBJEXT) refclock_chu$U.$(OBJEXT) \
- refclock_conf$U.$(OBJEXT) refclock_datum$U.$(OBJEXT) \
- refclock_dumbclock$U.$(OBJEXT) refclock_fg$U.$(OBJEXT) \
- refclock_gpsvme$U.$(OBJEXT) refclock_heath$U.$(OBJEXT) \
- refclock_hopfser$U.$(OBJEXT) refclock_hopfpci$U.$(OBJEXT) \
- refclock_hpgps$U.$(OBJEXT) refclock_irig$U.$(OBJEXT) \
- refclock_jjy$U.$(OBJEXT) refclock_jupiter$U.$(OBJEXT) \
- refclock_leitch$U.$(OBJEXT) refclock_local$U.$(OBJEXT) \
- refclock_msfees$U.$(OBJEXT) refclock_mx4200$U.$(OBJEXT) \
- refclock_nmea$U.$(OBJEXT) refclock_oncore$U.$(OBJEXT) \
- refclock_palisade$U.$(OBJEXT) refclock_parse$U.$(OBJEXT) \
- refclock_pcf$U.$(OBJEXT) refclock_pst$U.$(OBJEXT) \
- refclock_ptbacts$U.$(OBJEXT) refclock_shm$U.$(OBJEXT) \
- refclock_tpro$U.$(OBJEXT) refclock_trak$U.$(OBJEXT) \
- refclock_true$U.$(OBJEXT) refclock_tt560$U.$(OBJEXT) \
- refclock_ulink$U.$(OBJEXT) refclock_usno$U.$(OBJEXT) \
- refclock_wwv$U.$(OBJEXT) refclock_wwvb$U.$(OBJEXT) \
- refclock_zyfer$U.$(OBJEXT) refclock_ripencc$U.$(OBJEXT) \
- refclock_neoclock4x$U.$(OBJEXT)
-libntpd_a_OBJECTS = $(am_libntpd_a_OBJECTS)
-EXTRA_PROGRAMS = check_y2k$(EXEEXT) ntpdsim$(EXEEXT)
-bin_PROGRAMS = ntpd$(EXEEXT) @MAKE_NTPDSIM@
-check_PROGRAMS = @MAKE_CHECK_Y2K@
-PROGRAMS = $(bin_PROGRAMS)
-
-check_y2k_SOURCES = check_y2k.c
-check_y2k_OBJECTS = check_y2k$U.$(OBJEXT)
-check_y2k_DEPENDENCIES = version.o libntpd.a libntpd.a \
- ../libntp/libntp.a
-check_y2k_LDFLAGS =
-am_ntpd_OBJECTS = cmd_args$U.$(OBJEXT) ntp_config$U.$(OBJEXT) \
- ntp_io$U.$(OBJEXT) ntpd$U.$(OBJEXT)
-ntpd_OBJECTS = $(am_ntpd_OBJECTS)
-ntpd_DEPENDENCIES = version.o libntpd.a libntpd.a ../libntp/libntp.a
-ntpd_LDFLAGS =
-am__objects_1 = ntpdsim-cmd_args$U.$(OBJEXT) \
- ntpdsim-ntp_config$U.$(OBJEXT) ntpdsim-ntp_io$U.$(OBJEXT) \
- ntpdsim-ntpd$U.$(OBJEXT)
-am_ntpdsim_OBJECTS = $(am__objects_1) ntpdsim-ntpsim$U.$(OBJEXT)
-ntpdsim_OBJECTS = $(am_ntpdsim_OBJECTS)
-ntpdsim_DEPENDENCIES = version.o libntpd.a libntpd.a \
- ../libntp/libntpsim.a
-ntpdsim_LDFLAGS =
-
-DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/check_y2k$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/cmd_args$U.Po ./$(DEPDIR)/map_vme$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_config$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_control$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_crypto$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_filegen$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_intres$U.Po ./$(DEPDIR)/ntp_io$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_loopfilter$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_monitor$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_peer$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_proto$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_refclock$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_request$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_restrict$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_timer$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntp_util$U.Po ./$(DEPDIR)/ntpd$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-cmd_args$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntp_config$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntp_io$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntpd$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/ntpdsim-ntpsim$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_acts$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_arbiter$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_arc$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_as2201$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_atom$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_bancomm$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_chronolog$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_chu$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_conf$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_datum$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_dumbclock$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_fg$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_gpsvme$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_heath$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_hopfpci$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_hopfser$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_hpgps$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_irig$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_jjy$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_jupiter$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_leitch$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_local$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_msfees$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_mx4200$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_neoclock4x$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_nmea$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_oncore$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_palisade$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_parse$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_pcf$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_pst$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_ptbacts$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_ripencc$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_shm$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_tpro$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_trak$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_true$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_tt560$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_ulink$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_usno$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_wwv$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_wwvb$U.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/refclock_zyfer$U.Po
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-DIST_SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) \
- $(ntpdsim_SOURCES)
-DIST_COMMON = $(srcdir)/Makefile.in Makefile.am
-SOURCES = $(libntpd_a_SOURCES) check_y2k.c $(ntpd_SOURCES) $(ntpdsim_SOURCES)
-
-all: all-am
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../bincheck.mf $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ntpd/Makefile'; \
cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu ntpd/Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
-
-AR = ar
+ $(AUTOMAKE) --foreign ntpd/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
@@ -355,17 +363,17 @@ 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)
+ test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
@list='$(bin_PROGRAMS)'; for p in $$list; do \
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
if test -f $$p \
+ || test -f $$p1 \
; then \
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \
- $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
else :; fi; \
done
@@ -373,15 +381,23 @@ uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
- rm -f $(DESTDIR)$(bindir)/$$f; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
done
clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
clean-checkPROGRAMS:
- -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+ @list='$(check_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
check_y2k$(EXEEXT): $(check_y2k_OBJECTS) $(check_y2k_DEPENDENCIES)
@rm -f check_y2k$(EXEEXT)
$(LINK) $(check_y2k_LDFLAGS) $(check_y2k_OBJECTS) $(check_y2k_LDADD) $(LIBS)
@@ -393,12 +409,10 @@ ntpdsim$(EXEEXT): $(ntpdsim_OBJECTS) $(ntpdsim_DEPENDENCIES)
$(LINK) $(ntpdsim_LDFLAGS) $(ntpdsim_OBJECTS) $(ntpdsim_LDADD) $(LIBS)
mostlyclean-compile:
- -rm -f *.$(OBJEXT) core *.core
+ -rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
-
-ANSI2KNR = ../util/ansi2knr
../util/ansi2knr:
cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr
@@ -407,7 +421,6 @@ mostlyclean-kr:
@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@
@@ -424,10 +437,13 @@ mostlyclean-kr:
@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)/ntpd-opts$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-ntpd-opts$U.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpdsim-ntpdsim-opts$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@
@@ -451,7 +467,6 @@ mostlyclean-kr:
@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@
@@ -460,156 +475,138 @@ mostlyclean-kr:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_parse$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pcf$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_pst$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ptbacts$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ripencc$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_shm$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tpro$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_trak$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_true$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tt560$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_ulink$U.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_usno$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwv$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwvb$U.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_zyfer$U.Po@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
-@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; 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)/'`$<
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
-@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
-@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
-@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
-@am__fastdepCC_TRUE@ fi
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; 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`
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-cmd_args$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntp_config$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntp_io$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntpd$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntpd$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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-ntpd-opts$U.o: ntpd-opts$U.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd-opts$U.o -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo" -c -o ntpdsim-ntpd-opts$U.o `test -f 'ntpd-opts$U.c' || echo '$(srcdir)/'`ntpd-opts$U.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo" "$(DEPDIR)/ntpdsim-ntpd-opts$U.Po"; else rm -f "$(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd-opts$U.c' object='ntpdsim-ntpd-opts$U.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd-opts$U.o `test -f 'ntpd-opts$U.c' || echo '$(srcdir)/'`ntpd-opts$U.c
+
+ntpdsim-ntpd-opts$U.obj: ntpd-opts$U.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpd-opts$U.obj -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo" -c -o ntpdsim-ntpd-opts$U.obj `if test -f 'ntpd-opts$U.c'; then $(CYGPATH_W) 'ntpd-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd-opts$U.c'; fi`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo" "$(DEPDIR)/ntpdsim-ntpd-opts$U.Po"; else rm -f "$(DEPDIR)/ntpdsim-ntpd-opts$U.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpd-opts$U.c' object='ntpdsim-ntpd-opts$U.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpd-opts$U.obj `if test -f 'ntpd-opts$U.c'; then $(CYGPATH_W) 'ntpd-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpd-opts$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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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
+@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" -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"; else rm -f "$(DEPDIR)/ntpdsim-ntpsim$U.Tpo"; exit 1; 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@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(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`
+
+ntpdsim-ntpdsim-opts$U.o: ntpdsim-opts$U.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpdsim-opts$U.o -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo" -c -o ntpdsim-ntpdsim-opts$U.o `test -f 'ntpdsim-opts$U.c' || echo '$(srcdir)/'`ntpdsim-opts$U.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo" "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Po"; else rm -f "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpdsim-opts$U.c' object='ntpdsim-ntpdsim-opts$U.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpdsim-opts$U.o `test -f 'ntpdsim-opts$U.c' || echo '$(srcdir)/'`ntpdsim-opts$U.c
+
+ntpdsim-ntpdsim-opts$U.obj: ntpdsim-opts$U.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -MT ntpdsim-ntpdsim-opts$U.obj -MD -MP -MF "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo" -c -o ntpdsim-ntpdsim-opts$U.obj `if test -f 'ntpdsim-opts$U.c'; then $(CYGPATH_W) 'ntpdsim-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpdsim-opts$U.c'; fi`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo" "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Po"; else rm -f "$(DEPDIR)/ntpdsim-ntpdsim-opts$U.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ntpdsim-opts$U.c' object='ntpdsim-ntpdsim-opts$U.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ntpdsim_CFLAGS) $(CFLAGS) -c -o ntpdsim-ntpdsim-opts$U.obj `if test -f 'ntpdsim-opts$U.c'; then $(CYGPATH_W) 'ntpdsim-opts$U.c'; else $(CYGPATH_W) '$(srcdir)/ntpdsim-opts$U.c'; fi`
check_y2k_.c: check_y2k.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/check_y2k.c; then echo $(srcdir)/check_y2k.c; else echo check_y2k.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
cmd_args_.c: cmd_args.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/cmd_args.c; then echo $(srcdir)/cmd_args.c; else echo cmd_args.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-map_vme_.c: map_vme.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/map_vme.c; then echo $(srcdir)/map_vme.c; else echo map_vme.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
ntp_config_.c: ntp_config.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_config.c; then echo $(srcdir)/ntp_config.c; else echo ntp_config.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
ntp_control_.c: ntp_control.c $(ANSI2KNR)
@@ -642,6 +639,10 @@ ntp_util_.c: ntp_util.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_util.c; then echo $(srcdir)/ntp_util.c; else echo ntp_util.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
ntpd_.c: ntpd.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpd.c; then echo $(srcdir)/ntpd.c; else echo ntpd.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+ntpd-opts_.c: ntpd-opts.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpd-opts.c; then echo $(srcdir)/ntpd-opts.c; else echo ntpd-opts.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
+ntpdsim-opts_.c: ntpdsim-opts.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntpdsim-opts.c; then echo $(srcdir)/ntpdsim-opts.c; else echo ntpdsim-opts.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)
@@ -688,8 +689,6 @@ refclock_leitch_.c: refclock_leitch.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_leitch.c; then echo $(srcdir)/refclock_leitch.c; else echo refclock_leitch.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_local_.c: refclock_local.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_local.c; then echo $(srcdir)/refclock_local.c; else echo refclock_local.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_msfees_.c: refclock_msfees.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_msfees.c; then echo $(srcdir)/refclock_msfees.c; else echo refclock_msfees.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_mx4200_.c: refclock_mx4200.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_mx4200.c; then echo $(srcdir)/refclock_mx4200.c; else echo refclock_mx4200.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_neoclock4x_.c: refclock_neoclock4x.c $(ANSI2KNR)
@@ -706,67 +705,122 @@ refclock_pcf_.c: refclock_pcf.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pcf.c; then echo $(srcdir)/refclock_pcf.c; else echo refclock_pcf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_pst_.c: refclock_pst.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_pst.c; then echo $(srcdir)/refclock_pst.c; else echo refclock_pst.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_ptbacts_.c: refclock_ptbacts.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ptbacts.c; then echo $(srcdir)/refclock_ptbacts.c; else echo refclock_ptbacts.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_ripencc_.c: refclock_ripencc.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ripencc.c; then echo $(srcdir)/refclock_ripencc.c; else echo refclock_ripencc.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_shm_.c: refclock_shm.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_shm.c; then echo $(srcdir)/refclock_shm.c; else echo refclock_shm.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_tpro_.c: refclock_tpro.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_tpro.c; then echo $(srcdir)/refclock_tpro.c; else echo refclock_tpro.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_trak_.c: refclock_trak.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_trak.c; then echo $(srcdir)/refclock_trak.c; else echo refclock_trak.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_true_.c: refclock_true.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_true.c; then echo $(srcdir)/refclock_true.c; else echo refclock_true.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_tt560_.c: refclock_tt560.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_tt560.c; then echo $(srcdir)/refclock_tt560.c; else echo refclock_tt560.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_ulink_.c: refclock_ulink.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_ulink.c; then echo $(srcdir)/refclock_ulink.c; else echo refclock_ulink.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-refclock_usno_.c: refclock_usno.c $(ANSI2KNR)
- $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_usno.c; then echo $(srcdir)/refclock_usno.c; else echo refclock_usno.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_wwv_.c: refclock_wwv.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwv.c; then echo $(srcdir)/refclock_wwv.c; else echo refclock_wwv.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_wwvb_.c: refclock_wwvb.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwvb.c; then echo $(srcdir)/refclock_wwvb.c; else echo refclock_wwvb.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
refclock_zyfer_.c: refclock_zyfer.c $(ANSI2KNR)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_zyfer.c; then echo $(srcdir)/refclock_zyfer.c; else echo refclock_zyfer.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > $@ || rm -f $@
-check_y2k_.$(OBJEXT) cmd_args_.$(OBJEXT) map_vme_.$(OBJEXT) \
-ntp_config_.$(OBJEXT) ntp_control_.$(OBJEXT) ntp_crypto_.$(OBJEXT) \
-ntp_filegen_.$(OBJEXT) ntp_intres_.$(OBJEXT) ntp_io_.$(OBJEXT) \
-ntp_loopfilter_.$(OBJEXT) ntp_monitor_.$(OBJEXT) ntp_peer_.$(OBJEXT) \
-ntp_proto_.$(OBJEXT) ntp_refclock_.$(OBJEXT) ntp_request_.$(OBJEXT) \
-ntp_restrict_.$(OBJEXT) ntp_timer_.$(OBJEXT) ntp_util_.$(OBJEXT) \
-ntpd_.$(OBJEXT) ntpsim_.$(OBJEXT) refclock_acts_.$(OBJEXT) \
-refclock_arbiter_.$(OBJEXT) refclock_arc_.$(OBJEXT) \
-refclock_as2201_.$(OBJEXT) refclock_atom_.$(OBJEXT) \
-refclock_bancomm_.$(OBJEXT) refclock_chronolog_.$(OBJEXT) \
-refclock_chu_.$(OBJEXT) refclock_conf_.$(OBJEXT) \
-refclock_datum_.$(OBJEXT) refclock_dumbclock_.$(OBJEXT) \
-refclock_fg_.$(OBJEXT) refclock_gpsvme_.$(OBJEXT) \
-refclock_heath_.$(OBJEXT) refclock_hopfpci_.$(OBJEXT) \
-refclock_hopfser_.$(OBJEXT) refclock_hpgps_.$(OBJEXT) \
-refclock_irig_.$(OBJEXT) refclock_jjy_.$(OBJEXT) \
-refclock_jupiter_.$(OBJEXT) refclock_leitch_.$(OBJEXT) \
-refclock_local_.$(OBJEXT) refclock_msfees_.$(OBJEXT) \
-refclock_mx4200_.$(OBJEXT) refclock_neoclock4x_.$(OBJEXT) \
-refclock_nmea_.$(OBJEXT) refclock_oncore_.$(OBJEXT) \
-refclock_palisade_.$(OBJEXT) refclock_parse_.$(OBJEXT) \
-refclock_pcf_.$(OBJEXT) refclock_pst_.$(OBJEXT) \
-refclock_ptbacts_.$(OBJEXT) refclock_ripencc_.$(OBJEXT) \
-refclock_shm_.$(OBJEXT) refclock_tpro_.$(OBJEXT) \
-refclock_trak_.$(OBJEXT) refclock_true_.$(OBJEXT) \
-refclock_tt560_.$(OBJEXT) refclock_ulink_.$(OBJEXT) \
-refclock_usno_.$(OBJEXT) refclock_wwv_.$(OBJEXT) \
-refclock_wwvb_.$(OBJEXT) refclock_zyfer_.$(OBJEXT) : $(ANSI2KNR)
+check_y2k_.$(OBJEXT) check_y2k_.lo cmd_args_.$(OBJEXT) cmd_args_.lo \
+ntp_config_.$(OBJEXT) ntp_config_.lo ntp_control_.$(OBJEXT) \
+ntp_control_.lo ntp_crypto_.$(OBJEXT) ntp_crypto_.lo \
+ntp_filegen_.$(OBJEXT) ntp_filegen_.lo ntp_intres_.$(OBJEXT) \
+ntp_intres_.lo ntp_io_.$(OBJEXT) ntp_io_.lo ntp_loopfilter_.$(OBJEXT) \
+ntp_loopfilter_.lo ntp_monitor_.$(OBJEXT) ntp_monitor_.lo \
+ntp_peer_.$(OBJEXT) ntp_peer_.lo ntp_proto_.$(OBJEXT) ntp_proto_.lo \
+ntp_refclock_.$(OBJEXT) ntp_refclock_.lo ntp_request_.$(OBJEXT) \
+ntp_request_.lo ntp_restrict_.$(OBJEXT) ntp_restrict_.lo \
+ntp_timer_.$(OBJEXT) ntp_timer_.lo ntp_util_.$(OBJEXT) ntp_util_.lo \
+ntpd_.$(OBJEXT) ntpd_.lo ntpd-opts_.$(OBJEXT) ntpd-opts_.lo \
+ntpdsim-opts_.$(OBJEXT) ntpdsim-opts_.lo ntpsim_.$(OBJEXT) ntpsim_.lo \
+refclock_acts_.$(OBJEXT) refclock_acts_.lo refclock_arbiter_.$(OBJEXT) \
+refclock_arbiter_.lo refclock_arc_.$(OBJEXT) refclock_arc_.lo \
+refclock_as2201_.$(OBJEXT) refclock_as2201_.lo \
+refclock_atom_.$(OBJEXT) refclock_atom_.lo refclock_bancomm_.$(OBJEXT) \
+refclock_bancomm_.lo refclock_chronolog_.$(OBJEXT) \
+refclock_chronolog_.lo refclock_chu_.$(OBJEXT) refclock_chu_.lo \
+refclock_conf_.$(OBJEXT) refclock_conf_.lo refclock_datum_.$(OBJEXT) \
+refclock_datum_.lo refclock_dumbclock_.$(OBJEXT) \
+refclock_dumbclock_.lo refclock_fg_.$(OBJEXT) refclock_fg_.lo \
+refclock_gpsvme_.$(OBJEXT) refclock_gpsvme_.lo \
+refclock_heath_.$(OBJEXT) refclock_heath_.lo \
+refclock_hopfpci_.$(OBJEXT) refclock_hopfpci_.lo \
+refclock_hopfser_.$(OBJEXT) refclock_hopfser_.lo \
+refclock_hpgps_.$(OBJEXT) refclock_hpgps_.lo refclock_irig_.$(OBJEXT) \
+refclock_irig_.lo refclock_jjy_.$(OBJEXT) refclock_jjy_.lo \
+refclock_jupiter_.$(OBJEXT) refclock_jupiter_.lo \
+refclock_leitch_.$(OBJEXT) refclock_leitch_.lo \
+refclock_local_.$(OBJEXT) refclock_local_.lo \
+refclock_mx4200_.$(OBJEXT) refclock_mx4200_.lo \
+refclock_neoclock4x_.$(OBJEXT) refclock_neoclock4x_.lo \
+refclock_nmea_.$(OBJEXT) refclock_nmea_.lo refclock_oncore_.$(OBJEXT) \
+refclock_oncore_.lo refclock_palisade_.$(OBJEXT) refclock_palisade_.lo \
+refclock_parse_.$(OBJEXT) refclock_parse_.lo refclock_pcf_.$(OBJEXT) \
+refclock_pcf_.lo refclock_pst_.$(OBJEXT) refclock_pst_.lo \
+refclock_ripencc_.$(OBJEXT) refclock_ripencc_.lo \
+refclock_shm_.$(OBJEXT) refclock_shm_.lo refclock_tpro_.$(OBJEXT) \
+refclock_tpro_.lo refclock_true_.$(OBJEXT) refclock_true_.lo \
+refclock_tt560_.$(OBJEXT) refclock_tt560_.lo refclock_ulink_.$(OBJEXT) \
+refclock_ulink_.lo refclock_wwv_.$(OBJEXT) refclock_wwv_.lo \
+refclock_wwvb_.$(OBJEXT) refclock_wwvb_.lo refclock_zyfer_.$(OBJEXT) \
+refclock_zyfer_.lo : $(ANSI2KNR)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
uninstall-info-am:
-
-ETAGS = etags
-ETAGSFLAGS =
-
-CTAGS = ctags
-CTAGSFLAGS =
-
-tags: TAGS
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)"
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -776,6 +830,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
+tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
@@ -787,10 +842,11 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
- test -z "$(ETAGS_ARGS)$$tags$$unique" \
- || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique
-
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
@@ -813,12 +869,9 @@ GTAGS:
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-
-top_distdir = ..
-distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
+ $(mkdir_p) $(distdir)/..
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
@@ -830,7 +883,7 @@ distdir: $(DISTFILES)
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
- $(mkinstalldirs) "$(distdir)$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
@@ -848,12 +901,15 @@ distdir: $(DISTFILES)
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-am
-all-am: Makefile $(LIBRARIES) $(PROGRAMS)
-
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS)
installdirs:
- $(mkinstalldirs) $(DESTDIR)$(bindir)
-install: install-am
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -864,7 +920,7 @@ install-am: all-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- INSTALL_STRIP_FLAG=-s \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
@@ -872,51 +928,55 @@ mostlyclean-generic:
clean-generic:
distclean-generic:
- -rm -f $(CONFIG_CLEAN_FILES)
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
- clean-noinstLIBRARIES mostlyclean-am
+ clean-libtool clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
-
distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
+ distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
+html: html-am
+
info: info-am
info-am:
-install-data-am:
+install-data-am: install-man
install-exec-am: install-binPROGRAMS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
install-info: install-info-am
-install-man:
+install-man: install-man1
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
-
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
-mostlyclean-am: mostlyclean-compile mostlyclean-generic mostlyclean-kr
+mostlyclean-am: mostlyclean-compile mostlyclean-generic mostlyclean-kr \
+ mostlyclean-libtool
pdf: pdf-am
@@ -926,35 +986,78 @@ ps: ps-am
ps-am:
-uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-man
+
+uninstall-man: uninstall-man1
.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
+ clean-libtool clean-noinstLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-binPROGRAMS install-data \
+ install-data-am install-exec install-exec-am install-exec-hook \
+ install-info install-info-am install-man install-man1 \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-kr \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-binPROGRAMS uninstall-info-am \
+ uninstall-man uninstall-man1
check-local: @MAKE_CHECK_Y2K@
test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
+$(srcdir)/ntpd-opts.h: $(srcdir)/ntpd-opts.c
+$(srcdir)/ntpd-opts.c: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+ $(run_ag) ntpd-opts.def
+
+$(srcdir)/ntpd.1: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+ $(run_ag) -Tagman1.tpl -bntpd ntpd-opts.def
+
+$(srcdir)/ntpd-opts.texi $(srcdir)/ntpd-opts.menu: $(srcdir)/ntpd-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list)
+ $(run_ag) -Taginfo.tpl -DLEVEL=section ntpd-opts.def
+
+$(srcdir)/ntpdsim-opts.h: $(srcdir)/ntpdsim-opts.c
+$(srcdir)/ntpdsim-opts.c: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
+ $(run_ag) ntpdsim-opts.def
+
+$(srcdir)/ntpdsim.1: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
+ $(run_ag) -Tagman1.tpl -bntpdsim ntpdsim-opts.def
+
+$(srcdir)/ntpdsim-opts.texi $(srcdir)/ntpdsim-opts.menu: $(srcdir)/ntpdsim-opts.def $(srcdir)/ntpdbase-opts.def $(std_def_list) $(top_srcdir)/include/homerc.def
+ $(run_ag) -Taginfo.tpl -DLEVEL=section ntpdsim-opts.def
+
$(PROGRAMS): $(LDADD)
../libntp/libntp.a:
- cd ../libntp && $(MAKE)
+ cd ../libntp && $(MAKE) libntp.a
+
+../libntp/libntpsim.a:
+ cd ../libntp && $(MAKE) libntpsim.a
../libparse/libparse.a:
cd ../libparse && $(MAKE)
+$(top_srcdir)/version :
+ cd $(top_srcdir) && $(MAKE) version
+
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
+
+install-exec-hook:
+ @case ${BINSUBDIR} in \
+ bin) ODIR=${exec_prefix}/sbin ;; \
+ sbin) ODIR=${exec_prefix}/bin ;; \
+ esac; \
+ test -z "${bin_PROGRAMS}${bin_SCRIPTS}" \
+ || for i in ${bin_PROGRAMS} ${bin_SCRIPTS} " "; do \
+ test ! -f $$ODIR/$$i || echo "*** $$i is also in $$ODIR!"; \
+ done
+
+#
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/contrib/ntp/ntpd/cmd_args.c b/contrib/ntp/ntpd/cmd_args.c
index 3ed9b66..760bced 100644
--- a/contrib/ntp/ntpd/cmd_args.c
+++ b/contrib/ntp/ntpd/cmd_args.c
@@ -10,20 +10,20 @@
#include "ntp_cmdargs.h"
#ifdef SIM
-#include "ntpsim.h"
+# include "ntpsim.h"
+# include "ntpdsim-opts.h"
+# define OPTSTRUCT ntpdsimOptions
+#else
+# include "ntpd-opts.h"
+# define OPTSTRUCT ntpdOptions
#endif /* SIM */
/*
* Definitions of things either imported from or exported to outside
*/
extern char const *progname;
-int listen_to_virtual_ips = 1;
-
-#ifdef SYS_WINNT
-extern BOOL NoWinService;
-#endif
-
-static const char *ntp_options = "aAbB:c:C:dD:f:gi:k:l:LmnNO:p:P:qr:s:S:t:T:W:u:v:V:xY:Z:-:";
+extern const char *specific_interface;
+extern short default_ai_family;
#ifdef HAVE_NETINFO
extern int check_netinfo;
@@ -31,388 +31,202 @@ extern int check_netinfo;
/*
- * getstartup - search through the options looking for a debugging flag
+ * getCmdOpts - get command line options
*/
void
-getstartup(
+getCmdOpts(
int argc,
char *argv[]
)
{
+ extern const char *config_file;
int errflg;
- extern int priority_done;
- int c;
-
-#ifdef DEBUG
- debug = 0; /* no debugging by default */
-#endif
+ tOptions *myOptions = &OPTSTRUCT;
/*
- * This is a big hack. We don't really want to read command line
- * configuration until everything else is initialized, since
- * the ability to configure the system may depend on storage
- * and the like having been initialized. Except that we also
- * don't want to initialize anything until after detaching from
- * the terminal, but we won't know to do that until we've
- * parsed the command line. Do that now, crudely, and do it
- * again later. Our ntp_getopt() is explicitly reusable, by the
- * way. Your own mileage may vary.
- *
- * This hack is even called twice (to allow complete logging to file)
+ * Initialize, initialize
*/
errflg = 0;
- progname = argv[0];
- /*
- * Decode argument list
- */
- while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF)
- switch (c) {
-#ifdef DEBUG
- case 'd':
- ++debug;
- break;
- case 'D':
- debug = (int)atol(ntp_optarg);
- printf("Debug1: %s -> %x = %d\n", ntp_optarg, debug, debug);
- break;
-#else
- case 'd':
- case 'D':
- msyslog(LOG_ERR, "ntpd not compiled with -DDEBUG option - no DEBUG support");
- fprintf(stderr, "ntpd not compiled with -DDEBUG option - no DEBUG support\n");
- ++errflg;
- break;
-#endif
- case 'L':
- listen_to_virtual_ips = 0;
- break;
- case 'l':
- {
- FILE *new_file;
-
- if(strcmp(ntp_optarg, "stderr") == 0)
- new_file = stderr;
- else if(strcmp(ntp_optarg, "stdout") == 0)
- new_file = stdout;
- else
- new_file = fopen(ntp_optarg, "a");
- if (new_file != NULL) {
- NLOG(NLOG_SYSINFO)
- msyslog(LOG_NOTICE, "logging to file %s", ntp_optarg);
- if (syslog_file != NULL &&
- fileno(syslog_file) != fileno(new_file))
- (void)fclose(syslog_file);
-
- syslog_file = new_file;
- syslogit = 0;
- }
- else
- msyslog(LOG_ERR,
- "Cannot open log file %s",
- ntp_optarg);
- }
- break;
+ switch (WHICH_IDX_IPV4) {
+ case INDEX_OPT_IPV4:
+ default_ai_family = AF_INET;
+ break;
+ case INDEX_OPT_IPV6:
+ default_ai_family = AF_INET6;
+ break;
+ default:
+ /* ai_fam_templ = ai_fam_default; */
+ break;
+ }
- case 'n':
- case 'q':
- ++nofork;
-#ifdef SYS_WINNT
- NoWinService = TRUE;
-#endif
- break;
-
- case 'N':
- priority_done = 0;
- break;
-
- case '?':
- ++errflg;
- break;
-
- case '-':
- if ( ! strcmp(ntp_optarg, "version") ) {
- printf("%.80s: %.80s\n", progname, Version);
- exit(0);
- } else if ( ! strcmp(ntp_optarg, "help") ) {
- /* usage(); */
- /* exit(0); */
- ++errflg;
- } else if ( ! strcmp(ntp_optarg, "copyright") ) {
- printf("unknown\n");
- exit(0);
- } else {
- fprintf(stderr, "%.80s: Error unknown argument '--%.80s'\n",
- progname,
- ntp_optarg);
- exit(12);
- }
- break;
-
- default:
- break;
- }
+ if (HAVE_OPT( AUTHREQ ))
+ proto_config(PROTO_AUTHENTICATE, 1, 0., NULL);
- if (errflg || ntp_optind != argc) {
- (void) fprintf(stderr, "usage: %s [ -abdgmnqx ] [ -c config_file ] [ -e e_delay ]\n", progname);
- (void) fprintf(stderr, "\t\t[ -f freq_file ] [ -k key_file ] [ -l log_file ]\n");
- (void) fprintf(stderr, "\t\t[ -p pid_file ] [ -r broad_delay ] [ -s statdir ]\n");
- (void) fprintf(stderr, "\t\t[ -t trust_key ] [ -v sys_var ] [ -V default_sysvar ]\n");
-#if defined(HAVE_SCHED_SETSCHEDULER)
- (void) fprintf(stderr, "\t\t[ -P fixed_process_priority ]\n");
-#endif
-#ifdef HAVE_CLOCKCTL
- (void) fprintf(stderr, "\t\t[ -u user[:group] ] [ -i chrootdir ]\n");
+ if (HAVE_OPT( AUTHNOREQ ))
+ proto_config(PROTO_AUTHENTICATE, 0, 0., NULL);
+
+ if (HAVE_OPT( BCASTSYNC ))
+ proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
+
+ if (HAVE_OPT( CONFIGFILE )) {
+ config_file = OPT_ARG( CONFIGFILE );
+#ifdef HAVE_NETINFO
+ check_netinfo = 0;
#endif
- exit(2);
}
- ntp_optind = 0; /* reset ntp_optind to restart ntp_getopt */
-#ifdef DEBUG
- if (debug) {
-#ifdef HAVE_SETVBUF
- static char buf[BUFSIZ];
- setvbuf(stdout, buf, _IOLBF, BUFSIZ);
+ if (HAVE_OPT( DRIFTFILE ))
+ stats_config(STATS_FREQ_FILE, OPT_ARG( DRIFTFILE ));
+
+ if (HAVE_OPT( PANICGATE ))
+ allow_panic = TRUE;
+
+ if (HAVE_OPT( JAILDIR )) {
+#ifdef HAVE_DROPROOT
+ droproot = 1;
+ chrootdir = OPT_ARG( JAILDIR );
#else
- setlinebuf(stdout);
+ errflg++;
#endif
}
-#endif
-}
-/*
- * getCmdOpts - get command line options
- */
-void
-getCmdOpts(
- int argc,
- char *argv[]
- )
-{
- extern char *config_file;
- struct sockaddr_in inaddrntp;
- int errflg;
- int c;
+ if (HAVE_OPT( KEYFILE ))
+ getauthkeys(OPT_ARG( KEYFILE ));
- /*
- * Initialize, initialize
- */
- errflg = 0;
-#ifdef DEBUG
- debug = 0;
-#endif /* DEBUG */
+ if (HAVE_OPT( PIDFILE ))
+ stats_config(STATS_PID_FILE, OPT_ARG( PIDFILE ));
- progname = argv[0];
+ if (HAVE_OPT( QUIT ))
+ mode_ntpdate = TRUE;
- /*
- * Decode argument list
- */
- while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF) {
- switch (c) {
- case 'a':
- proto_config(PROTO_AUTHENTICATE, 1, 0., NULL);
- break;
-
- case 'A':
- proto_config(PROTO_AUTHENTICATE, 0, 0., NULL);
- break;
-
- case 'b':
- proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
- break;
-
- case 'c':
- config_file = ntp_optarg;
-#ifdef HAVE_NETINFO
- check_netinfo = 0;
-#endif
- break;
+ if (HAVE_OPT( PROPAGATIONDELAY ))
+ do {
+ double tmp;
+ const char *my_ntp_optarg = OPT_ARG( PROPAGATIONDELAY );
- case 'd':
-#ifdef DEBUG
- debug++;
-#else
- errflg++;
-#endif /* DEBUG */
- break;
+ if (sscanf(my_ntp_optarg, "%lf", &tmp) != 1) {
+ msyslog(LOG_ERR,
+ "command line broadcast delay value %s undecodable",
+ my_ntp_optarg);
+ } else {
+ proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
+ }
+ } while (0);
+
+ if (HAVE_OPT( STATSDIR ))
+ stats_config(STATS_STATSDIR, OPT_ARG( STATSDIR ));
+
+ if (HAVE_OPT( TRUSTEDKEY )) {
+ int ct = STACKCT_OPT( TRUSTEDKEY );
+ const char** pp = STACKLST_OPT( TRUSTEDKEY );
+
+ do {
+ u_long tkey;
+ const char* p = *pp++;
+
+ tkey = (int)atol(p);
+ if (tkey == 0 || tkey > NTP_MAXKEY) {
+ msyslog(LOG_ERR,
+ "command line trusted key %s is invalid",
+ p);
+ } else {
+ authtrust(tkey, 1);
+ }
+ } while (--ct > 0);
+ }
- case 'D':
-#ifdef DEBUG
- debug = (int)atol(ntp_optarg);
- printf("Debug2: %s -> %x = %d\n", ntp_optarg, debug, debug);
-#else
- errflg++;
-#endif /* DEBUG */
- break;
-
- case 'f':
- stats_config(STATS_FREQ_FILE, ntp_optarg);
- break;
-
- case 'g':
- allow_panic = TRUE;
- break;
-
- case 'i':
-#ifdef HAVE_CLOCKCTL
- if (!ntp_optarg)
- errflg++;
- else
- chrootdir = ntp_optarg;
- break;
-#else
- errflg++;
-#endif
- case 'k':
- getauthkeys(ntp_optarg);
- break;
-
- case 'L': /* already done at pre-scan */
- case 'l': /* already done at pre-scan */
- break;
-
- case 'm':
- inaddrntp.sin_family = AF_INET;
- inaddrntp.sin_port = htons(NTP_PORT);
- inaddrntp.sin_addr.s_addr = htonl(INADDR_NTP);
- proto_config(PROTO_MULTICAST_ADD, 0, 0., (struct sockaddr_storage*)&inaddrntp);
- sys_bclient = 1;
- break;
-
- case 'n': /* already done at pre-scan */
- break;
-
- case 'N': /* already done at pre-scan */
- break;
-
- case 'p':
- stats_config(STATS_PID_FILE, ntp_optarg);
- break;
-
- case 'P':
-#if defined(HAVE_SCHED_SETSCHEDULER)
- config_priority = (int)atol(ntp_optarg);
- config_priority_override = 1;
-#else
+ if (HAVE_OPT( USER )) {
+#ifdef HAVE_DROPROOT
+ char *ntp_optarg = OPT_ARG( USER );
+
+ droproot = 1;
+ user = malloc(strlen(ntp_optarg) + 1);
+ if (user == NULL) {
errflg++;
-#endif
- break;
-
- case 'q':
- mode_ntpdate = TRUE;
- break;
-
- case 'r':
- do {
- double tmp;
-
- if (sscanf(ntp_optarg, "%lf", &tmp) != 1) {
- msyslog(LOG_ERR,
- "command line broadcast delay value %s undecodable",
- ntp_optarg);
- } else {
- proto_config(PROTO_BROADDELAY, 0, tmp, NULL);
- }
- } while (0);
- break;
-
- case 'u':
-#ifdef HAVE_CLOCKCTL
- user = malloc(strlen(ntp_optarg) + 1);
- if ((user == NULL) || (ntp_optarg == NULL))
- errflg++;
+ } else {
(void)strncpy(user, ntp_optarg, strlen(ntp_optarg) + 1);
group = rindex(user, ':');
if (group)
*group++ = '\0'; /* get rid of the ':' */
+ }
#else
- errflg++;
+ errflg++;
#endif
- break;
- case 's':
- stats_config(STATS_STATSDIR, ntp_optarg);
- break;
-
- case 't':
- do {
- u_long tkey;
-
- tkey = (int)atol(ntp_optarg);
- if (tkey <= 0 || tkey > NTP_MAXKEY) {
- msyslog(LOG_ERR,
- "command line trusted key %s is invalid",
- ntp_optarg);
- } else {
- authtrust(tkey, 1);
- }
- } while (0);
- break;
-
- case 'v':
- case 'V':
- set_sys_var(ntp_optarg, strlen(ntp_optarg)+1,
- (u_short) (RW | ((c == 'V') ? DEF : 0)));
- break;
-
- case 'x':
- clock_max = 600;
- break;
+ }
+
+ if (HAVE_OPT( VAR )) {
+ int ct = STACKCT_OPT( VAR );
+ const char** pp = STACKLST_OPT( VAR );
+
+ do {
+ const char* my_ntp_optarg = *pp++;
+
+ set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1,
+ (u_short) (RW));
+ } while (--ct > 0);
+ }
+
+ if (HAVE_OPT( DVAR )) {
+ int ct = STACKCT_OPT( DVAR );
+ const char** pp = STACKLST_OPT( DVAR );
+
+ do {
+ const char* my_ntp_optarg = *pp++;
+
+ set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1,
+ (u_short) (RW | DEF));
+ } while (--ct > 0);
+ }
+
+ if (HAVE_OPT( SLEW ))
+ clock_max = 600;
+
+ if (HAVE_OPT( UPDATEINTERVAL )) {
+ long val = OPT_VALUE_UPDATEINTERVAL;
+
+ if (val >= 0)
+ interface_interval = val;
+ else {
+ msyslog(LOG_ERR,
+ "command line interface update interval %ld must be greater or equal to 0",
+ val);
+ errflg++;
+ }
+ }
#ifdef SIM
- case 'B':
- sscanf(ntp_optarg, "%lf", &ntp_node.bdly);
- break;
+ if (HAVE_OPT( SIMBROADCASTDELAY ))
+ sscanf(OPT_ARG( SIMBROADCASTDELAY ), "%lf", &ntp_node.bdly);
- case 'C':
- sscanf(ntp_optarg, "%lf", &ntp_node.snse);
- break;
+ if (HAVE_OPT( PHASENOISE ))
+ sscanf(OPT_ARG( PHASENOISE ), "%lf", &ntp_node.snse);
- case 'H':
- sscanf(ntp_optarg, "%lf", &ntp_node.slew);
- break;
+ if (HAVE_OPT( SIMSLEW ))
+ sscanf(OPT_ARG( SIMSLEW ), "%lf", &ntp_node.slew);
- case 'O':
- sscanf(ntp_optarg, "%lf", &ntp_node.clk_time);
- break;
+ if (HAVE_OPT( SERVERTIME ))
+ sscanf(OPT_ARG( SERVERTIME ), "%lf", &ntp_node.clk_time);
- case 'S':
- sscanf(ntp_optarg, "%lf", &ntp_node.sim_time);
- break;
+ if (HAVE_OPT( ENDSIMTIME ))
+ sscanf(OPT_ARG( ENDSIMTIME ), "%lf", &ntp_node.sim_time);
- case 'T':
- sscanf(ntp_optarg, "%lf", &ntp_node.ferr);
- break;
+ if (HAVE_OPT( FREQERR ))
+ sscanf(OPT_ARG( FREQERR ), "%lf", &ntp_node.ferr);
- case 'W':
- sscanf(ntp_optarg, "%lf", &ntp_node.fnse);
- break;
+ if (HAVE_OPT( WALKNOISE ))
+ sscanf(OPT_ARG( WALKNOISE ), "%lf", &ntp_node.fnse);
- case 'Y':
- sscanf(ntp_optarg, "%lf", &ntp_node.ndly);
- break;
+ if (HAVE_OPT( NDELAY ))
+ sscanf(OPT_ARG( NDELAY ), "%lf", &ntp_node.ndly);
- case 'Z':
- sscanf(ntp_optarg, "%lf", &ntp_node.pdly);
- break;
+ if (HAVE_OPT( PDELAY ))
+ sscanf(OPT_ARG( PDELAY ), "%lf", &ntp_node.pdly);
#endif /* SIM */
- default:
- errflg++;
- break;
- }
- }
- if (errflg || ntp_optind != argc) {
- (void) fprintf(stderr, "usage: %s [ -abdgmnx ] [ -c config_file ] [ -e e_delay ]\n", progname);
- (void) fprintf(stderr, "\t\t[ -f freq_file ] [ -k key_file ] [ -l log_file ]\n");
- (void) fprintf(stderr, "\t\t[ -p pid_file ] [ -r broad_delay ] [ -s statdir ]\n");
- (void) fprintf(stderr, "\t\t[ -t trust_key ] [ -v sys_var ] [ -V default_sysvar ]\n");
-#if defined(HAVE_SCHED_SETSCHEDULER)
- (void) fprintf(stderr, "\t\t[ -P fixed_process_priority ]\n");
-#endif
-#ifdef HAVE_CLOCKCTL
- (void) fprintf(stderr, "\t\t[ -u user[:group] ] [ -i chrootdir ]\n");
-#endif
- exit(2);
+ if (errflg || argc) {
+ printf("argc is <%d>\n", argc);
+ optionUsage(myOptions, 2);
}
return;
}
diff --git a/contrib/ntp/ntpd/map_vme.c b/contrib/ntp/ntpd/map_vme.c
deleted file mode 100644
index e4569ce..0000000
--- a/contrib/ntp/ntpd/map_vme.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/********************************************************/
-/* map_vme.c */
-/* VME control of TrueTime VME-SG sync gen card */
-/* and TrueTime GPS-VME receiver card */
-/* Version for 700 series HPUX 9.0 */
-/* Richard E.Schmidt, US Naval Observatory, Washington */
-/* 27 March 94 */
-/********************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_GPSVME)
-#include <stdio.h>
-#include <errno.h>
-#include <time.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/file.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <sys/rtprio.h> /* for rtprio */
-#include <sys/lock.h> /* for plock */
-#include "/etc/conf/machine/vme2.h"
-#include "/etc/conf/h/io.h"
-#include "gps.h"
-
-/* GLOBALS */
-void *gps_base;
-unsigned short *greg[NREGS];
-struct vme2_map_addr ma; /* memory mapped structure */
-int fd; /* file descriptor for VME */
-
-void unmap_vme ();
-
-caddr_t
-map_vme (
- char *filename
- )
-{
- int ret;
- caddr_t base;
- struct vme2_io_testx tx;
- caddr_t cp;
-
-#define VME_START_ADDR 0x00000 /* Starting address in A16N VME Space */
-#define VMESIZE 0xFF /* 256 bytes of A16N space length */
-
- /*
- To create the HP9000/700 series device file, /dev/vme2:
- mknod /dev/vme2 c 44 0x0; chmod 600 /dev/vme2
-
- Then must create /etc/vme.CFG and run /etc/vme_config and reboot.
- */
- if ((fd = open (filename, O_RDWR)) < 0) {
- printf("ERROR: VME bus adapter open failed. errno:%d\n",
- errno);
- if(errno == ENODEV) {
- printf("ENODEV. Is driver in kernel? vme2 in dfile?\n");
- }
- exit(errno);
- }
- tx.card_type = VME_A16;
- tx.vme_addr = VME_START_ADDR;
- tx.width = SHORT_WIDE;
-
- if(ioctl(fd, VME2_IO_TESTR, &tx)) {
- printf("ioctl to test VME space failed. Errno: %d\n",
- errno);
- exit(errno);
- }
- if(tx.error)
- printf("io_testr failed internal error %d\n",tx.error);
- if(tx.access_result < 0) {
- printf("io_testr failed\n");
- exit(2);
- }
-
- /* If successful mmap the device */
- /* NOW MAP THE CARD */
- ma.card_type = VME_A16;
- ma.vme_addr = VME_START_ADDR;
- ma.size = VMESIZE;
-
- if(ioctl(fd, VME2_MAP_ADDR, &ma)) {
- printf("ioctl to map VME space failed. Errno: %d\n",
- errno);
- exit(errno);
- }
- if(ma.error) {
- printf("ioctl to map VME failed\n");
- exit(ENOMEM);
- }
- base = ma.user_addr;
- return(base);
-}
-
-
-void
-unmap_vme(void)
-{
- if(ioctl(fd, VME2_UNMAP_ADDR, &ma))
- printf("ioctl to unmap VME space failed. Errno: %d\n",
- errno);
- close(fd);
- return;
-}
-
-
-int
-init_vme(boid)
-{
- /* set up address offsets */
-
- gps_base = map_vme (GPS_VME);
-
-/* offsets from base address: */
-
- greg[0] = (unsigned short *)gps_base + GFRZ1;
- greg[1] = (unsigned short *)gps_base + GUFRZ1;
- greg[2] = (unsigned short *)gps_base + GREG1A;
- greg[3] = (unsigned short *)gps_base + GREG1B;
- greg[4] = (unsigned short *)gps_base + GREG1C;
- greg[5] = (unsigned short *)gps_base + GREG1D;
- greg[6] = (unsigned short *)gps_base + GREG1E;
-
- return (0);
-}
-
-#else /* not (REFCLOCK && CLOCK_GPSVME) */
-int map_vme_bs;
-#endif /* not (REFCLOCK && CLOCK_GPSVME) */
diff --git a/contrib/ntp/ntpd/ntp_config.c b/contrib/ntp/ntpd/ntp_config.c
index f1428b1..beb4c48 100644
--- a/contrib/ntp/ntpd/ntp_config.c
+++ b/contrib/ntp/ntpd/ntp_config.c
@@ -15,8 +15,9 @@
#include "ntp_refclock.h"
#include "ntp_filegen.h"
#include "ntp_stdlib.h"
-#include "ntp_config.h"
-#include "ntp_cmdargs.h"
+#include <ntp_random.h>
+#include <isc/net.h>
+#include <isc/result.h>
#include <stdio.h>
#include <ctype.h>
@@ -35,10 +36,19 @@
#ifdef SYS_WINNT
# include <io.h>
-extern HANDLE ResolverThreadHandle;
+static HANDLE ResolverThreadHandle = NULL;
+HANDLE ResolverEventHandle;
+#else
+int resolver_pipe_fd[2]; /* used to let the resolver process alert the parent process */
#endif /* SYS_WINNT */
-#include <netdb.h>
+/*
+ * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
+ * so #include these later.
+ */
+
+#include "ntp_config.h"
+#include "ntp_cmdargs.h"
extern int priority_done;
@@ -73,6 +83,7 @@ static struct keyword keywords[] = {
{ "disable", CONFIG_DISABLE },
{ "driftfile", CONFIG_DRIFTFILE },
{ "enable", CONFIG_ENABLE },
+ { "end", CONFIG_END },
{ "filegen", CONFIG_FILEGEN },
{ "fudge", CONFIG_FUDGE },
{ "includefile", CONFIG_INCLUDEFILE },
@@ -115,9 +126,12 @@ static struct keyword mod_keywords[] = {
{ "minpoll", CONF_MOD_MINPOLL },
{ "mode", CONF_MOD_MODE }, /* refclocks */
{ "noselect", CONF_MOD_NOSELECT },
+ { "preempt", CONF_MOD_PREEMPT },
+ { "true", CONF_MOD_TRUE },
{ "prefer", CONF_MOD_PREFER },
{ "ttl", CONF_MOD_TTL }, /* NTP peers */
{ "version", CONF_MOD_VERSION },
+ { "dynamic", CONF_MOD_DYNAMIC },
{ "", CONFIG_UNKNOWN }
};
@@ -158,7 +172,7 @@ static struct keyword fudge_keywords[] = {
{ "flag2", CONF_FDG_FLAG2 },
{ "flag3", CONF_FDG_FLAG3 },
{ "flag4", CONF_FDG_FLAG4 },
- { "refid", CONF_FDG_REFID },
+ { "refid", CONF_FDG_REFID }, /* this mapping should be cleaned up (endianness, \0) - kd 20041031 */
{ "stratum", CONF_FDG_STRATUM },
{ "time1", CONF_FDG_TIME1 },
{ "time2", CONF_FDG_TIME2 },
@@ -202,7 +216,6 @@ static struct keyword flags_keywords[] = {
{ "kernel", PROTO_KERNEL },
{ "monitor", PROTO_MONITOR },
{ "ntp", PROTO_NTP },
- { "pps", PROTO_PPS },
{ "stats", PROTO_FILEGEN },
{ "", CONFIG_UNKNOWN }
};
@@ -236,10 +249,16 @@ static struct keyword tinker_keywords[] = {
*/
static struct keyword tos_keywords[] = {
{ "minclock", CONF_TOS_MINCLOCK },
+ { "maxclock", CONF_TOS_MAXCLOCK },
{ "minsane", CONF_TOS_MINSANE },
{ "floor", CONF_TOS_FLOOR },
{ "ceiling", CONF_TOS_CEILING },
{ "cohort", CONF_TOS_COHORT },
+ { "mindist", CONF_TOS_MINDISP },
+ { "maxdist", CONF_TOS_MAXDIST },
+ { "maxhop", CONF_TOS_MAXHOP },
+ { "beacon", CONF_TOS_BEACON },
+ { "orphan", CONF_TOS_ORPHAN },
{ "", CONFIG_UNKNOWN }
};
@@ -251,6 +270,7 @@ static struct keyword crypto_keywords[] = {
{ "cert", CONF_CRYPTO_CERT },
{ "gqpar", CONF_CRYPTO_GQPAR },
{ "host", CONF_CRYPTO_RSA },
+ { "ident", CONF_CRYPTO_IDENT },
{ "iffpar", CONF_CRYPTO_IFFPAR },
{ "leap", CONF_CRYPTO_LEAP },
{ "mvpar", CONF_CRYPTO_MVPAR },
@@ -309,7 +329,7 @@ static struct masks logcfg_item[] = {
*/
#define MAXTOKENS 20 /* 20 tokens on line */
#define MAXLINE 1024 /* maximum length of line */
-#define MAXPHONE 5 /* maximum number of phone strings */
+#define MAXPHONE 10 /* maximum number of phone strings */
#define MAXPPS 20 /* maximum length of PPS device string */
#define MAXINCLUDELEVEL 5 /* maximum include file levels */
@@ -339,10 +359,10 @@ static char res_file[MAX_PATH];
/*
* Definitions of things either imported from or exported to outside
*/
-char const *progname;
-char sys_phone[MAXPHONE][MAXDIAL]; /* ACTS phone numbers */
+
+short default_ai_family = AF_UNSPEC; /* Default either IPv4 or IPv6 */
+char *sys_phone[MAXPHONE] = {NULL}; /* ACTS phone numbers */
char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
-char pps_device[MAXPPS + 1]; /* PPS device name */
#if defined(HAVE_SCHED_SETSCHEDULER)
int config_priority_override = 0;
int config_priority;
@@ -386,7 +406,13 @@ static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
#endif
static int gettokens P((FILE *, char *, char **, int *));
static int matchkey P((char *, struct keyword *, int));
-static int getnetnum P((const char *, struct sockaddr_storage *, int));
+enum gnn_type {
+ t_UNK, /* Unknown */
+ t_REF, /* Refclock */
+ t_MSK /* Network Mask */
+ };
+static int getnetnum P((const char *, struct sockaddr_storage *, int,
+ enum gnn_type));
static void save_resolve P((char *, int, int, int, int, u_int, int,
keyid_t, u_char *));
static void do_resolve_internal P((void));
@@ -472,6 +498,7 @@ getconfig(
register int i;
int c;
int errflg;
+ int status;
int istart;
int peerversion;
int minpoll;
@@ -501,7 +528,7 @@ getconfig(
* Initialize, initialize
*/
errflg = 0;
- /* HMS: don't initialize debug to 0 here! */
+
#ifndef SYS_WINNT
config_file = CONFIG_FILE;
#else
@@ -520,9 +547,7 @@ getconfig(
alt_config_file = alt_config_file_storage;
#endif /* SYS_WINNT */
- progname = argv[0];
res_fp = NULL;
- memset((char *)sys_phone, 0, sizeof(sys_phone));
ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
/*
@@ -573,6 +598,8 @@ getconfig(
}
for (;;) {
+ if (tok == CONFIG_END)
+ break;
if (fp[includelevel])
tok = gettokens(fp[includelevel], line, tokens, &ntokens);
#ifdef HAVE_NETINFO
@@ -612,6 +639,7 @@ getconfig(
istart = 1;
memset((char *)&peeraddr, 0, sizeof(peeraddr));
+ peeraddr.ss_family = default_ai_family;
switch (matchkey(tokens[istart], addr_type, 0)) {
case CONF_ADDR_IPV4:
peeraddr.ss_family = AF_INET;
@@ -623,7 +651,10 @@ getconfig(
break;
}
- if (!getnetnum(tokens[istart], &peeraddr, 0)) {
+ status = getnetnum(tokens[istart], &peeraddr, 0, t_UNK);
+ if (status == -1)
+ break; /* Found IPv6 address */
+ if(status != 1) {
errflg = -1;
} else {
errflg = 0;
@@ -684,7 +715,10 @@ getconfig(
}
}
}
-
+ if (peeraddr.ss_family == AF_INET6 &&
+ isc_net_probeipv6() != ISC_R_SUCCESS)
+ break;
+
peerversion = NTP_VERSION;
minpoll = NTP_MINDPOLL;
maxpoll = NTP_MAXDPOLL;
@@ -760,10 +794,17 @@ getconfig(
peerflags |= FLAG_PREFER;
break;
+ case CONF_MOD_PREEMPT:
+ peerflags |= FLAG_PREEMPT;
+ break;
+
case CONF_MOD_NOSELECT:
peerflags |= FLAG_NOSELECT;
break;
+ case CONF_MOD_TRUE:
+ peerflags |= FLAG_TRUE;
+
case CONF_MOD_BURST:
peerflags |= FLAG_BURST;
break;
@@ -771,6 +812,13 @@ getconfig(
case CONF_MOD_IBURST:
peerflags |= FLAG_IBURST;
break;
+
+ case CONF_MOD_DYNAMIC:
+ msyslog(LOG_WARNING,
+ "Warning: the \"dynamic\" keyword has been obsoleted"
+ " and will be removed in the next release\n");
+ break;
+
#ifdef OPENSSL
case CONF_MOD_SKEY:
peerflags |= FLAG_SKEY |
@@ -821,10 +869,6 @@ getconfig(
"configuration of %s failed",
stoa(&peeraddr));
}
- if (tok == CONFIG_MANYCASTCLIENT)
- proto_config(PROTO_MULTICAST_ADD,
- 0, 0., &peeraddr);
-
} else if (errflg == -1) {
save_resolve(tokens[1], hmode, peerversion,
minpoll, maxpoll, peerflags, ttl,
@@ -837,6 +881,16 @@ getconfig(
stats_config(STATS_FREQ_FILE, tokens[1]);
else
stats_config(STATS_FREQ_FILE, (char *)0);
+ stats_write_period = stats_write_tolerance = 0;
+ if (ntokens >= 3)
+ stats_write_period = 60 * atol(tokens[2]);
+ if (stats_write_period <= 0)
+ stats_write_period = 3600;
+ if (ntokens >= 4) {
+ double ftemp;
+ sscanf(tokens[3], "%lf", &ftemp);
+ stats_write_tolerance = ftemp / 100;
+ }
break;
case CONFIG_PIDFILE:
@@ -846,6 +900,12 @@ getconfig(
stats_config(STATS_PID_FILE, (char *)0);
break;
+ case CONFIG_END:
+ for ( i = 0; i <= includelevel; i++ ) {
+ fclose(fp[i]);
+ }
+ break;
+
case CONFIG_INCLUDEFILE:
if (ntokens < 2) {
msyslog(LOG_ERR, "includefile needs one argument");
@@ -925,7 +985,11 @@ getconfig(
break;
case CONFIG_BROADCASTCLIENT:
- proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
+ if (ntokens == 1) {
+ proto_config(PROTO_BROADCLIENT, 1, 0., NULL);
+ } else {
+ proto_config(PROTO_BROADCLIENT, 2, 0., NULL);
+ }
break;
case CONFIG_MULTICASTCLIENT:
@@ -933,6 +997,7 @@ getconfig(
if (ntokens > 1) {
istart = 1;
memset((char *)&peeraddr, 0, sizeof(peeraddr));
+ peeraddr.ss_family = default_ai_family;
switch (matchkey(tokens[istart],
addr_type, 0)) {
case CONF_ADDR_IPV4:
@@ -955,7 +1020,8 @@ getconfig(
memset((char *)&peeraddr, 0,
sizeof(peeraddr));
peeraddr.ss_family = maskaddr.ss_family;
- if (getnetnum(tokens[i], &peeraddr, 1))
+ if (getnetnum(tokens[i], &peeraddr, 1,
+ t_UNK) == 1)
proto_config(PROTO_MULTICAST_ADD,
0, 0., &peeraddr);
}
@@ -963,7 +1029,7 @@ getconfig(
proto_config(PROTO_MULTICAST_ADD,
0, 0., NULL);
if (tok == CONFIG_MULTICASTCLIENT)
- sys_bclient = 1;
+ proto_config(PROTO_MULTICAST_ADD, 1, 0., NULL);
else if (tok == CONFIG_MANYCASTSERVER)
sys_manycastserver = 1;
break;
@@ -980,7 +1046,7 @@ getconfig(
"Keys directory name required");
break;
}
- keysdir = emalloc(strlen(tokens[1]) + 1);
+ keysdir = (char *)emalloc(strlen(tokens[1]) + 1);
strcpy(keysdir, tokens[1]);
break;
@@ -1038,7 +1104,7 @@ getconfig(
temp = matchkey(tokens[i++], tos_keywords, 1);
if (i > ntokens - 1) {
msyslog(LOG_ERR,
- "tinker: missing argument");
+ "tos: missing argument");
errflg++;
break;
}
@@ -1049,6 +1115,10 @@ getconfig(
proto_config(PROTO_MINCLOCK, 0, ftemp, NULL);
break;
+ case CONF_TOS_MAXCLOCK:
+ proto_config(PROTO_MAXCLOCK, 0, ftemp, NULL);
+ break;
+
case CONF_TOS_MINSANE:
proto_config(PROTO_MINSANE, 0, ftemp, NULL);
break;
@@ -1064,6 +1134,26 @@ getconfig(
case CONF_TOS_COHORT:
proto_config(PROTO_COHORT, 0, ftemp, NULL);
break;
+
+ case CONF_TOS_MINDISP:
+ proto_config(PROTO_MINDISP, 0, ftemp, NULL);
+ break;
+
+ case CONF_TOS_MAXDIST:
+ proto_config(PROTO_MAXDIST, 0, ftemp, NULL);
+ break;
+
+ case CONF_TOS_MAXHOP:
+ proto_config(PROTO_MAXHOP, 0, ftemp, NULL);
+ break;
+
+ case CONF_TOS_ORPHAN:
+ proto_config(PROTO_ORPHAN, 0, ftemp, NULL);
+ break;
+
+ case CONF_TOS_BEACON:
+ proto_config(PROTO_BEACON, 0, ftemp, NULL);
+ break;
}
}
break;
@@ -1089,15 +1179,15 @@ getconfig(
}
switch(temp) {
case CONF_DISCARD_AVERAGE:
- res_avg_interval = atoi(tokens[i++]);
+ res_avg_interval = atoi(tokens[i]);
break;
case CONF_DISCARD_MINIMUM:
- res_min_interval = atoi(tokens[i++]);
+ res_min_interval = atoi(tokens[i]);
break;
case CONF_DISCARD_MONITOR:
- mon_age = atoi(tokens[i++]);
+ mon_age = atoi(tokens[i]);
break;
default:
@@ -1147,6 +1237,11 @@ getconfig(
tokens[i]);
break;
+ case CONF_CRYPTO_IDENT:
+ crypto_config(CRYPTO_CONF_IDENT,
+ tokens[i]);
+ break;
+
case CONF_CRYPTO_IFFPAR:
crypto_config(CRYPTO_CONF_IFFPAR,
tokens[i]);
@@ -1198,6 +1293,7 @@ getconfig(
}
istart = 1;
memset((char *)&peeraddr, 0, sizeof(peeraddr));
+ peeraddr.ss_family = default_ai_family;
switch (matchkey(tokens[istart], addr_type, 0)) {
case CONF_ADDR_IPV4:
peeraddr.ss_family = AF_INET;
@@ -1216,7 +1312,8 @@ getconfig(
if (STREQ(tokens[istart], "default")) {
if (peeraddr.ss_family == 0)
peeraddr.ss_family = AF_INET;
- } else if (!getnetnum(tokens[istart], &peeraddr, 1))
+ } else if (getnetnum(tokens[istart], &peeraddr, 1,
+ t_UNK) != 1)
break;
/*
@@ -1237,7 +1334,8 @@ getconfig(
break;
}
i++;
- if (!getnetnum(tokens[i], &maskaddr, 1))
+ if (getnetnum(tokens[i], &maskaddr, 1,
+ t_MSK) != 1)
errflg++;
break;
@@ -1386,6 +1484,7 @@ getconfig(
}
istart = 1;
memset((char *)&peeraddr, 0, sizeof(peeraddr));
+ peeraddr.ss_family = default_ai_family;
switch (matchkey(tokens[istart], addr_type, 0)) {
case CONF_ADDR_IPV4:
peeraddr.ss_family = AF_INET;
@@ -1397,7 +1496,7 @@ getconfig(
break;
}
- if (!getnetnum(tokens[istart], &peeraddr, 1))
+ if (getnetnum(tokens[istart], &peeraddr, 1, t_UNK) != 1)
break;
/*
@@ -1437,8 +1536,8 @@ getconfig(
memset((char *)&maskaddr, 0,
sizeof(maskaddr));
maskaddr.ss_family = peeraddr.ss_family;
- if (!getnetnum(tokens[++i],
- &maskaddr, 1)) {
+ if (getnetnum(tokens[++i],
+ &maskaddr, 1, t_UNK) != 1) {
errflg = 1;
break;
}
@@ -1479,7 +1578,7 @@ getconfig(
break;
}
memset((char *)&peeraddr, 0, sizeof(peeraddr));
- if (!getnetnum(tokens[1], &peeraddr, 1))
+ if (getnetnum(tokens[1], &peeraddr, 1, t_REF) != 1)
break;
if (!ISREFCLOCKADR(&peeraddr)) {
@@ -1534,10 +1633,10 @@ getconfig(
break;
case CONF_FDG_REFID:
- /* HMS: Endianness and 0 bytes? */
- /* XXX */
- strncpy((char *)&clock_stat.fudgeval2,
- tokens[++i], 4);
+ i++;
+ memcpy(&clock_stat.fudgeval2,
+ tokens[i], min(strlen(tokens[i]),
+ 4));
clock_stat.haveflags |= CLK_HAVEVAL2;
break;
@@ -1746,11 +1845,12 @@ getconfig(
break;
case CONFIG_PHONE:
- for (i = 1; i < ntokens && i < MAXPHONE; i++) {
- (void)strncpy(sys_phone[i - 1],
- tokens[i], MAXDIAL);
+ for (i = 1; i < ntokens && i < MAXPHONE - 1; i++) {
+ sys_phone[i - 1] =
+ emalloc(strlen(tokens[i]) + 1);
+ strcpy(sys_phone[i - 1], tokens[i]);
}
- sys_phone[i - 1][0] = '\0';
+ sys_phone[i] = NULL;
break;
case CONFIG_ADJ: {
@@ -1785,7 +1885,7 @@ getconfig(
for (i = 0; i < 8; i++)
for (j = 1; j < 100; ++j) {
- rankey[i] = (char) (RANDOM & 0xff);
+ rankey[i] = (char) (ntp_random() & 0xff);
if (rankey[i] != 0) break;
}
rankey[8] = 0;
@@ -1952,9 +2052,17 @@ gettokens_netinfo (
if (ISEOL(*tokens)) break;
}
}
- *ntokens = ntok + 1;
-
- config->val_index++;
+
+ if (ntok == MAXTOKENS) {
+ /* HMS: chomp it to lose the EOL? */
+ msyslog(LOG_ERR,
+ "gettokens_netinfo: too many tokens. Ignoring: %s",
+ tokens);
+ } else {
+ *ntokens = ntok + 1;
+ }
+
+ config->val_index++; /* HMS: Should this be in the 'else'? */
return keywords[prop_index].keytype;
}
@@ -2024,13 +2132,40 @@ gettokens (
}
}
- /*
- * Return the match
- */
- *ntokens = ntok + 1;
- ntok = matchkey(tokenlist[0], keywords, 1);
- if (ntok == CONFIG_UNKNOWN)
- goto again;
+ /* Heiko: Remove leading and trailing quotes around tokens */
+ {
+ int i,j = 0;
+
+
+ for (i = 0; i < ntok; i++) {
+ /* Now check if the first char is a quote and remove that */
+ if ( tokenlist[ntok][0] == '"' )
+ tokenlist[ntok]++;
+
+ /* Now check the last char ... */
+ j = strlen(tokenlist[ntok])-1;
+ if ( tokenlist[ntok][j] == '"' )
+ tokenlist[ntok][j] = '\0';
+ }
+
+ }
+
+ if (ntok == MAXTOKENS) {
+ --ntok;
+ /* HMS: chomp it to lose the EOL? */
+ msyslog(LOG_ERR,
+ "gettokens: too many tokens on the line. Ignoring %s",
+ cp);
+ } else {
+ /*
+ * Return the match
+ */
+ *ntokens = ntok + 1;
+ ntok = matchkey(tokenlist[0], keywords, 1);
+ if (ntok == CONFIG_UNKNOWN)
+ goto again;
+ }
+
return ntok;
}
@@ -2068,11 +2203,26 @@ static int
getnetnum(
const char *num,
struct sockaddr_storage *addr,
- int complain
+ int complain,
+ enum gnn_type a_type
)
{
struct addrinfo hints;
struct addrinfo *ptr;
+ int retval;
+
+#if 0
+ printf("getnetnum: <%s> is a %s (%d)\n",
+ num,
+ (a_type == t_UNK)
+ ? "t_UNK"
+ : (a_type == t_REF)
+ ? "t_REF"
+ : (a_type == t_MSK)
+ ? "t_MSK"
+ : "???",
+ a_type);
+#endif
/* Get host address. Looking for UDP datagram connection */
memset(&hints, 0, sizeof (hints));
@@ -2080,33 +2230,61 @@ getnetnum(
hints.ai_family = addr->ss_family;
else
hints.ai_family = AF_UNSPEC;
+ /*
+ * If we don't have an IPv6 stack, just look up IPv4 addresses
+ */
+ if (isc_net_probeipv6() != ISC_R_SUCCESS)
+ hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
+
+ if (a_type != t_UNK) {
+ hints.ai_flags = AI_NUMERICHOST;
+ }
+
#ifdef DEBUG
- if (debug > 3)
- printf("getaddrinfo %s\n", num);
+ if (debug > 3)
+ printf("getnetnum: calling getaddrinfo(%s,...)\n", num);
#endif
- if (getaddrinfo(num, "ntp", &hints, &ptr)!=0) {
+ retval = getaddrinfo(num, "ntp", &hints, &ptr);
+ if (retval != 0 ||
+ (ptr->ai_family == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) {
if (complain)
msyslog(LOG_ERR,
- "getaddrinfo: \"%s\" invalid host address, line ignored",
+ "getaddrinfo: \"%s\" invalid host address, ignored",
num);
#ifdef DEBUG
- if (debug > 3)
+ if (debug > 0)
printf(
"getaddrinfo: \"%s\" invalid host address%s.\n",
num, (complain)
- ? ", line ignored"
+ ? ", ignored"
: "");
#endif
- return 0;
+ if (retval == 0 &&
+ ptr->ai_family == AF_INET6 &&
+ isc_net_probeipv6() != ISC_R_SUCCESS)
+ {
+ return -1;
+ }
+ else {
+ return 0;
+ }
}
memcpy(addr, ptr->ai_addr, ptr->ai_addrlen);
#ifdef DEBUG
if (debug > 1)
- printf("getnetnum given %s, got %s \n",
- num, stoa(addr));
+ printf("getnetnum given %s, got %s (%s/%d)\n",
+ num, stoa(addr),
+ (a_type == t_UNK)
+ ? "t_UNK"
+ : (a_type == t_REF)
+ ? "t_REF"
+ : (a_type == t_MSK)
+ ? "t_MSK"
+ : "???",
+ a_type);
#endif
freeaddrinfo(ptr);
return 1;
@@ -2259,7 +2437,22 @@ do_resolve_internal(void)
(void) signal_no_reset(SIGCHLD, catchchild);
#ifndef SYS_VXWORKS
+ /* the parent process will write to the pipe
+ * in order to wake up to child process
+ * which may be waiting in a select() call
+ * on the read fd */
+ if (pipe(resolver_pipe_fd) < 0) {
+ msyslog(LOG_ERR,
+ "unable to open resolver pipe");
+ exit(1);
+ }
+
i = fork();
+ /* Shouldn't the code below be re-ordered?
+ * I.e. first check if the fork() returned an error, then
+ * check whether we're parent or child.
+ * Martin Burnicki
+ */
if (i == 0) {
/*
* this used to close everything
@@ -2294,6 +2487,9 @@ do_resolve_internal(void)
* THUS:
*/
+ /* This is the child process who will read the pipe,
+ * so we close the write fd */
+ close(resolver_pipe_fd[1]);
closelog();
kill_asyncio(0);
@@ -2342,6 +2538,11 @@ do_resolve_internal(void)
(void) signal_no_reset(SIGCHLD, SIG_DFL);
abort_resolve();
}
+ else {
+ /* This is the parent process who will write to the pipe,
+ * so we close the read fd */
+ close(resolver_pipe_fd[0]);
+ }
#else /* SYS_WINNT */
{
/* NT's equivalent of fork() is _spawn(), but the start point
@@ -2350,6 +2551,11 @@ do_resolve_internal(void)
*/
DWORD dwThreadId;
fflush(stdout);
+ ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (ResolverEventHandle == NULL) {
+ msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
+ abort_resolve();
+ }
ResolverThreadHandle = CreateThread(
NULL, /* no security attributes */
0, /* use default stack size */
@@ -2359,6 +2565,8 @@ do_resolve_internal(void)
&dwThreadId); /* returns the thread identifier */
if (ResolverThreadHandle == NULL) {
msyslog(LOG_ERR, "CreateThread() failed, can't start ntp_intres");
+ CloseHandle(ResolverEventHandle);
+ ResolverEventHandle = NULL;
abort_resolve();
}
}
diff --git a/contrib/ntp/ntpd/ntp_control.c b/contrib/ntp/ntpd/ntp_control.c
index cbcc8375..15f5856 100644
--- a/contrib/ntp/ntpd/ntp_control.c
+++ b/contrib/ntp/ntpd/ntp_control.c
@@ -14,6 +14,7 @@
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_control.h"
+#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
#include <stdio.h>
@@ -64,6 +65,9 @@ static void ctl_putid P((const char *, char *));
static void ctl_putarray P((const char *, double *, int));
static void ctl_putsys P((int));
static void ctl_putpeer P((int, struct peer *));
+#ifdef OPENSSL
+static void ctl_putfs P((const char *, tstamp_t));
+#endif
#ifdef REFCLOCK
static void ctl_putclock P((int, struct refclockstat *, int));
#endif /* REFCLOCK */
@@ -111,23 +115,26 @@ static struct ctl_var sys_var[] = {
{ CS_OFFSET, RO, "offset" }, /* 11 */
{ CS_DRIFT, RO, "frequency" }, /* 12 */
{ CS_JITTER, RO, "jitter" }, /* 13 */
- { CS_CLOCK, RO, "clock" }, /* 14 */
- { CS_PROCESSOR, RO, "processor" }, /* 15 */
- { CS_SYSTEM, RO, "system" }, /* 16 */
- { CS_VERSION, RO, "version" }, /* 17 */
- { CS_STABIL, RO, "stability" }, /* 18 */
- { CS_VARLIST, RO, "sys_var_list" }, /* 19 */
+ { CS_ERROR, RO, "noise" }, /* 14 */
+ { CS_CLOCK, RO, "clock" }, /* 15 */
+ { CS_PROCESSOR, RO, "processor" }, /* 16 */
+ { CS_SYSTEM, RO, "system" }, /* 17 */
+ { CS_VERSION, RO, "version" }, /* 18 */
+ { CS_STABIL, RO, "stability" }, /* 19 */
+ { CS_VARLIST, RO, "sys_var_list" }, /* 20 */
#ifdef OPENSSL
- { CS_FLAGS, RO, "flags" }, /* 20 */
- { CS_HOST, RO, "hostname" }, /* 21 */
- { CS_PUBLIC, RO, "hostkey" }, /* 22 */
- { CS_CERTIF, RO, "cert" }, /* 23 */
- { CS_REVTIME, RO, "refresh" }, /* 24 */
- { CS_LEAPTAB, RO, "leapseconds" }, /* 25 */
- { CS_TAI, RO, "tai" }, /* 26 */
- { CS_DIGEST, RO, "signature" }, /* 27 */
+ { CS_FLAGS, RO, "flags" }, /* 21 */
+ { CS_HOST, RO, "hostname" }, /* 22 */
+ { CS_PUBLIC, RO, "update" }, /* 23 */
+ { CS_CERTIF, RO, "cert" }, /* 24 */
+ { CS_REVTIME, RO, "expire" }, /* 25 */
+ { CS_LEAPTAB, RO, "leapsec" }, /* 26 */
+ { CS_TAI, RO, "tai" }, /* 27 */
+ { CS_DIGEST, RO, "signature" }, /* 28 */
+ { CS_IDENT, RO, "ident" }, /* 29 */
+ { CS_REVOKE, RO, "expire" }, /* 30 */
#endif /* OPENSSL */
- { 0, EOV, "" } /* 28 */
+ { 0, EOV, "" } /* 21/31 */
};
static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
@@ -154,14 +161,16 @@ static u_char def_sys_var[] = {
CS_OFFSET,
CS_DRIFT,
CS_JITTER,
+ CS_ERROR,
CS_STABIL,
#ifdef OPENSSL
CS_HOST,
CS_DIGEST,
CS_FLAGS,
CS_PUBLIC,
- CS_REVTIME,
+ CS_IDENT,
CS_LEAPTAB,
+ CS_TAI,
CS_CERTIF,
#endif /* OPENSSL */
0
@@ -194,7 +203,7 @@ static struct ctl_var peer_var[] = {
{ CP_REC, RO, "rec" }, /* 19 */
{ CP_XMT, RO, "xmt" }, /* 20 */
{ CP_REACH, RO, "reach" }, /* 21 */
- { CP_VALID, RO, "unreach" }, /* 22 */
+ { CP_UNREACH, RO, "unreach" }, /* 22 */
{ CP_TIMER, RO, "timer" }, /* 23 */
{ CP_DELAY, RO, "delay" }, /* 24 */
{ CP_OFFSET, RO, "offset" }, /* 25 */
@@ -209,18 +218,18 @@ static struct ctl_var peer_var[] = {
{ CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
{ CP_FLASH, RO, "flash" }, /* 35 */
{ CP_TTL, RO, "ttl" }, /* 36 */
- { CP_RANK, RO, "rank" }, /* 37 */
- { CP_VARLIST, RO, "peer_var_list" }, /* 38 */
+ { CP_VARLIST, RO, "peer_var_list" }, /* 37 */
#ifdef OPENSSL
- { CP_FLAGS, RO, "flags" }, /* 39 */
- { CP_HOST, RO, "hostname" }, /* 40 */
+ { CP_FLAGS, RO, "flags" }, /* 38 */
+ { CP_HOST, RO, "hostname" }, /* 39 */
+ { CP_VALID, RO, "valid" }, /* 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 */
+ { CP_IDENT, RO, "trust" }, /* 45 */
#endif /* OPENSSL */
- { 0, EOV, "" } /* 39/46 */
+ { 0, EOV, "" } /* 38/46 */
};
@@ -239,7 +248,7 @@ static u_char def_peer_var[] = {
CP_ROOTDISPERSION,
CP_REFID,
CP_REACH,
- CP_VALID,
+ CP_UNREACH,
CP_HMODE,
CP_PMODE,
CP_HPOLL,
@@ -261,6 +270,7 @@ static u_char def_peer_var[] = {
#ifdef OPENSSL
CP_HOST,
CP_DIGEST,
+ CP_VALID,
CP_FLAGS,
CP_IDENT,
CP_INITSEQ,
@@ -358,11 +368,11 @@ int num_ctl_traps;
static u_char clocktypes[] = {
CTL_SST_TS_NTP, /* REFCLK_NONE (0) */
CTL_SST_TS_LOCAL, /* REFCLK_LOCALCLOCK (1) */
- CTL_SST_TS_UHF, /* REFCLK_GPS_TRAK (2) */
+ CTL_SST_TS_UHF, /* deprecated REFCLK_GPS_TRAK (2) */
CTL_SST_TS_HF, /* REFCLK_WWV_PST (3) */
CTL_SST_TS_LF, /* REFCLK_WWVB_SPECTRACOM (4) */
CTL_SST_TS_UHF, /* REFCLK_TRUETIME (5) */
- CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) */
+ CTL_SST_TS_UHF, /* REFCLK_GOES_TRAK (6) IRIG_AUDIO? */
CTL_SST_TS_HF, /* REFCLK_CHU (7) */
CTL_SST_TS_LF, /* REFCLOCK_PARSE (default) (8) */
CTL_SST_TS_LF, /* REFCLK_GPS_MX4200 (9) */
@@ -370,8 +380,8 @@ static u_char clocktypes[] = {
CTL_SST_TS_UHF, /* REFCLK_GPS_ARBITER (11) */
CTL_SST_TS_UHF, /* REFCLK_IRIG_TPRO (12) */
CTL_SST_TS_ATOM, /* REFCLK_ATOM_LEITCH (13) */
- CTL_SST_TS_LF, /* REFCLK_MSF_EES (14) */
- CTL_SST_TS_UHF, /* REFCLK_TRUETIME (15) */
+ CTL_SST_TS_LF, /* deprecated REFCLK_MSF_EES (14) */
+ CTL_SST_TS_NTP, /* not used (15) */
CTL_SST_TS_UHF, /* REFCLK_IRIG_BANCOMM (16) */
CTL_SST_TS_UHF, /* REFCLK_GPS_DATU (17) */
CTL_SST_TS_TELEPHONE, /* REFCLK_NIST_ACTS (18) */
@@ -379,9 +389,9 @@ static u_char clocktypes[] = {
CTL_SST_TS_UHF, /* REFCLK_GPS_NMEA (20) */
CTL_SST_TS_UHF, /* REFCLK_GPS_VME (21) */
CTL_SST_TS_ATOM, /* REFCLK_ATOM_PPS (22) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_PTB_ACTS (23) */
- CTL_SST_TS_TELEPHONE, /* REFCLK_USNO (24) */
- CTL_SST_TS_UHF, /* REFCLK_TRUETIME (25) */
+ CTL_SST_TS_NTP, /* not used (23) */
+ CTL_SST_TS_NTP, /* not used (24) */
+ CTL_SST_TS_NTP, /* not used (25) */
CTL_SST_TS_UHF, /* REFCLK_GPS_HP (26) */
CTL_SST_TS_TELEPHONE, /* REFCLK_ARCRON_MSF (27) */
CTL_SST_TS_TELEPHONE, /* REFCLK_SHM (28) */
@@ -389,8 +399,8 @@ static u_char clocktypes[] = {
CTL_SST_TS_UHF, /* REFCLK_ONCORE (30) */
CTL_SST_TS_UHF, /* REFCLK_JUPITER (31) */
CTL_SST_TS_LF, /* REFCLK_CHRONOLOG (32) */
- CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (32) */
- CTL_SST_TS_LF, /* REFCLK_ULINK (33) */
+ CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (33) */
+ CTL_SST_TS_LF, /* REFCLK_ULINK (34) */
CTL_SST_TS_LF, /* REFCLK_PCF (35) */
CTL_SST_TS_LF, /* REFCLK_WWV (36) */
CTL_SST_TS_LF, /* REFCLK_FG (37) */
@@ -757,6 +767,7 @@ ctlsysstatus(void)
register u_char this_clock;
this_clock = CTL_SST_TS_UNSPEC;
+#ifdef REFCLOCK
if (sys_peer != 0) {
if (sys_peer->sstclktype != CTL_SST_TS_UNSPEC) {
this_clock = sys_peer->sstclktype;
@@ -770,6 +781,7 @@ ctlsysstatus(void)
this_clock |= CTL_SST_TS_PPS;
}
}
+#endif /* REFCLOCK */
return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
ctl_sys_num_events, ctl_sys_last_event);
}
@@ -996,6 +1008,41 @@ ctl_putuint(
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
+/*
+ * ctl_putfs - write a decoded filestamp into the response
+ */
+#ifdef OPENSSL
+static void
+ctl_putfs(
+ const char *tag,
+ tstamp_t uval
+ )
+{
+ register char *cp;
+ register const char *cq;
+ char buffer[200];
+ struct tm *tm = NULL;
+ time_t fstamp;
+
+ cp = buffer;
+ cq = tag;
+ while (*cq != '\0')
+ *cp++ = *cq++;
+
+ *cp++ = '=';
+ fstamp = uval - JAN_1970;
+ tm = gmtime(&fstamp);
+ if (tm == NULL)
+ return;
+
+ sprintf(cp, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
+ while (*cp != '\0')
+ cp++;
+ ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
+}
+#endif
+
/*
* ctl_puthex - write a tagged unsigned integer, in hex, into the response
@@ -1068,8 +1115,9 @@ ctl_putts(
*cp++ = *cq++;
*cp++ = '=';
- (void) sprintf(cp, "0x%08lx.%08lx", ts->l_ui & 0xffffffffL,
- ts->l_uf & 0xffffffffL);
+ (void) sprintf(cp, "0x%08lx.%08lx",
+ ts->l_ui & ULONG_CONST(0xffffffff),
+ ts->l_uf & ULONG_CONST(0xffffffff));
while (*cp != '\0')
cp++;
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
@@ -1105,7 +1153,6 @@ ctl_putadr(
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
-
/*
* ctl_putid - write a tagged clock ID into the response
*/
@@ -1242,6 +1289,10 @@ ctl_putsys(
ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
break;
+ case CS_ERROR:
+ ctl_putdbl(sys_var[CS_ERROR].text, clock_jitter * 1e3);
+ break;
+
case CS_CLOCK:
get_systime(&tmp);
ctl_putts(sys_var[CS_CLOCK].text, &tmp);
@@ -1366,32 +1417,46 @@ ctl_putsys(
case CS_CERTIF:
for (cp = cinfo; cp != NULL; cp = cp->link) {
- sprintf(cbuf, "%s %s 0x%x %u", cp->subject,
- cp->issuer, cp->flags,
- ntohl(cp->cert.fstamp));
+ sprintf(cbuf, "%s %s 0x%x", cp->subject,
+ cp->issuer, cp->flags);
ctl_putstr(sys_var[CS_CERTIF].text, cbuf,
strlen(cbuf));
+ ctl_putfs(sys_var[CS_REVOKE].text, cp->last);
}
break;
case CS_PUBLIC:
if (hostval.fstamp != 0)
- ctl_putuint(sys_var[CS_PUBLIC].text,
- ntohl(hostval.fstamp));
+ ctl_putfs(sys_var[CS_PUBLIC].text,
+ ntohl(hostval.tstamp));
break;
case CS_REVTIME:
if (hostval.tstamp != 0)
- ctl_putuint(sys_var[CS_REVTIME].text,
+ ctl_putfs(sys_var[CS_REVTIME].text,
ntohl(hostval.tstamp));
break;
+ case CS_IDENT:
+ if (iffpar_pkey != NULL)
+ ctl_putstr(sys_var[CS_IDENT].text,
+ iffpar_file, strlen(iffpar_file));
+ if (gqpar_pkey != NULL)
+ ctl_putstr(sys_var[CS_IDENT].text,
+ gqpar_file, strlen(gqpar_file));
+ if (mvpar_pkey != NULL)
+ ctl_putstr(sys_var[CS_IDENT].text,
+ mvpar_file, strlen(mvpar_file));
+ break;
+
case CS_LEAPTAB:
if (tai_leap.fstamp != 0)
- ctl_putuint(sys_var[CS_LEAPTAB].text,
+ ctl_putfs(sys_var[CS_LEAPTAB].text,
ntohl(tai_leap.fstamp));
- if (sys_tai != 0)
- ctl_putuint(sys_var[CS_TAI].text, sys_tai);
+ break;
+
+ case CS_TAI:
+ ctl_putuint(sys_var[CS_TAI].text, sys_tai);
break;
#endif /* OPENSSL */
}
@@ -1407,6 +1472,7 @@ ctl_putpeer(
struct peer *peer
)
{
+ int temp;
#ifdef OPENSSL
char str[256];
struct autokey *ap;
@@ -1440,8 +1506,13 @@ ctl_putpeer(
break;
case CP_DSTADR:
- ctl_putadr(peer_var[CP_DSTADR].text, 0,
- &(peer->dstadr->sin));
+ if (peer->dstadr) {
+ ctl_putadr(peer_var[CP_DSTADR].text, 0,
+ &(peer->dstadr->sin));
+ } else {
+ ctl_putadr(peer_var[CP_DSTADR].text, 0,
+ NULL);
+ }
break;
case CP_DSTPORT:
@@ -1487,13 +1558,8 @@ ctl_putpeer(
case CP_REFID:
if (peer->flags & FLAG_REFCLOCK) {
- if (peer->stratum > 0 && peer->stratum <
- STRATUM_UNSPEC)
- ctl_putadr(peer_var[CP_REFID].text,
- peer->refid, NULL);
- else
- ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
+ ctl_putid(peer_var[CP_REFID].text,
+ (char *)&peer->refid);
} else {
if (peer->stratum > 1 && peer->stratum <
STRATUM_UNSPEC)
@@ -1526,19 +1592,16 @@ ctl_putpeer(
break;
case CP_FLASH:
- ctl_puthex(peer_var[CP_FLASH].text, peer->flash);
+ temp = peer->flash;
+ ctl_puthex(peer_var[CP_FLASH].text, temp);
break;
case CP_TTL:
ctl_putint(peer_var[CP_TTL].text, sys_ttl[peer->ttl]);
break;
- case CP_VALID:
- ctl_putuint(peer_var[CP_VALID].text, peer->unreach);
- break;
-
- case CP_RANK:
- ctl_putuint(peer_var[CP_RANK].text, peer->rank);
+ case CP_UNREACH:
+ ctl_putuint(peer_var[CP_UNREACH].text, peer->unreach);
break;
case CP_TIMER:
@@ -1556,8 +1619,7 @@ ctl_putpeer(
break;
case CP_JITTER:
- ctl_putdbl(peer_var[CP_JITTER].text,
- SQRT(peer->jitter) * 1e3);
+ ctl_putdbl(peer_var[CP_JITTER].text, peer->jitter * 1e3);
break;
case CP_DISPERSION:
@@ -1653,14 +1715,17 @@ ctl_putpeer(
case CP_HOST:
if (peer->subject != NULL)
- ctl_putstr(peer_var[CP_HOST].text, peer->subject,
- strlen(peer->subject));
+ ctl_putstr(peer_var[CP_HOST].text,
+ peer->subject, strlen(peer->subject));
+ break;
+
+ case CP_VALID: /* not used */
break;
case CP_IDENT:
if (peer->issuer != NULL)
- ctl_putstr(peer_var[CP_IDENT].text, peer->issuer,
- strlen(peer->issuer));
+ ctl_putstr(peer_var[CP_IDENT].text,
+ peer->issuer, strlen(peer->issuer));
break;
case CP_INITSEQ:
@@ -1668,7 +1733,7 @@ ctl_putpeer(
break;
ctl_putint(peer_var[CP_INITSEQ].text, ap->seq);
ctl_puthex(peer_var[CP_INITKEY].text, ap->key);
- ctl_putuint(peer_var[CP_INITTSP].text,
+ ctl_putfs(peer_var[CP_INITTSP].text,
ntohl(peer->recval.tstamp));
break;
#endif /* OPENSSL */
@@ -1895,14 +1960,24 @@ ctl_getitem(
cp++;
while (cp < reqend && *cp != ',') {
*tp++ = *cp++;
- if (tp >= buf + sizeof(buf))
+ if (tp >= buf + sizeof(buf)) {
+ ctl_error(CERR_BADFMT);
+ numctlbadpkts++;
+#if 0 /* Avoid possible DOS attack */
+/* If we get a smarter msyslog we can re-enable this */
+ msyslog(LOG_WARNING,
+ "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
+ stoa(rmt_addr), SRCPORT(rmt_addr)
+ );
+#endif
return (0);
+ }
}
if (cp < reqend)
cp++;
*tp-- = '\0';
while (tp >= buf) {
- if (!isspace((unsigned char)(*tp)))
+ if (!isspace((unsigned int)(*tp)))
break;
*tp-- = '\0';
}
@@ -1978,7 +2053,7 @@ read_status(
n = 0;
rpkt.status = htons(ctlsysstatus());
- for (i = 0; i < HASH_SIZE; i++) {
+ for (i = 0; i < NTP_HASH_SIZE; i++) {
for (peer = assoc_hash[i]; peer != 0;
peer = peer->ass_next) {
ass_stat[n++] = htons(peer->associd);
@@ -2273,7 +2348,7 @@ read_clock_status(
peer = sys_peer;
} else {
peer = 0;
- for (i = 0; peer == 0 && i < HASH_SIZE; i++) {
+ for (i = 0; peer == 0 && i < NTP_HASH_SIZE; i++) {
for (peer = assoc_hash[i]; peer != 0;
peer = peer->ass_next) {
if (peer->flags & FLAG_REFCLOCK)
@@ -2904,7 +2979,7 @@ set_var(
void
set_sys_var(
- char *data,
+ const char *data,
u_long size,
u_short def
)
diff --git a/contrib/ntp/ntpd/ntp_crypto.c b/contrib/ntp/ntpd/ntp_crypto.c
index 3e67703..84adbdd 100644
--- a/contrib/ntp/ntpd/ntp_crypto.c
+++ b/contrib/ntp/ntpd/ntp_crypto.c
@@ -16,6 +16,7 @@
#include "ntp_stdlib.h"
#include "ntp_unixtime.h"
#include "ntp_string.h"
+#include <ntp_random.h>
#include "openssl/asn1_mac.h"
#include "openssl/bn.h"
@@ -98,7 +99,6 @@
* Global cryptodata in host byte order
*/
u_int32 crypto_flags = 0x0; /* status word */
-u_int sys_tai; /* current UTC offset from TAI */
/*
* Global cryptodata in network byte order
@@ -107,6 +107,12 @@ struct cert_info *cinfo = NULL; /* certificate info/value */
struct value hostval; /* host value */
struct value pubkey; /* public key */
struct value tai_leap; /* leapseconds table */
+EVP_PKEY *iffpar_pkey = NULL; /* IFF parameters */
+EVP_PKEY *gqpar_pkey = NULL; /* GQ parameters */
+EVP_PKEY *mvpar_pkey = NULL; /* MV parameters */
+char *iffpar_file = NULL; /* IFF parameters file */
+char *gqpar_file = NULL; /* GQ parameters file */
+char *mvpar_file = NULL; /* MV parameters file */
/*
* Private cryptodata in host byte order
@@ -114,22 +120,17 @@ 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 if_fstamp = 0; /* IFF filestamp */
static tstamp_t gq_fstamp = 0; /* GQ file stamp */
-static tstamp_t mv_fstamp = 0; /* MV file stamp */
+static tstamp_t mv_fstamp = 0; /* MV filestamp */
+static u_int ident_scheme = 0; /* server identity scheme */
/*
* Cryptotypes
@@ -192,6 +193,9 @@ session_key(
u_int32 header[10]; /* data in network byte order */
u_int hdlen, len;
+ if (!dstadr)
+ return 0;
+
/*
* Generate the session key and key ID. If the lifetime is
* greater than zero, install the key and call it trusted.
@@ -205,6 +209,7 @@ session_key(
header[3] = htonl(private);
hdlen = 4 * sizeof(u_int32);
break;
+
case AF_INET6:
memcpy(&header[0], &GET_INADDR6(*srcadr),
sizeof(struct in6_addr));
@@ -238,13 +243,17 @@ session_key(
/*
* make_keylist - generate key list
*
+ * Returns
+ * XEVNT_OK success
+ * XEVNT_PER host certificate expired
+ *
* This routine constructs a pseudo-random sequence by repeatedly
* hashing the session key starting from a given source address,
* destination address, private value and the next key ID of the
* preceeding session key. The last entry on the list is saved along
* with its sequence number and public signature.
*/
-void
+int
make_keylist(
struct peer *peer, /* peer structure pointer */
struct interface *dstadr /* interface */
@@ -257,9 +266,12 @@ make_keylist(
keyid_t keyid = 0; /* next key ID */
keyid_t cookie; /* private value */
u_long lifetime;
- u_int len;
+ u_int len, mpoll;
int i;
+ if (!dstadr)
+ return XEVNT_OK;
+
/*
* Allocate the key list if necessary.
*/
@@ -273,9 +285,8 @@ make_keylist(
* NTP_MAXKEY.
*/
while (1) {
- keyid = (u_long)RANDOM & 0xffffffff;
- if (keyid <= NTP_MAXKEY)
- continue;
+ keyid = (ntp_random() + NTP_MAXKEY + 1) & ((1 <<
+ sizeof(keyid_t)) - 1);
if (authhavekey(keyid))
continue;
break;
@@ -288,7 +299,8 @@ make_keylist(
* included in the hash is zero if broadcast mode, the peer
* cookie if client mode or the host cookie if symmetric modes.
*/
- lifetime = min(sys_automax, (unsigned long) NTP_MAXSESSION * (1 <<(peer->kpoll)));
+ mpoll = 1 << min(peer->ppoll, peer->hpoll);
+ lifetime = min(sys_automax, NTP_MAXSESSION * mpoll);
if (peer->hmode == MODE_BROADCAST)
cookie = 0;
else
@@ -298,9 +310,9 @@ make_keylist(
peer->keynumber = i;
keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
cookie, lifetime);
- lifetime -= 1 << peer->kpoll;
+ lifetime -= mpoll;
if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
- lifetime <= (unsigned long)(1 << (peer->kpoll)))
+ lifetime <= mpoll)
break;
}
@@ -320,7 +332,10 @@ make_keylist(
vp->fstamp = hostval.tstamp;
vp->vallen = htonl(sizeof(struct autokey));
vp->siglen = 0;
- if (vp->tstamp != 0) {
+ if (tstamp != 0) {
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
if (vp->sig == NULL)
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
@@ -337,8 +352,9 @@ make_keylist(
if (debug)
printf("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
ntohl(ap->seq), ntohl(ap->key), cookie,
- ntohl(vp->tstamp), ntohl(vp->fstamp), peer->kpoll);
+ ntohl(vp->tstamp), ntohl(vp->fstamp), peer->hpoll);
#endif
+ return (XEVNT_OK);
}
@@ -374,14 +390,10 @@ crypto_recv(
X509 *cert; /* X509 certificate */
char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
keyid_t cookie; /* crumbles */
+ int hismode; /* packet mode */
int rval = XEVNT_OK;
u_char *ptr;
u_int32 temp32;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- struct timex ntv; /* kernel interface structure */
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
/*
* Initialize. Note that the packet has already been checked for
@@ -394,6 +406,7 @@ crypto_recv(
* association ID is saved only if nonzero.
*/
authlen = LEN_PKT_NOMAC;
+ hismode = (int)PKT_MODE((&rbufp->recv_pkt)->li_vn_mode);
while ((has_mac = rbufp->recv_length - authlen) > MAX_MAC_LEN) {
pkt = (u_int32 *)&rbufp->recv_pkt + authlen / 4;
ep = (struct exten *)pkt;
@@ -404,7 +417,7 @@ crypto_recv(
#ifdef DEBUG
if (debug)
printf(
- "crypto_recv: flags 0x%x ext offset %d len %u code %x assocID %d\n",
+ "crypto_recv: flags 0x%x ext offset %d len %u code 0x%x assocID %d\n",
peer->crypto, authlen, len, code >> 16,
associd);
#endif
@@ -413,8 +426,7 @@ crypto_recv(
* 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))) {
+ if (((code >> 24) & 0x3f) != CRYPTO_VN || len < 8) {
sys_unknownversion++;
code |= CRYPTO_ERROR;
}
@@ -444,15 +456,21 @@ crypto_recv(
* 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
+ * symmetric modes. The server name field might be
* useful to implement access controls in future.
*/
case CRYPTO_ASSOC:
/*
- * Pass the extension field to the transmit
- * side.
+ * If the machine is running when this message
+ * arrives, the other fellow has reset and so
+ * must we. Otherwise, pass the extension field
+ * to the transmit side.
*/
+ if (peer->crypto) {
+ rval = XEVNT_ERR;
+ break;
+ }
fp = emalloc(len);
memcpy(fp, ep, len);
temp32 = CRYPTO_RESP;
@@ -464,12 +482,13 @@ crypto_recv(
/*
* Discard the message if it has already been
- * stored or the server is not synchronized.
+ * stored or the message has been amputated.
*/
- if (peer->crypto || !fstamp)
+ if (peer->crypto)
break;
- if (len < VALUE_LEN + vallen) {
+ if (vallen == 0 || vallen > MAXHOSTNAME ||
+ len < VALUE_LEN + vallen) {
rval = XEVNT_LEN;
break;
}
@@ -481,51 +500,68 @@ crypto_recv(
* 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.
+ * confirms the server signature.
*/
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: ident host 0x%x server 0x%x\n",
+ crypto_flags, fstamp);
+#endif
+ temp32 = (crypto_flags | ident_scheme) &
+ fstamp & CRYPTO_FLAG_MASK;
if (crypto_flags & CRYPTO_FLAG_PRIV) {
- if (!(fstamp & CRYPTO_FLAG_PRIV))
+ if (!(fstamp & CRYPTO_FLAG_PRIV)) {
rval = XEVNT_KEY;
- else
+ break;
+
+ } else {
fstamp |= CRYPTO_FLAG_VALID |
- CRYPTO_FLAG_VRFY;
- } else if (crypto_flags & CRYPTO_FLAG_MASK &&
- !(crypto_flags & fstamp &
- CRYPTO_FLAG_MASK)) {
+ CRYPTO_FLAG_VRFY |
+ CRYPTO_FLAG_SIGN;
+ }
+ /*
+ * In symmetric modes it is an error if either
+ * peer requests identity and the other peer
+ * does not support it.
+ */
+ } else if ((hismode == MODE_ACTIVE || hismode ==
+ MODE_PASSIVE) && ((crypto_flags | fstamp) &
+ CRYPTO_FLAG_MASK) && !temp32) {
+ rval = XEVNT_KEY;
+ break;
+ /*
+ * It is an error if the client requests
+ * identity and the server does not support it.
+ */
+ } else if (hismode == MODE_CLIENT && (fstamp &
+ CRYPTO_FLAG_MASK) && !temp32) {
rval = XEVNT_KEY;
+ break;
}
/*
- * Discard the message if identity error.
+ * Otherwise, the identity scheme(s) are those
+ * that both client and server support.
*/
- if (rval != XEVNT_OK)
- break;
+ fstamp = temp32 | (fstamp & ~CRYPTO_FLAG_MASK);
/*
- * Discard the message if the host name length
- * is unreasonable or the signature digest NID
- * is not supported.
+ * Discard the message if 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)
+ 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.
+ * digest/signature type.
*/
- if (crypto_flags & CRYPTO_FLAG_PRIV)
- fstamp |= CRYPTO_FLAG_SIGN;
peer->crypto = fstamp;
peer->digest = dp;
peer->subject = emalloc(vallen + 1);
@@ -554,12 +590,8 @@ crypto_recv(
case CRYPTO_CERT | CRYPTO_RESP:
/*
- * Discard the message if invalid or identity
- * already confirmed.
+ * Discard the message if invalid.
*/
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- break;
-
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -589,7 +621,7 @@ crypto_recv(
strcpy(peer->issuer, cinfo->issuer);
/*
- * We plug in the public key and group key in
+ * We plug in the public key and lifetime from
* the first certificate received. However, note
* that this certificate might not be signed by
* the server, so we can't check the
@@ -602,7 +634,7 @@ crypto_recv(
peer->pkey = X509_get_pubkey(cert);
X509_free(cert);
}
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
temp32 = cinfo->nid;
sprintf(statstr, "cert %s 0x%x %s (%u) fs %u",
cinfo->subject, cinfo->flags,
@@ -627,12 +659,13 @@ crypto_recv(
case CRYPTO_IFF | CRYPTO_RESP:
/*
- * Discard the message if invalid or identity
- * already confirmed.
+ * Discard the message if invalid or certificate
+ * trail not trusted.
*/
- if (peer->crypto & CRYPTO_FLAG_VRFY)
+ if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
+ rval = XEVNT_ERR;
break;
-
+ }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -651,7 +684,7 @@ crypto_recv(
peer->crypto |= CRYPTO_FLAG_VRFY |
CRYPTO_FLAG_PROV;
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
sprintf(statstr, "iff fs %u",
ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
@@ -674,12 +707,13 @@ crypto_recv(
case CRYPTO_GQ | CRYPTO_RESP:
/*
- * Discard the message if invalid or identity
- * already confirmed.
+ * Discard the message if invalid or certificate
+ * trail not trusted.
*/
- if (peer->crypto & CRYPTO_FLAG_VRFY)
+ if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
+ rval = XEVNT_ERR;
break;
-
+ }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -698,7 +732,7 @@ crypto_recv(
peer->crypto |= CRYPTO_FLAG_VRFY |
CRYPTO_FLAG_PROV;
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
sprintf(statstr, "gq fs %u",
ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
@@ -714,12 +748,13 @@ crypto_recv(
case CRYPTO_MV | CRYPTO_RESP:
/*
- * Discard the message if invalid or identity
- * already confirmed.
+ * Discard the message if invalid or certificate
+ * trail not trusted.
*/
- if (peer->crypto & CRYPTO_FLAG_VRFY)
+ if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
+ rval = XEVNT_ERR;
break;
-
+ }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -738,7 +773,7 @@ crypto_recv(
peer->crypto |= CRYPTO_FLAG_VRFY |
CRYPTO_FLAG_PROV;
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
sprintf(statstr, "mv fs %u",
ntohl(ep->fstamp));
record_crypto_stats(&peer->srcadr, statstr);
@@ -747,47 +782,6 @@ crypto_recv(
printf("crypto_recv: %s\n", statstr);
#endif
break;
-
- /*
- * X509 certificate sign response. Validate the
- * certificate signed by the server and install. Later
- * this can be provided to clients of this server in
- * lieu of the self signed certificate in order to
- * validate the public key.
- */
- case CRYPTO_SIGN | CRYPTO_RESP:
-
- /*
- * Discard the message if invalid or identity
- * not confirmed.
- */
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, NULL, peer)) !=
- XEVNT_OK)
- break;
-
- /*
- * Scan the certificate list to delete old
- * versions and link the newest version first on
- * the list.
- */
- if ((rval = cert_install(ep, peer)) != XEVNT_OK) break;
-
- peer->crypto |= CRYPTO_FLAG_SIGN;
- peer->flash &= ~TEST10;
- temp32 = cinfo->nid;
- sprintf(statstr, "sign %s 0x%x %s (%u) fs %u",
- cinfo->issuer, cinfo->flags,
- OBJ_nid2ln(temp32), temp32,
- ntohl(ep->fstamp));
- record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("crypto_recv: %s\n", statstr);
-#endif
- break;
/*
* Cookie request in symmetric modes. Roll a random
@@ -797,12 +791,13 @@ crypto_recv(
case CRYPTO_COOK:
/*
- * Discard the message if invalid or identity
- * not confirmed.
+ * Discard the message if invalid or certificate
+ * trail not trusted.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+ if (!(peer->crypto & CRYPTO_FLAG_VALID)) {
+ rval = XEVNT_ERR;
break;
-
+ }
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -817,7 +812,7 @@ crypto_recv(
fp->opcode |= htonl(temp32);
peer->cmmd = fp;
if (peer->crypto & CRYPTO_FLAG_AGREE) {
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
break;
}
@@ -832,7 +827,7 @@ crypto_recv(
RAND_bytes((u_char *)&peer->pcookie, 4);
peer->crypto &= ~CRYPTO_FLAG_AUTO;
peer->crypto |= CRYPTO_FLAG_AGREE;
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
sprintf(statstr, "cook %x ts %u fs %u",
peer->pcookie, ntohl(ep->tstamp),
ntohl(ep->fstamp));
@@ -855,9 +850,10 @@ crypto_recv(
* not confirmed or signature not verified with
* respect to the cookie values.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+ if (!(peer->crypto & CRYPTO_FLAG_VRFY)) {
+ rval = XEVNT_ERR;
break;
-
+ }
if ((rval = crypto_verify(ep, &peer->cookval,
peer)) != XEVNT_OK)
break;
@@ -896,7 +892,7 @@ crypto_recv(
else
peer->crypto &= ~CRYPTO_FLAG_AUTO;
peer->crypto |= CRYPTO_FLAG_AGREE;
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
sprintf(statstr, "cook %x ts %u fs %u",
peer->pcookie, ntohl(ep->tstamp),
ntohl(ep->fstamp));
@@ -924,9 +920,10 @@ crypto_recv(
* not confirmed or signature not verified with
* respect to the receive autokey values.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+ if (!(peer->crypto & CRYPTO_FLAG_VRFY)) {
+ rval = XEVNT_ERR;
break;
-
+ }
if ((rval = crypto_verify(ep, &peer->recval,
peer)) != XEVNT_OK)
break;
@@ -946,7 +943,7 @@ crypto_recv(
bp->key = ntohl(ap->key);
peer->pkeyid = bp->key;
peer->crypto |= CRYPTO_FLAG_AUTO;
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
sprintf(statstr,
"auto seq %d key %x ts %u fs %u", bp->seq,
bp->key, ntohl(ep->tstamp),
@@ -957,6 +954,49 @@ crypto_recv(
printf("crypto_recv: %s\n", statstr);
#endif
break;
+
+ /*
+ * X509 certificate sign response. Validate the
+ * certificate signed by the server and install. Later
+ * this can be provided to clients of this server in
+ * lieu of the self signed certificate in order to
+ * validate the public key.
+ */
+ case CRYPTO_SIGN | CRYPTO_RESP:
+
+ /*
+ * Discard the message if invalid or not
+ * proventic.
+ */
+ if (!(peer->crypto & CRYPTO_FLAG_PROV)) {
+ rval = XEVNT_ERR;
+ break;
+ }
+ if ((rval = crypto_verify(ep, NULL, peer)) !=
+ XEVNT_OK)
+ break;
+
+ /*
+ * Scan the certificate list to delete old
+ * versions and link the newest version first on
+ * the list.
+ */
+ if ((rval = cert_install(ep, peer)) != XEVNT_OK)
+ break;
+
+ peer->crypto |= CRYPTO_FLAG_SIGN;
+ peer->flash &= ~TEST8;
+ 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 leapseconds table in symmetric modes. This
@@ -970,12 +1010,8 @@ crypto_recv(
case CRYPTO_TAI:
/*
- * Discard the message if invalid or identity
- * not confirmed.
+ * Discard the message if invalid.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
if ((rval = crypto_verify(ep, NULL, peer)) !=
XEVNT_OK)
break;
@@ -991,7 +1027,7 @@ crypto_recv(
fp->opcode |= htonl(temp32);
peer->cmmd = fp;
if (len <= VALUE_LEN) {
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
break;
}
/* fall through */
@@ -999,22 +1035,18 @@ crypto_recv(
case CRYPTO_TAI | CRYPTO_RESP:
/*
- * Discard the message if invalid or identity
- * not confirmed or signature not verified with
- * respect to the leapsecond table values.
+ * If this is a response, discard the message if
+ * signature not verified with respect to the
+ * leapsecond table values.
*/
- if (!(peer->crypto & CRYPTO_FLAG_VRFY))
- break;
-
- if ((rval = crypto_verify(ep, &peer->tai_leap,
- peer)) != XEVNT_OK)
- break;
+ if (peer->cmmd == NULL) {
+ 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.
+ * Initialize peer variables with latest update.
*/
peer->tai_leap.tstamp = ep->tstamp;
peer->tai_leap.fstamp = ep->fstamp;
@@ -1035,25 +1067,12 @@ crypto_recv(
tai_leap.ptr = emalloc(vallen);
memcpy(tai_leap.ptr, ep->pkt, vallen);
crypto_update();
- sys_tai = vallen / 4 + TAI_1972 - 1;
}
crypto_flags |= CRYPTO_FLAG_TAI;
peer->crypto |= CRYPTO_FLAG_LEAP;
- peer->flash &= ~TEST10;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- /*
- * If the kernel cooperates, initialize the
- * current TAI offset.
- */
- ntv.modes = MOD_TAI;
- ntv.constant = sys_tai;
- (void)ntp_adjtime(&ntv);
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
- sprintf(statstr, "leap %u ts %u fs %u",
- vallen, ntohl(ep->tstamp),
- ntohl(ep->fstamp));
+ peer->flash &= ~TEST8;
+ 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)
@@ -1068,6 +1087,7 @@ crypto_recv(
* valid field length. Remaining checks are below and on
* the transmit side.
*/
+ case CRYPTO_CERT:
case CRYPTO_IFF:
case CRYPTO_GQ:
case CRYPTO_MV:
@@ -1076,7 +1096,6 @@ crypto_recv(
rval = XEVNT_LEN;
break;
}
-
/* fall through */
/*
@@ -1088,7 +1107,7 @@ crypto_recv(
*/
default:
if (code & (CRYPTO_RESP | CRYPTO_ERROR)) {
- rval = XEVNT_LEN;
+ rval = XEVNT_ERR;
} else if ((rval = crypto_verify(ep, NULL,
peer)) == XEVNT_OK) {
fp = emalloc(len);
@@ -1100,24 +1119,27 @@ crypto_recv(
}
/*
- * We log everything except length/format errors and
+ * We don't log length/format/timestamp 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.
+ * scan and we return the laundry to the caller. A
+ * length/format/timestamp error on transmit is
+ * cheerfully ignored, as the message is not sent.
*/
- if (rval != XEVNT_OK) {
+ if (rval > XEVNT_TSP) {
sprintf(statstr,
"error %x opcode %x ts %u fs %u", rval,
code, tstamp, fstamp);
- if (rval > XEVNT_TSP)
- record_crypto_stats(&peer->srcadr,
- statstr);
+ record_crypto_stats(&peer->srcadr, statstr);
report_event(rval, peer);
#ifdef DEBUG
if (debug)
printf("crypto_recv: %s\n", statstr);
#endif
break;
+
+ } else if (rval > XEVNT_OK && (code & CRYPTO_RESP)) {
+ rval = XEVNT_OK;
}
authlen += len;
}
@@ -1148,9 +1170,10 @@ crypto_xmit(
struct peer *peer; /* peer structure pointer */
u_int opcode; /* extension field opcode */
struct exten *fp; /* extension pointers */
- struct cert_info *cp; /* certificate info/value pointer */
+ struct cert_info *cp, *xp; /* certificate info/value pointer */
char certname[MAXHOSTNAME + 1]; /* subject name buffer */
char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
+ tstamp_t tstamp;
u_int vallen;
u_int len;
struct value vtemp;
@@ -1170,21 +1193,22 @@ crypto_xmit(
fp->associd = htonl(associd);
len = 8;
rval = XEVNT_OK;
+ tstamp = crypto_time();
switch (opcode & 0xffff0000) {
/*
* Send association request and response with status word and
* host name. Note, this message is not signed and the filestamp
- * contains only the status word. We check at this point whether
- * the identity schemes are compatible to save tears later on.
+ * contains only the status word.
*/
case CRYPTO_ASSOC | CRYPTO_RESP:
+ len += crypto_send(fp, &hostval);
+ fp->fstamp = htonl(crypto_flags);
+ break;
+
case CRYPTO_ASSOC:
len += crypto_send(fp, &hostval);
- if (crypto_time() == 0)
- fp->fstamp = 0;
- else
- fp->fstamp = htonl(crypto_flags);
+ fp->fstamp = htonl(crypto_flags | ident_scheme);
break;
/*
@@ -1196,17 +1220,15 @@ crypto_xmit(
vtemp.tstamp = ep->tstamp;
vtemp.fstamp = ep->fstamp;
vtemp.vallen = ep->vallen;
- vtemp.ptr = (unsigned char *)ep->pkt;
+ vtemp.ptr = (u_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.
+ * from the certificate cache. If the request contains no
+ * subject name, assume the name of this host. This is for
+ * backwards compatibility. Private certificates are never sent.
*/
case CRYPTO_SIGN:
case CRYPTO_CERT | CRYPTO_RESP:
@@ -1214,23 +1236,61 @@ crypto_xmit(
if (vallen == 8) {
strcpy(certname, sys_hostname);
} else if (vallen == 0 || vallen > MAXHOSTNAME) {
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_LEN;
break;
} else {
memcpy(certname, ep->pkt, vallen);
certname[vallen] = '\0';
}
+
+ /*
+ * Find all certificates with matching subject. If a
+ * self-signed, trusted certificate is found, use that.
+ * If not, use the first one with matching subject. A
+ * private certificate is never divulged or signed.
+ */
+ xp = NULL;
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 (xp == NULL)
+ xp = cp;
+ if (strcmp(certname, cp->issuer) ==
+ 0 && cp->flags & CERT_TRUST) {
+ xp = cp;
+ break;
+ }
}
}
- if (cp == NULL)
- opcode |= CRYPTO_ERROR;
+
+ /*
+ * Be careful who you trust. If not yet synchronized,
+ * give back an empty response. If certificate not found
+ * or beyond the lifetime, return an error. This is to
+ * avoid a bad dude trying to get an expired certificate
+ * re-signed. Otherwise, send it.
+ *
+ * Note the timestamp and filestamp are taken from the
+ * certificate value structure. For all certificates the
+ * timestamp is the latest signature update time. For
+ * host and imported certificates the filestamp is the
+ * creation epoch. For signed certificates the filestamp
+ * is the creation epoch of the trusted certificate at
+ * the base of the certificate trail. In principle, this
+ * allows strong checking for signature masquerade.
+ */
+ if (tstamp == 0)
+ break;
+
+ if (xp == NULL)
+ rval = XEVNT_CRT;
+ else if (tstamp < xp->first || tstamp > xp->last)
+ rval = XEVNT_SRV;
+ else
+ len += crypto_send(fp, &xp->cert);
break;
/*
@@ -1238,21 +1298,23 @@ crypto_xmit(
*/
case CRYPTO_IFF:
if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_ERR;
break;
}
- if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK)
+ if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK) {
len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
+ value_free(&vtemp);
+ }
break;
/*
* Send response in Schnorr (IFF) identity scheme.
*/
case CRYPTO_IFF | CRYPTO_RESP:
- if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK)
+ if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK) {
len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
+ value_free(&vtemp);
+ }
break;
/*
@@ -1260,21 +1322,23 @@ crypto_xmit(
*/
case CRYPTO_GQ:
if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_ERR;
break;
}
- if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK)
+ if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK) {
len += crypto_send(fp, &vtemp);
- value_free(&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)
+ if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK) {
len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
+ value_free(&vtemp);
+ }
break;
/*
@@ -1282,21 +1346,23 @@ crypto_xmit(
*/
case CRYPTO_MV:
if ((peer = findpeerbyassoc(ep->pkt[0])) == NULL) {
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_ERR;
break;
}
- if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK)
+ if ((rval = crypto_alice3(peer, &vtemp)) == XEVNT_OK) {
len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
+ value_free(&vtemp);
+ }
break;
/*
* Send response in MV identity scheme.
*/
case CRYPTO_MV | CRYPTO_RESP:
- if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK)
+ if ((rval = crypto_bob3(ep, &vtemp)) == XEVNT_OK) {
len += crypto_send(fp, &vtemp);
- value_free(&vtemp);
+ value_free(&vtemp);
+ }
break;
/*
@@ -1327,14 +1393,14 @@ crypto_xmit(
*/
case CRYPTO_COOK | CRYPTO_RESP:
if ((opcode & 0xffff) < VALUE_LEN) {
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_LEN;
break;
}
if (PKT_MODE(xpkt->li_vn_mode) == MODE_SERVER) {
tcookie = cookie;
} else {
if ((peer = findpeerbyassoc(associd)) == NULL) {
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_ERR;
break;
}
tcookie = peer->pcookie;
@@ -1354,7 +1420,7 @@ crypto_xmit(
*/
case CRYPTO_AUTO | CRYPTO_RESP:
if ((peer = findpeerbyassoc(associd)) == NULL) {
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_ERR;
break;
}
peer->flags &= ~FLAG_ASSOC;
@@ -1363,8 +1429,8 @@ crypto_xmit(
/*
* Send leapseconds table and signature. Use the values from the
- * tai structure. If no table has been loaded, just send a
- * request.
+ * tai structure. If no table has been loaded, just send an
+ * empty request.
*/
case CRYPTO_TAI:
case CRYPTO_TAI | CRYPTO_RESP:
@@ -1378,22 +1444,24 @@ crypto_xmit(
*/
default:
if (opcode & CRYPTO_RESP)
- opcode |= CRYPTO_ERROR;
+ rval = XEVNT_ERR;
}
/*
- * 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.
+ * In case of error, flame the log. If a request, toss the
+ * puppy; if a response, return so the sender can flame, too.
*/
- if (rval > XEVNT_TSP) {
+ if (rval != XEVNT_OK) {
opcode |= CRYPTO_ERROR;
sprintf(statstr, "error %x opcode %x", rval, opcode);
record_crypto_stats(srcadr_sin, statstr);
+ report_event(rval, NULL);
#ifdef DEBUG
if (debug)
printf("crypto_xmit: %s\n", statstr);
#endif
+ if (!(opcode & CRYPTO_RESP))
+ return (0);
}
/*
@@ -1405,8 +1473,8 @@ crypto_xmit(
#ifdef DEBUG
if (debug)
printf(
- "crypto_xmit: ext offset %d len %u code %x assocID %d\n",
- start, len, opcode>> 16, associd);
+ "crypto_xmit: flags 0x%x ext offset %d len %u code 0x%x assocID %d\n",
+ crypto_flags, start, len, opcode >> 16, associd);
#endif
return (len);
}
@@ -1423,6 +1491,7 @@ crypto_xmit(
* XEVNT_PUB bad or missing public key
* XEVNT_SGL bad signature length
* XEVNT_SIG signature not verified
+ * XEVNT_ERR protocol error
*/
static int
crypto_verify(
@@ -1433,16 +1502,15 @@ crypto_verify(
{
EVP_PKEY *pkey; /* server public key */
EVP_MD_CTX ctx; /* signature context */
- tstamp_t tstamp; /* timestamp */
- tstamp_t fstamp; /* filestamp */
+ tstamp_t tstamp, tstamp1 = 0; /* timestamp */
+ tstamp_t fstamp, fstamp1 = 0; /* filestamp */
u_int vallen; /* value length */
u_int siglen; /* signature length */
u_int opcode, len;
- int rval;
int i;
/*
- * We require valid opcode and field length, timestamp,
+ * We require valid opcode and field lengths, timestamp,
* filestamp, public key, digest, signature length and
* signature, where relevant. Note that preliminary length
* checks are done in the main loop.
@@ -1457,7 +1525,8 @@ crypto_verify(
* header, no need for further checking.
*/
if (opcode & CRYPTO_ERROR)
- return (XEVNT_LEN);
+ return (XEVNT_ERR);
+
if (opcode & CRYPTO_RESP) {
if (len < VALUE_LEN)
return (XEVNT_LEN);
@@ -1465,91 +1534,93 @@ crypto_verify(
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.
+ * value and signature. Note both the value and signature fields
+ * are rounded up to the next word.
*/
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)
+ if (len < VALUE_LEN + ((vallen + 3) / 4) * 4 + ((siglen + 3) /
+ 4) * 4)
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);
+ /*
+ * Punt if this is a response with no data. Punt if this is a
+ * request and a previous response is pending.
+ */
+ if (opcode & CRYPTO_RESP) {
+ if (vallen == 0)
+ return (XEVNT_LEN);
+ } else {
+ if (peer->cmmd != NULL)
+ return (XEVNT_LEN);
}
/*
- * 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.
+ * Check for valid timestamp and filestamp. If the timestamp is
+ * zero, the sender is not synchronized and signatures are
+ * disregarded. If not, the timestamp must not precede the
+ * filestamp. The timestamp and filestamp must not precede the
+ * corresponding values in the value structure, if present. 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.
+ */
+ tstamp = ntohl(ep->tstamp);
+ fstamp = ntohl(ep->fstamp);
+ if (tstamp == 0)
+ return (XEVNT_OK);
+
+ if (tstamp < fstamp)
+ return (XEVNT_TSP);
+
+ if (vp != NULL) {
+ tstamp1 = ntohl(vp->tstamp);
+ fstamp1 = ntohl(vp->fstamp);
+ if ((tstamp < tstamp1 || (tstamp == tstamp1 &&
+ (peer->crypto & CRYPTO_FLAG_AUTO))))
+ return (XEVNT_TSP);
+
+ if ((tstamp < fstamp1 || fstamp < fstamp1))
+ return (XEVNT_FSP);
+ }
+
+ /*
+ * Check for valid signature length, public key and digest
+ * algorithm.
*/
- rval = XEVNT_OK;
if (crypto_flags & peer->crypto & CRYPTO_FLAG_PRIV)
pkey = sign_pkey;
else
pkey = peer->pkey;
- tstamp = ntohl(ep->tstamp);
- fstamp = ntohl(ep->fstamp);
- if (tstamp == 0 || tstamp < fstamp) {
- rval = XEVNT_TSP;
- } else if (vp != NULL && (tstamp < ntohl(vp->tstamp) ||
- (tstamp == ntohl(vp->tstamp) && (peer->crypto &
- CRYPTO_FLAG_AUTO)))) {
- rval = XEVNT_TSP;
- } else if (vp != NULL && (tstamp < ntohl(vp->fstamp) || fstamp <
- ntohl(vp->fstamp))) {
- rval = XEVNT_FSP;
-
- /*
- * If a public key and digest is present, and if valid key
- * length, check for valid signature. Note that the first valid
- * signature lights the proventic bit.
- */
- } else if (pkey == NULL || peer->digest == NULL) {
- /* fall through */
- } else if (siglen != (u_int) EVP_PKEY_size(pkey)) {
- rval = XEVNT_SGL;
- } else {
- EVP_VerifyInit(&ctx, peer->digest);
- EVP_VerifyUpdate(&ctx, (u_char *)&ep->tstamp, vallen +
- 12);
- if (EVP_VerifyFinal(&ctx, (u_char *)&ep->pkt[i], siglen,
- pkey)) {
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- peer->crypto |= CRYPTO_FLAG_PROV;
- } else {
- rval = XEVNT_SIG;
- }
+ if (siglen == 0 || pkey == NULL || peer->digest == NULL)
+ return (XEVNT_OK);
+
+ if (siglen != (u_int)EVP_PKEY_size(pkey))
+ return (XEVNT_SGL);
+
+ /*
+ * Darn, I thought we would never get here. Verify the
+ * signature. If the identity exchange is verified, light the
+ * proventic bit. If no client identity scheme is specified,
+ * avoid doing the sign exchange.
+ */
+ 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))
+ return (XEVNT_SIG);
+
+ if (peer->crypto & CRYPTO_FLAG_VRFY) {
+ peer->crypto |= CRYPTO_FLAG_PROV;
+ if (!(crypto_flags & CRYPTO_FLAG_MASK))
+ peer->crypto |= CRYPTO_FLAG_SIGN;
}
-#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);
+ return (XEVNT_OK);
}
@@ -1561,6 +1632,7 @@ crypto_verify(
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
* XEVNT_CKY bad or missing cookie
+ * XEVNT_PER host certificate expired
*/
static int
crypto_encrypt(
@@ -1610,6 +1682,10 @@ crypto_encrypt(
vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
+
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -1642,9 +1718,6 @@ crypto_ident(
* been found and the CRYPTO_FLAG_VALID bit is set, so the
* certificate issuer is valid.
*/
- if (peer->crypto & CRYPTO_FLAG_VRFY)
- return (0);
-
if (peer->ident_pkey != NULL)
EVP_PKEY_free(peer->ident_pkey);
if (peer->crypto & CRYPTO_FLAG_GQ) {
@@ -1688,8 +1761,7 @@ crypto_ident(
}
/*
- * No compatible identity scheme is available. Use the default
- * TC scheme.
+ * No compatible identity scheme is available. Life is hard.
*/
msyslog(LOG_INFO,
"crypto_ident: no compatible identity scheme found");
@@ -1724,6 +1796,9 @@ crypto_args(
len += strlen(str);
ep = emalloc(len);
memset(ep, 0, len);
+ if (opcode == 0)
+ return (ep);
+
ep->opcode = htonl(opcode + len);
/*
@@ -1813,13 +1888,14 @@ void
crypto_update(void)
{
EVP_MD_CTX ctx; /* message digest context */
- struct cert_info *cp, *cpn, **zp; /* certificate info/value */
+ struct cert_info *cp, *cpn; /* certificate info/value */
char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
tstamp_t tstamp; /* NTP timestamp */
u_int len;
if ((tstamp = crypto_time()) == 0)
return;
+
hostval.tstamp = htonl(tstamp);
/*
@@ -1842,29 +1918,21 @@ crypto_update(void)
/*
* 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.
+ * was generated. Note we do not throw expired certificates
+ * away; they may have signed younger ones.
*/
- 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;
- }
+ 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);
}
/*
@@ -1946,6 +2014,7 @@ asn2ntp (
*/
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)
@@ -1983,6 +2052,9 @@ bighash(
EVP_DigestUpdate(&ctx, ptr, len);
EVP_DigestFinal(&ctx, dgst, &len);
BN_bin2bn(dgst, len, bk);
+
+ /* XXX MEMLEAK? free ptr? */
+
return (1);
}
@@ -2036,7 +2108,7 @@ bighash(
* Returns
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing identity parameters
+ * XEVNT_ID bad or missing group key
*/
static int
crypto_alice(
@@ -2055,6 +2127,7 @@ crypto_alice(
*/
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);
@@ -2086,6 +2159,10 @@ crypto_alice(
vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
+
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2101,7 +2178,9 @@ crypto_alice(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
+ * XEVNT_ID bad or missing group key
+ * XEVNT_ERR protocol error
+ * XEVNT_PER host expired certificate
*/
static int
crypto_bob(
@@ -2122,9 +2201,9 @@ crypto_bob(
* If the IFF parameters are not valid, something awful
* happened or we are being tormented.
*/
- if (!(crypto_flags & CRYPTO_FLAG_IFF)) {
+ if (iffpar_pkey == NULL) {
msyslog(LOG_INFO, "crypto_bob: scheme unavailable");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
dsa = iffpar_pkey->pkey.dsa;
@@ -2135,7 +2214,7 @@ crypto_bob(
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);
+ return (XEVNT_ERR);
}
/*
@@ -2167,7 +2246,7 @@ crypto_bob(
msyslog(LOG_ERR, "crypto_bob %s\n",
ERR_error_string(ERR_get_error(), NULL));
DSA_SIG_free(sdsa);
- return (XEVNT_PUB);
+ return (XEVNT_ERR);
}
vp->vallen = htonl(len);
ptr = emalloc(len);
@@ -2177,6 +2256,10 @@ crypto_bob(
vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
+
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2193,8 +2276,8 @@ crypto_bob(
* Returns
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
+ * XEVNT_ID bad or missing group key
* XEVNT_FSP bad filestamp
- * XEVNT_ID bad or missing identity parameters
*/
int
crypto_iff(
@@ -2216,7 +2299,7 @@ crypto_iff(
*/
if (peer->ident_pkey == NULL) {
msyslog(LOG_INFO, "crypto_iff: scheme unavailable");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
if (ntohl(ep->fstamp) != peer->fstamp) {
msyslog(LOG_INFO, "crypto_iff: invalid filestamp %u",
@@ -2229,7 +2312,7 @@ crypto_iff(
}
if (peer->iffval == NULL) {
msyslog(LOG_INFO, "crypto_iff: missing challenge");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
/*
@@ -2241,7 +2324,7 @@ crypto_iff(
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);
+ return (XEVNT_ERR);
}
/*
@@ -2262,6 +2345,7 @@ crypto_iff(
DSA_SIG_free(sdsa);
if (temp == 0)
return (XEVNT_OK);
+
else
return (XEVNT_ID);
}
@@ -2325,7 +2409,8 @@ crypto_iff(
* Returns
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing identity parameters
+ * XEVNT_ID bad or missing group key
+ * XEVNT_PER host certificate expired
*/
static int
crypto_alice2(
@@ -2344,6 +2429,7 @@ crypto_alice2(
*/
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);
@@ -2375,6 +2461,10 @@ crypto_alice2(
vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
+
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2390,7 +2480,9 @@ crypto_alice2(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
+ * XEVNT_ID bad or missing group key
+ * XEVNT_ERR protocol error
+ * XEVNT_PER host certificate expired
*/
static int
crypto_bob2(
@@ -2411,9 +2503,9 @@ crypto_bob2(
* If the GQ parameters are not valid, something awful
* happened or we are being tormented.
*/
- if (!(crypto_flags & CRYPTO_FLAG_GQ)) {
+ if (gqpar_pkey == NULL) {
msyslog(LOG_INFO, "crypto_bob2: scheme unavailable");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
rsa = gqpar_pkey->pkey.rsa;
@@ -2424,7 +2516,7 @@ crypto_bob2(
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);
+ return (XEVNT_ERR);
}
/*
@@ -2456,7 +2548,7 @@ crypto_bob2(
msyslog(LOG_ERR, "crypto_bob2 %s\n",
ERR_error_string(ERR_get_error(), NULL));
DSA_SIG_free(sdsa);
- return (XEVNT_PUB);
+ return (XEVNT_ERR);
}
vp->vallen = htonl(len);
ptr = emalloc(len);
@@ -2466,6 +2558,10 @@ crypto_bob2(
vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
+
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2482,8 +2578,9 @@ crypto_bob2(
* Returns
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
+ * XEVNT_ID bad or missing group keys
+ * XEVNT_ERR protocol error
* XEVNT_FSP bad filestamp
- * XEVNT_ID bad or missing identity parameters
*/
int
crypto_gq(
@@ -2505,7 +2602,7 @@ crypto_gq(
*/
if (peer->ident_pkey == NULL) {
msyslog(LOG_INFO, "crypto_gq: scheme unavailable");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
if (ntohl(ep->fstamp) != peer->fstamp) {
msyslog(LOG_INFO, "crypto_gq: invalid filestamp %u",
@@ -2518,7 +2615,7 @@ crypto_gq(
}
if (peer->iffval == NULL) {
msyslog(LOG_INFO, "crypto_gq: missing challenge");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
/*
@@ -2531,7 +2628,7 @@ crypto_gq(
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);
+ return (XEVNT_ERR);
}
/*
@@ -2553,6 +2650,7 @@ crypto_gq(
DSA_SIG_free(sdsa);
if (temp == 0)
return (XEVNT_OK);
+
else
return (XEVNT_ID);
}
@@ -2637,7 +2735,8 @@ crypto_gq(
* Returns
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
- * XEVNT_ID bad or missing identity parameters
+ * XEVNT_ID bad or missing group key
+ * XEVNT_PER host certificate expired
*/
static int
crypto_alice3(
@@ -2656,6 +2755,7 @@ crypto_alice3(
*/
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);
@@ -2687,6 +2787,10 @@ crypto_alice3(
vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
+
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2702,7 +2806,8 @@ crypto_alice3(
*
* Returns
* XEVNT_OK success
- * XEVNT_PUB bad or missing public key
+ * XEVNT_ERR protocol error
+ * XEVNT_PER host certificate expired
*/
static int
crypto_bob3(
@@ -2723,9 +2828,9 @@ crypto_bob3(
* If the MV parameters are not valid, something awful
* happened or we are being tormented.
*/
- if (!(crypto_flags & CRYPTO_FLAG_MV)) {
+ if (mvpar_pkey == NULL) {
msyslog(LOG_INFO, "crypto_bob3: scheme unavailable");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
dsa = mvpar_pkey->pkey.dsa;
@@ -2736,7 +2841,7 @@ crypto_bob3(
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);
+ return (XEVNT_ERR);
}
/*
@@ -2773,7 +2878,7 @@ crypto_bob3(
msyslog(LOG_ERR, "crypto_bob3 %s\n",
ERR_error_string(ERR_get_error(), NULL));
DSA_free(sdsa);
- return (XEVNT_PUB);
+ return (XEVNT_ERR);
}
vp->vallen = htonl(len);
ptr = emalloc(len);
@@ -2783,6 +2888,10 @@ crypto_bob3(
vp->siglen = 0;
if (tstamp == 0)
return (XEVNT_OK);
+
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
vp->sig = emalloc(sign_siglen);
EVP_SignInit(&ctx, sign_digest);
EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2799,8 +2908,9 @@ crypto_bob3(
* Returns
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
+ * XEVNT_ID bad or missing group key
+ * XEVNT_ERR protocol error
* XEVNT_FSP bad filestamp
- * XEVNT_ID bad or missing identity parameters
*/
int
crypto_mv(
@@ -2822,7 +2932,7 @@ crypto_mv(
*/
if (peer->ident_pkey == NULL) {
msyslog(LOG_INFO, "crypto_mv: scheme unavailable");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
if (ntohl(ep->fstamp) != peer->fstamp) {
msyslog(LOG_INFO, "crypto_mv: invalid filestamp %u",
@@ -2835,7 +2945,7 @@ crypto_mv(
}
if (peer->iffval == NULL) {
msyslog(LOG_INFO, "crypto_mv: missing challenge");
- return (XEVNT_PUB);
+ return (XEVNT_ID);
}
/*
@@ -2847,7 +2957,7 @@ crypto_mv(
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);
+ return (XEVNT_ERR);
}
/*
@@ -2870,6 +2980,7 @@ crypto_mv(
DSA_free(sdsa);
if (temp == 0)
return (XEVNT_OK);
+
else
return (XEVNT_ID);
}
@@ -3026,7 +3137,7 @@ cert_parse(
if (strcmp(ret->subject, ret->issuer) == 0) {
if (!X509_verify(cert, ret->pkey)) {
msyslog(LOG_INFO,
- "cert_parse: invalid signature not verified %s",
+ "cert_parse: signature not verified %s",
pathbuf);
cert_free(ret);
X509_free(cert);
@@ -3040,8 +3151,8 @@ cert_parse(
*/
if (ret->first > ret->last || ret->first < fstamp) {
msyslog(LOG_INFO,
- "cert_parse: expired %s",
- ret->subject);
+ "cert_parse: invalid certificate %s first %u last %u fstamp %u",
+ ret->subject, ret->first, ret->last, fstamp);
cert_free(ret);
X509_free(cert);
return (NULL);
@@ -3064,21 +3175,38 @@ cert_parse(
/*
- * cert_sign - sign x509 certificate and update value structure.
+ * cert_sign - sign x509 certificate equest 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.
+ * The certificate request includes a copy of the host certificate,
+ * which includes the version number, subject name and public key of the
+ * host. The resulting certificate includes these values plus the
+ * serial number, issuer name and valid interval of the server. The
+ * valid interval extends from the current time to the same time one
+ * year hence. This may extend the life of the signed certificate beyond
+ * that of the signer certificate.
+ *
+ * It is convenient to use the NTP seconds of the current time as the
+ * serial number. In the value structure the timestamp is the current
+ * time and the filestamp is taken from the extension field. Note this
+ * routine is called only when the client clock is synchronized to a
+ * proventic source, so timestamp comparisons are valid.
+ *
+ * The host certificate is valid from the time it was generated for a
+ * period of one year. A signed certificate is valid from the time of
+ * signature for a period of one year, but only the host certificate (or
+ * sign certificate if used) is actually used to encrypt and decrypt
+ * signatures. The signature trail is built from the client via the
+ * intermediate servers to the trusted server. Each signature on the
+ * trail must be valid at the time of signature, but it could happen
+ * that a signer certificate expire before the signed certificate, which
+ * remains valid until its expiration.
*
* Returns
* XEVNT_OK success
* XEVNT_PUB bad or missing public key
* XEVNT_CRT bad or missing certificate
* XEVNT_VFY certificate not verified
+ * XEVNT_PER host certificate expired
*/
static int
cert_sign(
@@ -3100,11 +3228,16 @@ cert_sign(
/*
* Decode ASN.1 objects and construct certificate structure.
+ * Make sure the system clock is synchronized to a proventic
+ * source.
*/
tstamp = crypto_time();
if (tstamp == 0)
return (XEVNT_TSP);
+ if (tstamp < cinfo->first || tstamp > cinfo->last)
+ return (XEVNT_PER);
+
ptr = (u_char *)ep->pkt;
if ((req = d2i_X509(NULL, &ptr, ntohl(ep->vallen))) == NULL) {
msyslog(LOG_ERR, "cert_sign %s\n",
@@ -3123,7 +3256,7 @@ cert_sign(
/*
* Generate X509 certificate signed by this server. For this
- * prupose the issuer name is the server name. Also copy any
+ * purpose the issuer name is the server name. Also copy any
* extensions that might be present.
*/
cert = X509_new();
@@ -3135,7 +3268,7 @@ cert_sign(
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);
+ (u_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);
@@ -3209,11 +3342,12 @@ cert_valid(
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))
+ if (cert == NULL || !X509_verify(cert, pkey))
return (XEVNT_VFY);
- cinf->flags |= CERT_SIGN;
+
X509_free(cert);
return (XEVNT_OK);
}
@@ -3230,7 +3364,7 @@ cert_valid(
*
* Returns
* XEVNT_OK success
- * XEVNT_PER certificate expired
+ * XEVNT_FSP bad or missing filestamp
* XEVNT_CRT bad or missing certificate
*/
int
@@ -3240,33 +3374,28 @@ cert_install(
)
{
struct cert_info *cp, *xp, *yp, **zp;
- int rval;
- tstamp_t tstamp;
/*
* Parse and validate the signed certificate. If valid,
* construct the info/value structure; otherwise, scamper home.
- * Note this allows a certificate not-before time to be in the
- * future, but not a not-after time to be in the past.
*/
if ((cp = cert_parse((u_char *)ep->pkt, ntohl(ep->vallen),
ntohl(ep->fstamp))) == NULL)
return (XEVNT_CRT);
- tstamp = crypto_time();
- if (tstamp > cp->last) {
- cert_free(cp);
- return (XEVNT_PER);
- }
-
/*
* Scan certificate list looking for another certificate with
* the same subject and issuer. If another is found with the
* same or older filestamp, unlink it and return the goodies to
- * the heap. If another is found with a later filetsamp, discard
+ * the heap. If another is found with a later filestamp, discard
* the new one and leave the building.
+ *
+ * Make a note to study this issue again. An earlier certificate
+ * with a long lifetime might be overtaken by a later
+ * certificate with a short lifetime, thus invalidating the
+ * earlier signature. However, we gotta find a way to leak old
+ * stuff from the cache, so we do it anyway.
*/
- rval = XEVNT_OK;
yp = cp;
zp = &cinfo;
for (xp = cinfo; xp != NULL; xp = xp->link) {
@@ -3278,7 +3407,7 @@ cert_install(
cert_free(xp);
} else {
cert_free(cp);
- return (XEVNT_TSP);
+ return (XEVNT_FSP);
}
break;
}
@@ -3288,29 +3417,42 @@ cert_install(
cinfo = yp;
/*
- * Scan the certificate list to see if Y is signed by X.
+ * Scan the certificate list to see if Y is signed by X. This is
+ * independent of order.
*/
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 the issuer of certificate Y matches the
+ * subject of certificate X, verify the
+ * signature of Y using the public key of X. If
+ * so, X signs Y.
*/
- if (strcmp(yp->issuer, xp->subject) != 0)
+ if (strcmp(yp->issuer, xp->subject) != 0 ||
+ xp->flags & CERT_ERROR)
continue;
if (cert_valid(yp, xp->pkey) != XEVNT_OK) {
yp->flags |= CERT_ERROR;
continue;
}
- xp->flags |= CERT_SIGN;
+
+ /*
+ * The signature Y is valid only if it begins
+ * during the lifetime of X; however, it is not
+ * necessarily an error, since some other
+ * certificate might sign Y.
+ */
+ if (yp->first < xp->first || yp->first >
+ xp->last)
+ continue;
+
+ yp->flags |= CERT_SIGN;
/*
* If X is trusted, then Y is trusted. Note that
- * we might stumble over a self signed
+ * 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
@@ -3319,10 +3461,10 @@ cert_install(
* this might result in a loop that could
* persist until timeout.
*/
- if (!(xp->flags & CERT_TRUST))
+ if (!(xp->flags & (CERT_TRUST | CERT_VALID)))
continue;
- yp->flags |= CERT_TRUST;
+ yp->flags |= CERT_VALID;
/*
* If subject Y matches the server subject name,
@@ -3359,7 +3501,7 @@ cert_install(
* That was awesome. Now update the timestamps and signatures.
*/
crypto_update();
- return (rval);
+ return (XEVNT_OK);
}
@@ -3432,16 +3574,19 @@ crypto_key(
if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
msyslog(LOG_ERR, "crypto_key: no data %s\n",
filename);
+ (void)fclose(str);
return (NULL);
}
if ((ptr = strrchr(ptr, '.')) == NULL) {
msyslog(LOG_ERR, "crypto_key: no filestamp %s\n",
filename);
+ (void)fclose(str);
return (NULL);
}
if (sscanf(++ptr, "%u", fstamp) != 1) {
msyslog(LOG_ERR, "crypto_key: invalid timestamp %s\n",
filename);
+ (void)fclose(str);
return (NULL);
}
@@ -3523,16 +3668,19 @@ crypto_cert(
if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
msyslog(LOG_ERR, "crypto_cert: no data %s\n",
filename);
+ (void)fclose(str);
return (NULL);
}
if ((ptr = strrchr(ptr, '.')) == NULL) {
msyslog(LOG_ERR, "crypto_cert: no filestamp %s\n",
filename);
+ (void)fclose(str);
return (NULL);
}
if (sscanf(++ptr, "%u", &fstamp) != 1) {
msyslog(LOG_ERR, "crypto_cert: invalid filestamp %s\n",
filename);
+ (void)fclose(str);
return (NULL);
}
@@ -3542,6 +3690,7 @@ crypto_cert(
if (!PEM_read(str, &name, &header, &data, &len)) {
msyslog(LOG_ERR, "crypto_cert %s\n",
ERR_error_string(ERR_get_error(), NULL));
+ (void)fclose(str);
return (NULL);
}
free(header);
@@ -3550,6 +3699,7 @@ crypto_cert(
name);
free(name);
free(data);
+ (void)fclose(str);
return (NULL);
}
free(name);
@@ -3559,8 +3709,10 @@ crypto_cert(
*/
ret = cert_parse(data, len, fstamp);
free(data);
+ (void)fclose(str);
if (ret == NULL)
return (NULL);
+
if ((ptr = strrchr(linkname, '\n')) != NULL)
*ptr = '\0';
sprintf(statstr, "%s 0x%x len %lu", &linkname[2], ret->flags,
@@ -3590,20 +3742,16 @@ crypto_tai(
{
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) */
+ u_int32 leapsec[MAX_LEAP]; /* NTP time at leaps */
+ int offset; /* offset at leap (s) */
char filename[MAXFILENAME]; /* name of leapseconds file */
char linkname[MAXFILENAME]; /* file link (for filestamp) */
char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
tstamp_t fstamp; /* filestamp */
u_int len;
- char *ptr;
- int rval, i;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- struct timex ntv; /* kernel interface structure */
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
+ u_int32 *ptr;
+ char *dp;
+ int rval, i, j;
/*
* Open the file and discard comment lines. If the first
@@ -3625,12 +3773,12 @@ crypto_tai(
rval = readlink(filename, linkname, MAXFILENAME - 1);
if (rval > 0) {
linkname[rval] = '\0';
- ptr = strrchr(linkname, '.');
+ dp = strrchr(linkname, '.');
} else {
- ptr = strrchr(filename, '.');
+ dp = strrchr(filename, '.');
}
- if (ptr != NULL)
- sscanf(++ptr, "%u", &fstamp);
+ if (dp != NULL)
+ sscanf(++dp, "%u", &fstamp);
else
fstamp = 0;
tai_leap.fstamp = htonl(fstamp);
@@ -3647,22 +3795,26 @@ crypto_tai(
*/
i = 0;
while (i < MAX_LEAP) {
- ptr = fgets(buf, NTP_MAXSTRLEN - 1, str);
- if (ptr == NULL)
+ dp = fgets(buf, NTP_MAXSTRLEN - 1, str);
+ if (dp == NULL)
break;
+
if (strlen(buf) < 1)
continue;
+
if (*buf == '#')
continue;
- if (sscanf(buf, "%u %u", &leapsec[i], &offset) != 2)
+
+ if (sscanf(buf, "%u %d", &leapsec[i], &offset) != 2)
continue;
- if (i != (int)(offset - TAI_1972)) {
+
+ if (i != offset - TAI_1972)
break;
- }
+
i++;
}
fclose(str);
- if (ptr != NULL) {
+ if (dp != NULL) {
msyslog(LOG_INFO,
"crypto_tai: leapseconds file %s error %d", cp,
rval);
@@ -3671,29 +3823,17 @@ crypto_tai(
/*
* The extension field table entries consists of the NTP seconds
- * of leap insertion in reverse order, so that the most recent
- * insertion is the first entry in the table.
+ * of leap insertion in network byte order.
*/
- len = i * 4;
+ len = i * sizeof(u_int32);
tai_leap.vallen = htonl(len);
ptr = emalloc(len);
- tai_leap.ptr = (unsigned char *) ptr;
- for (; i >= 0; i--) {
- *ptr++ = (char) htonl(leapsec[i]);
- }
+ tai_leap.ptr = (u_char *)ptr;
+ for (j = 0; j < i; j++)
+ *ptr++ = htonl(leapsec[j]);
crypto_flags |= CRYPTO_FLAG_TAI;
- sys_tai = len / 4 + TAI_1972 - 1;
-#ifdef KERNEL_PLL
-#if NTP_API > 3
- ntv.modes = MOD_TAI;
- ntv.constant = sys_tai;
- if (ntp_adjtime(&ntv) == TIME_ERROR)
- msyslog(LOG_INFO,
- "crypto_tai: kernel TAI update failed");
-#endif /* NTP_API */
-#endif /* KERNEL_PLL */
- sprintf(statstr, "%s link %d fs %u offset %u", cp, rval, fstamp,
- ntohl(tai_leap.vallen) / 4 + TAI_1972 - 1);
+ sprintf(statstr, "%s fs %u leap %u len %u", cp, fstamp,
+ leapsec[--j], len);
record_crypto_stats(NULL, statstr);
#ifdef DEBUG
if (debug)
@@ -3727,6 +3867,7 @@ crypto_setup(void)
*/
if (!crypto_flags)
return;
+
gethostname(filename, MAXFILENAME);
bytes = strlen(filename) + 1;
sys_hostname = emalloc(bytes);
@@ -3806,7 +3947,7 @@ crypto_setup(void)
exit (-1);
}
hostval.vallen = htonl(strlen(sys_hostname));
- hostval.ptr = (unsigned char *) sys_hostname;
+ hostval.ptr = (u_char *)sys_hostname;
/*
* Construct public key extension field for agreement scheme.
@@ -3909,7 +4050,7 @@ crypto_setup(void)
* 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,
+ if (cinfo->flags & CERT_TRUST && strcmp(cinfo->subject,
cinfo->issuer) != 0) {
if (cert_valid(cinfo, sign_pkey) != XEVNT_OK) {
msyslog(LOG_ERR,
@@ -4009,6 +4150,18 @@ crypto_config(
break;
/*
+ * Set identity scheme.
+ */
+ case CRYPTO_CONF_IDENT:
+ if (!strcasecmp(cp, "iff"))
+ ident_scheme |= CRYPTO_FLAG_IFF;
+ else if (!strcasecmp(cp, "gq"))
+ ident_scheme |= CRYPTO_FLAG_GQ;
+ else if (!strcasecmp(cp, "mv"))
+ ident_scheme |= CRYPTO_FLAG_MV;
+ break;
+
+ /*
* Set certificate file name.
*/
case CRYPTO_CONF_CERT:
diff --git a/contrib/ntp/ntpd/ntp_filegen.c b/contrib/ntp/ntpd/ntp_filegen.c
index 59a1d91..932d1b6 100644
--- a/contrib/ntp/ntpd/ntp_filegen.c
+++ b/contrib/ntp/ntpd/ntp_filegen.c
@@ -13,7 +13,7 @@
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#include <stdio.h>
@@ -55,6 +55,25 @@ static int valid_fileref P((char *, char *));
static FILEGEN *filegen_unregister P((char *));
#endif /* UNUSED */
+static void filegen_init P((char *, const char *, FILEGEN *));
+
+/*
+ * filegen_init
+ */
+
+static void
+filegen_init(char *prefix, const char *basename, FILEGEN *fp)
+{
+ fp->fp = NULL;
+ fp->prefix = prefix; /* Yes, this is TOTALLY lame! */
+ fp->basename = (char*)emalloc(strlen(basename) + 1);
+ strcpy(fp->basename, basename);
+ fp->id = 0;
+ fp->type = FILEGEN_DAY;
+ fp->flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
+}
+
+
/*
* open a file generation according to the current settings of gen
* will also provide a link to basename if requested to do so
@@ -169,7 +188,8 @@ filegen_open(
free(savename);
} else {
/*
- * there is at least a second link tpo this file
+ * there is at least a second link to
+ * this file.
* just remove the conflicting one
*/
if (
@@ -335,6 +355,11 @@ filegen_setup(
* reopen new file generation file on change of generation id
*/
if (gen->fp == NULL || gen->id != new_gen) {
+#if DEBUG
+ if (debug)
+ printf("filegen %0x %lu %lu %lu\n", gen->type, now,
+ gen->id, new_gen);
+#endif
filegen_open(gen, new_gen);
}
}
@@ -477,6 +502,7 @@ filegen_get(
void
filegen_register(
+ char *prefix,
const char *name,
FILEGEN *filegen
)
@@ -487,6 +513,9 @@ filegen_register(
if (debug > 3)
printf("filegen_register(\"%s\",%x)\n", name, (u_int)filegen);
#endif
+
+ filegen_init(prefix, name, filegen);
+
while (*f) {
if ((*f)->name == name || strcmp(name, (*f)->name) == 0) {
#ifdef XXX /* this gives the Alpha compiler fits */
diff --git a/contrib/ntp/ntpd/ntp_intres.c b/contrib/ntp/ntpd/ntp_intres.c
index 7f27f21..2a4b51f 100644
--- a/contrib/ntp/ntpd/ntp_intres.c
+++ b/contrib/ntp/ntpd/ntp_intres.c
@@ -15,6 +15,11 @@
* might go about autoconfiguring an NTP distribution network.
*
*/
+ /*
+ * For special situations define the FORCE_DNSRETRY Macro
+ * to force retries even if it fails the lookup.
+ * Use with extreme caution since it will then retry forever.
+ */
#ifdef HAVE_CONFIG_H
# include <config.h>
@@ -29,7 +34,6 @@
#include <stdio.h>
#include <ctype.h>
-#include <netdb.h>
#include <signal.h>
/**/
@@ -40,6 +44,9 @@
# include <sys/param.h> /* MAXHOSTNAMELEN (often) */
#endif
+#include <isc/net.h>
+#include <isc/result.h>
+
#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
/*
@@ -135,7 +142,6 @@ char *req_file; /* name of the file with configuration info */
/* end stuff to be filled in */
-static RETSIGTYPE bong P((int));
static void checkparent P((void));
static void removeentry P((struct conf_entry *));
static void addentry P((char *, int, int, int, int, u_int,
@@ -167,6 +173,23 @@ struct ntp_res_c_pkt { /* Control packet: */
};
+static void resolver_exit P((int));
+
+/*
+ * Call here instead of just exiting
+ */
+
+static void resolver_exit (int code)
+{
+#ifdef SYS_WINNT
+ CloseHandle(ResolverEventHandle);
+ ResolverEventHandle = NULL;
+ ExitThread(code); /* Just to kill the thread not the process */
+#else
+ exit(code); /* kill the forked process */
+#endif
+}
+
/*
* ntp_res_recv: Process an answer from the resolver
*/
@@ -193,11 +216,13 @@ void
ntp_intres(void)
{
FILE *in;
-#ifdef HAVE_SIGSUSPEND
- sigset_t set;
-
- sigemptyset(&set);
-#endif /* HAVE_SIGSUSPEND */
+ struct timeval tv;
+ fd_set fdset;
+#ifdef SYS_WINNT
+ DWORD rc;
+#else
+ int rc;
+#endif
#ifdef DEBUG
if (debug > 1) {
@@ -210,7 +235,7 @@ ntp_intres(void)
if (!authistrusted(req_keyid)) {
msyslog(LOG_ERR, "invalid request keyid %08x",
req_keyid );
- exit(1);
+ resolver_exit(1);
}
}
@@ -222,106 +247,93 @@ ntp_intres(void)
if ((in = fopen(req_file, "r")) == NULL) {
msyslog(LOG_ERR, "can't open configuration file %s: %m",
req_file);
- exit(1);
+ resolver_exit(1);
}
readconf(in, req_file);
(void) fclose(in);
+#ifdef DEBUG
if (!debug )
+#endif
(void) unlink(req_file);
/*
- * Sleep a little to make sure the server is completely up
- */
-
- sleep(SLEEPTIME);
-
- /*
- * Make a first cut at resolving the bunch
- */
- doconfigure(1);
- if (confentries == NULL) {
-#if defined SYS_WINNT
- ExitThread(0); /* Don't want to kill whole NT process */
-#else
- exit(0); /* done that quick */
-#endif
- }
-
- /*
- * Here we've got some problem children. Set up the timer
- * and wait for it.
+ * Set up the timers to do first shot immediately.
*/
- resolve_value = resolve_timer = MINRESOLVE;
+ resolve_timer = 0;
+ resolve_value = MINRESOLVE;
config_timer = CONFIG_TIME;
-#ifndef SYS_WINNT
- (void) signal_no_reset(SIGALRM, bong);
- alarm(ALARM_TIME);
-#endif /* SYS_WINNT */
for (;;) {
- if (confentries == NULL)
- exit(0);
-
checkparent();
if (resolve_timer == 0) {
- if (resolve_value < MAXRESOLVE)
- resolve_value <<= 1;
+ /*
+ * Sleep a little to make sure the network is completely up
+ */
+ sleep(SLEEPTIME);
+ doconfigure(1);
+
+ /* prepare retry, in case there's more work to do */
resolve_timer = resolve_value;
#ifdef DEBUG
if (debug > 2)
msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
#endif
+ if (resolve_value < MAXRESOLVE)
+ resolve_value <<= 1;
+
config_timer = CONFIG_TIME;
- doconfigure(1);
- continue;
- } else if (config_timer == 0) {
+ } else if (config_timer == 0) { /* MB: in which case would this be required ? */
+ doconfigure(0);
+ /* MB: should we check now if we could exit, similar to the code above? */
config_timer = CONFIG_TIME;
#ifdef DEBUG
if (debug > 2)
msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
#endif
- doconfigure(0);
+ }
+
+ if (confentries == NULL)
+ resolver_exit(0); /* done */
+
+#ifdef SYS_WINNT
+ rc = WaitForSingleObject(ResolverEventHandle, 1000 * ALARM_TIME); /* in milliseconds */
+
+ if ( rc == WAIT_OBJECT_0 ) { /* signaled by the main thread */
+ resolve_timer = 0; /* retry resolving immediately */
continue;
}
-#ifndef SYS_WINNT
- /*
- * There is a race in here. Is okay, though, since
- * all it does is delay things by 30 seconds.
- */
-# ifdef HAVE_SIGSUSPEND
- sigsuspend(&set);
-# else
- sigpause(0);
-# endif /* HAVE_SIGSUSPEND */
-#else
+
+ if ( rc != WAIT_TIMEOUT ) /* not timeout: error */
+ resolver_exit(1);
+
+#else /* not SYS_WINNT */
+ tv.tv_sec = ALARM_TIME;
+ tv.tv_usec = 0;
+ FD_ZERO(&fdset);
+ FD_SET(resolver_pipe_fd[0], &fdset);
+ rc = select(resolver_pipe_fd[0] + 1, &fdset, (fd_set *)0, (fd_set *)0, &tv);
+
+ if (rc > 0) { /* parent process has written to the pipe */
+ read(resolver_pipe_fd[0], (char *)&rc, sizeof(rc)); /* make pipe empty */
+ resolve_timer = 0; /* retry resolving immediately */
+ continue;
+ }
+
+ if ( rc < 0 ) /* select() returned error */
+ resolver_exit(1);
+#endif
+
+ /* normal timeout, keep on waiting */
if (config_timer > 0)
- config_timer--;
+ config_timer--;
if (resolve_timer > 0)
- resolve_timer--;
- sleep(ALARM_TIME);
-#endif /* SYS_WINNT */
+ resolve_timer--;
}
}
-#ifndef SYS_WINNT
-/*
- * bong - service and reschedule an alarm() interrupt
- */
-static RETSIGTYPE
-bong(
- int sig
- )
-{
- if (config_timer > 0)
- config_timer--;
- if (resolve_timer > 0)
- resolve_timer--;
- alarm(ALARM_TIME);
-}
-#endif /* SYS_WINNT */
/*
* checkparent - see if our parent process is still running
@@ -344,7 +356,7 @@ checkparent(void)
*/
if (getppid() == 1) {
msyslog(LOG_INFO, "parent died before we finished, exiting");
- exit(0);
+ resolver_exit(0);
}
#endif /* SYS_WINNT && SYS_VXWORKS*/
}
@@ -411,7 +423,9 @@ addentry(
ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));
ce->ce_name = cp;
ce->ce_peeraddr = 0;
+#ifdef ISC_PLATFORM_HAVEIPV6
ce->ce_peeraddr6 = in6addr_any;
+#endif
ANYSOCK(&ce->peer_store);
ce->ce_hmode = (u_char)mode;
ce->ce_version = (u_char)version;
@@ -450,17 +464,18 @@ findhostaddr(
)
{
struct addrinfo *addr;
+ struct addrinfo hints;
int error;
checkparent(); /* make sure our guy is still running */
- if (entry->ce_name != NULL && SOCKNUL(&entry->peer_store)) {
+ if (entry->ce_name != NULL && !SOCKNUL(&entry->peer_store)) {
/* HMS: Squawk? */
msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");
return 1;
}
- if (entry->ce_name == NULL && !SOCKNUL(&entry->peer_store)) {
+ if (entry->ce_name == NULL && SOCKNUL(&entry->peer_store)) {
msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
return 0;
}
@@ -471,7 +486,16 @@ findhostaddr(
msyslog(LOG_INFO, "findhostaddr: Resolving <%s>",
entry->ce_name);
#endif /* DEBUG */
- error = getaddrinfo(entry->ce_name, NULL, NULL, &addr);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ /*
+ * If the IPv6 stack is not available look only for IPv4 addresses
+ */
+ if (isc_net_probeipv6() != ISC_R_SUCCESS)
+ hints.ai_family = AF_INET;
+
+ error = getaddrinfo(entry->ce_name, NULL, &hints, &addr);
if (error == 0) {
entry->peer_store = *((struct sockaddr_storage*)(addr->ai_addr));
if (entry->peer_store.ss_family == AF_INET) {
@@ -484,6 +508,10 @@ findhostaddr(
entry->ce_config.v6_flag = 1;
}
}
+ else if (error == EAI_NONAME)
+ {
+ msyslog(LOG_ERR, "host name not found: %s", entry->ce_name);
+ }
} else {
#ifdef DEBUG
if (debug > 2)
@@ -496,15 +524,37 @@ findhostaddr(
(char *)&entry->ce_name, MAXHOSTNAMELEN,
NULL, 0, 0);
}
+#ifdef DEBUG
+ if (debug > 2)
+ printf("intres: got error status of: %d\n", error);
+#endif
+ /*
+ * If the resolver failed, see if the failure is
+ * temporary. If so, return success.
+ */
if (error != 0) {
- /*
- * If the resolver is in use, see if the failure is
- * temporary. If so, return success.
- */
- if (h_errno == TRY_AGAIN)
- return (1);
- return (0);
+ switch (error)
+ {
+ case EAI_AGAIN:
+ return (1);
+ case EAI_NONAME:
+#ifndef FORCE_DNSRETRY
+ return (0);
+#else
+ return (1);
+#endif
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ case EAI_FAIL:
+#ifdef EAI_SYSTEM
+ case EAI_SYSTEM:
+ return (1);
+#endif
+ default:
+ return (0);
+ }
}
if (entry->ce_name) {
@@ -531,22 +581,28 @@ openntp(void)
{
struct addrinfo hints;
struct addrinfo *addrResult;
+ const char *localhost = "127.0.0.1"; /* Use IPv6 loopback */
- if (sockfd >= 0)
+ if (sockfd != INVALID_SOCKET)
return;
memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
+
+ /*
+ * For now only bother with IPv4
+ */
+ hints.ai_family = AF_INET;
+
hints.ai_socktype = SOCK_DGRAM;
- if (getaddrinfo(NULL, "ntp", &hints, &addrResult)!=0) {
+ if (getaddrinfo(localhost, "ntp", &hints, &addrResult)!=0) {
msyslog(LOG_ERR, "getaddrinfo failed: %m");
- exit(1);
+ resolver_exit(1);
}
sockfd = socket(addrResult->ai_family, addrResult->ai_socktype, 0);
if (sockfd == -1) {
msyslog(LOG_ERR, "socket() failed: %m");
- exit(1);
+ resolver_exit(1);
}
/*
@@ -556,13 +612,13 @@ openntp(void)
#if defined(O_NONBLOCK)
if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
msyslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");
- exit(1);
+ resolver_exit(1);
}
#else
#if defined(FNDELAY)
if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
msyslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
- exit(1);
+ resolver_exit(1);
}
#else
# include "Bletch: NEED NON BLOCKING IO"
@@ -573,13 +629,13 @@ openntp(void)
int on = 1;
if (ioctlsocket(sockfd,FIONBIO,(u_long *) &on) == SOCKET_ERROR) {
msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
- exit(1); /* Windows NT - set socket in non-blocking mode */
+ resolver_exit(1); /* Windows NT - set socket in non-blocking mode */
}
}
#endif /* SYS_WINNT */
if (connect(sockfd, addrResult->ai_addr, addrResult->ai_addrlen) == -1) {
msyslog(LOG_ERR, "openntp: connect() failed: %m");
- exit(1);
+ resolver_exit(1);
}
freeaddrinfo(addrResult);
}
@@ -607,7 +663,7 @@ request(
checkparent(); /* make sure our guy is still running */
- if (sockfd < 0)
+ if (sockfd == INVALID_SOCKET)
openntp();
#ifdef SYS_WINNT
@@ -643,7 +699,7 @@ request(
/* Make sure mbz_itemsize <= sizeof reqpkt.data */
if (sizeof(struct conf_peer) > sizeof (reqpkt.data)) {
msyslog(LOG_ERR, "Bletch: conf_peer is too big for reqpkt.data!");
- exit(1);
+ resolver_exit(1);
}
memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer));
reqpkt.keyid = htonl(req_keyid);
@@ -678,7 +734,7 @@ request(
overlap.Offset = overlap.OffsetHigh = (DWORD)0;
overlap.hEvent = hReadWriteEvent;
ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n,
- (LPDWORD)&NumberOfBytesWritten, (LPOVERLAPPED)&overlap);
+ NULL, (LPOVERLAPPED)&overlap);
if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
msyslog(LOG_ERR, "send to NTP server failed: %m");
return 0;
@@ -689,6 +745,11 @@ request(
msyslog(LOG_ERR, "WaitForSingleObject failed: %m");
return 0;
}
+ if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
+ (LPDWORD)&NumberOfBytesWritten, FALSE)) {
+ msyslog(LOG_ERR, "GetOverlappedResult for WriteFile fails: %m");
+ return 0;
+ }
#endif /* SYS_WINNT */
@@ -718,8 +779,10 @@ request(
}
else if (n == 0)
{
+#ifdef DEBUG
if (debug)
msyslog(LOG_INFO, "select() returned 0.");
+#endif
return 0;
}
@@ -734,7 +797,7 @@ request(
}
#else /* Overlapped I/O used on non-blocking sockets on Windows NT */
ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, (DWORD)REQ_LEN_MAC,
- (LPDWORD)&NumberOfBytesRead, (LPOVERLAPPED)&overlap);
+ NULL, (LPOVERLAPPED)&overlap);
if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
msyslog(LOG_ERR, "ReadFile() fails: %m");
return 0;
@@ -742,11 +805,16 @@ request(
dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
if (dwWait == WAIT_FAILED) {
- msyslog(LOG_ERR, "WaitForSingleObject fails: %m");
+ msyslog(LOG_ERR, "WaitForSingleObject for ReadFile fails: %m");
return 0;
}
continue;
}
+ if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
+ (LPDWORD)&NumberOfBytesRead, FALSE)) {
+ msyslog(LOG_ERR, "GetOverlappedResult fails: %m");
+ return 0;
+ }
n = NumberOfBytesRead;
#endif /* SYS_WINNT */
@@ -941,7 +1009,7 @@ readconf(
msyslog(LOG_ERR,
"tokenizing error in file `%s', quitting",
name);
- exit(1);
+ resolver_exit(1);
}
}
@@ -950,7 +1018,7 @@ readconf(
msyslog(LOG_ERR,
"format error for integer token `%s', file `%s', quitting",
token[i], name);
- exit(1);
+ resolver_exit(1);
}
}
@@ -959,27 +1027,27 @@ readconf(
intval[TOK_HMODE] != MODE_BROADCAST) {
msyslog(LOG_ERR, "invalid mode (%ld) in file %s",
intval[TOK_HMODE], name);
- exit(1);
+ resolver_exit(1);
}
if (intval[TOK_VERSION] > NTP_VERSION ||
intval[TOK_VERSION] < NTP_OLDVERSION) {
msyslog(LOG_ERR, "invalid version (%ld) in file %s",
intval[TOK_VERSION], name);
- exit(1);
+ resolver_exit(1);
}
if (intval[TOK_MINPOLL] < NTP_MINPOLL ||
intval[TOK_MINPOLL] > NTP_MAXPOLL) {
msyslog(LOG_ERR, "invalid MINPOLL value (%ld) in file %s",
intval[TOK_MINPOLL], name);
- exit(1);
+ resolver_exit(1);
}
if (intval[TOK_MAXPOLL] < NTP_MINPOLL ||
intval[TOK_MAXPOLL] > NTP_MAXPOLL) {
msyslog(LOG_ERR, "invalid MAXPOLL value (%ld) in file %s",
intval[TOK_MAXPOLL], name);
- exit(1);
+ resolver_exit(1);
}
if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE | FLAG_PREFER |
@@ -987,7 +1055,7 @@ readconf(
!= 0) {
msyslog(LOG_ERR, "invalid flags (%ld) in file %s",
intval[TOK_FLAGS], name);
- exit(1);
+ resolver_exit(1);
}
flags = 0;
@@ -1026,6 +1094,12 @@ doconfigure(
register struct conf_entry *ce;
register struct conf_entry *ceremove;
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO, "Running doconfigure %s DNS",
+ dores ? "with" : "without" );
+#endif
+
ce = confentries;
while (ce != NULL) {
#ifdef DEBUG
@@ -1034,7 +1108,7 @@ doconfigure(
"doconfigure: <%s> has peeraddr %s",
ce->ce_name, stoa(&ce->peer_store));
#endif
- if (dores && !SOCKNUL(&(ce->peer_store))) {
+ if (dores && SOCKNUL(&(ce->peer_store))) {
if (!findhostaddr(ce)) {
msyslog(LOG_ERR,
"couldn't resolve `%s', giving up on it",
diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c
index 9f2acea..faa4646 100644
--- a/contrib/ntp/ntpd/ntp_io.c
+++ b/contrib/ntp/ntpd/ntp_io.c
@@ -12,9 +12,10 @@
#include "ntp_io.h"
#include "iosignal.h"
#include "ntp_refclock.h"
-#include "ntp_if.h"
#include "ntp_stdlib.h"
+#include "ntp_request.h"
#include "ntp.h"
+#include "ntp_unixtime.h"
/* Don't include ISC's version of IPv6 variables and structures */
#define ISC_IPV6_H 1
@@ -31,28 +32,53 @@
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET_IN_SYSTM_H
-# include <netinet/in_systm.h>
-#else /* Some old linux systems at least have in_system.h instead. */
-# ifdef HAVE_NETINET_IN_SYSTEM_H
-# include <netinet/in_system.h>
-# endif
-#endif /* HAVE_NETINET_IN_SYSTM_H */
-#ifdef HAVE_NETINET_IP_H
-# include <netinet/ip.h>
-#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
# include <sys/sockio.h>
#endif
-#include <arpa/inet.h>
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+
+/*
+ * setsockopt does not always have the same arg declaration
+ * across all platforms. If it's not defined we make it empty
+ */
+
+#ifndef SETSOCKOPT_ARG_CAST
+#define SETSOCKOPT_ARG_CAST
+#endif
+
+/*
+ * Set up some macros to look for IPv6 and IPv6 multicast
+ */
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && !defined(DISABLE_IPV6)
+
+#define INCLUDE_IPV6_SUPPORT
+
+#if defined(INCLUDE_IPV6_SUPPORT) && defined(IPV6_JOIN_GROUP) && defined(IPV6_LEAVE_GROUP)
+#define INCLUDE_IPV6_MULTICAST_SUPPORT
+
+#endif /* IPV6 Multicast Support */
+#endif /* IPv6 Support */
extern int listen_to_virtual_ips;
+extern const char *specific_interface;
+
+#if defined(SO_TIMESTAMP) && defined(SCM_TIMESTAMP)
+#if defined(CMSG_FIRSTHDR)
+#define HAVE_TIMESTAMP
+#define USE_TIMESTAMP_CMSG
+#ifndef TIMESTAMP_CTLMSGBUF_SIZE
+#define TIMESTAMP_CTLMSGBUF_SIZE 1536 /* moderate default */
+#endif
+#else
+/* fill in for old/other timestamp interfaces */
+#endif
+#endif
#if defined(SYS_WINNT)
#include <transmitbuff.h>
@@ -106,12 +132,10 @@ u_long io_timereset; /* time counters were reset */
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 */
+
+volatile int disable_dynamic_updates; /* when set to != 0 dynamic updates won't happen */
#ifdef REFCLOCK
/*
@@ -141,43 +165,118 @@ static struct refclockio *refio;
*/
fd_set activefds;
int maxactivefd;
+/*
+ * bit alternating value to detect verified interfaces during an update cycle
+ */
+static u_char sys_interphase = 0;
-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));
+static struct interface *new_interface P((struct interface *));
+static void add_interface P((struct interface *));
+static int update_interfaces P((u_short, interface_receiver_t, void *));
+static void remove_interface P((struct interface *));
+static struct interface *create_interface P((u_short, struct interface *));
+
+static int move_fd P((SOCKET));
+
+/*
+ * Multicast functions
+ */
+static isc_boolean_t addr_ismulticast P((struct sockaddr_storage *));
+/*
+ * Not all platforms support multicast
+ */
+#ifdef MCAST
+static isc_boolean_t socket_multicast_enable P((struct interface *, int, struct sockaddr_storage *));
+static isc_boolean_t socket_multicast_disable P((struct interface *, struct sockaddr_storage *));
+#endif
+
+#ifdef DEBUG
+static void print_interface P((struct interface *, char *, char *));
+#define DPRINT_INTERFACE(_LVL_, _ARGS_) do { if (debug >= (_LVL_)) { print_interface _ARGS_; } } while (0)
+#else
+#define DPRINT_INTERFACE(_LVL_, _ARGS_)
#endif
-static char * fdbits P((int, fd_set *));
-static void set_reuseaddr P((int));
typedef struct vsock vsock_t;
+enum desc_type { FD_TYPE_SOCKET, FD_TYPE_FILE };
struct vsock {
SOCKET fd;
+ enum desc_type type;
ISC_LINK(vsock_t) link;
};
-ISC_LIST(vsock_t) sockets_list;
+#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
+/*
+ * async notification processing (e. g. routing sockets)
+ */
+/*
+ * support for receiving data on fd that is not a refclock or a socket
+ * like e. g. routing sockets
+ */
+struct asyncio_reader {
+ SOCKET fd; /* fd to be read */
+ void *data; /* possibly local data */
+ void (*receiver)(struct asyncio_reader *); /* input handler */
+ ISC_LINK(struct asyncio_reader) link; /* the list this is being kept in */
+};
+
+ISC_LIST(struct asyncio_reader) asyncio_reader_list;
+
+static void delete_asyncio_reader P((struct asyncio_reader *));
+static struct asyncio_reader *new_asyncio_reader P((void));
+static void add_asyncio_reader P((struct asyncio_reader *, enum desc_type));
+static void remove_asyncio_reader P((struct asyncio_reader *));
+
+#endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
+
+static void init_async_notifications P((void));
+
+static int create_sockets P((u_short));
+static SOCKET open_socket P((struct sockaddr_storage *, int, int, struct interface *));
+static char * fdbits P((int, fd_set *));
+static void set_reuseaddr P((int));
+static isc_boolean_t socket_broadcast_enable P((struct interface *, SOCKET, struct sockaddr_storage *));
+static isc_boolean_t socket_broadcast_disable P((struct interface *, struct sockaddr_storage *));
+
+ISC_LIST(vsock_t) fd_list;
typedef struct remaddr remaddr_t;
struct remaddr {
- struct sockaddr_storage addr;
- int if_index;
- ISC_LINK(remaddr_t) link;
+ struct sockaddr_storage addr;
+ struct interface *interface;
+ 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));
+ISC_LIST(struct interface) inter_list;
+
+static struct interface *wildipv4 = NULL;
+static struct interface *wildipv6 = NULL;
+
+static void add_fd_to_list P((SOCKET, enum desc_type));
+static void close_and_delete_fd_from_list P((SOCKET));
+static void add_addr_to_list P((struct sockaddr_storage *, struct interface *));
+static void delete_addr_from_list P((struct sockaddr_storage *));
+static struct interface *find_addr_in_list P((struct sockaddr_storage *));
+static struct interface *find_flagged_addr_in_list P((struct sockaddr_storage *, int));
+static void create_wildcards P((u_short));
+static isc_boolean_t address_okay P((struct interface *));
+static void convert_isc_if P((isc_interface_t *, struct interface *, u_short));
+static void delete_interface_from_list P((struct interface *));
+static struct interface *getinterface P((struct sockaddr_storage *, int));
+static struct interface *findlocalinterface P((struct sockaddr_storage *, int));
+static struct interface *findlocalcastinterface P((struct sockaddr_storage *, int));
+
+/*
+ * Routines to read the ntp packets
+ */
+#if !defined(HAVE_IO_COMPLETION_PORT)
+static inline int read_network_packet P((SOCKET, struct interface *, l_fp));
+static inline int read_refclock_packet P((SOCKET, struct refclockio *, l_fp));
+#endif
#ifdef SYS_WINNT
/*
@@ -209,6 +308,168 @@ connection_reset_fix(SOCKET fd) {
return (ISC_R_UNEXPECTED);
}
#endif
+
+/*
+ * on Unix systems the stdio library typically
+ * makes use of file descriptors in the lower
+ * integer range. stdio usually will make use
+ * of the file descriptor in the range of
+ * [0..FOPEN_MAX)
+ * in order to keep this range clean for socket
+ * file descriptors we attempt to move them above
+ * FOPEM_MAX. This is not as easy as it sounds as
+ * FOPEN_MAX changes from implementation to implementation
+ * and may exceed to current file decriptor limits.
+ * We are using following strategy:
+ * - keep a current socket fd boundary initialized with
+ * max(0, min(getdtablesize() - FD_CHUNK, FOPEN_MAX))
+ * - attempt to move the descriptor to the boundary or
+ * above.
+ * - if that fails and boundary > 0 set boundary
+ * to min(0, socket_fd_boundary - FD_CHUNK)
+ * -> retry
+ * if failure and boundary == 0 return old fd
+ * - on success close old fd return new fd
+ *
+ * effects:
+ * - fds will be moved above the socket fd boundary
+ * if at all possible.
+ * - the socket boundary will be reduced until
+ * allocation is possible or 0 is reached - at this
+ * point the algrithm will be disabled
+ */
+static int move_fd(SOCKET fd)
+{
+#if !defined(SYS_WINNT) && defined(F_DUPFD)
+#ifndef FD_CHUNK
+#define FD_CHUNK 10
+#endif
+/*
+ * number of fds we would like to have for
+ * stdio FILE* available.
+ * we can pick a "low" number as our use of
+ * FILE* is limited to log files and temporarily
+ * to data and config files. Except for log files
+ * we don't keep the other FILE* open beyond the
+ * scope of the function that opened it.
+ */
+#ifndef FD_PREFERRED_SOCKBOUNDARY
+#define FD_PREFERRED_SOCKBOUNDARY 48
+#endif
+
+#ifndef HAVE_GETDTABLESIZE
+/*
+ * if we have no idea about the max fd value set up things
+ * so we will start at FOPEN_MAX
+ */
+#define getdtablesize() (FOPEN_MAX+FD_CHUNK)
+#endif
+
+#ifndef FOPEN_MAX
+#define FOPEN_MAX 20 /* assume that for the lack of anything better */
+#endif
+ static SOCKET socket_boundary = -1;
+ SOCKET newfd;
+
+ /*
+ * check whether boundary has be set up
+ * already
+ */
+ if (socket_boundary == -1) {
+ socket_boundary = max(0, min(getdtablesize() - FD_CHUNK,
+ min(FOPEN_MAX, FD_PREFERRED_SOCKBOUNDARY)));
+#ifdef DEBUG
+ msyslog(LOG_DEBUG, "ntp_io: estimated max descriptors: %d, initial socket boundary: %d",
+ getdtablesize(), socket_boundary);
+#endif
+ }
+
+ /*
+ * Leave a space for stdio to work in. potentially moving the
+ * socket_boundary lower until allocation succeeds.
+ */
+ do {
+ if (fd >= 0 && fd < socket_boundary) {
+ /* inside reserved range: attempt to move fd */
+ newfd = fcntl(fd, F_DUPFD, socket_boundary);
+
+ if (newfd != -1) {
+ /* success: drop the old one - return the new one */
+ (void)close(fd);
+ return (newfd);
+ }
+ } else {
+ /* outside reserved range: no work - return the original one */
+ return (fd);
+ }
+ socket_boundary = max(0, socket_boundary - FD_CHUNK);
+#ifdef DEBUG
+ msyslog(LOG_DEBUG, "ntp_io: selecting new socket boundary: %d",
+ socket_boundary);
+#endif
+ } while (socket_boundary > 0);
+#endif /* !defined(SYS_WINNT) && defined(F_DUPFD) */
+ return (fd);
+}
+
+#ifdef DEBUG_TIMING
+/*
+ * collect timing information for various processing
+ * paths. currently we only pass then on to the file
+ * for later processing. this could also do histogram
+ * based analysis in other to reduce the load (and skew)
+ * dur to the file output
+ */
+void
+collect_timing(struct recvbuf *rb, const char *tag, int count, l_fp *dts)
+{
+ char buf[2048];
+
+ snprintf(buf, sizeof(buf), "%s %d %s %s",
+ (rb != NULL) ?
+ ((rb->dstadr) ? stoa(&rb->recv_srcadr) : "-REFCLOCK-") : "-",
+ count, lfptoa(dts, 9), tag);
+ record_timing_stats(buf);
+}
+#endif
+
+/*
+ * About dynamic interfaces, sockets, reception and more...
+ *
+ * the code solves following tasks:
+ *
+ * - keep a current list of active interfaces in order
+ * to bind to to the interface address on NTP_PORT so that
+ * all wild and specific bindings for NTP_PORT are taken by ntpd
+ * to avoid other daemons messing with the time or sockets.
+ * - all interfaces keep a list of peers that are referencing
+ * the interface in order to quickly re-assign the peers to
+ * new interface in case an interface is deleted (=> gone from system or
+ * down)
+ * - have a preconfigured socket ready with the right local address
+ * for transmission and reception
+ * - have an address list for all destination addresses used within ntpd
+ * to find the "right" preconfigured socket.
+ * - facilitate updating the internal interface list with respect to
+ * the current kernel state
+ *
+ * special issues:
+ *
+ * - mapping of multicast addresses to the interface affected is not always
+ * one to one - especially on hosts with multiple interfaces
+ * the code here currently allocates a separate interface entry for those
+ * multicast addresses
+ * iff it is able to bind to a *new* socket with the multicast address (flags |= MCASTIF)
+ * in case of failure the multicast address is bound to an existing interface.
+ * - on some systems it is perfectly legal to assign the same address to
+ * multiple interfaces. Therefore this code does not keep a list of interfaces
+ * but a list of interfaces that represent a unique address as determined by the kernel
+ * by the procedure in findlocalinterface. Thus it is perfectly legal to see only
+ * one representative of a group of real interfaces if they share the same address.
+ *
+ * Frank Kardel 20050910
+ */
+
/*
* init_io - initialize I/O data structures and call socket creation routine
*/
@@ -216,6 +477,11 @@ void
init_io(void)
{
#ifdef SYS_WINNT
+ if (!Win32InitSockets())
+ {
+ netsyslog(LOG_ERR, "No useable winsock.dll: %m");
+ exit(1);
+ }
init_transmitbuff();
#endif /* SYS_WINNT */
@@ -230,28 +496,27 @@ init_io(void)
handler_calls = handler_pkts = 0;
io_timereset = 0;
loopback_interface = NULL;
- loopback6_interface = NULL;
+ any_interface = NULL;
+ any6_interface = NULL;
#ifdef REFCLOCK
- refio = 0;
+ refio = NULL;
#endif
#if defined(HAVE_SIGNALED_IO)
(void) set_signal();
#endif
-#ifdef SYS_WINNT
- if (!Win32InitSockets())
- {
- netsyslog(LOG_ERR, "No useable winsock.dll: %m");
- exit(1);
- }
-#endif /* SYS_WINNT */
+ ISC_LIST_INIT(fd_list);
- ISC_LIST_INIT(sockets_list);
+#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
+ ISC_LIST_INIT(asyncio_reader_list);
+#endif
ISC_LIST_INIT(remoteaddr_list);
+ ISC_LIST_INIT(inter_list);
+
/*
* Create the sockets
*/
@@ -259,95 +524,436 @@ init_io(void)
(void) create_sockets(htons(NTP_PORT));
UNBLOCKIO();
+ init_async_notifications();
+
+ DPRINTF(3, ("init_io: maxactivefd %d\n", maxactivefd));
+}
+
#ifdef DEBUG
- if (debug)
- printf("init_io: maxactivefd %d\n", maxactivefd);
+/*
+ * function to dump the contents of the interface structure
+ * for debugging use only.
+ */
+void
+interface_dump(struct interface *itf)
+{
+ u_char* cp;
+ int i;
+ /* Limit the size of the sockaddr_storage hex dump */
+ int maxsize = min(32, sizeof(struct sockaddr_storage));
+
+ printf("Dumping interface: %p\n", itf);
+ printf("fd = %d\n", itf->fd);
+ printf("bfd = %d\n", itf->bfd);
+ printf("sin = %s,\n", stoa(&(itf->sin)));
+ cp = (u_char*) &(itf->sin);
+ for(i = 0; i < maxsize; i++)
+ {
+ printf("%02x", *cp++);
+ if((i+1)%4 == 0)
+ printf(" ");
+ }
+ printf("\n");
+ printf("bcast = %s,\n", stoa(&(itf->bcast)));
+ cp = (u_char*) &(itf->bcast);
+ for(i = 0; i < maxsize; i++)
+ {
+ printf("%02x", *cp++);
+ if((i+1)%4 == 0)
+ printf(" ");
+ }
+ printf("\n");
+ printf("mask = %s,\n", stoa(&(itf->mask)));
+ cp = (u_char*) &(itf->mask);
+ for(i = 0; i < maxsize; i++)
+ {
+ printf("%02x", *cp++);
+ if((i+1)%4 == 0)
+ printf(" ");
+ }
+ printf("\n");
+ printf("name = %s\n", itf->name);
+ printf("flags = 0x%08x\n", itf->flags);
+ printf("last_ttl = %d\n", itf->last_ttl);
+ printf("addr_refid = %08x\n", itf->addr_refid);
+ printf("num_mcast = %d\n", itf->num_mcast);
+ printf("received = %ld\n", itf->received);
+ printf("sent = %ld\n", itf->sent);
+ printf("notsent = %ld\n", itf->notsent);
+ printf("ifindex = %u\n", itf->ifindex);
+ printf("scopeid = %u\n", itf->scopeid);
+ printf("peercnt = %u\n", itf->peercnt);
+ printf("phase = %u\n", itf->phase);
+}
+
+/*
+ * print_interface - helper to output debug information
+ */
+static void
+print_interface(struct interface *iface, char *pfx, char *sfx)
+{
+ printf("%sinterface #%d: fd=%d, bfd=%d, name=%s, flags=0x%x, scope=%d, ifindex=%d",
+ pfx,
+ iface->ifnum,
+ iface->fd,
+ iface->bfd,
+ iface->name,
+ iface->flags,
+ iface->scopeid,
+ iface->ifindex);
+ /* Leave these as three printf calls. */
+ printf(", sin=%s",
+ stoa((&iface->sin)));
+ if (iface->flags & INT_BROADCAST)
+ printf(", bcast=%s,",
+ stoa((&iface->bcast)));
+ if (iface->family == AF_INET)
+ printf(", mask=%s",
+ stoa((&iface->mask)));
+ printf(", %s:%s", iface->ignore_packets == ISC_FALSE ? "Enabled" : "Disabled", sfx);
+ if (debug > 4) /* in-depth debugging only */
+ interface_dump(iface);
+}
+
#endif
+
+#if !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET)
+/*
+ * create an asyncio_reader structure
+ */
+static struct asyncio_reader *
+new_asyncio_reader()
+{
+ struct asyncio_reader *reader;
+
+ reader = (struct asyncio_reader *)emalloc(sizeof(struct asyncio_reader));
+
+ memset((char *)reader, 0, sizeof(*reader));
+ ISC_LINK_INIT(reader, link);
+ reader->fd = INVALID_SOCKET;
+ return reader;
}
-int
-create_wildcards(u_short port) {
+/*
+ * delete a reader
+ */
+static void
+delete_asyncio_reader(struct asyncio_reader *reader)
+{
+ free(reader);
+}
- int idx = 0;
+/*
+ * add asynchio_reader
+ */
+static void
+add_asyncio_reader(struct asyncio_reader *reader, enum desc_type type)
+{
+ ISC_LIST_APPEND(asyncio_reader_list, reader, link);
+ add_fd_to_list(reader->fd, type);
+}
+
+/*
+ * remove asynchio_reader
+ */
+static void
+remove_asyncio_reader(struct asyncio_reader *reader)
+{
+ ISC_LIST_UNLINK_TYPE(asyncio_reader_list, reader, link, struct asyncio_reader);
+
+ if (reader->fd != INVALID_SOCKET)
+ close_and_delete_fd_from_list(reader->fd);
+
+ reader->fd = INVALID_SOCKET;
+}
+#endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */
+
+/*
+ * interface list enumerator - visitor pattern
+ */
+void
+interface_enumerate(interface_receiver_t receiver, void *data)
+{
+ interface_info_t ifi;
+ struct interface *interf;
+
+ ifi.action = IFS_EXISTS;
+
+ for (interf = ISC_LIST_HEAD(inter_list);
+ interf != NULL;
+ interf = ISC_LIST_NEXT(interf, link)) {
+ ifi.interface = interf;
+ receiver(data, &ifi);
+ }
+}
+
+/*
+ * do standard initialization of interface structure
+ */
+static void
+init_interface(struct interface *interface)
+{
+ memset((char *)interface, 0, sizeof(struct interface));
+ ISC_LINK_INIT(interface, link);
+ ISC_LIST_INIT(interface->peers);
+ interface->fd = INVALID_SOCKET;
+ interface->bfd = INVALID_SOCKET;
+ interface->num_mcast = 0;
+ interface->received = 0;
+ interface->sent = 0;
+ interface->notsent = 0;
+ interface->peercnt = 0;
+ interface->phase = sys_interphase;
+}
+
+/*
+ * create new interface structure initialize from
+ * template structure or via standard initialization
+ * function
+ */
+static struct interface *
+new_interface(struct interface *interface)
+{
+ static u_int sys_ifnum = 0;
+
+ struct interface *iface = (struct interface *)emalloc(sizeof(struct interface));
+
+ if (interface != NULL)
+ {
+ memcpy((char*)iface, (char*)interface, sizeof(*interface));
+ }
+ else
+ {
+ init_interface(iface);
+ }
+
+ iface->ifnum = sys_ifnum++; /* count every new instance of an interface in the system */
+ iface->starttime = current_time;
+
+ return iface;
+}
+
+/*
+ * return interface storage into free memory pool
+ */
+static void
+delete_interface(struct interface *interface)
+{
+ free(interface);
+}
+
+/*
+ * link interface into list of known interfaces
+ */
+static void
+add_interface(struct interface *interface)
+{
/*
- * create pseudo-interface with wildcard IPv4 address
+ * Calculate the address hash
*/
- 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)
+ interface->addr_refid = addr2refid(&interface->sin);
+
+ ISC_LIST_APPEND(inter_list, interface, link);
+ ninterfaces++;
+}
+
+/*
+ * remove interface from known interface list and clean up
+ * associated resources
+ */
+static void
+remove_interface(struct interface *interface)
+{
+ struct sockaddr_storage resmask;
+
+ ISC_LIST_UNLINK_TYPE(inter_list, interface, link, struct interface);
+
+ delete_interface_from_list(interface);
+
+ if (interface->fd != INVALID_SOCKET)
+ {
+ msyslog(LOG_INFO, "Deleting interface #%d %s, %s#%d, interface stats: received=%ld, sent=%ld, dropped=%ld, active_time=%ld secs",
+ interface->ifnum,
+ interface->name,
+ stoa((&interface->sin)),
+ NTP_PORT, /* XXX should extract port from sin structure */
+ interface->received,
+ interface->sent,
+ interface->notsent,
+ current_time - interface->starttime);
+
+ close_and_delete_fd_from_list(interface->fd);
+ }
+
+ if (interface->bfd != INVALID_SOCKET)
+ {
+ msyslog(LOG_INFO, "Deleting interface #%d %s, broadcast address %s#%d",
+ interface->ifnum,
+ interface->name,
+ stoa((&interface->bcast)),
+ (u_short) NTP_PORT); /* XXX extract port from sin structure */
+ close_and_delete_fd_from_list(interface->bfd);
+ }
+
+ ninterfaces--;
+ ntp_monclearinterface(interface);
+
+ /* remove restrict interface entry */
+
+ /*
+ * Blacklist bound interface address
+ */
+ SET_HOSTMASK(&resmask, interface->sin.ss_family);
+ hack_restrict(RESTRICT_REMOVEIF, &interface->sin, &resmask,
+ RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
+}
+
+static void
+list_if_listening(struct interface *interface, u_short port)
+{
+ msyslog(LOG_INFO, "Listening on interface #%d %s, %s#%d %s",
+ interface->ifnum,
+ interface->name,
+ stoa((&interface->sin)),
+ ntohs( (u_short) port),
+ (interface->ignore_packets == ISC_FALSE) ?
+ "Enabled": "Disabled");
+}
+
+static void
+create_wildcards(u_short port) {
+ isc_boolean_t okipv4 = ISC_TRUE;
/*
- * enable possible multicast reception on the broadcast socket
+ * create pseudo-interface with wildcard IPv4 address
*/
- 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);
+#ifdef IPV6_V6ONLY
+ if(isc_net_probeipv4() != ISC_R_SUCCESS)
+ okipv4 = ISC_FALSE;
+#endif
+
+ if(okipv4 == ISC_TRUE) {
+ struct interface *interface = new_interface(NULL);
+
+ interface->family = AF_INET;
+ interface->sin.ss_family = AF_INET;
+ ((struct sockaddr_in*)&interface->sin)->sin_addr.s_addr = htonl(INADDR_ANY);
+ ((struct sockaddr_in*)&interface->sin)->sin_port = port;
+ (void) strncpy(interface->name, "wildcard", sizeof(interface->name));
+ interface->mask.ss_family = AF_INET;
+ ((struct sockaddr_in*)&interface->mask)->sin_addr.s_addr = htonl(~(u_int32)0);
+ interface->flags = INT_BROADCAST | INT_UP | INT_WILDCARD;
+ interface->ignore_packets = ISC_TRUE;
+#if defined(MCAST)
+ /*
+ * enable possible multicast reception on the broadcast socket
+ */
+ interface->bcast.ss_family = AF_INET;
+ ((struct sockaddr_in*)&interface->bcast)->sin_port = port;
+ ((struct sockaddr_in*)&interface->bcast)->sin_addr.s_addr = htonl(INADDR_ANY);
#endif /* MCAST */
- wildipv4 = idx;
- idx++;
+ interface->fd = open_socket(&interface->sin,
+ interface->flags, 1, interface);
+
+ if (interface->fd != INVALID_SOCKET) {
+ wildipv4 = interface;
+ any_interface = interface;
+
+ add_addr_to_list(&interface->sin, interface);
+ add_interface(interface);
+ list_if_listening(interface, port);
+ } else {
+ msyslog(LOG_ERR, "unable to bind to wildcard socket address %s - another process may be running - EXITING",
+ stoa((&interface->sin)));
+ exit(1);
+ }
+ }
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
/*
* create pseudo-interface with wildcard IPv6 address
*/
if (isc_net_probeipv6() == ISC_R_SUCCESS) {
- inter_list[idx].sin.ss_family = AF_INET6;
- ((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_addr = in6addr_any;
- ((struct sockaddr_in6*)&inter_list[idx].sin)->sin6_port = port;
- (void) strncpy(inter_list[idx].name, "wildcard", sizeof(inter_list[idx].name));
- inter_list[idx].mask.ss_family = AF_INET6;
- memset(&((struct sockaddr_in6*)&inter_list[idx].mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));
- inter_list[idx].bfd = INVALID_SOCKET;
- inter_list[idx].num_mcast = 0;
- inter_list[idx].received = 0;
- inter_list[idx].sent = 0;
- inter_list[idx].notsent = 0;
- inter_list[idx].flags = 0;
- any6_interface = &inter_list[idx];
- wildipv6 = idx;
- idx++;
+ struct interface *interface = new_interface(NULL);
+
+ interface->family = AF_INET6;
+ interface->sin.ss_family = AF_INET6;
+ ((struct sockaddr_in6*)&interface->sin)->sin6_addr = in6addr_any;
+ ((struct sockaddr_in6*)&interface->sin)->sin6_port = port;
+# ifdef ISC_PLATFORM_HAVESCOPEID
+ ((struct sockaddr_in6*)&interface->sin)->sin6_scope_id = 0;
+# endif
+ (void) strncpy(interface->name, "wildcard", sizeof(interface->name));
+ interface->mask.ss_family = AF_INET6;
+ memset(&((struct sockaddr_in6*)&interface->mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));
+ interface->flags = INT_UP | INT_WILDCARD;
+ interface->ignore_packets = ISC_TRUE;
+
+ interface->fd = open_socket(&interface->sin,
+ interface->flags, 1, interface);
+
+ if (interface->fd != INVALID_SOCKET) {
+ wildipv6 = interface;
+ any6_interface = interface;
+ add_addr_to_list(&interface->sin, interface);
+ add_interface(interface);
+ list_if_listening(interface, port);
+ } else {
+ msyslog(LOG_ERR, "unable to bind to wildcard socket address %s - another process may be running - EXITING",
+ stoa((&interface->sin)));
+ exit(1);
+ }
}
#endif
- return (idx);
}
-isc_boolean_t
-address_okay(isc_interface_t *isc_if) {
-#ifdef DEBUG
- if (debug > 2)
- printf("address_okay: listen Virtual: %d, IF name: %s, Up Flag: %d\n",
- listen_to_virtual_ips, isc_if->name, (isc_if->flags & INTERFACE_F_UP));
-#endif
+static isc_boolean_t
+address_okay(struct interface *iface) {
- if (listen_to_virtual_ips == 0 && (strchr(isc_if->name, (int)':') != NULL))
- return (ISC_FALSE);
+ DPRINTF(4, ("address_okay: listen Virtual: %d, IF name: %s\n",
+ listen_to_virtual_ips, iface->name));
- /* 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.
+ /*
+ * Always allow the loopback
*/
-/* if ((isc_if->flags & INTERFACE_F_UP) == 0)
- return (ISC_FALSE);
-*/
+ if((iface->flags & INT_LOOPBACK) != 0) {
+ DPRINTF(4, ("address_okay: loopback - OK\n"));
+ return (ISC_TRUE);
+ }
+
+ /*
+ * Check if the interface is specified
+ */
+ if (specific_interface != NULL) {
+ if (strcasecmp(iface->name, specific_interface) == 0) {
+ DPRINTF(4, ("address_okay: specific interface name matched - OK\n"));
+ return (ISC_TRUE);
+ } else {
+ DPRINTF(4, ("address_okay: specific interface name NOT matched - FAIL\n"));
+ return (ISC_FALSE);
+ }
+ }
+ else {
+ if (listen_to_virtual_ips == 0 &&
+ (strchr(iface->name, (int)':') != NULL)) {
+ DPRINTF(4, ("address_okay: virtual ip/alias - FAIL\n"));
+ return (ISC_FALSE);
+ }
+ }
+
+ DPRINTF(4, ("address_okay: OK\n"));
return (ISC_TRUE);
}
-void
-convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) {
+
+static void
+convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port)
+{
+ itf->scopeid = 0;
+ itf->family = (short) isc_if->af;
+ strcpy(itf->name, isc_if->name);
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));
@@ -367,35 +973,31 @@ convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) {
&(isc_if->netmask.type.in),
sizeof(struct in_addr));
((struct sockaddr_in*)&itf->mask)->sin_port = port;
-
- if (((isc_if->flags & INTERFACE_F_LOOPBACK) != 0) && (loopback_interface == NULL))
- {
- loopback_interface = itf;
- }
}
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
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));
+ sizeof(((struct sockaddr_in6 *)&itf->sin)->sin6_addr));
((struct sockaddr_in6 *)&itf->sin)->sin6_port = port;
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ ((struct sockaddr_in6 *)&itf->sin)->sin6_scope_id = isc_netaddr_getzone(&isc_if->address);
+ itf->scopeid = isc_netaddr_getzone(&isc_if->address);
+#endif
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;
- }
+ /* Copy the interface index */
+ itf->ifindex = isc_if->ifindex;
}
-#endif /* HAVE_IPV6 */
+#endif /* INCLUDE_IPV6_SUPPORT */
+
- /* Process the rest of the flags */
+ /* Process the rest of the flags */
if((isc_if->flags & INTERFACE_F_UP) != 0)
itf->flags |= INT_UP;
@@ -403,57 +1005,228 @@ convert_isc_if(isc_interface_t *isc_if, struct interface *itf, u_short port) {
itf->flags |= INT_LOOPBACK;
if((isc_if->flags & INTERFACE_F_POINTTOPOINT) != 0)
itf->flags |= INT_PPP;
+ if((isc_if->flags & INTERFACE_F_MULTICAST) != 0)
+ itf->flags |= INT_MULTICAST;
+
}
+
/*
- * create_sockets - create a socket for each interface plus a default
- * socket for when we don't know where to send
+ * refresh_interface
+ *
+ * some OSes have been observed to keep
+ * cached routes even when more specific routes
+ * become available.
+ * this can be mitigated by re-binding
+ * the socket.
*/
static int
-create_sockets(
- u_short port
+refresh_interface(struct interface * interface)
+{
+#ifdef OS_MISSES_SPECIFIC_ROUTE_UPDATES
+ if (interface->fd != INVALID_SOCKET)
+ {
+ close_and_delete_fd_from_list(interface->fd);
+ interface->fd = open_socket(&interface->sin,
+ interface->flags, 0, interface);
+ /*
+ * reset TTL indication so TTL is is set again
+ * next time around
+ */
+ interface->last_ttl = 0;
+ return interface->fd != INVALID_SOCKET;
+ }
+ else
+ {
+ return 0; /* invalid sockets are not refreshable */
+ }
+#else /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
+ return interface->fd != INVALID_SOCKET;
+#endif /* !OS_MISSES_SPECIFIC_ROUTE_UPDATES */
+}
+
+/*
+ * interface_update - externally callable update function
+ */
+void
+interface_update(interface_receiver_t receiver, void *data)
+{
+ if (!disable_dynamic_updates) {
+ int new_interface_found;
+
+ BLOCKIO();
+ new_interface_found = update_interfaces(htons(NTP_PORT), receiver, data);
+ UNBLOCKIO();
+
+ if (new_interface_found) {
+#ifdef DEBUG
+ msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver");
+#endif
+#ifdef SYS_WINNT
+ /* wake up the resolver thread */
+ if (ResolverEventHandle != NULL)
+ SetEvent(ResolverEventHandle);
+#else
+ /* write any single byte to the pipe to wake up the resolver process */
+ write( resolver_pipe_fd[1], &new_interface_found, 1 );
+#endif
+ }
+ }
+}
+
+/*
+ * find out if a given interface structure contains
+ * a wildcard address
+ */
+static int
+is_wildcard_addr(struct sockaddr_storage *sas)
+{
+ if (sas->ss_family == AF_INET &&
+ ((struct sockaddr_in*)sas)->sin_addr.s_addr == htonl(INADDR_ANY))
+ return 1;
+
+#ifdef INCLUDE_IPV6_SUPPORT
+ if (sas->ss_family == AF_INET6 &&
+ memcmp(&((struct sockaddr_in6*)sas)->sin6_addr, &in6addr_any,
+ sizeof(in6addr_any) == 0))
+ return 1;
+#endif
+
+ return 0;
+}
+
+#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
+/*
+ * enable/disable re-use of wildcard address socket
+ */
+static void
+set_wildcard_reuse(int family, int on)
+{
+ int onvalue = 1;
+ int offvalue = 0;
+ int *onoff;
+ SOCKET fd = INVALID_SOCKET;
+
+ onoff = on ? &onvalue : &offvalue;
+
+ switch (family) {
+ case AF_INET:
+ if (any_interface) {
+ fd = any_interface->fd;
+ }
+ break;
+
+#ifdef INCLUDE_IPV6_SUPPORT
+ case AF_INET6:
+ if (any6_interface) {
+ fd = any6_interface->fd;
+ }
+ break;
+#endif /* !INCLUDE_IPV6_SUPPORT */
+ }
+
+ if (fd != INVALID_SOCKET) {
+ if (setsockopt(fd, SOL_SOCKET,
+ SO_REUSEADDR, (char *)onoff,
+ sizeof(*onoff))) {
+ netsyslog(LOG_ERR, "set_wildcard_reuse: setsockopt(SO_REUSEADDR, %s) failed: %m", *onoff ? "on" : "off");
+ }
+ DPRINTF(4, ("set SO_REUSEADDR to %s on %s\n", *onoff ? "ON" : "OFF",
+ stoa((family == AF_INET) ?
+ &any_interface->sin : &any6_interface->sin)));
+ }
+}
+#endif /* OS_NEEDS_REUSEADDR_FOR_IFADDRBIND */
+
+/*
+ * update_interface strategy
+ *
+ * toggle configuration phase
+ *
+ * Phase 1:
+ * forall currently existing interfaces
+ * if address is known:
+ * drop socket - rebind again
+ *
+ * if address is NOT known:
+ * attempt to create a new interface entry
+ *
+ * Phase 2:
+ * forall currently known non MCAST and WILDCARD interfaces
+ * if interface does not match configuration phase (not seen in phase 1):
+ * remove interface from known interface list
+ * forall peers associated with this interface
+ * disconnect peer from this interface
+ *
+ * Phase 3:
+ * attempt to re-assign interfaces to peers
+ *
+ */
+
+static int
+update_interfaces(
+ u_short port,
+ interface_receiver_t receiver,
+ void *data
)
{
- struct sockaddr_storage resmask;
- int i;
+ interface_info_t ifi;
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;
+ int new_interface_found = 0;
-#ifdef DEBUG
- if (debug)
- printf("create_sockets(%d)\n", ntohs( (u_short) port));
-#endif
+ DPRINTF(3, ("update_interfaces(%d)\n", ntohs( (u_short) port)));
+#ifdef INCLUDE_IPV6_SUPPORT
if (isc_net_probeipv6() == ISC_R_SUCCESS)
scan_ipv6 = ISC_TRUE;
-#ifdef HAVE_IPV6
+#if defined(DEBUG)
else
- netsyslog(LOG_ERR, "no IPv6 interfaces found");
+ if(debug)
+ netsyslog(LOG_ERR, "no IPv6 interfaces found");
+#endif
+#endif
+ if (isc_net_probeipv6() == ISC_R_SUCCESS)
+ scan_ipv6 = ISC_TRUE;
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(DEBUG)
+ else
+ if(debug)
+ netsyslog(LOG_ERR, "no IPv6 interfaces found");
#endif
if (isc_net_probeipv4() == ISC_R_SUCCESS)
scan_ipv4 = ISC_TRUE;
+#ifdef DEBUG
else
- netsyslog(LOG_ERR, "no IPv4 interfaces found");
-
- nwilds = create_wildcards(port);
- idx = nwilds;
+ if(debug)
+ netsyslog(LOG_ERR, "no IPv4 interfaces found");
+#endif
+ /*
+ * phase one - scan interfaces
+ * - create those that are not found
+ * - update those that are found
+ */
result = isc_interfaceiter_create(mctx, &iter);
+
if (result != ISC_R_SUCCESS)
- return (result);
+ return 0;
+ sys_interphase ^= 0x1; /* toggle system phase for finding untouched (to be deleted) interfaces */
+
for (result = isc_interfaceiter_first(iter);
result == ISC_R_SUCCESS;
result = isc_interfaceiter_next(iter))
{
isc_interface_t isc_if;
- unsigned int family;
-
+ unsigned int family;
+ struct interface interface;
+ struct interface *iface;
+
result = isc_interfaceiter_current(iter, &isc_if);
+
if (result != ISC_R_SUCCESS)
break;
@@ -466,152 +1239,266 @@ create_sockets(
if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
continue;
- /* Check to see if we are going to use the interface */
- if (address_okay(&isc_if) == ISC_TRUE) {
- convert_isc_if(&isc_if, &inter_list[idx], port);
- inter_list[idx].fd = INVALID_SOCKET;
- inter_list[idx].bfd = INVALID_SOCKET;
- inter_list[idx].num_mcast = 0;
- inter_list[idx].received = 0;
- inter_list[idx].sent = 0;
- inter_list[idx].notsent = 0;
- idx++;
+ /*
+ * create prototype
+ */
+ init_interface(&interface);
+
+ convert_isc_if(&isc_if, &interface, port);
+
+ /*
+ * Check to see if we are going to use the interface
+ * If we don't use it we mark it to drop any packet
+ * received but we still must create the socket and
+ * bind to it. This prevents other apps binding to it
+ * and potentially causing problems with more than one
+ * process fiddling with the clock
+ */
+ if (address_okay(&interface) == ISC_TRUE) {
+ interface.ignore_packets = ISC_FALSE;
+ }
+ else {
+ interface.ignore_packets = ISC_TRUE;
+ }
+
+ DPRINT_INTERFACE(4, (&interface, "examining ", "\n"));
+
+ if (!(interface.flags & INT_UP)) { /* interfaces must be UP to be usable */
+ DPRINTF(4, ("skipping interface %s (%s) - DOWN\n", interface.name, stoa(&interface.sin)));
+ continue;
+ }
+
+ /*
+ * skip any interfaces UP and bound to a wildcard
+ * address - some dhcp clients produce that in the
+ * wild
+ */
+ if (is_wildcard_addr(&interface.sin))
+ continue;
+
+ /*
+ * map to local *address* in order
+ * to map all duplicate interfaces to an interface structure
+ * with the appropriate socket (our name space is
+ * (ip-address) - NOT (interface name, ip-address))
+ */
+ iface = getinterface(&interface.sin, INT_WILDCARD);
+
+ if (iface && refresh_interface(iface))
+ {
+ /*
+ * found existing and up to date interface - mark present
+ */
+
+ iface->phase = sys_interphase;
+ DPRINT_INTERFACE(4, (iface, "updating ", " present\n"));
+ ifi.action = IFS_EXISTS;
+ ifi.interface = iface;
+ if (receiver)
+ receiver(data, &ifi);
+ }
+ else
+ {
+ /*
+ * this is new or refreshing failed - add to our interface list
+ * if refreshing failed we will delete the interface structure in
+ * phase 2 as the interface was not marked current. We can bind to
+ * the address as the refresh code already closed the offending socket
+ */
+
+ iface = create_interface(port, &interface);
+
+ if (iface)
+ {
+ ifi.action = IFS_CREATED;
+ ifi.interface = iface;
+ if (receiver)
+ receiver(data, &ifi);
+
+ new_interface_found = 1;
+
+ DPRINT_INTERFACE(3, (iface, "updating ", " new - created\n"));
+ }
+ else
+ {
+ DPRINT_INTERFACE(3, (&interface, "updating ", " new - creation FAILED"));
+
+ msyslog(LOG_INFO, "failed to initialize interface for address %s", stoa(&interface.sin));
+ continue;
+ }
}
}
+
isc_interfaceiter_destroy(&iter);
- ninterfaces = idx;
/*
- * I/O Completion Ports don't care about the select and FD_SET
+ * phase 2 - delete gone interfaces - reassigning peers to other interfaces
*/
-#ifndef HAVE_IO_COMPLETION_PORT
- maxactivefd = 0;
- FD_ZERO(&activefds);
-#endif
- for (i = 0; i < ninterfaces; i++) {
- inter_list[i].fd = open_socket(&inter_list[i].sin,
- inter_list[i].flags & INT_BROADCAST, 0);
- if (inter_list[i].bfd != INVALID_SOCKET)
- msyslog(LOG_INFO, "Listening on interface %s, %s#%d",
- inter_list[i].name,
- stoa((&inter_list[i].sin)),
- NTP_PORT);
- if ((inter_list[i].flags & INT_BROADCAST) &&
- inter_list[i].bfd != INVALID_SOCKET)
- msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
- stoa((&inter_list[i].bcast)),
- NTP_PORT);
-#if defined (HAVE_IO_COMPLETION_PORT)
- if (inter_list[i].fd != INVALID_SOCKET) {
- io_completion_port_add_socket(inter_list[i].fd, &inter_list[i]);
+ {
+ struct interface *interf = ISC_LIST_HEAD(inter_list);
+
+ while (interf != NULL)
+ {
+ struct interface *next = ISC_LIST_NEXT(interf, link);
+
+ if (!(interf->flags & (INT_WILDCARD|INT_MCASTIF))) {
+ /*
+ * if phase does not match sys_phase this interface was not
+ * enumerated during interface scan - so it is gone and
+ * will be deleted here unless it is solely an MCAST/WILDCARD interface
+ */
+ if (interf->phase != sys_interphase) {
+ struct peer *peer;
+ DPRINT_INTERFACE(3, (interf, "updating ", "GONE - deleting\n"));
+ remove_interface(interf);
+
+ ifi.action = IFS_DELETED;
+ ifi.interface = interf;
+ if (receiver)
+ receiver(data, &ifi);
+
+ peer = ISC_LIST_HEAD(interf->peers);
+ /*
+ * disconnect peer from deleted interface
+ */
+ while (peer != NULL) {
+ struct peer *npeer = ISC_LIST_NEXT(peer, ilink);
+
+ /*
+ * this one just lost it's interface
+ */
+ set_peerdstadr(peer, NULL);
+
+ peer = npeer;
+ }
+
+ /*
+ * update globals in case we lose
+ * a loopback interface
+ */
+ if (interf == loopback_interface)
+ loopback_interface = NULL;
+
+ delete_interface(interf);
+ }
+ }
+ interf = next;
}
-#endif
}
/*
- * Now that we have opened all the sockets, turn off the reuse
- * flag for security.
+ * phase 3 - re-configure as the world has changed if necessary
*/
- set_reuseaddr(0);
+ refresh_all_peerinterfaces();
+ return new_interface_found;
+}
+
+/*
+ * 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
+ )
+{
+#ifndef HAVE_IO_COMPLETION_PORT
/*
- * Blacklist all bound interface addresses
- * Wildcard interfaces are ignored.
+ * I/O Completion Ports don't care about the select and FD_SET
*/
+ maxactivefd = 0;
+ FD_ZERO(&activefds);
+#endif
- 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);
- }
+ DPRINTF(2, ("create_sockets(%d)\n", ntohs( (u_short) port)));
+ create_wildcards(port);
+
+ update_interfaces(port, NULL, NULL);
+
/*
- * Calculate the address hash for each interface address.
+ * Now that we have opened all the sockets, turn off the reuse
+ * flag for security.
*/
- for (i = 0; i < ninterfaces; i++) {
- inter_list[i].addr_refid = addr2refid(&inter_list[i].sin);
- }
+ set_reuseaddr(0);
+ DPRINTF(2, ("create_sockets: Total interfaces = %d\n", ninterfaces));
-#ifdef DEBUG
- if (debug > 1) {
- printf("create_sockets: ninterfaces=%d\n", ninterfaces);
- for (i = 0; i < ninterfaces; i++) {
- printf("interface %d: fd=%d, bfd=%d, name=%.8s, flags=0x%x\n",
- i,
- inter_list[i].fd,
- inter_list[i].bfd,
- inter_list[i].name,
- inter_list[i].flags);
- /* Leave these as three printf calls. */
- printf(" sin=%s",
- stoa((&inter_list[i].sin)));
- if (inter_list[i].flags & INT_BROADCAST)
- printf(" bcast=%s,",
- stoa((&inter_list[i].bcast)));
- printf(" mask=%s\n",
- stoa((&inter_list[i].mask)));
- }
- }
-#endif
return ninterfaces;
}
/*
- * io_setbclient - open the broadcast client sockets
+ * create_interface - create a new interface for a given prototype
+ * binding the socket.
*/
-void
-io_setbclient(void)
+static struct interface *
+create_interface(
+ u_short port,
+ struct interface *iface
+ )
{
- int i;
+ struct sockaddr_storage resmask;
+ struct interface *interface;
-#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;
+ DPRINTF(2, ("create_interface(%s#%d)\n", stoa(&iface->sin), ntohs( (u_short) port)));
- /* Is this a broadcast address? */
- if (!(inter_list[i].flags & INT_BROADCAST))
- continue;
+ /* build an interface */
+ interface = new_interface(iface);
+
+ /*
+ * create socket
+ */
+ interface->fd = open_socket(&interface->sin,
+ interface->flags, 0, interface);
+
+ if (interface->fd != INVALID_SOCKET)
+ list_if_listening(interface, port);
+
+ if ((interface->flags & INT_BROADCAST) &&
+ interface->bfd != INVALID_SOCKET)
+ msyslog(LOG_INFO, "Listening on broadcast address %s#%d",
+ stoa((&interface->bcast)),
+ ntohs( (u_short) port));
+
+ if (interface->fd == INVALID_SOCKET &&
+ interface->bfd == INVALID_SOCKET) {
+ msyslog(LOG_ERR, "unable to create socket on %s (%d) for %s#%d",
+ interface->name,
+ interface->ifnum,
+ stoa((&interface->sin)),
+ ntohs( (u_short) port));
+ delete_interface(interface);
+ return NULL;
+ }
+
+ /*
+ * Blacklist bound interface address
+ */
+
+ SET_HOSTMASK(&resmask, interface->sin.ss_family);
+ hack_restrict(RESTRICT_FLAGS, &interface->sin, &resmask,
+ RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
+
+ /*
+ * set globals with the first found
+ * loopback interface of the appropriate class
+ */
+ if ((loopback_interface == NULL) &&
+ (interface->family == AF_INET) &&
+ ((interface->flags & INT_LOOPBACK) != 0))
+ {
+ loopback_interface = interface;
+ }
- /* Do we already have the broadcast address open? */
- if (inter_list[i].flags & INT_BCASTOPEN)
- continue;
+ /*
+ * put into our interface list
+ */
+ add_addr_to_list(&interface->sin, interface);
+ add_interface(interface);
-#ifdef SYS_SOLARIS
- inter_list[i].bcast.sin_addr.s_addr = htonl(INADDR_ANY);
-#endif
-#ifdef OPEN_BCAST_SOCKET /* Was: !SYS_DOMAINOS && !SYS_LINUX */
- inter_list[i].bfd = open_socket(&inter_list[i].bcast,
- INT_BROADCAST, 1);
- if (inter_list[i].bfd != INVALID_SOCKET) {
- inter_list[i].flags |= INT_BCASTOPEN;
-#if defined (HAVE_IO_COMPLETION_PORT)
- io_completion_port_add_socket(inter_list[i].bfd, &inter_list[i]);
-#endif
- }
-#ifdef DEBUG
- if (debug) {
- if (inter_list[i].bfd != INVALID_SOCKET)
- printf("io_setbclient: Opened broadcast client on interface %d, socket: %d\n",
- i, inter_list[i].bfd);
- else
- printf("io_setbclient: Unable to Open broadcast client on interface %d\n",
- i);
- }
-#endif
-#endif
- }
-#ifdef OPEN_BCAST_SOCKET
- set_reuseaddr(0);
-#endif
-#ifdef DEBUG
- if (debug)
- printf("io_setbclient: Opened broadcast clients\n");
-#endif
+ DPRINT_INTERFACE(2, (interface, "created ", "\n"));
+ return interface;
}
/*
@@ -621,15 +1508,22 @@ io_setbclient(void)
*/
static void
set_reuseaddr(int flag) {
- int i;
-
- for (i=0; i < ninterfaces; i++) {
+ struct interface *interf;
+
+ for (interf = ISC_LIST_HEAD(inter_list);
+ interf != NULL;
+ interf = ISC_LIST_NEXT(interf, link)) {
+ if (interf->flags & INT_WILDCARD)
+ continue;
+
/*
- * if inter_list[ n ].fd is -1, we might have a adapter
+ * if interf->fd is INVALID_SOCKET, we might have a adapter
* configured but not present
*/
- if (inter_list[i].fd != INVALID_SOCKET) {
- if (setsockopt(inter_list[i].fd, SOL_SOCKET,
+ DPRINTF(4, ("setting SO_REUSEADDR on %.16s@%s to %s\n", interf->name, stoa(&interf->sin), flag ? "on" : "off"));
+
+ if (interf->fd != INVALID_SOCKET) {
+ if (setsockopt(interf->fd, SOL_SOCKET,
SO_REUSEADDR, (char *)&flag,
sizeof(flag))) {
netsyslog(LOG_ERR, "set_reuseaddr: setsockopt(SO_REUSEADDR, %s) failed: %m", flag ? "on" : "off");
@@ -638,203 +1532,422 @@ set_reuseaddr(int flag) {
}
}
-
/*
- * io_multicast_add() - add multicast group address
+ * This is just a wrapper around an internal function so we can
+ * make other changes as necessary later on
*/
void
-io_multicast_add(
- struct sockaddr_storage addr
- )
+enable_broadcast(struct interface *iface, struct sockaddr_storage *baddr)
{
-#ifdef MCAST
- struct ip_mreq mreq;
- int i = ninterfaces; /* Use the next interface */
- u_int32 haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
- struct in_addr iaddr;
- SOCKET s;
- struct sockaddr_in *sinp;
+#ifdef SO_BROADCAST
+ socket_broadcast_enable(iface, iface->fd, baddr);
+#endif
+}
-#ifdef HAVE_IPV6
- struct ipv6_mreq mreq6;
- struct in6_addr iaddr6;
- struct sockaddr_in6 *sin6p;
-#endif /* HAVE_IPV6 */
+#ifdef OPEN_BCAST_SOCKET
+/*
+ * Enable a broadcast address to a given socket
+ * The socket is in the inter_list all we need to do is enable
+ * broadcasting. It is not this function's job to select the socket
+ */
+static isc_boolean_t
+socket_broadcast_enable(struct interface *iface, SOCKET fd, struct sockaddr_storage *maddr)
+{
+#ifdef SO_BROADCAST
+ int on = 1;
- switch (addr.ss_family)
+ if (maddr->ss_family == AF_INET)
+ {
+ /* if this interface can support broadcast, set SO_BROADCAST */
+ if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
+ (char *)&on, sizeof(on)))
+ {
+ netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) enable failure on address %s: %m",
+ stoa(maddr));
+ }
+#ifdef DEBUG
+ else if (debug > 1) {
+ printf("Broadcast enabled on socket %d for address %s\n",
+ fd, stoa(maddr));
+ }
+#endif
+ }
+ iface->flags |= INT_BCASTOPEN;
+ return ISC_TRUE;
+#else
+ return ISC_FALSE;
+#endif /* SO_BROADCAST */
+}
+
+/*
+ * Remove a broadcast address from a given socket
+ * The socket is in the inter_list all we need to do is disable
+ * broadcasting. It is not this function's job to select the socket
+ */
+static isc_boolean_t
+socket_broadcast_disable(struct interface *iface, struct sockaddr_storage *maddr)
+{
+#ifdef SO_BROADCAST
+ int off = 0; /* This seems to be OK as an int */
+
+ if (maddr->ss_family == AF_INET)
+ {
+ if (setsockopt(iface->fd, SOL_SOCKET, SO_BROADCAST,
+ (char *)&off, sizeof(off)))
+ {
+ netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) disable failure on address %s: %m",
+ stoa(maddr));
+ }
+ }
+ iface->flags &= ~INT_BCASTOPEN;
+ return ISC_TRUE;
+#else
+ return ISC_FALSE;
+#endif /* SO_BROADCAST */
+}
+
+#endif /* OPEN_BCAST_SOCKET */
+/*
+ * Check to see if the address is a multicast address
+ */
+static isc_boolean_t
+addr_ismulticast(struct sockaddr_storage *maddr)
+{
+ switch (maddr->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;
+ if (!IN_CLASSD(ntohl(((struct sockaddr_in*)maddr)->sin_addr.s_addr))) {
+ DPRINTF(4, ("multicast address %s not class D\n", stoa(maddr)));
+ return (ISC_FALSE);
}
- 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;
+ else
+ {
+ return (ISC_TRUE);
}
- 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
+ case AF_INET6 :
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ if (!IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)maddr)->sin6_addr)) {
+ DPRINTF(4, ("address %s not IPv6 multicast address\n", stoa(maddr)));
+ return (ISC_FALSE);
+ }
+ else
+ {
+ return (ISC_TRUE);
}
+/*
+ * If we don't have IPV6 support any IPV6 address is not multicast
+ */
+#else
+ return (ISC_FALSE);
+#endif
+ /*
+ * Never valid
+ */
+ default:
+ return (ISC_FALSE);
+ }
+}
+
+/*
+ * Multicast servers need to set the appropriate Multicast interface
+ * socket option in order for it to know which interface to use for
+ * send the multicast packet.
+ */
+void
+enable_multicast_if(struct interface *iface, struct sockaddr_storage *maddr)
+{
+#ifdef MCAST
+ /*u_char*/ TYPEOF_IP_MULTICAST_LOOP off = 0;
+
+ switch (maddr->ss_family)
+ {
+ case AF_INET:
+ if (setsockopt(iface->fd, IPPROTO_IP, IP_MULTICAST_IF,
+ (char *)&(((struct sockaddr_in*)&iface->sin)->sin_addr.s_addr),
+ sizeof(struct in_addr)) == -1) {
+ netsyslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_IF failure: %m on socket %d, addr %s for multicast address %s",
+ iface->fd, stoa(&iface->sin), stoa(maddr));
+ return;
+ }
+#ifdef IP_MULTICAST_LOOP
/*
- * 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)
+ * Don't send back to itself, but allow it to fail to set it
+ */
+ if (setsockopt(iface->fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+ SETSOCKOPT_ARG_CAST &off, sizeof(off)) == -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);
+ "setsockopt IP_MULTICAST_LOOP failure: %m on socket %d, addr %s for multicast address %s",
+ iface->fd, stoa(&iface->sin), stoa(maddr));
+ }
+#endif
+ DPRINTF(4, ("Added IPv4 multicast interface on socket %d, addr %s for multicast address %s\n",
+ iface->fd, stoa(&iface->sin),
+ stoa(maddr)));
break;
-#ifdef HAVE_IPV6
- case AF_INET6 :
-
- iaddr6 = ((struct sockaddr_in6*)&addr)->sin6_addr;
- if (!IN6_IS_ADDR_MULTICAST(&iaddr6)) {
+ case AF_INET6:
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ &iface->scopeid, sizeof(iface->scopeid)) == -1) {
netsyslog(LOG_ERR,
- "address %s not IPv6 multicast address",
- stoa(&addr));
+ "setsockopt IPV6_MULTICAST_IF failure: %m on socket %d, addr %s, scope %d for multicast address %s",
+ iface->fd, stoa(&iface->sin), iface->scopeid,
+ stoa(maddr));
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;
+#ifdef IPV6_MULTICAST_LOOP
+ /*
+ * Don't send back to itself, but allow it to fail to set it
+ */
+ if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+ &off, sizeof(off)) == -1) {
+ netsyslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_LOOP failure: %m on socket %d, addr %s for multicast address %s",
+ iface->fd, stoa(&iface->sin), stoa(maddr));
}
- 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);
+#endif
+ DPRINTF(4, ("Added IPv6 multicast interface on socket %d, addr %s, scope %d for multicast address %s\n",
+ iface->fd, stoa(&iface->sin), iface->scopeid,
+ stoa(maddr)));
+ break;
+#else
+ return;
+#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
+ }
+ return;
+#endif
+}
+
+/*
+ * Add a multicast address to a given socket
+ * The socket is in the inter_list all we need to do is enable
+ * multicasting. It is not this function's job to select the socket
+ */
+static isc_boolean_t
+socket_multicast_enable(struct interface *iface, int lscope, struct sockaddr_storage *maddr)
+{
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ struct ipv6_mreq mreq6;
+ struct in6_addr iaddr6;
+#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
+
+ struct ip_mreq mreq;
+
+ if (find_addr_in_list(maddr)) {
+ DPRINTF(4, ("socket_multicast_enable(%s): already enabled\n", stoa(maddr)));
+ return ISC_TRUE;
+ }
+
+ switch (maddr->ss_family)
+ {
+ case AF_INET:
+ memset((char *)&mreq, 0, sizeof(mreq));
+ mreq.imr_multiaddr = (((struct sockaddr_in*)maddr)->sin_addr);
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (setsockopt(iface->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *)&mreq, sizeof(mreq)) == -1) {
+ netsyslog(LOG_ERR,
+ "setsockopt IP_ADD_MEMBERSHIP failure: %m on socket %d, addr %s for %x / %x (%s)",
+ iface->fd, stoa(&iface->sin),
+ mreq.imr_multiaddr.s_addr,
+ mreq.imr_interface.s_addr, stoa(maddr));
+ return ISC_FALSE;
+ }
+ DPRINTF(4, ("Added IPv4 multicast membership on socket %d, addr %s for %x / %x (%s)\n",
+ iface->fd, stoa(&iface->sin),
+ mreq.imr_multiaddr.s_addr,
+ mreq.imr_interface.s_addr, stoa(maddr)));
+ break;
+ case AF_INET6:
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
/*
- * Try opening a socket for the specified class D address. This
- * works under SunOS 4.x, but not OSF1 .. :-(
+ * Enable reception of multicast packets
+ * If the address is link-local we can get the interface index
+ * from the scope id. Don't do this for other types of multicast
+ * addresses. For now let the kernel figure it out.
*/
- 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
+ memset((char *)&mreq6, 0, sizeof(mreq6));
+ iaddr6 = ((struct sockaddr_in6*)maddr)->sin6_addr;
+ mreq6.ipv6mr_multiaddr = iaddr6;
+ mreq6.ipv6mr_interface = lscope;
+
+ if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ (char *)&mreq6, sizeof(mreq6)) == -1) {
+ netsyslog(LOG_ERR,
+ "setsockopt IPV6_JOIN_GROUP failure: %m on socket %d, addr %s for interface %d(%s)",
+ iface->fd, stoa(&iface->sin),
+ mreq6.ipv6mr_interface, stoa(maddr));
+ return ISC_FALSE;
}
+ DPRINTF(4, ("Added IPv6 multicast group on socket %d, addr %s for interface %d(%s)\n",
+ iface->fd, stoa(&iface->sin),
+ mreq6.ipv6mr_interface, stoa(maddr)));
+ break;
+#else
+ return ISC_FALSE;
+#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
+ }
+ iface->flags |= INT_MCASTOPEN;
+ iface->num_mcast++;
+ add_addr_to_list(maddr, iface);
+ return ISC_TRUE;
+}
+
+/*
+ * Remove a multicast address from a given socket
+ * The socket is in the inter_list all we need to do is disable
+ * multicasting. It is not this function's job to select the socket
+ */
+static isc_boolean_t
+socket_multicast_disable(struct interface *iface, struct sockaddr_storage *maddr)
+{
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ struct ipv6_mreq mreq6;
+ struct in6_addr iaddr6;
+#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
+
+ struct ip_mreq mreq;
+ memset((char *)&mreq, 0, sizeof(mreq));
+
+ if (find_addr_in_list(maddr) == NULL) {
+ DPRINTF(4, ("socket_multicast_disable(%s): not enabled\n", stoa(maddr)));
+ return ISC_TRUE;
+ }
+ switch (maddr->ss_family)
+ {
+ case AF_INET:
+ mreq.imr_multiaddr = (((struct sockaddr_in*)&maddr)->sin_addr);
+ mreq.imr_interface.s_addr = ((struct sockaddr_in*)&iface->sin)->sin_addr.s_addr;
+ if (setsockopt(iface->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (char *)&mreq, sizeof(mreq)) == -1) {
+ netsyslog(LOG_ERR,
+ "setsockopt IP_DROP_MEMBERSHIP failure: %m on socket %d, addr %s for %x / %x (%s)",
+ iface->fd, stoa(&iface->sin),
+ mreq.imr_multiaddr.s_addr,
+ mreq.imr_interface.s_addr, stoa(maddr));
+ return ISC_FALSE;
+ }
+ break;
+ case AF_INET6:
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
/*
- * enable reception of multicast packets
+ * Disable reception of multicast packets
+ * If the address is link-local we can get the interface index
+ * from the scope id. Don't do this for other types of multicast
+ * addresses. For now let the kernel figure it out.
*/
+ iaddr6 = ((struct sockaddr_in6*)&maddr)->sin6_addr;
mreq6.ipv6mr_multiaddr = iaddr6;
- mreq6.ipv6mr_interface = 0;
- if(setsockopt(inter_list[i].fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- (char *)&mreq6, sizeof(mreq6)) == -1)
+ mreq6.ipv6mr_interface = iface->scopeid;
+
+ if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_LEAVE_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);
+ "setsockopt IPV6_LEAVE_GROUP failure: %m on socket %d, addr %s for %d(%s)",
+ iface->fd, stoa(&iface->sin),
+ mreq6.ipv6mr_interface, stoa(maddr));
+ return ISC_FALSE;
+ }
break;
-#endif /* HAVE_IPV6 */
+#else
+ return ISC_FALSE;
+#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
+
+ }
+ iface->num_mcast--;
+ if (iface->num_mcast <= 0) {
+ iface->num_mcast = 0;
+ iface->flags &= ~INT_MCASTOPEN;
}
+ return ISC_TRUE;
+}
+
+/*
+ * io_setbclient - open the broadcast client sockets
+ */
+void
+io_setbclient(void)
+{
+#ifdef OPEN_BCAST_SOCKET
+ struct interface *interf;
+ int nif = 0;
+ isc_boolean_t jstatus;
+ SOCKET fd;
+
+ set_reuseaddr(1);
+
+ for (interf = ISC_LIST_HEAD(inter_list);
+ interf != NULL;
+ interf = ISC_LIST_NEXT(interf, link)) {
+ if (interf->flags & INT_WILDCARD)
+ continue;
+
+ /* use only allowed addresses */
+ if (interf->ignore_packets == ISC_TRUE)
+ continue;
+ /* Only IPv4 addresses are valid for broadcast */
+ if (interf->sin.ss_family != AF_INET)
+ continue;
+ /* Is this a broadcast address? */
+ if (!(interf->flags & INT_BROADCAST))
+ continue;
+
+ /* Skip the loopback addresses */
+ if (interf->flags & INT_LOOPBACK)
+ continue;
+
+ /* Do we already have the broadcast address open? */
+ if (interf->flags & INT_BCASTOPEN) {
+ /* account for already open interfaces to aviod misleading warning below */
+ nif++;
+ continue;
+ }
+
+ /*
+ * Try to open the broadcast address
+ */
+ interf->family = AF_INET;
+ interf->bfd = open_socket(&interf->bcast,
+ INT_BROADCAST, 0, interf);
+
+ /*
+ * If we succeeded then we use it otherwise
+ * enable the underlying address
+ */
+ if (interf->bfd == INVALID_SOCKET) {
+ fd = interf->fd;
+ }
+ else {
+ fd = interf->bfd;
+ }
+
+ /* Enable Broadcast on socket */
+ jstatus = socket_broadcast_enable(interf, fd, &interf->sin);
+ if (jstatus == ISC_TRUE)
+ {
+ nif++;
+ netsyslog(LOG_INFO,"io_setbclient: Opened broadcast client on interface #%d %s, socket: %d",
+ interf->ifnum, interf->name, fd);
+ interf->addr_refid = addr2refid(&interf->sin);
+ }
+ }
+ set_reuseaddr(0);
#ifdef DEBUG
if (debug)
- printf("io_multicast_add %s\n", stoa(&addr));
+ if (nif > 0)
+ printf("io_setbclient: Opened broadcast clients\n");
+#endif
+ if (nif == 0)
+ netsyslog(LOG_ERR, "Unable to listen for broadcasts, no broadcast interfaces available");
+#else
+ netsyslog(LOG_ERR, "io_setbclient: Broadcast Client disabled by build");
#endif
-#else /* MCAST */
- netsyslog(LOG_ERR,
- "cannot add multicast address %s as no MCAST support",
- stoa(&addr));
-#endif /* MCAST */
}
/*
@@ -843,139 +1956,225 @@ io_multicast_add(
void
io_unsetbclient(void)
{
- int i;
+ struct interface *interf;
+ isc_boolean_t lstatus;
- for (i = nwilds; i < ninterfaces; i++)
+ for (interf = ISC_LIST_HEAD(inter_list);
+ interf != NULL;
+ interf = ISC_LIST_NEXT(interf, link))
{
- if (!(inter_list[i].flags & INT_BCASTOPEN))
+ if (interf->flags & INT_WILDCARD)
+ continue;
+
+ if (!(interf->flags & INT_BCASTOPEN))
continue;
- close_socket(inter_list[i].bfd);
- inter_list[i].bfd = INVALID_SOCKET;
- inter_list[i].flags &= ~INT_BCASTOPEN;
+ lstatus = socket_broadcast_disable(interf, &interf->sin);
}
}
-
/*
- * io_multicast_del() - delete multicast group address
+ * io_multicast_add() - add multicast group address
*/
void
-io_multicast_del(
+io_multicast_add(
struct sockaddr_storage addr
)
{
#ifdef MCAST
- int i;
- struct ip_mreq mreq;
- u_int32 haddr;
-
-#ifdef HAVE_IPV6
- struct ipv6_mreq mreq6;
- struct in6_addr haddr6;
-#endif /* HAVE_IPV6 */
+ struct interface *interface, *iface;
+ int lscope = 0;
+
+ /*
+ * Check to see if this is a multicast address
+ */
+ if (addr_ismulticast(&addr) == ISC_FALSE)
+ return;
- switch (addr.ss_family)
+ /* If we already have it we can just return */
+ if (find_flagged_addr_in_list(&addr, INT_MCASTOPEN|INT_MCASTIF) != NULL)
{
- case AF_INET :
+ netsyslog(LOG_INFO, "Duplicate request found for multicast address %s",
+ stoa(&addr));
+ return;
+ }
- haddr = ntohl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
+#ifndef MULTICAST_NONEWSOCKET
+ interface = new_interface(NULL);
+
+ /*
+ * Open a new socket for the multicast address
+ */
+ interface->sin.ss_family = addr.ss_family;
+ interface->family = addr.ss_family;
- if (!IN_CLASSD(haddr))
- {
+ switch(addr.ss_family) {
+ case AF_INET:
+ memcpy(&(((struct sockaddr_in *)&interface->sin)->sin_addr),
+ &(((struct sockaddr_in*)&addr)->sin_addr),
+ sizeof(struct in_addr));
+ ((struct sockaddr_in*)&interface->sin)->sin_port = htons(NTP_PORT);
+ memset(&((struct sockaddr_in*)&interface->mask)->sin_addr.s_addr, 0xff, sizeof(struct in_addr));
+ break;
+ case AF_INET6:
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ memcpy(&(((struct sockaddr_in6 *)&interface->sin)->sin6_addr),
+ &((struct sockaddr_in6*)&addr)->sin6_addr,
+ sizeof(struct in6_addr));
+ ((struct sockaddr_in6*)&interface->sin)->sin6_port = htons(NTP_PORT);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ ((struct sockaddr_in6*)&interface->sin)->sin6_scope_id = ((struct sockaddr_in6*)&addr)->sin6_scope_id;
+#endif
+ memset(&((struct sockaddr_in6*)&interface->mask)->sin6_addr.s6_addr, 0xff, sizeof(struct in6_addr));
+#endif
+ iface = findlocalcastinterface(&addr, INT_MULTICAST);
+ if (iface) {
+# ifdef ISC_PLATFORM_HAVESCOPEID
+ lscope = ((struct sockaddr_in6*)&iface->sin)->sin6_scope_id;
+# endif
+ DPRINTF(4, ("Found interface #%d %s, scope: %d for address %s\n", iface->ifnum, iface->name, lscope, stoa(&addr)));
+ }
+ break;
+ }
+
+ set_reuseaddr(1);
+ interface->bfd = INVALID_SOCKET;
+ interface->fd = open_socket(&interface->sin,
+ INT_MULTICAST, 0, interface);
+
+ if (interface->fd != INVALID_SOCKET)
+ {
+ interface->bfd = INVALID_SOCKET;
+ interface->ignore_packets = ISC_FALSE;
+ interface->flags |= INT_MCASTIF;
+
+ (void) strncpy(interface->name, "multicast",
+ sizeof(interface->name));
+ ((struct sockaddr_in*)&interface->mask)->sin_addr.s_addr =
+ htonl(~(u_int32)0);
+ DPRINT_INTERFACE(2, (interface, "multicast add ", "\n"));
+ /* socket_multicast_enable() will add this address to the addresslist */
+ add_interface(interface);
+ list_if_listening(interface, htons(NTP_PORT));
+ }
+ else
+ {
+ delete_interface(interface); /* re-use existing interface */
+ interface = NULL;
+ if (addr.ss_family == AF_INET)
+ interface = wildipv4;
+ else if (addr.ss_family == AF_INET6)
+ interface = wildipv6;
+
+ if (interface != NULL) {
+ /* HACK ! -- stuff in an address */
+ interface->bcast = addr;
+ netsyslog(LOG_ERR,
+ "...multicast address %s using wildcard interface #%d %s",
+ stoa(&addr), interface->ifnum, interface->name);
+ } else {
netsyslog(LOG_ERR,
- "invalid multicast address %s", stoa(&addr));
+ "No multicast socket available to use for address %s",
+ stoa(&addr));
return;
}
+ }
+#else
+ /*
+ * For the case where we can't use a separate socket
+ */
+ interface = findlocalcastinterface(&addr, INT_MULTICAST);
+ /*
+ * If we don't have a valid socket, just return
+ */
+ if (!interface)
+ {
+ netsyslog(LOG_ERR,
+ "Cannot add multicast address %s: Cannot find slot",
+ stoa(&addr));
+ return;
+ }
+
+#endif
+ {
+ isc_boolean_t jstatus;
+ jstatus = socket_multicast_enable(interface, lscope, &addr);
+
+ if (jstatus == ISC_TRUE)
+ netsyslog(LOG_INFO, "Added Multicast Listener %s on interface #%d %s\n", stoa(&addr), interface->ifnum, interface->name);
+ else
+ netsyslog(LOG_ERR, "Failed to add Multicast Listener %s\n", stoa(&addr));
+ }
+#else /* MCAST */
+ netsyslog(LOG_ERR,
+ "Cannot add multicast address %s: no Multicast support",
+ stoa(&addr));
+#endif /* MCAST */
+ return;
+}
+
+/*
+ * io_multicast_del() - delete multicast group address
+ */
+void
+io_multicast_del(
+ struct sockaddr_storage addr
+ )
+{
+#ifdef MCAST
+ struct interface *interface;
+ isc_boolean_t lstatus;
+
+ /*
+ * Check to see if this is a multicast address
+ */
+ if (addr_ismulticast(&addr) == ISC_FALSE)
+ {
+ netsyslog(LOG_ERR,
+ "invalid multicast address %s", stoa(&addr));
+ return;
+ }
+ switch (addr.ss_family)
+ {
+ case AF_INET :
/*
- * Disable reception of multicast packets
- */
- mreq.imr_multiaddr = ((struct sockaddr_in*)&addr)->sin_addr;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- for (i = 0; i < ninterfaces; i++)
- {
- /* Be sure it's the correct family */
- if (inter_list[i].sin.ss_family != AF_INET)
- continue;
- if (!(inter_list[i].flags & INT_MULTICAST))
- continue;
- if (!(inter_list[i].fd < 0))
- continue;
- if (!SOCKCMP(&addr, &inter_list[i].sin))
- continue;
- if (i != wildipv4)
- {
- /* we have an explicit fd, so we can close it */
- close_socket(inter_list[i].fd);
- memset((char *)&inter_list[i], 0, sizeof(struct interface));
- inter_list[i].fd = INVALID_SOCKET;
- inter_list[i].bfd = INVALID_SOCKET;
- }
- else
- {
- /* We are sharing "any address" port :-( Don't close it! */
- if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- (char *)&mreq, sizeof(mreq)) == -1)
- netsyslog(LOG_ERR, "setsockopt IP_DROP_MEMBERSHIP fails on address: %s %m",
- stoa(&addr));
- inter_list[i].num_mcast--;
- /* If there are none left negate the Multicast flag */
- if(inter_list[i].num_mcast == 0)
- inter_list[i].flags &= ~INT_MULTICAST;
- }
+ * Disable reception of multicast packets
+ */
+ interface = find_flagged_addr_in_list(&addr, INT_MCASTOPEN);
+ while ( interface != NULL) {
+ lstatus = socket_multicast_disable(interface, &addr);
+ interface = find_flagged_addr_in_list(&addr, INT_MCASTOPEN);
}
break;
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
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++)
+ * Disable reception of multicast packets
+ */
+ for (interface = ISC_LIST_HEAD(inter_list);
+ interface != NULL;
+ interface = ISC_LIST_NEXT(interface, link))
{
+ if (interface->flags & INT_WILDCARD)
+ continue;
+
/* Be sure it's the correct family */
- if (inter_list[i].sin.ss_family != AF_INET6)
+ if (interface->sin.ss_family != AF_INET6)
continue;
- if (!(inter_list[i].flags & INT_MULTICAST))
+ if (!(interface->flags & INT_MCASTOPEN))
continue;
- if (!(inter_list[i].fd < 0))
+ if (!(interface->fd < 0))
continue;
- if (!SOCKCMP(&addr, &inter_list[i].sin))
+ if (!SOCKCMP(&addr, &interface->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;
- }
+ lstatus = socket_multicast_disable(interface, &addr);
}
break;
-#endif /* HAVE_IPV6 */
+#endif /* INCLUDE_IPV6_MULTICAST_SUPPORT */
+
}/* switch */
+
delete_addr_from_list(&addr);
#else /* not MCAST */
@@ -983,6 +2182,76 @@ io_multicast_del(
#endif /* not MCAST */
}
+/*
+ * init_nonblocking_io() - set up descriptor to be non blocking
+ */
+static void init_nonblocking_io(SOCKET fd)
+{
+ /*
+ * set non-blocking,
+ */
+
+#ifdef USE_FIONBIO
+ /* in vxWorks we use FIONBIO, but the others are defined for old systems, so
+ * all hell breaks loose if we leave them defined
+ */
+#undef O_NONBLOCK
+#undef FNDELAY
+#undef O_NDELAY
+#endif
+
+#if defined(O_NONBLOCK) /* POSIX */
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+ {
+ netsyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ /*NOTREACHED*/
+ }
+#elif defined(FNDELAY)
+ if (fcntl(fd, F_SETFL, FNDELAY) < 0)
+ {
+ netsyslog(LOG_ERR, "fcntl(FNDELAY) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ /*NOTREACHED*/
+ }
+#elif defined(O_NDELAY) /* generally the same as FNDELAY */
+ if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
+ {
+ netsyslog(LOG_ERR, "fcntl(O_NDELAY) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ /*NOTREACHED*/
+ }
+#elif defined(FIONBIO)
+ {
+ int on = 1;
+# if defined(SYS_WINNT)
+
+ if (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
+# else
+ if (ioctl(fd,FIONBIO,&on) < 0)
+# endif
+ {
+ netsyslog(LOG_ERR, "ioctl(FIONBIO) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ /*NOTREACHED*/
+ }
+ }
+#elif defined(FIOSNBIO)
+ if (ioctl(fd,FIOSNBIO,&on) < 0)
+ {
+ netsyslog(LOG_ERR, "ioctl(FIOSNBIO) fails on fd #%d: %m",
+ fd);
+ exit(1);
+ /*NOTREACHED*/
+ }
+#else
+# include "Bletch: Need non-blocking I/O!"
+#endif
+}
/*
* open_socket - open a socket, returning the file descriptor
@@ -992,12 +2261,14 @@ static SOCKET
open_socket(
struct sockaddr_storage *addr,
int flags,
- int turn_off_reuse
+ int turn_off_reuse,
+ struct interface *interf
)
{
int errval;
SOCKET fd;
- int on = 1, off = 0;
+ int on = 1, off = 0; /* int is OK for REUSEADR per */
+ /* http://www.kohala.com/start/mcast.api.txt */
#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
int tos;
#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
@@ -1009,70 +2280,84 @@ open_socket(
#ifndef SYS_WINNT
if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) < 0) {
errval = errno;
- if(addr->ss_family == AF_INET)
- netsyslog(LOG_ERR, "socket(AF_INET, SOCK_DGRAM, 0) failed on address %s: %m",
- stoa(addr));
- else if(addr->ss_family == AF_INET6)
- netsyslog(LOG_ERR, "socket(AF_INET6, SOCK_DGRAM, 0) failed on address %s: %m",
- stoa(addr));
- if (errval == EPROTONOSUPPORT || errval == EAFNOSUPPORT ||
- errval == EPFNOSUPPORT)
- return (INVALID_SOCKET);
- exit(1);
- /*NOTREACHED*/
- }
#else
if ( (fd = socket(addr->ss_family, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
errval = WSAGetLastError();
+#endif
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));
+#ifndef SYS_WINNT
+ if (errval == EPROTONOSUPPORT || errval == EAFNOSUPPORT ||
+ errval == EPFNOSUPPORT)
+#else
if (errval == WSAEPROTONOSUPPORT || errval == WSAEAFNOSUPPORT ||
errval == WSAEPFNOSUPPORT)
+#endif
return (INVALID_SOCKET);
+ msyslog(LOG_ERR, "unexpected error code %d (not PROTONOSUPPORT|AFNOSUPPORT|FPNOSUPPORT) - exiting", errval);
exit(1);
/*NOTREACHED*/
}
+#ifdef SYS_WINNT
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 */
+ /*
+ * Fixup the file descriptor for some systems
+ * See bug #530 for details of the issue.
+ */
+ fd = move_fd(fd);
+
+ /*
+ * set SO_REUSEADDR since we will be binding the same port
+ * number on each interface according to flag
+ */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof(on)))
+ turn_off_reuse ? (char *)&off : (char *)&on, sizeof(on)))
{
- netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR on fails on address %s: %m",
- stoa(addr));
+ netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR %s on fails on address %s: %m",
+ turn_off_reuse ? "off" : "on", stoa(addr));
+
+ closesocket(fd);
+
+ return INVALID_SOCKET;
}
+ /*
+ * IPv4 specific options go here
+ */
+ if (addr->ss_family == AF_INET) {
#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
/* set IP_TOS to minimize packet delay */
- tos = IPTOS_LOWDELAY;
- if (addr->ss_family == AF_INET)
+ tos = IPTOS_LOWDELAY;
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));
}
+#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
+ }
+ /*
+ * IPv6 specific options go here
+ */
+ if (addr->ss_family == AF_INET6) {
#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 */
+#endif /* IPV6_V6ONLY */
#if defined(IPV6_BINDV6ONLY)
- if (addr->ss_family == AF_INET6)
if (setsockopt(fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
(char*)&on, sizeof(on)))
{
@@ -1081,238 +2366,119 @@ open_socket(
stoa(addr));
}
#endif /* IPV6_BINDV6ONLY */
-#endif /* IPV6_V6ONLY */
-
-#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
+ }
+#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
/*
- * bind the local address.
+ * some OSes don't allow binding to more specific
+ * addresses if a wildcard address already bound
+ * to the port and SO_REUSEADDR is not set
*/
- if (bind(fd, (struct sockaddr *)addr, SOCKLEN(addr)) < 0) {
- char buff[160];
-
- if(addr->ss_family == AF_INET)
- sprintf(buff,
- "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=%d fails: %%m",
- fd, addr->ss_family, (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
- stoa(addr),
- IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)), flags);
- else if(addr->ss_family == AF_INET6)
- sprintf(buff,
- "bind() fd %d, family %d, port %d, addr %s, in6_is_addr_multicast=%d flags=%d fails: %%m",
- fd, addr->ss_family, (int)ntohs(((struct sockaddr_in6*)addr)->sin6_port),
- stoa(addr),
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr), flags);
- else return INVALID_SOCKET;
-
- netsyslog(LOG_ERR, buff);
- closesocket(fd);
-
- /*
- * soft fail if opening a multicast address
- */
- if(addr->ss_family == AF_INET){
- if(IN_CLASSD(ntohl(((struct sockaddr_in*)addr)->sin_addr.s_addr)))
- return (INVALID_SOCKET);
- }
- else {
- if(IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr))
- return (INVALID_SOCKET);
- }
-#if 0
- exit(1);
-#else
- return INVALID_SOCKET;
-#endif
+ if (!is_wildcard_addr(addr)) {
+ set_wildcard_reuse(addr->ss_family, 1);
}
-#ifdef DEBUG
- if (debug)
- printf("bind() fd %d, family %d, port %d, addr %s, flags=%d\n",
- fd,
- addr->ss_family,
- (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
- stoa(addr),
- flags);
#endif
/*
- * I/O Completion Ports don't care about the select and FD_SET
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- if (fd > maxactivefd)
- maxactivefd = fd;
- FD_SET(fd, &activefds);
-#endif
- add_socket_to_list(fd);
- /*
- * set non-blocking,
+ * bind the local address.
*/
+ errval = bind(fd, (struct sockaddr *)addr, SOCKLEN(addr));
-#ifdef USE_FIONBIO
- /* in vxWorks we use FIONBIO, but the others are defined for old systems, so
- * all hell breaks loose if we leave them defined
+#ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND
+ /*
+ * some OSes don't allow binding to more specific
+ * addresses if a wildcard address already bound
+ * to the port and REUSE_ADDR is not set
*/
-#undef O_NONBLOCK
-#undef FNDELAY
-#undef O_NDELAY
+ if (!is_wildcard_addr(addr)) {
+ set_wildcard_reuse(addr->ss_family, 0);
+ }
#endif
-#if defined(O_NONBLOCK) /* POSIX */
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(O_NONBLOCK) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#elif defined(FNDELAY)
- if (fcntl(fd, F_SETFL, FNDELAY) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(FNDELAY) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#elif defined(O_NDELAY) /* generally the same as FNDELAY */
- if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
- {
- netsyslog(LOG_ERR, "fcntl(O_NDELAY) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#elif defined(FIONBIO)
-# if defined(VMS)
- if (ioctl(fd,FIONBIO,&on) < 0)
-# elif defined(SYS_WINNT)
- if (ioctlsocket(fd,FIONBIO,(u_long *) &on) == SOCKET_ERROR)
+ if (errval < 0) {
+ /*
+ * Don't log this under all conditions
+ */
+ if (turn_off_reuse == 0
+#ifdef DEBUG
+ || debug > 1
+#endif
+ ) {
+ if (addr->ss_family == AF_INET)
+ netsyslog(LOG_ERR,
+ "bind() fd %d, family %d, port %d, addr %s, in_classd=%d flags=0x%x 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);
+#ifdef INCLUDE_IPV6_SUPPORT
+ else if (addr->ss_family == AF_INET6)
+ netsyslog(LOG_ERR,
+ "bind() fd %d, family %d, port %d, scope %d, addr %s, in6_is_addr_multicast=%d flags=0x%x fails: %m",
+ fd, addr->ss_family, (int)ntohs(((struct sockaddr_in6*)addr)->sin6_port),
+# ifdef ISC_PLATFORM_HAVESCOPEID
+ ((struct sockaddr_in6*)addr)->sin6_scope_id
# else
- if (ioctl(fd,FIONBIO,&on) < 0)
+ -1
# endif
- {
- netsyslog(LOG_ERR, "ioctl(FIONBIO) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
+ , stoa(addr),
+ IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr), flags);
+#endif
+ }
+
+ closesocket(fd);
+
+ return INVALID_SOCKET;
}
-#elif defined(FIOSNBIO)
- if (ioctl(fd,FIOSNBIO,&on) < 0)
+
+#ifdef HAVE_TIMESTAMP
{
- netsyslog(LOG_ERR, "ioctl(FIOSNBIO) fails on address %s: %m",
- stoa(addr));
- exit(1);
- /*NOTREACHED*/
- }
-#else
-# include "Bletch: Need non-blocking I/O!"
+ if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP,
+ (char*)&on, sizeof(on)))
+ {
+ netsyslog(LOG_DEBUG,
+ "setsockopt SO_TIMESTAMP on fails on address %s: %m",
+ stoa(addr));
+ }
+#ifdef DEBUG
+ else
+ {
+ DPRINTF(4, ("setsockopt SO_TIMESTAMP enabled on fd %d address %s\n", fd, stoa(addr)));
+ }
+#endif
+ }
#endif
+ DPRINTF(4, ("bind() fd %d, family %d, port %d, addr %s, flags=0x%x\n",
+ fd,
+ addr->ss_family,
+ (int)ntohs(((struct sockaddr_in*)addr)->sin_port),
+ stoa(addr),
+ flags));
+ init_nonblocking_io(fd);
+
#ifdef HAVE_SIGNALED_IO
init_socket_sig(fd);
#endif /* not HAVE_SIGNALED_IO */
- /*
- * Turn off the SO_REUSEADDR socket option. It apparently
- * causes heartburn on systems with multicast IP installed.
- * On normal systems it only gets looked at when the address
- * is being bound anyway..
- */
- if (turn_off_reuse)
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&off, sizeof(off)))
- {
- netsyslog(LOG_ERR, "setsockopt SO_REUSEADDR off fails on address %s: %m",
- stoa(addr));
- }
-
-#ifdef SO_BROADCAST
- /* if this interface can support broadcast, set SO_BROADCAST */
- if (flags & INT_BROADCAST)
- {
- if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
- (char *)&on, sizeof(on)))
- {
- netsyslog(LOG_ERR, "setsockopt(SO_BROADCAST) on address %s: %m",
- stoa(addr));
- }
- }
-#endif /* SO_BROADCAST */
+ add_fd_to_list(fd, FD_TYPE_SOCKET);
#if !defined(SYS_WINNT) && !defined(VMS)
-# ifdef DEBUG
- if (debug > 1)
- printf("flags for fd %d: 0%o\n", fd,
- fcntl(fd, F_GETFL, 0));
-# endif
+ DPRINTF(4, ("flags for fd %d: 0x%x\n", fd,
+ fcntl(fd, F_GETFL, 0)));
#endif /* SYS_WINNT || VMS */
- return fd;
-}
-
-
-/*
- * close_socket - close a socket and remove from the activefd list
- */
-static void
-close_socket(
- SOCKET fd
- )
-{
- SOCKET i, newmax;
-
- (void) closesocket(fd);
-
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- FD_CLR( (u_int) fd, &activefds);
-
- if (fd == maxactivefd) {
- newmax = 0;
- for (i = 0; i < maxactivefd; i++)
- if (FD_ISSET(i, &activefds))
- newmax = i;
- maxactivefd = newmax;
- }
-#endif
- delete_socket_from_list(fd);
-
-}
-
-
+#if defined (HAVE_IO_COMPLETION_PORT)
/*
- * close_file - close a file and remove from the activefd list
- * added 1/31/1997 Greg Schueman for Windows NT portability
+ * Add the socket to the completion port
*/
-#ifdef REFCLOCK
-static void
-close_file(
- SOCKET fd
- )
-{
- int i, newmax;
-
- (void) close(fd);
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- FD_CLR( (u_int) fd, &activefds);
-
- if (fd == maxactivefd) {
- newmax = 0;
- for (i = 0; i < maxactivefd; i++)
- if (FD_ISSET(i, &activefds))
- newmax = i;
- maxactivefd = newmax;
+ if (io_completion_port_add_socket(fd, interf))
+ {
+ msyslog(LOG_ERR, "unable to set up io completion port - EXITING");
+ exit(1);
}
#endif
- delete_socket_from_list(fd);
-
+ return fd;
}
-#endif
-
/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
/*
@@ -1343,87 +2509,98 @@ sendpkt(
struct in_addr addr;
};
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
struct cache6 {
u_short port;
struct in6_addr addr;
};
-#endif /* HAVE_IPV6 */
+#endif /* INCLUDE_IPV6_SUPPORT */
+
#ifndef ERRORCACHESIZE
#define ERRORCACHESIZE 8
#endif
#if ERRORCACHESIZE > 0
static struct cache badaddrs[ERRORCACHESIZE];
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
static struct cache6 badaddrs6[ERRORCACHESIZE];
-#endif /* HAVE_IPV6 */
+#endif /* INCLUDE_IPV6_SUPPORT */
#else
#define badaddrs ((struct cache *)0) /* Only used in empty loops! */
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
#define badaddrs6 ((struct cache6 *)0) /* Only used in empty loops! */
-#endif /* HAVE_IPV6 */
+#endif /* INCLUDE_IPV6_SUPPORT */
#endif
#ifdef DEBUG
if (debug > 1)
- printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n",
- (ttl >= 0) ? "\tMCAST\t*****" : "",
- inter->fd, stoa(dest),
- stoa(&inter->sin), ttl, len);
+ {
+ if (inter != NULL)
+ {
+ printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n",
+ (ttl > 0) ? "\tMCAST\t***** " : "",
+ inter->fd, stoa(dest),
+ stoa(&inter->sin), ttl, len);
+ }
+ else
+ {
+ printf("%ssendpkt(dst=%s, ttl=%d, len=%d): no interface - IGNORED\n",
+ (ttl > 0) ? "\tMCAST\t***** " : "",
+ stoa(dest),
+ ttl, len);
+ }
+ }
#endif
+ if (inter == NULL) /* unbound peer - drop request and wait for better network conditions */
+ return;
+
#ifdef MCAST
- switch (inter->sin.ss_family) {
-
- case AF_INET :
-
+ /*
+ * for the moment we use the bcast option to set multicast ttl
+ */
+ if (ttl > 0 && ttl != inter->last_ttl) {
+
/*
- * 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
+ */
+ int rtc;
+
+ switch (inter->sin.ss_family) {
+
+ case AF_INET :
+ {
+ u_char mttl = (u_char) 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;
+ rtc = setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
+ (const void *) &mttl, sizeof(mttl));
+ break;
}
- break;
-
-#ifdef HAVE_IPV6
- case AF_INET6 :
+
+#ifdef INCLUDE_IPV6_SUPPORT
+ case AF_INET6 :
+ {
+ u_int ittl = (u_char) ttl;
- /*
- * for the moment we use the bcast option to set
- * multicast max hops
- */
- if (ttl > 0 && ttl != inter->last_ttl) {
-
- /*
- * set the multicast ttl for outgoing packets
- */
- if (setsockopt(inter->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- &ttl, sizeof(ttl)) == -1)
- netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails on address %s: %m",
- stoa(&inter->sin));
- else
- inter->last_ttl = ttl;
- }
- break;
-#endif /* HAVE_IPV6 */
-
- default :
- exit(1);
+ rtc = setsockopt(inter->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ (const void *) &ittl, sizeof(ittl));
+ break;
+ }
+#endif /* INCLUDE_IPV6_SUPPORT */
+ default: /* just NOP if not supported */
+ rtc = 0;
+ break;
+ }
+
+ if (rtc != 0) {
+ netsyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS fails on address %s: %m",
+ stoa(&inter->sin));
+ }
+ else
+ inter->last_ttl = ttl;
}
-
#endif /* MCAST */
for (slot = ERRORCACHESIZE; --slot >= 0; )
@@ -1432,14 +2609,13 @@ sendpkt(
badaddrs[slot].addr.s_addr == ((struct sockaddr_in*)dest)->sin_addr.s_addr)
break;
}
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
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 */
+#endif /* INCLUDE_IPV6_SUPPORT */
#if defined(HAVE_IO_COMPLETION_PORT)
err = io_completion_port_sendto(inter, pkt, len, dest);
@@ -1479,7 +2655,7 @@ sendpkt(
}
break;
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
case AF_INET6 :
for (slot = ERRORCACHESIZE; --slot >= 0; )
@@ -1490,13 +2666,13 @@ sendpkt(
break;
}
break;
-#endif /* HAVE_IPV6 */
-
- default :
- exit(1);
+#endif /* INCLUDE_IPV6_SUPPORT */
+ default: /* don't care if not supported */
+ break;
}
- netsyslog(LOG_ERR, "sendto(%s): %m", stoa(dest));
+ netsyslog(LOG_ERR, "sendto(%s) (fd=%d): %m",
+ stoa(dest), inter->fd);
}
}
else
@@ -1513,11 +2689,13 @@ sendpkt(
case AF_INET :
badaddrs[slot].port = 0;
break;
-#ifdef HAVE_IPV6
+#ifdef INCLUDE_IPV6_SUPPORT
case AF_INET6 :
badaddrs6[slot].port = 0;
break;
-#endif /* HAVE_IPV6 */
+#endif /* INCLUDE_IPV6_SUPPORT */
+ default: /* don't care if not supported */
+ break;
}
}
}
@@ -1550,363 +2728,506 @@ fdbits(
}
/*
- * input_handler - receive packets asynchronously
+ * Routine to read the refclock packets for a specific interface
+ * Return the number of bytes read. That way we know if we should
+ * read it again or go on to the next one if no bytes returned
*/
-void
-input_handler(
- l_fp *cts
- )
+static inline int
+read_refclock_packet(SOCKET fd, struct refclockio *rp, l_fp ts)
{
- register int i, n;
+ int i;
+ int buflen;
register struct recvbuf *rb;
- register int doing;
- register SOCKET fd;
- struct timeval tvzero;
- int fromlen;
- l_fp ts; /* Timestamp at BOselect() gob */
- l_fp ts_e; /* Timestamp at EOselect() gob */
- fd_set fds;
- int select_count = 0;
- static int handler_count = 0;
- ++handler_count;
- if (handler_count != 1)
- msyslog(LOG_ERR, "input_handler: handler_count is %d!", handler_count);
- handler_calls++;
- ts = *cts;
+ rb = get_free_recv_buffer();
- for (;;)
+ if (rb == NULL)
{
/*
- * Do a poll to see who has data
+ * No buffer space available - just drop the packet
*/
+ char buf[RX_BUFF_SIZE];
+
+ buflen = read(fd, buf, sizeof buf);
+ packets_dropped++;
+ return (buflen);
+ }
- fds = activefds;
- tvzero.tv_sec = tvzero.tv_usec = 0;
+ i = (rp->datalen == 0
+ || rp->datalen > sizeof(rb->recv_space))
+ ? sizeof(rb->recv_space) : rp->datalen;
+ buflen = read(fd, (char *)&rb->recv_space, (unsigned)i);
+ if (buflen < 0)
+ {
+ if (errno != EINTR && errno != EAGAIN) {
+ netsyslog(LOG_ERR, "clock read fd %d: %m", fd);
+ }
+ freerecvbuf(rb);
+ return (buflen);
+ }
+
+ /*
+ * Got one. Mark how and when it got here,
+ * put it on the full list and do bookkeeping.
+ */
+ rb->recv_length = buflen;
+ rb->recv_srcclock = rp->srcclock;
+ rb->dstadr = 0;
+ rb->fd = fd;
+ rb->recv_time = ts;
+ rb->receiver = rp->clock_recv;
+
+ if (rp->io_input)
+ {
/*
- * If we have something to do, freeze a timestamp.
- * See below for the other cases (nothing (left) to do or error)
+ * have direct input routine for refclocks
*/
- while (0 < (n = select(maxactivefd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero)))
+ if (rp->io_input(rb) == 0)
{
- ++select_count;
- ++handler_pkts;
-
-#ifdef REFCLOCK
/*
- * Check out the reference clocks first, if any
+ * data was consumed - nothing to pass up
+ * into block input machine
*/
- if (refio != 0)
- {
- register struct refclockio *rp;
+ freerecvbuf(rb);
+ return (buflen);
+ }
+ }
+
+ add_full_recv_buffer(rb);
- for (rp = refio; rp != 0 && n > 0; rp = rp->next)
- {
- fd = rp->fd;
- if (FD_ISSET(fd, &fds))
- {
- n--;
- if (free_recvbuffs() == 0)
- {
- char buf[RX_BUFF_SIZE];
-
- (void) read(fd, buf, sizeof buf);
- packets_dropped++;
- goto select_again;
- }
-
- rb = get_free_recv_buffer();
-
- i = (rp->datalen == 0
- || rp->datalen > sizeof(rb->recv_space))
- ? sizeof(rb->recv_space) : rp->datalen;
- rb->recv_length =
- read(fd, (char *)&rb->recv_space, (unsigned)i);
-
- if (rb->recv_length == -1)
- {
- netsyslog(LOG_ERR, "clock read fd %d: %m", fd);
- freerecvbuf(rb);
- goto select_again;
- }
+ rp->recvcount++;
+ packets_received++;
+ return (buflen);
+}
- /*
- * Got one. Mark how
- * and when it got here,
- * put it on the full
- * list and do
- * bookkeeping.
- */
- rb->recv_srcclock = rp->srcclock;
- rb->dstadr = 0;
- rb->fd = fd;
- rb->recv_time = ts;
- rb->receiver = rp->clock_recv;
-
- if (rp->io_input)
- {
- /*
- * have direct
- * input routine
- * for refclocks
- */
- if (rp->io_input(rb) == 0)
- {
- /*
- * data
- * was
- * consumed
- * -
- * nothing
- * to
- * pass
- * up
- * into
- * block
- * input
- * machine
- */
- freerecvbuf(rb);
-#if 1
- goto select_again;
-#else
- continue;
+#ifdef HAVE_TIMESTAMP
+/*
+ * extract timestamps from control message buffer
+ */
+static l_fp
+ fetch_timestamp(struct recvbuf *rb, struct msghdr *msghdr, l_fp ts)
+{
+#ifdef USE_TIMESTAMP_CMSG
+ struct cmsghdr *cmsghdr;
+
+ cmsghdr = CMSG_FIRSTHDR(msghdr);
+ while (cmsghdr != NULL) {
+ switch (cmsghdr->cmsg_type)
+ {
+ case SCM_TIMESTAMP:
+ {
+ struct timeval *tvp = (struct timeval *)CMSG_DATA(cmsghdr);
+ double dtemp;
+ l_fp nts;
+ DPRINTF(4, ("fetch_timestamp: system network time stamp: %ld.%06ld\n", tvp->tv_sec, tvp->tv_usec));
+ nts.l_i = tvp->tv_sec + JAN_1970;
+ dtemp = tvp->tv_usec / 1e6;
+
+ /* fuzz lower bits not covered by precision */
+ if (sys_precision != 0)
+ dtemp += (ntp_random() / FRAC - .5) / (1 <<
+ -sys_precision);
+
+ nts.l_uf = (u_int32)(dtemp*FRAC);
+#ifdef DEBUG_TIMING
+ {
+ l_fp dts = ts;
+ L_SUB(&dts, &nts);
+ collect_timing(rb, "input processing delay", 1, &dts);
+ DPRINTF(4, ("fetch_timestamp: timestamp delta: %s (incl. prec fuzz)\n", lfptoa(&dts, 9)));
+ }
+#endif
+ ts = nts; /* network time stamp */
+ break;
+ }
+ default:
+ DPRINTF(4, ("fetch_timestamp: skipping control message 0x%x\n", cmsghdr->cmsg_type));
+ break;
+ }
+ cmsghdr = CMSG_NXTHDR(msghdr, cmsghdr);
+ }
+#endif
+ return ts;
+}
#endif
- }
- }
- add_full_recv_buffer(rb);
+/*
+ * Routine to read the network NTP packets for a specific interface
+ * Return the number of bytes read. That way we know if we should
+ * read it again or go on to the next one if no bytes returned
+ */
+static inline int
+read_network_packet(SOCKET fd, struct interface *itf, l_fp ts)
+{
+ GETSOCKNAME_SOCKLEN_TYPE fromlen;
+ int buflen;
+ register struct recvbuf *rb;
+#ifdef HAVE_TIMESTAMP
+ struct msghdr msghdr;
+ struct iovec iovec;
+ char control[TIMESTAMP_CTLMSGBUF_SIZE]; /* pick up control messages */
+#endif
- rp->recvcount++;
- packets_received++;
- }
- }
- }
-#endif /* REFCLOCK */
+ /*
+ * Get a buffer and read the frame. If we
+ * haven't got a buffer, or this is received
+ * on a disallowed socket, just dump the
+ * packet.
+ */
- /*
- * Loop through the interfaces looking for data
- * to read.
- */
- for (i = ninterfaces - 1; (i >= 0) && (n > 0); i--)
- {
- for (doing = 0; (doing < 2) && (n > 0); doing++)
- {
- if (doing == 0)
- {
- fd = inter_list[i].fd;
- }
- else
- {
- if (!(inter_list[i].flags & INT_BCASTOPEN))
- break;
- fd = inter_list[i].bfd;
- }
- if (fd < 0) continue;
- if (FD_ISSET(fd, &fds))
- {
- n--;
+ rb = get_free_recv_buffer();
- /*
- * Get a buffer and read
- * the frame. If we
- * haven't got a buffer,
- * or this is received
- * on the wild card
- * socket, just dump the
- * packet.
- */
- if (
-#ifdef UDP_WILDCARD_DELIVERY
- /*
- * these guys manage to put properly addressed
- * packets into the wildcard queue
- */
- (free_recvbuffs() == 0)
-#else
- ((i == wildipv4) || (i == wildipv6)||
- (free_recvbuffs() == 0))
-#endif
- )
+ if (rb == NULL || itf->ignore_packets == ISC_TRUE)
{
char buf[RX_BUFF_SIZE];
struct sockaddr_storage from;
-
- fromlen = sizeof from;
- (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*)&from, &fromlen);
-#ifdef DEBUG
- if (debug)
- printf("%s on %d(%lu) fd=%d from %s\n",
- (i) ? "drop" : "ignore",
- i, free_recvbuffs(), fd,
- stoa(&from));
-#endif
- if (i == wildipv4 || i == wildipv6)
- packets_ignored++;
+ if (rb != NULL)
+ freerecvbuf(rb);
+
+ fromlen = sizeof(from);
+ buflen = recvfrom(fd, buf, sizeof(buf), 0,
+ (struct sockaddr*)&from, &fromlen);
+ DPRINTF(4, ("%s on (%lu) fd=%d from %s\n",
+ (itf->ignore_packets == ISC_TRUE) ? "ignore" : "drop",
+ free_recvbuffs(), fd,
+ stoa(&from)));
+ if (itf->ignore_packets == ISC_TRUE)
+ packets_ignored++;
else
- packets_dropped++;
- goto select_again;
+ packets_dropped++;
+ return (buflen);
}
- rb = get_free_recv_buffer();
-
fromlen = sizeof(struct sockaddr_storage);
+
+#ifndef HAVE_TIMESTAMP
rb->recv_length = recvfrom(fd,
- (char *)&rb->recv_space,
- sizeof(rb->recv_space), 0,
- (struct sockaddr *)&rb->recv_srcadr,
- &fromlen);
- if (rb->recv_length == 0
-#ifdef EWOULDBLOCK
- || errno==EWOULDBLOCK
+ (char *)&rb->recv_space,
+ sizeof(rb->recv_space), 0,
+ (struct sockaddr *)&rb->recv_srcadr,
+ &fromlen);
+#else
+ iovec.iov_base = (void *)&rb->recv_space;
+ iovec.iov_len = sizeof(rb->recv_space);
+ msghdr.msg_name = (void *)&rb->recv_srcadr;
+ msghdr.msg_namelen = sizeof(rb->recv_srcadr);
+ msghdr.msg_iov = &iovec;
+ msghdr.msg_iovlen = 1;
+ msghdr.msg_control = (void *)&control;
+ msghdr.msg_controllen = sizeof(control);
+ msghdr.msg_flags = 0;
+ rb->recv_length = recvmsg(fd, &msghdr, 0);
#endif
+
+ buflen = rb->recv_length;
+
+ if (buflen == 0 || (buflen == -1 &&
+ (errno==EWOULDBLOCK
#ifdef EAGAIN
- || errno==EAGAIN
+ || errno==EAGAIN
#endif
- ) {
+ ))) {
freerecvbuf(rb);
- continue;
+ return (buflen);
}
- else if (rb->recv_length < 0)
+ else if (buflen < 0)
{
netsyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
- stoa(&rb->recv_srcadr), fd);
-#ifdef DEBUG
- if (debug)
- printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd);
-#endif
+ stoa(&rb->recv_srcadr), fd);
+ DPRINTF(5, ("read_network_packet: fd=%d dropped (bad recvfrom)\n", fd));
freerecvbuf(rb);
- continue;
+ return (buflen);
}
+
#ifdef DEBUG
if (debug > 2) {
if(rb->recv_srcadr.ss_family == AF_INET)
- printf("input_handler: if=%d fd=%d length %d from %08lx %s\n",
- i, fd, rb->recv_length,
+ printf("read_network_packet: fd=%d length %d from %08lx %s\n",
+ fd, buflen,
(u_long)ntohl(((struct sockaddr_in*)&rb->recv_srcadr)->sin_addr.s_addr) &
0x00000000ffffffff,
- stoa(&rb->recv_srcadr));
+ stoa(&rb->recv_srcadr));
else
- printf("input_handler: if=%d fd=%d length %d from %s\n",
- i, fd, rb->recv_length,
+ printf("read_network_packet: fd=%d length %d from %s\n",
+ fd, buflen,
stoa(&rb->recv_srcadr));
- }
+ }
#endif
/*
* Got one. Mark how and when it got here,
* put it on the full list and do bookkeeping.
*/
- rb->dstadr = &inter_list[i];
+ rb->dstadr = itf;
rb->fd = fd;
+#ifdef HAVE_TIMESTAMP
+ ts = fetch_timestamp(rb, &msghdr, ts); /* pick up a network time stamp if possible */
+#endif
rb->recv_time = ts;
rb->receiver = receive;
add_full_recv_buffer(rb);
- inter_list[i].received++;
+ itf->received++;
packets_received++;
- goto select_again;
- }
- /* Check more interfaces */
- }
- }
- select_again:;
- /*
- * Done everything from that select. Poll again.
- */
- }
+ return (buflen);
+}
+
+/*
+ * input_handler - receive packets asynchronously
+ */
+void
+input_handler(
+ l_fp *cts
+ )
+{
+
+ int buflen;
+ int n;
+ int doing;
+ SOCKET fd;
+ struct timeval tvzero;
+ l_fp ts; /* Timestamp at BOselect() gob */
+#ifdef DEBUG_TIMING
+ l_fp ts_e; /* Timestamp at EOselect() gob */
+#endif
+ fd_set fds;
+ int select_count = 0;
+ struct interface *interface;
+#if defined(HAS_ROUTING_SOCKET)
+ struct asyncio_reader *asyncio_reader;
+#endif
+
+ handler_calls++;
+
+ /*
+ * If we have something to do, freeze a timestamp.
+ * See below for the other cases (nothing (left) to do or error)
+ */
+ ts = *cts;
+
+ /*
+ * Do a poll to see who has data
+ */
+
+ fds = activefds;
+ tvzero.tv_sec = tvzero.tv_usec = 0;
+ n = select(maxactivefd+1, &fds, (fd_set *)0, (fd_set *)0, &tvzero);
+
+ /*
+ * If there are no packets waiting just return
+ */
+ if (n < 0)
+ {
+ int err = errno;
/*
- * If nothing more to do, try again.
- * If nothing to do, just return.
- * If an error occurred, complain and return.
+ * extended FAU debugging output
*/
- if (n == 0)
+ if (err != EINTR)
+ netsyslog(LOG_ERR,
+ "select(%d, %s, 0L, 0L, &0.0) error: %m",
+ maxactivefd+1,
+ fdbits(maxactivefd, &activefds));
+ if (err == EBADF) {
+ int j, b;
+ fds = activefds;
+ for (j = 0; j <= maxactivefd; j++)
+ if ((FD_ISSET(j, &fds) && (read(j, &b, 0) == -1)))
+ netsyslog(LOG_ERR, "Bad file descriptor %d", j);
+ }
+ return;
+ }
+ else if (n == 0)
+ return;
+
+ ++handler_pkts;
+
+#ifdef REFCLOCK
+ /*
+ * Check out the reference clocks first, if any
+ */
+
+ if (refio != NULL)
+ {
+ register struct refclockio *rp;
+
+ for (rp = refio; rp != NULL; rp = rp->next)
{
- if (select_count == 0) /* We really had nothing to do */
+ fd = rp->fd;
+
+ if (FD_ISSET(fd, &fds))
{
- if (debug)
- netsyslog(LOG_DEBUG, "input_handler: select() returned 0");
- --handler_count;
- return;
- }
- /* We've done our work */
- get_systime(&ts_e);
- /*
- * (ts_e - ts) is the amount of time we spent
- * processing this gob of file descriptors. Log
- * it.
- */
- L_SUB(&ts_e, &ts);
- if (debug > 3)
- netsyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
+ do {
+ ++select_count;
+ buflen = read_refclock_packet(fd, rp, ts);
+ } while (buflen > 0);
- /* just bail. */
- --handler_count;
- return;
- }
- else if (n == -1)
- {
- int err = errno;
+ } /* End if (FD_ISSET(fd, &fds)) */
+ } /* End for (rp = refio; rp != 0 && n > 0; rp = rp->next) */
+ } /* End if (refio != 0) */
- /*
- * extended FAU debugging output
- */
- if (err != EINTR)
- netsyslog(LOG_ERR,
- "select(%d, %s, 0L, 0L, &0.0) error: %m",
- maxactivefd+1,
- fdbits(maxactivefd, &activefds));
- if (err == EBADF) {
- int j, b;
-
- fds = activefds;
- for (j = 0; j <= maxactivefd; j++)
- if (
- (FD_ISSET(j, &fds) && (read(j, &b, 0) == -1))
- )
- netsyslog(LOG_ERR, "Bad file descriptor %d", j);
+#endif /* REFCLOCK */
+
+ /*
+ * Loop through the interfaces looking for data to read.
+ */
+ for (interface = ISC_LIST_TAIL(inter_list);
+ interface != NULL;
+ interface = ISC_LIST_PREV(interface, link))
+ {
+ for (doing = 0; (doing < 2); doing++)
+ {
+ if (doing == 0)
+ {
+ fd = interface->fd;
}
- --handler_count;
- return;
+ else
+ {
+ if (!(interface->flags & INT_BCASTOPEN))
+ break;
+ fd = interface->bfd;
+ }
+ if (fd < 0) continue;
+ if (FD_ISSET(fd, &fds))
+ {
+ do {
+ ++select_count;
+ buflen = read_network_packet(fd, interface, ts);
+ } while (buflen > 0);
+ }
+ /* Check more interfaces */
}
}
- msyslog(LOG_ERR, "input_handler: fell out of infinite for(;;) loop!");
- --handler_count;
+
+#ifdef HAS_ROUTING_SOCKET
+ /*
+ * scan list of asyncio readers - currently only used for routing sockets
+ */
+ asyncio_reader = ISC_LIST_TAIL(asyncio_reader_list);
+
+ while (asyncio_reader != NULL)
+ {
+ struct asyncio_reader *next = ISC_LIST_PREV(asyncio_reader, link);
+ if (FD_ISSET(asyncio_reader->fd, &fds)) {
+ ++select_count;
+ asyncio_reader->receiver(asyncio_reader);
+ }
+ asyncio_reader = next;
+ }
+#endif /* HAS_ROUTING_SOCKET */
+
+ /*
+ * Done everything from that select.
+ */
+
+ /*
+ * If nothing to do, just return.
+ * If an error occurred, complain and return.
+ */
+ if (select_count == 0) /* We really had nothing to do */
+ {
+#ifdef DEBUG
+ if (debug)
+ netsyslog(LOG_DEBUG, "input_handler: select() returned 0");
+#endif
+ return;
+ }
+ /* We've done our work */
+#ifdef DEBUG_TIMING
+ get_systime(&ts_e);
+ /*
+ * (ts_e - ts) is the amount of time we spent
+ * processing this gob of file descriptors. Log
+ * it.
+ */
+ L_SUB(&ts_e, &ts);
+ collect_timing(NULL, "input handler", 1, &ts_e);
+ if (debug > 3)
+ netsyslog(LOG_INFO, "input_handler: Processed a gob of fd's in %s msec", lfptoms(&ts_e, 6));
+#endif
+ /* just bail. */
return;
}
#endif
+
/*
- * findinterface - find interface corresponding to address
+ * findinterface - find local interface corresponding to address
*/
struct interface *
findinterface(
struct sockaddr_storage *addr
)
{
+ struct interface *interface;
+
+ interface = findlocalinterface(addr, INT_WILDCARD);
+
+ if (interface == NULL)
+ {
+ DPRINTF(4, ("Found no interface for address %s - returning wildcard\n",
+ stoa(addr)));
+
+ return (ANY_INTERFACE_CHOOSE(addr));
+ }
+ else
+ {
+ DPRINTF(4, ("Found interface #%d %s for address %s\n",
+ interface->ifnum, interface->name, stoa(addr)));
+
+ return (interface);
+ }
+}
+
+/*
+ * findlocalinterface - find local interface index corresponding to address
+ *
+ * This code attempts to find the local sending address for an outgoing
+ * address by connecting a new socket to destinationaddress:NTP_PORT
+ * and reading the sockname of the resulting connect.
+ * the complicated sequence simulates the routing table lookup
+ * for to first hop without duplicating any of the routing logic into
+ * ntpd. preferably we would have used an API call - but its not there -
+ * so this is the best we can do here short of duplicating to entire routing
+ * logic in ntpd which would be a silly and really unportable thing to do.
+ *
+ */
+static struct interface *
+findlocalinterface(
+ struct sockaddr_storage *addr,
+ int flags
+ )
+{
SOCKET s;
- int rtn, i;
+ int rtn;
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.
- */
+ GETSOCKNAME_SOCKLEN_TYPE saddrlen = SOCKLEN(addr);
+ struct interface *iface;
+
+ DPRINTF(4, ("Finding interface for addr %s in list of addresses\n",
+ stoa(addr));)
+
memset(&saddr, 0, sizeof(saddr));
saddr.ss_family = addr->ss_family;
- if(addr->ss_family == AF_INET)
+ 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);
+ ((struct sockaddr_in*)&saddr)->sin_port = htons(NTP_PORT);
+ }
+#ifdef INCLUDE_IPV6_SUPPORT
+ 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_in6*)&saddr)->sin6_port = htons(NTP_PORT);
+# ifdef ISC_PLATFORM_HAVESCOPEID
+ ((struct sockaddr_in6*)&saddr)->sin6_scope_id = ((struct sockaddr_in6*)addr)->sin6_scope_id;
+# endif
+ }
+#endif
+
s = socket(addr->ss_family, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
- return ANY_INTERFACE_CHOOSE(addr);
+ return NULL;
rtn = connect(s, (struct sockaddr *)&saddr, SOCKLEN(&saddr));
#ifndef SYS_WINNT
@@ -1916,7 +3237,7 @@ findinterface(
#endif
{
closesocket(s);
- return ANY_INTERFACE_CHOOSE(addr);
+ return NULL;
}
rtn = getsockname(s, (struct sockaddr *)&saddr, &saddrlen);
@@ -1926,21 +3247,132 @@ findinterface(
#else
if (rtn == SOCKET_ERROR)
#endif
- return ANY_INTERFACE_CHOOSE(addr);
+ return NULL;
- for (i = 0; i < ninterfaces; i++) {
- /*
- * First look if is the the correct family
- */
- if(inter_list[i].sin.ss_family != saddr.ss_family)
- continue;
- /*
- * We match the unicast address only.
- */
- if (SOCKCMP(&inter_list[i].sin, &saddr))
- return (&inter_list[i]);
+ DPRINTF(4, ("findlocalinterface: kernel maps %s to %s\n", stoa(addr), stoa(&saddr)));
+
+ iface = getinterface(&saddr, flags);
+
+ /* Don't both with ignore interfaces */
+ if (iface != NULL && iface->ignore_packets == ISC_TRUE)
+ {
+ return NULL;
+ }
+ else
+ {
+ return iface;
+ }
+}
+
+/*
+ * fetch an interface structure the matches the
+ * address is has the given flags not set
+ */
+static struct interface *
+getinterface(struct sockaddr_storage *addr, int flags)
+{
+ struct interface *interface = find_addr_in_list(addr);
+
+ if (interface != NULL && interface->flags & flags)
+ {
+ return NULL;
+ }
+ else
+ {
+ return interface;
+ }
+}
+
+/*
+ * findlocalcastinterface - find local *cast interface index corresponding to address
+ * depending on the flags passed
+ */
+static struct interface *
+findlocalcastinterface(
+ struct sockaddr_storage *addr, int flags
+ )
+{
+ struct interface *interface;
+ struct interface *nif = NULL;
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ isc_boolean_t want_linklocal;
+#endif
+
+ /*
+ * see how kernel maps the mcast address
+ */
+ nif = findlocalinterface(addr, 0);
+
+ if (nif) {
+ DPRINTF(2, ("findlocalcastinterface: kernel recommends interface #%d %s\n", nif->ifnum, nif->name));
+ return nif;
+ }
+
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ want_linklocal = ISC_FALSE;
+ if (addr_ismulticast(addr) && flags == INT_MULTICAST)
+ {
+ if (IN6_IS_ADDR_MC_LINKLOCAL(&((struct sockaddr_in6*)addr)->sin6_addr))
+ {
+ want_linklocal = ISC_TRUE;
+ }
+ else if (IN6_IS_ADDR_MC_SITELOCAL(&((struct sockaddr_in6*)addr)->sin6_addr))
+ {
+ want_linklocal = ISC_TRUE;
+ }
+ }
+#endif
+
+ for (interface = ISC_LIST_HEAD(inter_list);
+ interface != NULL;
+ interface = ISC_LIST_NEXT(interface, link))
+ {
+ /* use only allowed addresses */
+ if (interface->ignore_packets == ISC_TRUE)
+ continue;
+
+ /* Skip the loopback and wildcard addresses */
+ if (interface->flags & (INT_LOOPBACK|INT_WILDCARD))
+ continue;
+
+ /* Skip if different family */
+ if(interface->sin.ss_family != addr->ss_family)
+ continue;
+
+ /* Is this it one of these based on flags? */
+ if (!(interface->flags & flags))
+ continue;
+
+ /* for IPv6 multicast check the address for linklocal */
+#ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
+ if (flags == INT_MULTICAST && interface->sin.ss_family == AF_INET6 &&
+ (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)&interface->sin)->sin6_addr))
+ && want_linklocal == ISC_TRUE)
+ {
+ nif = interface;
+ break;
+ }
+ /* If we want a linklocal address and this isn't it, skip */\
+ if (want_linklocal == ISC_TRUE)
+ continue;
+#endif
+ /* Otherwise just look for the flag */
+ if((interface->flags & flags))
+ {
+ nif = interface;
+ break;
+ }
}
- return ANY_INTERFACE_CHOOSE(addr);
+#ifdef DEBUG
+ if (debug > 2)
+ {
+ if (nif)
+ printf("findlocalcastinterface: found interface #%d %s\n", nif->ifnum, nif->name);
+ else
+ printf("findlocalcastinterface: no interface found for %s flags 0x%x\n", stoa(addr), flags);
+ }
+#endif
+ return (nif);
}
/*
@@ -1952,43 +3384,94 @@ findbcastinter(
)
{
#if !defined(MPE) && (defined(SIOCGIFCONF) || defined(SYS_WINNT))
- register int i;
+ struct interface *interface;
+
- i = find_addr_in_list(addr);
- if(i >= 0)
- return (&inter_list[i]);
+ DPRINTF(4, ("Finding broadcast/multicast interface for addr %s in list of addresses\n",
+ stoa(addr)));
- for (i = 0; i < ninterfaces; i++) {
+ interface = findlocalinterface(addr, INT_LOOPBACK|INT_WILDCARD);
+
+ if (interface != NULL)
+ {
+ DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n", interface->ifnum, interface->name));
+ return interface;
+ }
+
+ /* plan B - try to find something reasonable in our lists in case kernel lookup doesn't help */
+
+ for (interface = ISC_LIST_HEAD(inter_list);
+ interface != NULL;
+ interface = ISC_LIST_NEXT(interface, link))
+ {
+ if (interface->flags & INT_WILDCARD)
+ continue;
+
+ /* Don't bother with ignored interfaces */
+ if (interface->ignore_packets == ISC_TRUE)
+ continue;
+
/*
- * First look if this is the correct family
- */
- if(inter_list[i].sin.ss_family != addr->ss_family)
+ * First look if this is the correct family
+ */
+ if(interface->sin.ss_family != addr->ss_family)
continue;
+
+ /* Skip the loopback addresses */
+ if (interface->flags & INT_LOOPBACK)
+ continue;
+
+ /*
+ * If we are looking to match a multicast address grab it.
+ */
+ if (addr_ismulticast(addr) == ISC_TRUE && interface->flags & INT_MULTICAST)
+ {
+#ifdef INCLUDE_IPV6_SUPPORT
+ if(addr->ss_family == AF_INET6) {
+ /* Only use link-local address for link-scope mcast */
+ if(IN6_IS_ADDR_MC_LINKLOCAL(&((struct sockaddr_in6*)addr)->sin6_addr) &&
+ !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)&interface->sin)->sin6_addr)) {
+ continue;
+ }
+ }
+#endif
+ break;
+ }
+
/*
* We match only those interfaces marked as
* broadcastable and either the explicit broadcast
* address or the network portion of the IP address.
* Sloppy.
*/
- if (!(inter_list[i].flags & INT_BROADCAST))
- continue;
if(addr->ss_family == AF_INET) {
- if (SOCKCMP(&inter_list[i].bcast, addr))
- return (&inter_list[i]);
- if ((NSRCADR(&inter_list[i].sin) &
- NSRCADR(&inter_list[i].mask)) == (NSRCADR(addr) &
- NSRCADR(&inter_list[i].mask)))
- return (&inter_list[i]);
+ if (SOCKCMP(&interface->bcast, addr)) {
+ break;
+ }
+ if ((NSRCADR(&interface->sin) &
+ NSRCADR(&interface->mask)) == (NSRCADR(addr) &
+ NSRCADR(&interface->mask)))
+ break;
}
+#ifdef INCLUDE_IPV6_SUPPORT
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]);
- }
+ if (SOCKCMP(&interface->bcast, addr)) {
+ break;
+ }
+ if (SOCKCMP(netof(&interface->sin), netof(addr))) {
+ break;
+ }
+ }
+#endif
}
#endif /* SIOCGIFCONF */
- return ANY_INTERFACE_CHOOSE(addr);
+ if (interface == NULL) {
+ DPRINTF(4, ("No bcast interface found for %s\n", stoa(addr)));
+ return ANY_INTERFACE_CHOOSE(addr);
+ } else {
+ DPRINTF(4, ("Found bcast-/mcast- interface index #%d %s\n", interface->ifnum, interface->name));
+ return interface;
+ }
}
@@ -2012,36 +3495,6 @@ io_clr_stats(void)
#ifdef REFCLOCK
/*
- * This is a hack so that I don't have to fool with these ioctls in the
- * pps driver ... we are already non-blocking and turn on SIGIO thru
- * another mechanisim
- */
-int
-io_addclock_simple(
- struct refclockio *rio
- )
-{
- BLOCKIO();
- /*
- * Stuff the I/O structure in the list and mark the descriptor
- * in use. There is a harmless (I hope) race condition here.
- */
- rio->next = refio;
- refio = rio;
-
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
- if (rio->fd > maxactivefd)
- maxactivefd = rio->fd;
- FD_SET(rio->fd, &activefds);
-#endif
- UNBLOCKIO();
- return 1;
-}
-
-/*
* io_addclock - add a reference clock to the list and arrange that we
* get SIGIO interrupts from it.
*/
@@ -2056,33 +3509,31 @@ io_addclock(
* in use. There is a harmless (I hope) race condition here.
*/
rio->next = refio;
- refio = rio;
# ifdef HAVE_SIGNALED_IO
if (init_clock_sig(rio))
{
- refio = rio->next;
UNBLOCKIO();
return 0;
}
# elif defined(HAVE_IO_COMPLETION_PORT)
if (io_completion_port_add_clock_io(rio))
{
- add_socket_to_list(rio->fd);
- refio = rio->next;
UNBLOCKIO();
return 0;
}
# endif
/*
- * I/O Completion Ports don't care about select and fd_set
+ * enqueue
*/
-#ifndef HAVE_IO_COMPLETION_PORT
- if (rio->fd > maxactivefd)
- maxactivefd = rio->fd;
- FD_SET(rio->fd, &activefds);
-#endif
+ refio = rio;
+
+ /*
+ * register fd
+ */
+ add_fd_to_list(rio->fd, FD_TYPE_FILE);
+
UNBLOCKIO();
return 1;
}
@@ -2095,6 +3546,7 @@ io_closeclock(
struct refclockio *rio
)
{
+ BLOCKIO();
/*
* Remove structure from the list
*/
@@ -2106,20 +3558,15 @@ io_closeclock(
{
register struct refclockio *rp;
- for (rp = refio; rp != 0; rp = rp->next)
+ for (rp = refio; rp != NULL; rp = rp->next)
if (rp->next == rio)
{
rp->next = rio->next;
break;
}
- if (rp == 0)
- {
- /*
- * Internal error. Report it.
- */
- msyslog(LOG_ERR,
- "internal error: refclockio structure not found");
+ if (rp == NULL) {
+ UNBLOCKIO();
return;
}
}
@@ -2127,26 +3574,11 @@ io_closeclock(
/*
* Close the descriptor.
*/
- close_file(rio->fd);
+ close_and_delete_fd_from_list(rio->fd);
+ UNBLOCKIO();
}
#endif /* REFCLOCK */
- /*
- * I/O Completion Ports don't care about select and fd_set
- */
-#ifndef HAVE_IO_COMPLETION_PORT
-void
-kill_asyncio(
- int startfd
- )
-{
- SOCKET i;
-
- BLOCKIO();
- for (i = startfd; i <= maxactivefd; i++)
- (void)close_socket(i);
-}
-#else
/*
* On NT a SOCKET is an unsigned int so we cannot possibly keep it in
* an array. So we use one of the ISC_LIST functions to hold the
@@ -2160,58 +3592,119 @@ kill_asyncio(int startfd)
BLOCKIO();
- lsock = ISC_LIST_HEAD(sockets_list);
+ lsock = ISC_LIST_HEAD(fd_list);
while (lsock != NULL) {
+ /*
+ * careful here - list is being dismantled while
+ * we scan it - setting next here insures that
+ * we are able to correctly scan the list
+ */
next = ISC_LIST_NEXT(lsock, link);
- close_socket(lsock->fd);
+ /*
+ * will remove socket from list
+ */
+ close_and_delete_fd_from_list(lsock->fd);
lsock = next;
}
+ UNBLOCKIO();
}
-#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));
+static void
+add_fd_to_list(SOCKET fd, enum desc_type type) {
+ vsock_t *lsock = (vsock_t *)emalloc(sizeof(vsock_t));
lsock->fd = fd;
+ lsock->type = type;
- ISC_LIST_APPEND(sockets_list, lsock, link);
+ ISC_LIST_APPEND(fd_list, lsock, link);
+ /*
+ * I/O Completion Ports don't care about the select and FD_SET
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
+ /*
+ * keep activefds in sync
+ */
+ if (fd > maxactivefd)
+ maxactivefd = fd;
+ FD_SET( (u_int)fd, &activefds);
+#endif
}
-void
-delete_socket_from_list(SOCKET fd) {
+
+static void
+close_and_delete_fd_from_list(SOCKET fd) {
vsock_t *next;
- vsock_t *lsock = ISC_LIST_HEAD(sockets_list);
+ vsock_t *lsock = ISC_LIST_HEAD(fd_list);
while(lsock != NULL) {
next = ISC_LIST_NEXT(lsock, link);
if(lsock->fd == fd) {
- ISC_LIST_DEQUEUE(sockets_list, lsock, link);
+ ISC_LIST_DEQUEUE_TYPE(fd_list, lsock, link, vsock_t);
+
+ switch (lsock->type) {
+ case FD_TYPE_SOCKET:
+#ifdef SYS_WINNT
+ closesocket(lsock->fd);
+ break;
+#endif
+ case FD_TYPE_FILE:
+ (void) close(lsock->fd);
+ break;
+ default:
+ msyslog(LOG_ERR, "internal error - illegal descriptor type %d - EXITING", (int)lsock->type);
+ exit(1);
+ }
+
free(lsock);
+ /*
+ * I/O Completion Ports don't care about select and fd_set
+ */
+#ifndef HAVE_IO_COMPLETION_PORT
+ /*
+ * remove from activefds
+ */
+ FD_CLR( (u_int) fd, &activefds);
+
+ if (fd == maxactivefd) {
+ int i, newmax = 0;
+ for (i = 0; i < maxactivefd; i++)
+ if (FD_ISSET(i, &activefds))
+ newmax = i;
+ maxactivefd = newmax;
+ }
+#endif
break;
}
- else
- lsock = next;
+ 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);
+static void
+add_addr_to_list(struct sockaddr_storage *addr, struct interface *interface){
#ifdef DEBUG
- if (debug)
- printf("Added addr %s to list of addresses\n",
- stoa(addr));
+ if (find_addr_in_list(addr) == NULL) {
+#endif
+ /* not there yet - add to list */
+ remaddr_t *laddr = (remaddr_t *)emalloc(sizeof(remaddr_t));
+ memcpy(&laddr->addr, addr, sizeof(struct sockaddr_storage));
+ laddr->interface = interface;
+
+ ISC_LIST_APPEND(remoteaddr_list, laddr, link);
+
+ DPRINTF(4, ("Added addr %s to list of addresses\n",
+ stoa(addr)));
+#ifdef DEBUG
+ } else {
+ DPRINTF(4, ("WARNING: Attempt to add duplicate addr %s to address list\n",
+ stoa(addr)));
+ }
#endif
-
-
}
-void
+
+static void
delete_addr_from_list(struct sockaddr_storage *addr) {
remaddr_t *next;
@@ -2220,38 +3713,201 @@ delete_addr_from_list(struct sockaddr_storage *addr) {
while(laddr != NULL) {
next = ISC_LIST_NEXT(laddr, link);
if(SOCKCMP(&laddr->addr, addr)) {
- ISC_LIST_DEQUEUE(remoteaddr_list, laddr, link);
+ ISC_LIST_DEQUEUE_TYPE(remoteaddr_list, laddr, link, remaddr_t);
+ DPRINTF(4, ("Deleted addr %s from list of addresses\n",
+ stoa(addr)));
free(laddr);
break;
}
- else
- laddr = next;
+ laddr = next;
}
-#ifdef DEBUG
- if (debug)
- printf("Deleted addr %s from list of addresses\n",
- stoa(addr));
-#endif
}
-int
+
+static void
+delete_interface_from_list(struct interface *iface) {
+ remaddr_t *next;
+ remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
+
+ while(laddr != NULL) {
+ next = ISC_LIST_NEXT(laddr, link);
+ if (laddr->interface == iface) {
+ ISC_LIST_DEQUEUE_TYPE(remoteaddr_list, laddr, link, remaddr_t);
+ DPRINTF(4, ("Deleted addr %s for interface #%d %s from list of addresses\n",
+ stoa(&laddr->addr), iface->ifnum, iface->name));
+ free(laddr);
+ }
+ laddr = next;
+ }
+}
+
+static struct interface *
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
+ DPRINTF(4, ("Searching for addr %s in list of addresses - ",
+ stoa(addr)));
while(laddr != NULL) {
next = ISC_LIST_NEXT(laddr, link);
if(SOCKCMP(&laddr->addr, addr)) {
- return (laddr->if_index);
+ DPRINTF(4, ("FOUND\n"));
+ return laddr->interface;
+ }
+ else
+ laddr = next;
+ }
+ DPRINTF(4, ("NOT FOUND\n"));
+ return NULL; /* Not found */
+}
+
+/*
+ * Find the given address with the associated flag in the list
+ */
+static struct interface *
+find_flagged_addr_in_list(struct sockaddr_storage *addr, int flag) {
+
+ remaddr_t *next;
+ remaddr_t *laddr = ISC_LIST_HEAD(remoteaddr_list);
+ DPRINTF(4, ("Finding addr %s in list of addresses\n",
+ stoa(addr)));
+
+ while(laddr != NULL) {
+ next = ISC_LIST_NEXT(laddr, link);
+ if(SOCKCMP(&laddr->addr, addr) && (laddr->interface->flags & flag)) {
+ return laddr->interface;
break;
}
else
laddr = next;
}
- return (-1); /* Not found */
+ return NULL; /* Not found */
+}
+
+#ifdef HAS_ROUTING_SOCKET
+#include <net/route.h>
+
+#ifndef UPDATE_GRACE
+#define UPDATE_GRACE 2 /* wait UPDATE_GRACE seconds before scanning */
+#endif
+
+static void
+process_routing_msgs(struct asyncio_reader *reader)
+{
+ char buffer[5120];
+ char *p = buffer;
+
+ int cnt;
+
+ if (disable_dynamic_updates) {
+ /*
+ * discard ourselves if we are not need any more
+ * usually happens when running unprivileged
+ */
+ remove_asyncio_reader(reader);
+ delete_asyncio_reader(reader);
+ return;
+ }
+
+ cnt = read(reader->fd, buffer, sizeof(buffer));
+
+ if (cnt < 0) {
+ msyslog(LOG_ERR, "i/o error on routing socket %m - disabling");
+ remove_asyncio_reader(reader);
+ delete_asyncio_reader(reader);
+ return;
+ }
+
+ /*
+ * process routing message
+ */
+ while ((p + sizeof(struct rt_msghdr)) <= (buffer + cnt))
+ {
+ struct rt_msghdr *rtm;
+
+ rtm = (struct rt_msghdr *)p;
+ if (rtm->rtm_version != RTM_VERSION) {
+ msyslog(LOG_ERR, "version mismatch on routing socket %m - disabling");
+ remove_asyncio_reader(reader);
+ delete_asyncio_reader(reader);
+ return;
+ }
+
+ switch (rtm->rtm_type) {
+#ifdef RTM_NEWADDR
+ case RTM_NEWADDR:
+#endif
+#ifdef RTM_DELADDR
+ case RTM_DELADDR:
+#endif
+#ifdef RTM_ADD
+ case RTM_ADD:
+#endif
+#ifdef RTM_DELETE
+ case RTM_DELETE:
+#endif
+#ifdef RTM_REDIRECT
+ case RTM_REDIRECT:
+#endif
+#ifdef RTM_CHANGE
+ case RTM_CHANGE:
+#endif
+#ifdef RTM_LOSING
+ case RTM_LOSING:
+#endif
+#ifdef RTM_IFINFO
+ case RTM_IFINFO:
+#endif
+#ifdef RTM_IFANNOUNCE
+ case RTM_IFANNOUNCE:
+#endif
+ /*
+ * we are keen on new and deleted addresses and if an interface goes up and down or routing changes
+ */
+ DPRINTF(3, ("routing message op = %d: scheduling interface update\n", rtm->rtm_type));
+ timer_interfacetimeout(current_time + UPDATE_GRACE);
+ break;
+ default:
+ /*
+ * the rest doesn't bother us.
+ */
+ DPRINTF(4, ("routing message op = %d: ignored\n", rtm->rtm_type));
+ break;
+ }
+ p += rtm->rtm_msglen;
+ }
+}
+
+/*
+ * set up routing notifications
+ */
+static void
+init_async_notifications()
+{
+ struct asyncio_reader *reader;
+ int fd = socket(PF_ROUTE, SOCK_RAW, 0);
+
+ if (fd >= 0) {
+ fd = move_fd(fd);
+ init_nonblocking_io(fd);
+#if defined(HAVE_SIGNALED_IO)
+ init_socket_sig(fd);
+#endif /* HAVE_SIGNALED_IO */
+
+ reader = new_asyncio_reader();
+
+ reader->fd = fd;
+ reader->receiver = process_routing_msgs;
+
+ add_asyncio_reader(reader, FD_TYPE_SOCKET);
+ msyslog(LOG_INFO, "Listening on routing socket on fd #%d for interface updates", fd);
+ } else {
+ msyslog(LOG_ERR, "unable to open routing socket (%m) - using polled interface update");
+ }
+}
+#else
+static void
+init_async_notifications()
+{
}
+#endif
diff --git a/contrib/ntp/ntpd/ntp_loopfilter.c b/contrib/ntp/ntpd/ntp_loopfilter.c
index 99d1cc4..d0fa466c 100644
--- a/contrib/ntp/ntpd/ntp_loopfilter.c
+++ b/contrib/ntp/ntpd/ntp_loopfilter.c
@@ -38,11 +38,12 @@
#define CLOCK_MINSTEP 900. /* default stepout threshold (s) */
#define CLOCK_PANIC 1000. /* default panic threshold (s) */
#define CLOCK_PHI 15e-6 /* max frequency error (s/s) */
-#define CLOCK_PLL 16. /* PLL loop gain */
-#define CLOCK_FLL 8. /* FLL loop gain */
-#define CLOCK_AVG 4. /* parameter averaging constant */
+#define CLOCK_PLL 16. /* PLL loop gain (log2) */
+#define CLOCK_AVG 8. /* parameter averaging constant */
+#define CLOCK_FLL (NTP_MAXPOLL + CLOCK_AVG) /* FLL loop gain */
#define CLOCK_ALLAN 1500. /* compromise Allan intercept (s) */
#define CLOCK_DAY 86400. /* one day in seconds (s) */
+#define CLOCK_JUNE (CLOCK_DAY * 30) /* June in seconds (s) */
#define CLOCK_LIMIT 30 /* poll-adjust threshold */
#define CLOCK_PGATE 4. /* poll-adjust gate */
#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
@@ -52,31 +53,29 @@
* synchronization behavior during initialization and following a
* timewarp.
*
- * State < max > max Comments
+ * State < step > step Comments
* ====================================================
- * NSET FREQ FREQ no ntp.drift
+ * NSET FREQ step, FREQ no ntp.drift
*
- * FSET TSET if (allow) TSET, ntp.drift
- * else FREQ
+ * FSET SYNC step, SYNC ntp.drift
*
- * TSET SYNC FREQ time set
+ * FREQ if (mu < 900) if (mu < 900) set freq
+ * ignore ignore
+ * else else
+ * freq, SYNC freq, step, SYNC
*
- * FREQ SYNC if (mu < 900) FREQ calculate frequency
- * else if (allow) TSET
- * else FREQ
+ * SYNC SYNC if (mu < 900) adjust phase/freq
+ * ignore
+ * else
+ * SPIK
*
- * SYNC SYNC if (mu < 900) SYNC normal state
- * else SPIK
- *
- * SPIK SYNC if (allow) TSET spike detector
- * else FREQ
+ * SPIK SYNC step, SYNC set phase
*/
#define S_NSET 0 /* clock never set */
#define S_FSET 1 /* frequency set from the drift file */
-#define S_TSET 2 /* time set */
+#define S_SPIK 2 /* spike detected */
#define S_FREQ 3 /* frequency mode */
#define S_SYNC 4 /* clock synchronized */
-#define S_SPIK 5 /* spike detected */
/*
* Kernel PLL/PPS state machine. This is used with the kernel PLL
@@ -85,10 +84,18 @@
* If kernel support for the ntp_adjtime() system call is available, the
* ntp_control flag is set. The ntp_enable and kern_enable flags can be
* set at configuration time or run time using ntpdc. If ntp_enable is
- * false, the discipline loop is unlocked and no correctios of any kind
+ * false, the discipline loop is unlocked and no corrections of any kind
* are made. If both ntp_control and kern_enable are set, the kernel
* support is used as described above; if false, the kernel is bypassed
- * entirely and the daemon PLL used instead.
+ * entirely and the daemon discipline used instead.
+ *
+ * There have been three versions of the kernel discipline code. The
+ * first (microkernel) now in Solaris discipilnes the microseconds. The
+ * second and third (nanokernel) disciplines the clock in nanoseconds.
+ * These versions are identifed if the symbol STA_PLL is present in the
+ * header file /usr/include/sys/timex.h. The third and current version
+ * includes TAI offset and is identified by the symbol NTP_API with
+ * value 4.
*
* Each update to a prefer peer sets pps_stratum if it survives the
* intersection algorithm and its time is within range. The PPS time
@@ -118,16 +125,18 @@ double allan_xpt = CLOCK_ALLAN; /* Allan intercept (s) */
/*
* Program variables
*/
-static double clock_offset; /* clock offset adjustment (s) */
-double drift_comp; /* clock frequency (s/s) */
-double clock_stability; /* clock stability (s/s) */
-u_long pps_control; /* last pps sample time */
+static double clock_offset; /* offset (s) */
+double clock_jitter; /* offset jitter (s) */
+double drift_comp; /* frequency (s/s) */
+double clock_stability; /* frequency stability (wander) (s/s) */
+u_long sys_clocktime; /* last system clock update */
+u_long pps_control; /* last pps update */
+u_long sys_tai; /* UTC offset from TAI (s) */
static void rstclock P((int, u_long, double)); /* transition function */
#ifdef KERNEL_PLL
struct timex ntv; /* kernel API parameters */
int pll_status; /* status bits for kernel pll */
-int pll_nano; /* nanosecond kernel switch */
#endif /* KERNEL_PLL */
/*
@@ -145,12 +154,10 @@ int mode_ntpdate = FALSE; /* exit on first clock set */
/*
* Clock state machine variables
*/
-u_char sys_poll = NTP_MINDPOLL; /* system poll interval (log2 s) */
int state; /* clock discipline state */
-int tc_counter; /* hysteresis counter */
-u_long last_time; /* time of last clock update (s) */
-double last_offset; /* last clock offset (s) */
-double sys_jitter; /* system RMS jitter (s) */
+u_char sys_poll = NTP_MINDPOLL; /* time constant/poll (log2 s) */
+int tc_counter; /* jiggle counter */
+double last_offset; /* last offset (s) */
/*
* Huff-n'-puff filter variables
@@ -180,50 +187,61 @@ init_loopfilter(void)
{
/*
* Initialize state variables. Initially, we expect no drift
- * file, so set the state to S_NSET.
+ * file, so set the state to S_NSET. If a drift file is present,
+ * it will be detected later and the state set to S_FSET.
*/
- rstclock(S_NSET, current_time, 0);
+ rstclock(S_NSET, 0, 0);
+ clock_jitter = LOGTOD(sys_precision);
}
/*
- * 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.
+ * local_clock - the NTP logical clock loop filter.
+ *
+ * Return codes:
+ * -1 update ignored: exceeds panic threshold
+ * 0 update ignored: popcorn or exceeds step threshold
+ * 1 clock was slewed
+ * 2 clock was stepped
*
* LOCKCLOCK: The only thing this routine does is set the
* sys_rootdispersion variable equal to the peer dispersion.
*/
int
local_clock(
- struct peer *peer, /* synch source peer structure */
- double fp_offset, /* clock offset (s) */
- double epsil /* jittter (square s*s) */
+ struct peer *peer, /* synch source peer structure */
+ double fp_offset /* clock offset (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 rval; /* return code */
+ u_long mu; /* interval since last update (s) */
+ double flladj; /* FLL frequency adjustment (ppm) */
+ double plladj; /* PLL frequency adjustment (ppm) */
+ double clock_frequency; /* clock frequency adjustment (ppm) */
+ double dtemp, etemp; /* double temps */
+#ifdef OPENSSL
+ u_int32 *tpt;
+ int i;
+ u_int len;
+ long togo;
+#endif /* OPENSSL */
/*
- * If the loop is opened, monitor and record the offsets
- * anyway in order to determine the open-loop response.
+ * If the loop is opened or the NIST LOCKCLOCK is in use,
+ * monitor and record the offsets anyway in order to determine
+ * the open-loop response and then go home.
*/
#ifdef DEBUG
if (debug)
printf(
- "local_clock: assocID %d offset %.9f jitter %.9f state %d\n",
- peer->associd, fp_offset, SQRT(epsil), state);
+ "local_clock: assocID %d offset %.9f freq %.3f state %d\n",
+ peer->associd, fp_offset, drift_comp * 1e6, state);
#endif
#ifdef LOCKCLOCK
- sys_rootdispersion = peer->rootdispersion;
- return (0);
+ return (0);
#else /* LOCKCLOCK */
if (!ntp_enable) {
- record_loop_stats(fp_offset, drift_comp, SQRT(epsil),
+ record_loop_stats(fp_offset, drift_comp, clock_jitter,
clock_stability, sys_poll);
return (0);
}
@@ -234,8 +252,8 @@ local_clock(
* occur. The allow_panic defaults to FALSE, so the first panic
* will exit. It can be set TRUE by a command line option, in
* which case the clock will be set anyway and time marches on.
- * But, allow_panic will be set it FALSE when the update is
- * within the step range; so, subsequent panics will exit.
+ * But, allow_panic will be set FALSE when the update is less
+ * than the step threshold; so, subsequent panics will exit.
*/
if (fabs(fp_offset) > clock_panic && clock_panic > 0 &&
!allow_panic) {
@@ -251,7 +269,8 @@ local_clock(
* threshold, above which the clock will be stepped instead of
* slewed. The value defaults to 128 ms, but can be set to even
* unreasonable values. If set to zero, the clock will never be
- * stepped.
+ * stepped. Note that a slew will persist beyond the life of
+ * this program.
*
* Note that if ntpdate is active, the terminal does not detach,
* so the termination comments print directly to the console.
@@ -268,45 +287,24 @@ local_clock(
fp_offset);
printf("ntpd: time slew %+.6fs\n", fp_offset);
}
- record_loop_stats(fp_offset, drift_comp, SQRT(epsil),
+ record_loop_stats(fp_offset, drift_comp, clock_jitter,
clock_stability, sys_poll);
exit (0);
}
/*
- * If the clock has never been set, set it and initialize the
- * discipline parameters. We then switch to frequency mode to
- * speed the inital convergence process. If lucky, after an hour
- * the ntp.drift file is created and initialized and we don't
- * get here again.
- */
- if (state == S_NSET) {
- if (fabs(fp_offset) > clock_max && clock_max > 0) {
- step_systime(fp_offset);
- msyslog(LOG_NOTICE, "time reset %+.6f s",
- fp_offset);
- reinit_timer();
- }
- rstclock(S_FREQ, peer->epoch, 0);
- return (1);
- }
-
- /*
- * Update the jitter estimate.
- */
- oerror = sys_jitter;
- dtemp = SQUARE(sys_jitter);
- sys_jitter = SQRT(dtemp + (epsil - dtemp) / CLOCK_AVG);
-
- /*
* The huff-n'-puff filter finds the lowest delay in the recent
* interval. This is used to correct the offset by one-half the
* difference between the sample delay and minimum delay. This
* is most effective if the delays are highly assymetric and
* clockhopping is avoided and the clock frequency wander is
* relatively small.
+ *
+ * Note either there is no prefer peer or this update is from
+ * the prefer peer.
*/
- if (sys_huffpuff != NULL) {
+ if (sys_huffpuff != NULL && (sys_prefer == NULL || sys_prefer ==
+ peer)) {
if (peer->delay < sys_huffpuff[sys_huffptr])
sys_huffpuff[sys_huffptr] = peer->delay;
if (peer->delay < sys_mindly)
@@ -332,83 +330,125 @@ local_clock(
* However, if the step threshold is set to zero, a step will
* never occur. See the instruction manual for the details how
* these actions interact with the command line options.
+ *
+ * Note the system poll is set to minpoll only if the clock is
+ * stepped. Note also the kernel is disabled if step is
+ * disabled or greater than 0.5 s.
*/
- retval = 0;
- if (sys_poll > peer->maxpoll)
- sys_poll = peer->maxpoll;
- else if (sys_poll < peer->minpoll)
- sys_poll = peer->minpoll;
clock_frequency = flladj = plladj = 0;
- mu = peer->epoch - last_time;
+ mu = peer->epoch - sys_clocktime;
+ if (clock_max == 0 || clock_max > 0.5)
+ kern_enable = 0;
+ rval = 1;
if (fabs(fp_offset) > clock_max && clock_max > 0) {
switch (state) {
/*
- * In S_TSET state the time has been set at the last
- * valid update and the offset at that time set to zero.
- * If following that we cruise outside the capture
- * range, assume a really bad frequency error and switch
- * to S_FREQ state.
- */
- case S_TSET:
- state = S_FREQ;
- break;
-
- /*
- * In S_SYNC state we ignore outlyers. At the first
- * outlyer after the stepout threshold, switch to S_SPIK
- * state.
+ * In S_SYNC state we ignore the first outlyer amd
+ * switch to S_SPIK state.
*/
case S_SYNC:
- if (mu < clock_minstep)
- return (0);
state = S_SPIK;
return (0);
/*
- * In S_FREQ state we ignore outlyers. At the first
- * outlyer after 900 s, compute the apparent phase and
- * frequency correction.
+ * In S_FREQ state we ignore outlyers and inlyers. At
+ * the first outlyer after the stepout threshold,
+ * compute the apparent frequency correction and step
+ * the phase.
*/
case S_FREQ:
if (mu < clock_minstep)
return (0);
+
+ clock_frequency = (fp_offset - clock_offset) /
+ mu;
+
/* fall through to S_SPIK */
/*
- * In S_SPIK state a large correction is necessary.
- * Since the outlyer may be due to a large frequency
- * error, compute the apparent frequency correction.
+ * In S_SPIK state we ignore succeeding outlyers until
+ * either an inlyer is found or the stepout threshold is
+ * exceeded.
*/
case S_SPIK:
- clock_frequency = (fp_offset - clock_offset) /
- mu;
+ if (mu < clock_minstep)
+ return (0);
+
/* fall through to default */
/*
- * We get here directly in S_FSET state and indirectly
- * from S_FREQ and S_SPIK states. The clock is either
- * reset or shaken, but never stirred.
- */
+ * We get here by default in S_NSET and S_FSET states
+ * and from above in S_FREQ or S_SPIK states.
+ *
+ * In S_NSET state an initial frequency correction is
+ * not available, usually because the frequency file has
+ * not yet been written. Since the time is outside the
+ * step threshold, the clock is stepped. The frequency
+ * will be set directly following the stepout interval.
+ *
+ * In S_FSET state the initial frequency has been set
+ * from the frequency file. Since the time is outside
+ * the step threshold, the clock is stepped immediately,
+ * rather than after the stepout interval. Guys get
+ * nervous if it takes 17 minutes to set the clock for
+ * the first time.
+ *
+ * In S_FREQ and S_SPIK states the stepout threshold has
+ * expired and the phase is still above the step
+ * threshold. Note that a single spike greater than the
+ * step threshold is always suppressed, even at the
+ * longer poll intervals.
+ */
default:
step_systime(fp_offset);
msyslog(LOG_NOTICE, "time reset %+.6f s",
fp_offset);
reinit_timer();
- rstclock(S_TSET, peer->epoch, 0);
- retval = 1;
+ tc_counter = 0;
+ sys_poll = NTP_MINPOLL;
+ sys_tai = 0;
+ clock_jitter = LOGTOD(sys_precision);
+ rval = 2;
+ if (state == S_NSET) {
+ rstclock(S_FREQ, peer->epoch, 0);
+ return (rval);
+ }
break;
}
+ rstclock(S_SYNC, peer->epoch, 0);
} else {
+
+ /*
+ * The offset is less than the step threshold. Calculate
+ * the jitter as the exponentially weighted offset
+ * differences.
+ */
+ etemp = SQUARE(clock_jitter);
+ dtemp = SQUARE(max(fabs(fp_offset - last_offset),
+ LOGTOD(sys_precision)));
+ clock_jitter = SQRT(etemp + (dtemp - etemp) /
+ CLOCK_AVG);
switch (state) {
/*
- * In S_FSET state this is the first update. Adjust the
- * phase, but don't adjust the frequency until the next
+ * In S_NSET state this is the first update received and
+ * the frequency has not been initialized. Adjust the
+ * phase, but do not adjust the frequency until after
+ * the stepout threshold.
+ */
+ case S_NSET:
+ rstclock(S_FREQ, peer->epoch, fp_offset);
+ break;
+
+ /*
+ * In S_FSET state this is the first update received and
+ * the frequency has been initialized. Adjust the phase,
+ * but do not adjust the frequency until the next
* update.
*/
case S_FSET:
- rstclock(S_TSET, peer->epoch, fp_offset);
+ rstclock(S_SYNC, peer->epoch, fp_offset);
break;
/*
@@ -419,76 +459,78 @@ local_clock(
case S_FREQ:
if (mu < clock_minstep)
return (0);
+
clock_frequency = (fp_offset - clock_offset) /
mu;
rstclock(S_SYNC, peer->epoch, fp_offset);
break;
/*
- * Either the clock has just been set or the previous
- * update was a spike and ignored. Since this update is
- * not an outlyer, fold the tent and resume life.
- */
- case S_TSET:
- case S_SPIK:
- state = S_SYNC;
- /* fall through to default */
-
- /*
- * We come here in the normal case for linear phase and
- * frequency adjustments. If the difference between the
- * last offset and the current one exceeds the jitter by
- * CLOCK_SGATE and the interval since the last update is
- * less than twice the system poll interval, consider
- * the update a popcorn spike and ignore it..
+ * We get here by default in S_SYNC and S_SPIK states.
+ * Here we compute the frequency update due to PLL and
+ * FLL contributions.
*/
default:
allow_panic = FALSE;
- dtemp = fabs(fp_offset - last_offset);
-/*
- if (dtemp > CLOCK_SGATE * oerror && mu <
- (u_long) ULOGTOD(sys_poll + 1)) {
-#ifdef DEBUG
- if (debug)
- printf(
- "local_clock: popcorn %.6f %.6f\n",
- dtemp, oerror);
-#endif
- last_offset = fp_offset;
- return (0);
- }
-*/
/*
* The FLL and PLL frequency gain constants
* depend on the poll interval and Allan
- * intercept. The PLL constant is calculated
- * throughout the poll interval range, but the
- * update interval is clamped so as not to
- * exceed the poll interval. The FLL gain is
- * zero below one-half the Allan intercept and
- * unity at MAXPOLL. It decreases as 1 /
- * (MAXPOLL + 1 - poll interval) in a feeble
- * effort to match the loop stiffness to the
- * Allan wobble. Particularly for the PLL, these
- * measures allow oversampling, but not
- * undersampling and insure stability even when
- * the rules of fair engagement are broken.
+ * intercept. The PLL is always used, but
+ * becomes ineffective above the Allan
+ * intercept. The FLL is not used below one-half
+ * the Allan intercept. Above that the loop gain
+ * increases in steps to 1 / CLOCK_AVG.
*/
if (ULOGTOD(sys_poll) > allan_xpt / 2) {
- dtemp = NTP_MAXPOLL + 1 - sys_poll;
+ dtemp = CLOCK_FLL - sys_poll;
flladj = (fp_offset - clock_offset) /
(max(mu, allan_xpt) * dtemp);
}
+
+ /*
+ * For the PLL the integration interval
+ * (numerator) is the minimum of the update
+ * interval and poll interval. This allows
+ * oversampling, but not undersampling.
+ */
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;
+ rstclock(S_SYNC, peer->epoch, fp_offset);
break;
}
}
+#ifdef OPENSSL
+ /*
+ * Scan the loopsecond table to determine the TAI offset. If
+ * there is a scheduled leap in future, set the leap warning,
+ * but only if less than 30 days before the leap.
+ */
+ tpt = (u_int32 *)tai_leap.ptr;
+ len = ntohl(tai_leap.vallen) / sizeof(u_int32);
+ if (tpt != NULL) {
+ for (i = 0; i < len; i++) {
+ togo = (long)ntohl(tpt[i]) -
+ (long)peer->rec.l_ui;
+ if (togo > 0) {
+ if (togo < CLOCK_JUNE)
+ leap_next |= LEAP_ADDSECOND;
+ break;
+ }
+ }
+#if defined(STA_NANO) && NTP_API == 4
+ if (pll_control && kern_enable && sys_tai == 0) {
+ memset(&ntv, 0, sizeof(ntv));
+ ntv.modes = MOD_TAI;
+ ntv.constant = i + TAI_1972 - 1;
+ ntp_adjtime(&ntv);
+ }
+#endif /* STA_NANO */
+ sys_tai = i + TAI_1972 - 1;
+ }
+#endif /* OPENSSL */
#ifdef KERNEL_PLL
/*
* This code segment works when clock adjustments are made using
@@ -499,6 +541,11 @@ local_clock(
* DECstation 5000/240 and Alpha AXP, additional kernel
* modifications provide a true microsecond clock and nanosecond
* clock, respectively.
+ *
+ * Important note: The kernel discipline is used only if the
+ * step threshold is less than 0.5 s, as anything higher can
+ * lead to overflow problems. This might occur if some misguided
+ * lad set the step threshold to something ridiculous.
*/
if (pll_control && kern_enable) {
@@ -511,60 +558,68 @@ local_clock(
* variables, which will be read later by the local
* clock driver. Afterwards, remember the time and
* frequency offsets for jitter and stability values and
- * to update the drift file.
+ * to update the frequency file.
*/
memset(&ntv, 0, sizeof(ntv));
if (ext_enable) {
ntv.modes = MOD_STATUS;
} else {
+ struct tm *tm = NULL;
+ time_t tstamp;
+
+#ifdef STA_NANO
+ ntv.modes = MOD_BITS | MOD_NANO;
+#else /* STA_NANO */
ntv.modes = MOD_BITS;
+#endif /* STA_NANO */
if (clock_offset < 0)
dtemp = -.5;
else
dtemp = .5;
- if (pll_nano) {
- ntv.offset = (int32)(clock_offset *
- 1e9 + dtemp);
- ntv.constant = sys_poll;
- } else {
- ntv.offset = (int32)(clock_offset *
- 1e6 + dtemp);
- ntv.constant = sys_poll - 4;
- }
+#ifdef STA_NANO
+ ntv.offset = (int32)(clock_offset * 1e9 +
+ dtemp);
+ ntv.constant = sys_poll;
+#else /* STA_NANO */
+ ntv.offset = (int32)(clock_offset * 1e6 +
+ dtemp);
+ ntv.constant = sys_poll - 4;
+#endif /* STA_NANO */
+
+ /*
+ * The frequency is set directly only if
+ * clock_frequency is nonzero coming out of FREQ
+ * state.
+ */
if (clock_frequency != 0) {
ntv.modes |= MOD_FREQUENCY;
ntv.freq = (int32)((clock_frequency +
drift_comp) * 65536e6);
}
- ntv.esterror = (u_int32)(sys_jitter * 1e6);
+ ntv.esterror = (u_int32)(clock_jitter * 1e6);
ntv.maxerror = (u_int32)((sys_rootdelay / 2 +
sys_rootdispersion) * 1e6);
ntv.status = STA_PLL;
/*
- * Set the leap bits in the status word.
+ * Set the leap bits in the status word, but
+ * only on the last day of June or December.
*/
- if (sys_leap == LEAP_NOTINSYNC) {
- ntv.status |= STA_UNSYNC;
- } else if (calleapwhen(sys_reftime.l_ui) <
- CLOCK_DAY) {
- if (sys_leap & LEAP_ADDSECOND)
- ntv.status |= STA_INS;
- else if (sys_leap & LEAP_DELSECOND)
- ntv.status |= STA_DEL;
+ tstamp = peer->rec.l_ui - JAN_1970;
+ tm = gmtime(&tstamp);
+ if (tm != NULL) {
+ if ((tm->tm_mon + 1 == 6 &&
+ tm->tm_mday == 30) || (tm->tm_mon +
+ 1 == 12 && tm->tm_mday == 31)) {
+ if (leap_next & LEAP_ADDSECOND)
+ ntv.status |= STA_INS;
+ else if (leap_next &
+ LEAP_DELSECOND)
+ ntv.status |= STA_DEL;
+ }
}
/*
- * Switch to FLL mode if the poll interval is
- * greater than MAXDPOLL, so that the kernel
- * loop behaves as the daemon loop; viz.,
- * selects the FLL when necessary, etc. For
- * legacy only.
- */
- if (sys_poll > NTP_MAXDPOLL)
- ntv.status |= STA_FLL;
-
- /*
* If the PPS signal is up and enabled, light
* the frequency bit. If the PPS driver is
* working, light the phase bit as well. If not,
@@ -583,29 +638,28 @@ local_clock(
/*
* Pass the stuff to the kernel. If it squeals, turn off
- * the pigs. In any case, fetch the kernel offset and
+ * the pig. In any case, fetch the kernel offset and
* frequency and pretend we did it here.
*/
if (ntp_adjtime(&ntv) == TIME_ERROR) {
- if (ntv.status != pll_status)
- NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
- msyslog(LOG_NOTICE,
- "kernel time sync disabled %04x",
- ntv.status);
+ NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
+ msyslog(LOG_NOTICE,
+ "kernel time sync error %04x", ntv.status);
ntv.status &= ~(STA_PPSFREQ | STA_PPSTIME);
} else {
- if (ntv.status != pll_status)
+ if ((ntv.status ^ pll_status) & ~STA_FLL)
NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
msyslog(LOG_NOTICE,
- "kernel time sync enabled %04x",
+ "kernel time sync status change %04x",
ntv.status);
}
pll_status = ntv.status;
- if (pll_nano)
- clock_offset = ntv.offset / 1e9;
- else
- clock_offset = ntv.offset / 1e6;
- clock_frequency = ntv.freq / 65536e6 - drift_comp;
+#ifdef STA_NANO
+ clock_offset = ntv.offset / 1e9;
+#else /* STA_NANO */
+ clock_offset = ntv.offset / 1e6;
+#endif /* STA_NANO */
+ clock_frequency = ntv.freq / 65536e6;
flladj = plladj = 0;
/*
@@ -613,90 +667,91 @@ local_clock(
*/
if (ntv.status & STA_PPSTIME) {
pps_control = current_time;
- if (pll_nano)
- sys_jitter = ntv.jitter / 1e9;
- else
- sys_jitter = ntv.jitter / 1e6;
+#ifdef STA_NANO
+ clock_jitter = ntv.jitter / 1e9;
+#else /* STA_NANO */
+ clock_jitter = ntv.jitter / 1e6;
+#endif /* STA_NANO */
}
- }
+ } else {
#endif /* KERNEL_PLL */
+ /*
+ * We get here if the kernel discipline is not enabled.
+ * Adjust the clock frequency as the sum of the directly
+ * computed frequency (if measured) and the PLL and FLL
+ * increments.
+ */
+ clock_frequency = drift_comp + clock_frequency +
+ flladj + plladj;
+#ifdef KERNEL_PLL
+ }
+#endif /* KERNEL_PLL */
+
/*
- * Adjust the clock frequency and calculate the stability. If
- * kernel support is available, we use the results of the kernel
- * discipline instead of the PLL/FLL discipline. In this case,
- * drift_comp is a sham and used only for updating the drift
- * file and for billboard eye candy.
+ * Clamp the frequency within the tolerance range and calculate
+ * the frequency change since the last update.
*/
- dtemp = clock_frequency + flladj + plladj;
- etemp = drift_comp + dtemp;
- if (etemp > NTP_MAXFREQ)
- drift_comp = NTP_MAXFREQ;
- else if (etemp <= -NTP_MAXFREQ)
- drift_comp = -NTP_MAXFREQ;
- else
- drift_comp = etemp;
- if (fabs(etemp) > NTP_MAXFREQ)
+ if (fabs(clock_frequency) > NTP_MAXFREQ)
NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
msyslog(LOG_NOTICE,
"frequency error %.0f PPM exceeds tolerance %.0f PPM",
- etemp * 1e6, NTP_MAXFREQ * 1e6);
+ clock_frequency * 1e6, NTP_MAXFREQ * 1e6);
+ dtemp = SQUARE(clock_frequency - drift_comp);
+ if (clock_frequency > NTP_MAXFREQ)
+ drift_comp = NTP_MAXFREQ;
+ else if (clock_frequency < -NTP_MAXFREQ)
+ drift_comp = -NTP_MAXFREQ;
+ else
+ drift_comp = clock_frequency;
+ /*
+ * Calculate the wander as the exponentially weighted frequency
+ * differences.
+ */
etemp = SQUARE(clock_stability);
- dtemp = SQUARE(dtemp);
clock_stability = SQRT(etemp + (dtemp - etemp) / CLOCK_AVG);
/*
- * In SYNC state, adjust the poll interval. The trick here is to
- * compare the apparent frequency change induced by the system
- * jitter over the poll interval, or fritter, to the frequency
- * stability. If the fritter is greater than the stability,
- * phase noise predominates and the averaging interval is
- * increased; otherwise, it is decreased. A bit of hysteresis
+ * Here we adjust the poll interval by comparing the current
+ * offset with the clock jitter. If the offset is less than the
+ * clock jitter times a constant, then the averaging interval is
+ * increased, otherwise it is decreased. A bit of hysteresis
* helps calm the dance. Works best using burst mode.
*/
- if (state == S_SYNC) {
- if (sys_jitter > ULOGTOD(sys_poll) * clock_stability &&
- fabs(clock_offset) < CLOCK_PGATE * sys_jitter) {
- tc_counter += sys_poll;
- if (tc_counter > CLOCK_LIMIT) {
- tc_counter = CLOCK_LIMIT;
- if (sys_poll < peer->maxpoll) {
- tc_counter = 0;
- sys_poll++;
- }
+ if (fabs(clock_offset) < CLOCK_PGATE * clock_jitter) {
+ tc_counter += sys_poll;
+ if (tc_counter > CLOCK_LIMIT) {
+ tc_counter = CLOCK_LIMIT;
+ if (sys_poll < peer->maxpoll) {
+ tc_counter = 0;
+ sys_poll++;
}
- } else {
- tc_counter -= sys_poll << 1;
- if (tc_counter < -CLOCK_LIMIT) {
- tc_counter = -CLOCK_LIMIT;
- if (sys_poll > peer->minpoll) {
- tc_counter = 0;
- sys_poll--;
- }
+ }
+ } else {
+ tc_counter -= sys_poll << 1;
+ if (tc_counter < -CLOCK_LIMIT) {
+ tc_counter = -CLOCK_LIMIT;
+ if (sys_poll > peer->minpoll) {
+ tc_counter = 0;
+ sys_poll--;
}
}
}
/*
- * Update the system time variables.
+ * Yibbidy, yibbbidy, yibbidy; that'h all folks.
*/
- 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,
+ record_loop_stats(clock_offset, drift_comp, clock_jitter,
clock_stability, sys_poll);
-
#ifdef DEBUG
if (debug)
printf(
- "local_clock: mu %lu rootjit %.6f stab %.3f poll %d count %d\n",
- mu, dtemp, clock_stability * 1e6, sys_poll,
- tc_counter);
+ "local_clock: mu %lu jitr %.6f freq %.3f stab %.6f poll %d count %d\n",
+ mu, clock_jitter, drift_comp * 1e6,
+ clock_stability * 1e6, sys_poll, tc_counter);
#endif /* DEBUG */
- return (retval);
+ return (rval);
#endif /* LOCKCLOCK */
}
@@ -728,6 +783,14 @@ adj_host_clock(
#ifndef LOCKCLOCK
/*
+ * If clock discipline is disabled or if the kernel is enabled,
+ * get out of Dodge quick.
+ */
+ if (!ntp_enable || mode_ntpdate || (pll_control &&
+ kern_enable))
+ return;
+
+ /*
* Declare PPS kernel unsync if the pps signal has not been
* heard for a few minutes.
*/
@@ -739,30 +802,14 @@ adj_host_clock(
}
/*
- * If NTP is disabled or ntpdate mode enabled or the kernel
- * discipline enabled, we have no business going further.
- */
- if (!ntp_enable || mode_ntpdate || (pll_control && kern_enable))
- return;
-
- /*
- * Intricate wrinkle for legacy only. If the local clock driver
- * is in use and selected for synchronization, somebody else may
- * tinker the adjtime() syscall. If this is the case, the driver
- * is marked prefer and we have to avoid calling adjtime(),
- * since that may truncate the other guy's requests.
+ * Implement the phase and frequency adjustments. The gain
+ * factor (denominator) is not allowed to increase beyond the
+ * Allan intercept. It doesn't make sense to average phase noise
+ * beyond this point and it helps to damp residual offset at the
+ * longer poll intervals.
*/
- if (sys_peer != 0) {
- if (sys_peer->refclktype == REFCLK_LOCALCLOCK &&
- sys_peer->flags & FLAG_PREFER)
- return;
- }
-
- /*
- * Implement the phase and frequency adjustments. Note the
- * black art formerly practiced here has been whitewashed.
- */
- adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
+ adjustment = clock_offset / (CLOCK_PLL * min(ULOGTOD(sys_poll),
+ allan_xpt));
clock_offset -= adjustment;
adj_systime(adjustment + drift_comp);
#endif /* LOCKCLOCK */
@@ -770,25 +817,25 @@ adj_host_clock(
/*
- * Clock state machine. Enter new state and set state variables.
+ * Clock state machine. Enter new state and set state variables. Note we
+ * use the time of the last clock filter sample, which may be earlier
+ * than the current time.
*/
static void
rstclock(
- int trans, /* new state */
- u_long epoch, /* last time */
- double offset /* last offset */
+ int trans, /* new state */
+ u_long update, /* new update time */
+ double offset /* new offset */
)
{
- tc_counter = 0;
- sys_poll = NTP_MINPOLL;
- state = trans;
- last_time = epoch;
- last_offset = clock_offset = offset;
#ifdef DEBUG
if (debug)
- printf("local_clock: at %lu state %d\n", last_time,
- trans);
+ printf("local_clock: time %lu offset %.6f freq %.3f state %d\n",
+ update, offset, drift_comp * 1e6, trans);
#endif
+ state = trans;
+ sys_clocktime = update;
+ last_offset = clock_offset = offset;
}
@@ -802,6 +849,7 @@ huffpuff()
if (sys_huffpuff == NULL)
return;
+
sys_huffptr = (sys_huffptr + 1) % sys_hufflen;
sys_huffpuff[sys_huffptr] = 1e9;
sys_mindly = 1e9;
@@ -833,25 +881,20 @@ loop_config(
#ifdef KERNEL_PLL
/*
* Assume the kernel supports the ntp_adjtime() syscall.
- * If that syscall works, initialize the kernel
- * variables. Otherwise, continue leaving no harm
+ * If that syscall works, initialize the kernel time
+ * variables. Otherwise, continue leaving no harm
* behind. While at it, ask to set nanosecond mode. If
* the kernel agrees, rejoice; othewise, it does only
* microseconds.
- *
- * Call out the safety patrol. If ntpdate mode or if the
- * step threshold has been changed by the -x option or
- * tinker command, kernel discipline is unsafe, so don't
- * do any of this stuff.
*/
- if (mode_ntpdate || clock_max != CLOCK_MAX)
+ if (mode_ntpdate)
break;
pll_control = 1;
memset(&ntv, 0, sizeof(ntv));
#ifdef STA_NANO
ntv.modes = MOD_BITS | MOD_NANO;
-#else
+#else /* STA_NANO */
ntv.modes = MOD_BITS;
#endif /* STA_NANO */
ntv.maxerror = MAXDISPERSE;
@@ -881,11 +924,14 @@ loop_config(
#else /* SIGSYS */
ntp_adjtime(&ntv);
#endif /* SIGSYS */
+
+ /*
+ * Save the result status and light up an external clock
+ * if available.
+ */
pll_status = ntv.status;
if (pll_control) {
#ifdef STA_NANO
- if (pll_status & STA_NANO)
- pll_nano = 1;
if (pll_status & STA_CLK)
ext_enable = 1;
#endif /* STA_NANO */
@@ -910,34 +956,46 @@ loop_config(
*/
if (freq <= NTP_MAXFREQ && freq >= -NTP_MAXFREQ) {
drift_comp = freq;
- rstclock(S_FSET, current_time, 0);
+ rstclock(S_FSET, 0, 0);
} else {
drift_comp = 0;
}
#ifdef KERNEL_PLL
/*
- * Sanity check. If the kernel is enabled, load the
- * frequency and light up the loop. If not, set the
- * kernel frequency to zero and leave the loop dark. In
- * either case set the time to zero to cancel any
- * previous nonsense.
+ * Sanity check. If the kernel is available, load the
+ * frequency and light up the loop. Make sure the offset
+ * is zero to cancel any previous nonsense. If you don't
+ * want this initialization, remove the ntp.drift file.
*/
- if (pll_control) {
+ if (pll_control && kern_enable) {
memset((char *)&ntv, 0, sizeof(ntv));
ntv.modes = MOD_OFFSET | MOD_FREQUENCY;
- if (kern_enable) {
- ntv.modes |= MOD_STATUS;
- ntv.status = STA_PLL;
- ntv.freq = (int32)(drift_comp *
- 65536e6);
- }
- (void)ntp_adjtime(&ntv);
+ ntv.freq = (int32)(drift_comp * 65536e6);
+ ntp_adjtime(&ntv);
}
#endif /* KERNEL_PLL */
#endif /* LOCKCLOCK */
break;
+ case LOOP_KERN_CLEAR:
+#ifndef LOCKCLOCK
+#ifdef KERNEL_PLL
+ /* Completely turn off the kernel time adjustments. */
+ if (pll_control) {
+ memset((char *)&ntv, 0, sizeof(ntv));
+ ntv.modes = MOD_BITS | MOD_OFFSET | MOD_FREQUENCY;
+ ntv.status = STA_UNSYNC;
+ ntp_adjtime(&ntv);
+ NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
+ msyslog(LOG_INFO,
+ "kernel time sync disabled %04x",
+ ntv.status);
+ }
+#endif /* KERNEL_PLL */
+#endif /* LOCKCLOCK */
+ break;
+
/*
* Special tinker variables for Ulrich Windl. Very dangerous.
*/
@@ -974,7 +1032,7 @@ loop_config(
case LOOP_FREQ: /* initial frequency */
drift_comp = freq / 1e6;
- rstclock(S_FSET, current_time, 0);
+ rstclock(S_FSET, 0, 0);
break;
}
}
diff --git a/contrib/ntp/ntpd/ntp_monitor.c b/contrib/ntp/ntpd/ntp_monitor.c
index 6b288fc..753fa76 100644
--- a/contrib/ntp/ntpd/ntp_monitor.c
+++ b/contrib/ntp/ntpd/ntp_monitor.c
@@ -9,6 +9,7 @@
#include "ntp_io.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#include <ntp_random.h>
#include <stdio.h>
#include <signal.h>
@@ -177,11 +178,31 @@ mon_stop(
mon_mru_list.mru_prev = &mon_mru_list;
}
+void
+ntp_monclearinterface(struct interface *interface)
+{
+ struct mon_data *md;
+
+ for (md = mon_mru_list.mru_next; md != &mon_mru_list;
+ md = md->mru_next) {
+ if (md->interface == interface)
+ {
+ /* dequeue from mru list and put to free list */
+ md->mru_prev->mru_next = md->mru_next;
+ md->mru_next->mru_prev = md->mru_prev;
+ remove_from_hash(md);
+ md->hash_next = mon_free;
+ mon_free = md;
+ }
+ }
+}
/*
* ntp_monitor - record stats about this packet
+ *
+ * Returns 1 if the packet is at the head of the list, 0 otherwise.
*/
-void
+int
ntp_monitor(
struct recvbuf *rbufp
)
@@ -193,7 +214,7 @@ ntp_monitor(
register int mode;
if (mon_enabled == MON_OFF)
- return;
+ return 0;
pkt = &rbufp->recv_pkt;
memset(&addr, 0, sizeof(addr));
@@ -223,7 +244,7 @@ ntp_monitor(
md->mru_prev = &mon_mru_list;
mon_mru_list.mru_next->mru_prev = md;
mon_mru_list.mru_next = md;
- return;
+ return 1;
}
md = md->hash_next;
}
@@ -239,9 +260,10 @@ ntp_monitor(
* Preempt from the MRU list if old enough.
*/
md = mon_mru_list.mru_prev;
- if (((u_long)RANDOM & 0xffffffff) / FRAC >
+ /* We get 31 bits from ntp_random() */
+ if (((u_long)ntp_random()) / FRAC >
(double)(current_time - md->lasttime) / mon_age)
- return;
+ return 0;
md->mru_prev->mru_next = &mon_mru_list;
mon_mru_list.mru_prev = md->mru_prev;
@@ -266,7 +288,7 @@ ntp_monitor(
md->mode = (u_char) mode;
md->version = PKT_VERSION(pkt->li_vn_mode);
md->interface = rbufp->dstadr;
- md->cast_flags = (u_char)(((rbufp->dstadr->flags & INT_MULTICAST) &&
+ md->cast_flags = (u_char)(((rbufp->dstadr->flags & INT_MCASTOPEN) &&
rbufp->fd == md->interface->fd) ? MDF_MCAST: rbufp->fd ==
md->interface->bfd ? MDF_BCAST : MDF_UCAST);
@@ -280,6 +302,7 @@ ntp_monitor(
md->mru_prev = &mon_mru_list;
mon_mru_list.mru_next->mru_prev = md;
mon_mru_list.mru_next = md;
+ return 1;
}
diff --git a/contrib/ntp/ntpd/ntp_peer.c b/contrib/ntp/ntpd/ntp_peer.c
index cf8a600..deeec5b 100644
--- a/contrib/ntp/ntpd/ntp_peer.c
+++ b/contrib/ntp/ntpd/ntp_peer.c
@@ -10,10 +10,15 @@
#include "ntpd.h"
#include "ntp_stdlib.h"
+#include <ntp_random.h>
#ifdef OPENSSL
#include "openssl/rand.h"
#endif /* OPENSSL */
+#ifdef SYS_WINNT
+extern int accept_wildcard_if_for_winnt;
+#endif
+
/*
* Table of valid association combinations
* ---------------------------------------
@@ -21,14 +26,12 @@
* packet->mode
* peer->mode | UNSPEC ACTIVE PASSIVE CLIENT SERVER BCAST
* ---------- | ---------------------------------------------
- * NO_PEER | e 1 e 1 1 1
+ * NO_PEER | e 1 0 1 1 1
* ACTIVE | e 1 1 0 0 0
* PASSIVE | e 1 e 0 0 0
* CLIENT | e 0 0 0 1 1
* SERVER | e 0 0 0 0 0
- * BCAST | e 0 0 0 0 0
- * CONTROL | e 0 0 0 0 0
- * PRIVATE | e 0 0 0 0 0
+ * BCAST | e 0 0 0 0 0
* BCLIENT | e 0 0 0 e 1
*
* One point to note here: a packet in BCAST mode can potentially match
@@ -38,11 +41,13 @@
* circumvent that problem by requiring that the first b(m)roadcast
* received after the change back to BCLIENT mode sets the clock.
*/
+#define AM_MODES 7 /* number of rows and columns */
+#define NO_PEER 0 /* action when no peer is found */
int AM[AM_MODES][AM_MODES] = {
/* { UNSPEC, ACTIVE, PASSIVE, CLIENT, SERVER, BCAST } */
-/*NONE*/{ AM_ERR, AM_NEWPASS, AM_ERR, AM_FXMIT, AM_MANYCAST, AM_NEWBCL},
+/*NONE*/{ AM_ERR, AM_NEWPASS, AM_NOMATCH, AM_FXMIT, AM_MANYCAST, AM_NEWBCL},
/*A*/ { AM_ERR, AM_PROCPKT, AM_PROCPKT, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
@@ -54,11 +59,7 @@ int AM[AM_MODES][AM_MODES] = {
/*BCST*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-/*CNTL*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*PRIV*/{ AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH},
-
-/*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_ERR, AM_PROCPKT},
+/*BCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_PROCPKT},
};
#define MATCH_ASSOC(x,y) AM[(x)][(y)]
@@ -74,10 +75,10 @@ int AM[AM_MODES][AM_MODES] = {
/*
* Peer hash tables
*/
-struct peer *peer_hash[HASH_SIZE]; /* peer hash table */
-int peer_hash_count[HASH_SIZE]; /* peers in each bucket */
-struct peer *assoc_hash[HASH_SIZE]; /* association ID hash table */
-int assoc_hash_count[HASH_SIZE]; /* peers in each bucket */
+struct peer *peer_hash[NTP_HASH_SIZE]; /* peer hash table */
+int peer_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
+struct peer *assoc_hash[NTP_HASH_SIZE]; /* association ID hash table */
+int assoc_hash_count[NTP_HASH_SIZE]; /* peers in each bucket */
static struct peer *peer_free; /* peer structures free list */
int peer_free_count; /* count of free structures */
@@ -102,10 +103,12 @@ u_long assocpeer_calls; /* calls to findpeerbyassoc */
u_long peer_allocations; /* allocations from free list */
u_long peer_demobilizations; /* structs freed to free list */
int total_peer_structs; /* peer structs */
-int peer_associations; /* active associations */
+int peer_associations; /* mobilized associations */
+int peer_preempt; /* preemptable associations */
static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
-static void getmorepeermem P((void));
+static void getmorepeermem P((void));
+static struct interface *select_peerinterface P((struct peer *, struct sockaddr_storage *, struct interface *, u_char));
/*
* init_peer - initialize peer data structures and counters
@@ -121,7 +124,7 @@ init_peer(void)
/*
* Clear hash table and counters.
*/
- for (i = 0; i < HASH_SIZE; i++) {
+ for (i = 0; i < NTP_HASH_SIZE; i++) {
peer_hash[i] = 0;
peer_hash_count[i] = 0;
assoc_hash[i] = 0;
@@ -148,9 +151,7 @@ init_peer(void)
/*
* Initialize our first association ID
*/
- current_association_ID = (associd_t)ranp2(16);
- if (current_association_ID == 0)
- current_association_ID = 1;
+ while ((current_association_ID = ntp_random() & 0xffff) == 0);
}
@@ -193,7 +194,7 @@ findexistingpeer(
* same peer through different interfaces in the hash table.
*/
if (start_peer == 0)
- peer = peer_hash[HASH_ADDR(addr)];
+ peer = peer_hash[NTP_HASH_ADDR(addr)];
else
peer = start_peer->next;
@@ -218,19 +219,18 @@ struct peer *
findpeer(
struct sockaddr_storage *srcadr,
struct interface *dstadr,
- int fd,
- int pkt_mode,
- int *action
+ int pkt_mode,
+ int *action
)
{
register struct peer *peer;
int hash;
findpeer_calls++;
- hash = HASH_ADDR(srcadr);
+ hash = NTP_HASH_ADDR(srcadr);
for (peer = peer_hash[hash]; peer != NULL; peer = peer->next) {
- if (SOCKCMP(srcadr, &peer->srcadr)
- && NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
+ if (SOCKCMP(srcadr, &peer->srcadr) &&
+ NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
/*
* if the association matching rules determine
@@ -240,14 +240,6 @@ findpeer(
*action = MATCH_ASSOC(peer->hmode, pkt_mode);
/*
- * Sigh! Check if BCLIENT peer in client
- * server mode, else return error.
- */
- if ((*action == AM_POSSBCL) && !(peer->flags &
- FLAG_MCAST))
- *action = AM_ERR;
-
- /*
* if an error was returned, exit back right
* here.
*/
@@ -269,7 +261,9 @@ findpeer(
*action = MATCH_ASSOC(NO_PEER, pkt_mode);
return ((struct peer *)0);
}
- peer->dstadr = dstadr;
+
+ set_peerdstadr(peer, dstadr);
+
return (peer);
}
@@ -286,7 +280,7 @@ findpeerbyassoc(
assocpeer_calls++;
- hash = assoc & HASH_MASK;
+ hash = assoc & NTP_HASH_MASK;
for (peer = assoc_hash[hash]; peer != 0; peer =
peer->ass_next) {
if (assoc == peer->associd)
@@ -309,15 +303,13 @@ clear_all(void)
* This routine is called when the clock is stepped, and so all
* previously saved time values are untrusted.
*/
- for (n = 0; n < HASH_SIZE; n++) {
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
- if (peer->flags & FLAG_CONFIG) {
- if (!(peer->cast_flags & (MDF_ACAST |
- MDF_MCAST | MDF_BCAST)))
- peer_clear(peer, "STEP");
- } else {
- unpeer(peer);
+ if (!(peer->cast_flags & (MDF_ACAST | MDF_MCAST |
+ MDF_BCAST))) {
+ peer->hpoll = peer->minpoll;
+ peer_clear(peer, "STEP");
}
}
}
@@ -353,13 +345,19 @@ unpeer(
#endif /* OPENSSL */
#ifdef DEBUG
if (debug)
- printf("demobilize %u %d\n", peer_to_remove->associd,
- peer_associations);
+ printf("demobilize %u %d %d\n", peer_to_remove->associd,
+ peer_associations, peer_preempt);
#endif
- peer_clear(peer_to_remove, "NULL");
- hash = HASH_ADDR(&peer_to_remove->srcadr);
+ set_peerdstadr(peer_to_remove, NULL);
+
+ /* XXXMEMLEAK? peer_clear->crypto allocation */
+
+ hash = NTP_HASH_ADDR(&peer_to_remove->srcadr);
peer_hash_count[hash]--;
peer_demobilizations++;
+ peer_associations--;
+ if (peer_to_remove->flags & FLAG_PREEMPT)
+ peer_preempt--;
#ifdef REFCLOCK
/*
* If this peer is actually a clock, shut it down first
@@ -389,7 +387,7 @@ unpeer(
/*
* Remove him from the association hash as well.
*/
- hash = peer_to_remove->associd & HASH_MASK;
+ hash = peer_to_remove->associd & NTP_HASH_MASK;
assoc_hash_count[hash]--;
if (assoc_hash[hash] == peer_to_remove)
assoc_hash[hash] = peer_to_remove->ass_next;
@@ -412,7 +410,6 @@ unpeer(
peer_to_remove->next = peer_free;
peer_free = peer_to_remove;
peer_free_count++;
- peer_associations--;
}
@@ -440,13 +437,18 @@ peer_config(
* First search from the beginning for an association with given
* remote address and mode. If an interface is given, search
* from there to find the association which matches that
- * destination.
+ * destination. If the given interface is "any", track down
+ * the actual interface, because that's what gets put into the
+ * peer structure.
*/
peer = findexistingpeer(srcadr, (struct peer *)0, hmode);
if (dstadr != 0) {
while (peer != 0) {
if (peer->dstadr == dstadr)
break;
+ if (dstadr == ANY_INTERFACE_CHOOSE(srcadr) &&
+ peer->dstadr == findinterface(srcadr))
+ break;
peer = findexistingpeer(srcadr, peer, hmode);
}
}
@@ -525,6 +527,197 @@ peer_config(
return (peer);
}
+/*
+ * setup peer dstadr field keeping it in sync with the interface structures
+ */
+void
+set_peerdstadr(struct peer *peer, struct interface *interface)
+{
+ if (peer->dstadr != interface) {
+ if (interface != NULL &&
+ (peer->cast_flags & MDF_BCLNT) &&
+ (interface->flags & INT_MCASTIF) &&
+ peer->burst) {
+ /*
+ * don't accept updates to a true multicast reception
+ * interface while a BCLNT peer is running it's
+ * unicast protocol
+ */
+ return;
+ }
+
+ if (peer->dstadr != NULL)
+ {
+ peer->dstadr->peercnt--;
+ ISC_LIST_UNLINK_TYPE(peer->dstadr->peers, peer, ilink, struct peer);
+ }
+
+ DPRINTF(4, ("set_peerdstadr(%s): change interface from %s to %s\n",
+ stoa(&peer->srcadr),
+ (peer->dstadr != NULL) ? stoa(&peer->dstadr->sin) : "<null>",
+ (interface != NULL) ? stoa(&interface->sin) : "<null>"));
+
+ peer->dstadr = interface;
+
+ if (peer->dstadr != NULL)
+ {
+ ISC_LIST_APPEND(peer->dstadr->peers, peer, ilink);
+ peer->dstadr->peercnt++;
+ }
+ }
+}
+
+/*
+ * attempt to re-rebind interface if necessary
+ */
+static void
+peer_refresh_interface(struct peer *peer)
+{
+ struct interface *niface, *piface;
+
+ niface = select_peerinterface(peer, &peer->srcadr, NULL, peer->cast_flags);
+
+#ifdef DEBUG
+ if (debug > 3)
+ {
+ printf(
+ "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ",
+ peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
+ stoa(&peer->srcadr),
+ peer->hmode, peer->version, peer->minpoll,
+ peer->maxpoll, peer->flags, peer->cast_flags,
+ peer->ttl, peer->keyid);
+ if (niface != NULL)
+ {
+ printf("fd=%d, bfd=%d, name=%.16s, flags=0x%x, scope=%d, ",
+ niface->fd,
+ niface->bfd,
+ niface->name,
+ niface->flags,
+ niface->scopeid);
+ /* Leave these as three printf calls. */
+ printf(", sin=%s",
+ stoa((&niface->sin)));
+ if (niface->flags & INT_BROADCAST)
+ printf(", bcast=%s,",
+ stoa((&niface->bcast)));
+ printf(", mask=%s\n",
+ stoa((&niface->mask)));
+ }
+ else
+ {
+ printf("<NONE>\n");
+ }
+ }
+#endif
+
+ piface = peer->dstadr;
+
+ set_peerdstadr(peer, niface);
+
+ if (peer->dstadr) {
+ /*
+ * clear crypto if we change the local address
+ */
+ if (peer->dstadr != piface && !(peer->cast_flags & MDF_BCLNT)) {
+ peer_crypto_clear(peer);
+ }
+
+ /*
+ * Broadcast needs the socket enabled for broadcast
+ */
+ if (peer->cast_flags & MDF_BCAST) {
+ enable_broadcast(peer->dstadr, &peer->srcadr);
+ }
+
+ /*
+ * Multicast needs the socket interface enabled for multicast
+ */
+ if (peer->cast_flags & MDF_MCAST) {
+ enable_multicast_if(peer->dstadr, &peer->srcadr);
+ }
+ }
+}
+
+/*
+ * refresh_all_peerinterfaces - see that all interface bindings are up to date
+ */
+void
+refresh_all_peerinterfaces(void)
+{
+ struct peer *peer, *next_peer;
+ int n;
+
+ /*
+ * this is called when the interface list has changed
+ * give all peers a chance to find a better interface
+ */
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
+ for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
+ next_peer = peer->next;
+ peer_refresh_interface(peer);
+ }
+ }
+}
+
+
+/*
+ * find an interface suitable for the src address
+ */
+static struct interface *
+select_peerinterface(struct peer *peer, struct sockaddr_storage *srcadr, struct interface *dstadr, u_char cast_flags)
+{
+ struct interface *interface;
+
+ /*
+ * Initialize the peer structure and dance the interface jig.
+ * Reference clocks step the loopback waltz, the others
+ * squaredance around the interface list looking for a buddy. If
+ * the dance peters out, there is always the wildcard interface.
+ * This might happen in some systems and would preclude proper
+ * operation with public key cryptography.
+ */
+ if (ISREFCLOCKADR(srcadr))
+ interface = loopback_interface;
+ else
+ if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
+ interface = findbcastinter(srcadr);
+#ifdef DEBUG
+ if (debug > 3) {
+ if (interface != NULL)
+ printf("Found *-cast interface address %s, for address %s\n",
+ stoa(&(interface)->sin), stoa(srcadr));
+ else
+ printf("No *-cast local address found for address %s\n",
+ stoa(srcadr));
+ }
+#endif
+ /*
+ * If it was a multicast packet, findbcastinter() may not
+ * find it, so try a little harder.
+ */
+ if (interface == ANY_INTERFACE_CHOOSE(srcadr))
+ interface = findinterface(srcadr);
+ }
+ else if (dstadr != NULL && dstadr != ANY_INTERFACE_CHOOSE(srcadr))
+ interface = dstadr;
+ else
+ interface = findinterface(srcadr);
+
+ /*
+ * we do not bind to the wildcard interfaces for output
+ * as our (network) source address would be undefined and
+ * crypto will not work without knowing the own transmit address
+ */
+ if (interface != NULL && interface->flags & INT_WILDCARD)
+#ifdef SYS_WINNT
+ if ( !accept_wildcard_if_for_winnt )
+#endif
+ interface = NULL;
+
+
+ return interface;
+}
/*
* newpeer - initialize a new peer association
@@ -559,6 +752,8 @@ newpeer(
peer_free = peer->next;
peer_free_count--;
peer_associations++;
+ if (flags & FLAG_PREEMPT)
+ peer_preempt++;
memset((char *)peer, 0, sizeof(struct peer));
/*
@@ -568,34 +763,41 @@ newpeer(
if (++current_association_ID == 0)
++current_association_ID;
- /*
- * Initialize the peer structure and dance the interface jig.
- * Reference clocks step the loopback waltz, the others
- * squaredance around the interface list looking for a buddy. If
- * the dance peters out, there is always the wildcard interface.
- * This might happen in some systems and would preclude proper
- * operation with public key cryptography.
- */
- if (ISREFCLOCKADR(srcadr))
- peer->dstadr = loopback_interface;
- else if (cast_flags & (MDF_BCLNT | MDF_ACAST | MDF_MCAST | MDF_BCAST)) {
- peer->dstadr = findbcastinter(srcadr);
- /*
- * If it was a multicast packet, findbcastinter() may not
- * find it, so try a little harder.
- */
- if (peer->dstadr == ANY_INTERFACE_CHOOSE(srcadr))
- peer->dstadr = findinterface(srcadr);
- } else if (dstadr != NULL && dstadr != ANY_INTERFACE_CHOOSE(srcadr))
- peer->dstadr = dstadr;
- else
- peer->dstadr = findinterface(srcadr);
+ DPRINTF(3, ("newpeer: cast flags: 0x%x for address: %s\n",
+ cast_flags, stoa(srcadr)));
+
+ ISC_LINK_INIT(peer, ilink); /* set up interface link chain */
peer->srcadr = *srcadr;
+ set_peerdstadr(peer, select_peerinterface(peer, srcadr, dstadr,
+ cast_flags));
peer->hmode = (u_char)hmode;
peer->version = (u_char)version;
peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
peer->flags = flags;
+#ifdef DEBUG
+ if (debug > 2) {
+ if (peer->dstadr)
+ printf("newpeer: using fd %d and our addr %s\n",
+ peer->dstadr->fd,
+ stoa(&peer->dstadr->sin));
+ else
+ printf("newpeer: local interface currently not bound\n");
+ }
+#endif
+
+ /*
+ * Broadcast needs the socket enabled for broadcast
+ */
+ if (cast_flags & MDF_BCAST && peer->dstadr) {
+ enable_broadcast(peer->dstadr, srcadr);
+ }
+ /*
+ * Multicast needs the socket interface enabled for multicast
+ */
+ if (cast_flags & MDF_MCAST && peer->dstadr) {
+ enable_multicast_if(peer->dstadr, srcadr);
+ }
if (key != 0)
peer->flags |= FLAG_AUTHENABLE;
if (key > NTP_MAXKEY)
@@ -604,6 +806,7 @@ newpeer(
peer->ttl = (u_char)ttl;
peer->keyid = key;
peer->precision = sys_precision;
+ peer->hpoll = peer->minpoll;
if (cast_flags & MDF_ACAST)
peer_clear(peer, "ACST");
else if (cast_flags & MDF_MCAST)
@@ -621,8 +824,10 @@ newpeer(
peer->timereset = current_time;
peer->timereachable = current_time;
peer->timereceived = current_time;
+
#ifdef REFCLOCK
if (ISREFCLOCKADR(&peer->srcadr)) {
+
/*
* We let the reference clock support do clock
* dependent initialization. This includes setting
@@ -633,6 +838,8 @@ newpeer(
/*
* Dump it, something screwed up
*/
+ set_peerdstadr(peer, NULL);
+
peer->next = peer_free;
peer_free = peer;
peer_free_count++;
@@ -644,34 +851,30 @@ newpeer(
/*
* Put the new peer in the hash tables.
*/
- i = HASH_ADDR(&peer->srcadr);
+ i = NTP_HASH_ADDR(&peer->srcadr);
peer->next = peer_hash[i];
peer_hash[i] = peer;
peer_hash_count[i]++;
- i = peer->associd & HASH_MASK;
+ i = peer->associd & NTP_HASH_MASK;
peer->ass_next = assoc_hash[i];
assoc_hash[i] = peer;
assoc_hash_count[i]++;
+
#ifdef OPENSSL
if (peer->flags & FLAG_SKEY) {
sprintf(statstr, "newpeer %d", peer->associd);
record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
- if (debug)
- printf("peer: %s\n", statstr);
-#endif
+ DPRINTF(1, ("peer: %s\n", statstr));
}
#endif /* OPENSSL */
-#ifdef DEBUG
- if (debug)
- printf(
- "newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n",
- peer->dstadr == NULL ? "null" : stoa(&peer->dstadr->sin),
+
+ DPRINTF(1, ("newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n",
+ peer->dstadr == NULL ? "<null>" : stoa(&peer->dstadr->sin),
stoa(&peer->srcadr),
peer->hmode, peer->version, peer->minpoll,
peer->maxpoll, peer->flags, peer->cast_flags,
- peer->ttl, peer->keyid);
-#endif
+ peer->ttl, peer->keyid));
+
return (peer);
}
@@ -749,8 +952,6 @@ peer_reset(
peer->bogusorg = 0;
peer->oldpkt = 0;
peer->seldisptoolarge = 0;
- peer->selbroken = 0;
- peer->rank = 0;
peer->timereset = current_time;
}
@@ -764,7 +965,7 @@ peer_all_reset(void)
struct peer *peer;
int hash;
- for (hash = 0; hash < HASH_SIZE; hash++)
+ for (hash = 0; hash < NTP_HASH_SIZE; hash++)
for (peer = peer_hash[hash]; peer != 0; peer = peer->next)
peer_reset(peer);
}
@@ -790,13 +991,13 @@ expire_all(void)
*/
if (!crypto_flags)
return;
- for (n = 0; n < HASH_SIZE; n++) {
+
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
if (!(peer->flags & FLAG_SKEY)) {
continue;
- } else if (peer->cast_flags & MDF_ACAST) {
- peer_clear(peer, "ACST");
+
} else if (peer->hmode == MODE_ACTIVE ||
peer->hmode == MODE_PASSIVE) {
key_expire(peer);
@@ -808,7 +1009,6 @@ expire_all(void)
}
RAND_bytes((u_char *)&sys_private, 4);
crypto_update();
- resetmanycast();
}
#endif /* OPENSSL */
@@ -827,14 +1027,14 @@ findmanycastpeer(
int i;
/*
- * This routine is called upon arrival of a client-mode message
- * from a manycast server. Search the peer list for a manycast
+ * This routine is called upon arrival of a server-mode message
+ * from a manycast client. Search the peer list for a manycast
* client association where the last transmit timestamp matches
* the originate timestamp. This assumes the transmit timestamps
* for possibly more than one manycast association are unique.
*/
pkt = &rbufp->recv_pkt;
- for (i = 0; i < HASH_SIZE; i++) {
+ for (i = 0; i < NTP_HASH_SIZE; i++) {
if (peer_hash_count[i] == 0)
continue;
@@ -849,32 +1049,3 @@ findmanycastpeer(
}
return (NULL);
}
-
-
-/*
- * resetmanycast - reset all manycast clients
- */
-void
-resetmanycast(void)
-{
- register struct peer *peer;
- int i;
-
- /*
- * This routine is called when the number of client associations
- * falls below the minimum. Search the peer list for manycast
- * client associations and reset the ttl and poll interval.
- */
- for (i = 0; i < HASH_SIZE; i++) {
- if (peer_hash_count[i] == 0)
- continue;
-
- for (peer = peer_hash[i]; peer != 0; peer =
- peer->next) {
- if (peer->cast_flags & MDF_ACAST) {
- peer->ttl = 0;
- poll_update(peer, 0);
- }
- }
- }
-}
diff --git a/contrib/ntp/ntpd/ntp_proto.c b/contrib/ntp/ntpd/ntp_proto.c
index 451bc9a..0ab2498 100644
--- a/contrib/ntp/ntpd/ntp_proto.c
+++ b/contrib/ntp/ntpd/ntp_proto.c
@@ -25,19 +25,26 @@
#endif
/*
+ * This macro defines the authentication state. If x is 1 authentication
+ * is required; othewise it is optional.
+ */
+#define AUTH(x, y) ((x) ? (y) == AUTH_OK : (y) == AUTH_OK || \
+ (y) == AUTH_NONE)
+
+/*
* System variables are declared here. See Section 3.2 of the
* specification.
*/
u_char sys_leap; /* system leap indicator */
u_char sys_stratum; /* stratum of system */
-s_char sys_precision; /* local clock precision */
+s_char sys_precision; /* local clock precision (log2 s) */
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 */
+u_int32 sys_refid; /* source/loop in network byte order */
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_pps; /* our PPS peer */
struct peer *sys_prefer; /* our cherished peer */
int sys_kod; /* kod credit */
int sys_kod_rate = 2; /* max kod packets per second */
@@ -54,9 +61,12 @@ int sys_calldelay; /* modem callup delay (s) */
int sys_authenticate; /* requre authentication for config */
l_fp sys_authdelay; /* authentication delay */
static u_long sys_authdly[2]; /* authentication delay shift reg */
-static u_char leap_consensus; /* consensus of survivor leap bits */
-static double sys_selerr; /* select error (squares) */
-static double sys_syserr; /* system error (squares) */
+static double sys_mindisp = MINDISPERSE; /* min disp increment (s) */
+static double sys_maxdist = MAXDISTANCE; /* selection threshold (s) */
+double sys_jitter; /* system jitter (s) */
+static int sys_hopper; /* anticlockhop counter */
+static int sys_maxhop = MAXHOP; /* anticlockhop counter threshold */
+int leap_next; /* leap consensus */
keyid_t sys_private; /* private value for session seed */
int sys_manycastserver; /* respond to manycast client pkts */
int peer_ntpdate; /* active peers in ntpdate mode */
@@ -68,11 +78,15 @@ char *sys_hostname; /* gethostname() name */
/*
* TOS and multicast mapping stuff
*/
-int sys_floor = 1; /* cluster stratum floor */
-int sys_ceiling = STRATUM_UNSPEC; /* cluster stratum ceiling*/
+int sys_floor = 0; /* 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_maxclock = NTP_MAXCLOCK; /* maximum candidates */
int sys_cohort = 0; /* cohort switch */
+int sys_orphan = STRATUM_UNSPEC + 1; /* orphan stratum */
+double sys_orphandelay = 0; /* orphan root delay */
+int sys_beacon = BEACON; /* manycast beacon interval */
int sys_ttlmax; /* max ttl mapping vector index */
u_char sys_ttl[MAX_TTL]; /* ttl mapping vector */
@@ -91,13 +105,15 @@ u_long sys_badauth; /* bad authentication */
u_long sys_limitrejected; /* rate exceeded */
static double root_distance P((struct peer *));
-static double clock_combine P((struct peer **, int));
+static void clock_combine P((struct peer **, int));
static void peer_xmit P((struct peer *));
-static void fast_xmit P((struct recvbuf *, int, keyid_t, int));
+static void fast_xmit P((struct recvbuf *, int, keyid_t,
+ int));
static void clock_update P((void));
-int default_get_precision P((void));
+static int default_get_precision P((void));
static int peer_unfit P((struct peer *));
+
/*
* transmit - Transmit Procedure. See Section 3.4.2 of the
* specification.
@@ -109,193 +125,199 @@ transmit(
{
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...
*/
+ /*
+ * Orphan mode is active when enabled and when no servers less
+ * than the orphan statum are available. In this mode packets
+ * are sent at the orphan stratum. An orphan with no other
+ * synchronization source is an orphan parent. It assumes root
+ * delay zero and reference ID the loopback address. All others
+ * are orphan children with root delay randomized over a 1-s
+ * range. The root delay is used by the election algorithm to
+ * select the order of synchronization.
+ */
hpoll = peer->hpoll;
+ if (sys_orphan < STRATUM_UNSPEC && sys_peer == NULL) {
+ sys_leap = LEAP_NOWARNING;
+ sys_stratum = sys_orphan;
+ sys_refid = htonl(LOOPBACKADR);
+ sys_rootdelay = 0;
+ sys_rootdispersion = 0;
+ }
+
+ /*
+ * In broadcast mode the poll interval is never changed from
+ * minpoll.
+ */
if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {
+ peer->outdate = current_time;
+ peer_xmit(peer);
+ poll_update(peer, hpoll);
+ return;
+ }
- /*
- * In broadcast mode the poll interval is fixed
- * at minpoll.
- */
- hpoll = peer->minpoll;
- } else if (peer->cast_flags & MDF_ACAST) {
+ /*
+ * In manycast mode we start with unity ttl. The ttl is
+ * increased by one for each poll until either sys_maxclock
+ * servers have been found or the maximum ttl is reached. When
+ * sys_maxclock servers are found we stop polling until one or
+ * more servers have timed out or until less than minpoll
+ * associations turn up. In this case additional better servers
+ * are dragged in and preempt the existing ones.
+ */
+ if (peer->cast_flags & MDF_ACAST) {
+ peer->outdate = current_time;
+ if (peer->unreach > sys_beacon) {
+ peer->unreach = 0;
+ peer->ttl = 0;
+ peer_xmit(peer);
+ } else if (sys_survivors < sys_minclock ||
+ peer_preempt < sys_maxclock) {
+ if (peer->ttl < sys_ttlmax)
+ peer->ttl++;
+ peer_xmit(peer);
+ }
+ peer->unreach++;
+ poll_update(peer, hpoll);
+ return;
+ }
- /*
- * 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 unicast modes the dance is much more intricate. It is
+ * desigmed to back off whenever possible to minimize network
+ * traffic.
+ */
+ if (peer->burst == 0) {
+ u_char oreach;
/*
- * 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.
+ * Update the reachability status. If not heard for
+ * three consecutive polls, stuff infinity in the clock
+ * filter.
*/
- peer->unreach++;
- if (peer->unreach >= NTP_UNREACH) {
- hpoll++;
- if (peer->flags & FLAG_CONFIG) {
+ oreach = peer->reach;
+ peer->outdate = current_time;
+ if (peer == sys_peer)
+ sys_hopper++;
+ peer->reach <<= 1;
+ if (!(peer->reach & 0x07))
+ clock_filter(peer, 0., 0., MAXDISPERSE);
+ if (!peer->reach) {
- /*
- * If nothing is likely to change in
- * future, flash the access denied bit
- * so we won't bother the dude again.
- */
- if (memcmp((char *)&peer->refid,
- "DENY", 4) == 0 ||
- memcmp((char *)&peer->refid,
- "CRYP", 4) == 0)
- peer->flash |= TEST4;
- } else {
- unpeer(peer);
- return;
+ /*
+ * Here the peer is unreachable. If it was
+ * previously reachable, raise a trap.
+ */
+ if (oreach) {
+ report_event(EVNT_UNREACH, peer);
+ peer->timereachable = current_time;
}
- }
- if (peer->burst == 0) {
- u_char oreach;
- oreach = peer->reach;
- peer->reach <<= 1;
- peer->hyst *= HYST_TC;
- if (peer->reach == 0) {
-
- /*
- * If this association has become
- * unreachable, clear it and raise a
- * trap.
- */
- if (oreach != 0) {
- report_event(EVNT_UNREACH,
- peer);
- peer->timereachable =
- current_time;
- if (peer->flags & FLAG_CONFIG) {
- peer_clear(peer,
- "INIT");
- } else {
- unpeer(peer);
- return;
- }
- }
- if (peer->flags & FLAG_IBURST)
- peer->burst = NTP_BURST;
- } else {
- /*
- * Here the peer is reachable. If it has
- * not been heard for three consecutive
- * polls, stuff the clock filter. Next,
- * determine the poll interval. If the
- * peer is unfit for synchronization,
- * increase it by one; otherwise, use
- * the system poll interval.
- */
- if (!(peer->reach & 0x07)) {
- clock_filter(peer, 0., 0.,
- MAXDISPERSE);
- clock_select();
- }
- if (peer_unfit(peer))
- hpoll++;
- else
- hpoll = sys_poll;
- if (peer->flags & FLAG_BURST)
- peer->burst = NTP_BURST;
+ /*
+ * Send a burst if enabled, but only once after
+ * a peer becomes unreachable. If the prempt
+ * flag is dim, bump the unreach counter by one;
+ * otherwise, bump it by three.
+ */
+ if (peer->flags & FLAG_IBURST &&
+ peer->unreach == 0) {
+ peer->burst = NTP_BURST;
}
+ if (!(peer->flags & FLAG_PREEMPT))
+ peer->unreach++;
+ else
+ peer->unreach += 3;
} else {
/*
- * Source rate control. If we are restrained,
- * each burst consists of only one packet.
+ * Here the peer is reachable. Set the poll
+ * interval to the system poll interval. Send a
+ * burst only if enabled and the peer is fit.
+ *
+ * Respond to the peer evaluation produced by
+ * the selection algorithm. If less than the
+ * outlyer level, up the unreach by three. If
+ * there are excess associations, up the unreach
+ * by two if not a candidate and by one if so.
*/
- if (memcmp((char *)&peer->refid, "RSTR", 4) ==
- 0)
- peer->burst = 0;
- else
- peer->burst--;
- if (peer->burst == 0) {
- /*
- * If a broadcast client at this point,
- * the burst has concluded, so we switch
- * to client mode and purge the keylist,
- * since no further transmissions will
- * be made.
- */
- if (peer->cast_flags & MDF_BCLNT) {
- peer->hmode = MODE_BCLIENT;
+ if (!(peer->flags & FLAG_PREEMPT)) {
+ peer->unreach = 0;
+ } else if (peer->status < CTL_PST_SEL_SELCAND) {
+ peer->unreach += 3;
+ } else if (peer_preempt > sys_maxclock) {
+ if (peer->status < CTL_PST_SEL_SYNCCAND)
+ peer->unreach += 2;
+ else
+ peer->unreach++;
+ } else {
+ peer->unreach = 0;
+ }
+ hpoll = sys_poll;
+ if (peer->flags & FLAG_BURST &&
+ !peer_unfit(peer))
+ peer->burst = NTP_BURST;
+ }
+
+ /*
+ * Watch for timeout. If ephemeral or preemptable, toss
+ * the rascal; otherwise, bump the poll interval.
+ */
+ if (peer->unreach >= NTP_UNREACH) {
+ if (peer->flags & FLAG_PREEMPT ||
+ !(peer->flags & FLAG_CONFIG)) {
+ peer_clear(peer, "TIME");
+ unpeer(peer);
+ return;
+ } else {
+ hpoll++;
+ }
+ }
+ } else {
+ peer->burst--;
+
+ /*
+ * 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->burst == 0) {
+ if (peer->cast_flags & MDF_BCLNT) {
+ peer->hmode = MODE_BCLIENT;
#ifdef OPENSSL
- key_expire(peer);
+ key_expire(peer);
#endif /* OPENSSL */
- }
- poll_update(peer, hpoll);
- clock_select();
+ }
- /*
- * If ntpdate mode and the clock has not
- * been set and all peers have completed
- * the burst, we declare a successful
- * failure.
- */
- if (mode_ntpdate) {
- peer_ntpdate--;
- if (peer_ntpdate > 0) {
- poll_update(
- peer, hpoll);
- return;
- }
+ /*
+ * 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) {
msyslog(LOG_NOTICE,
"no reply; clock not set");
exit (0);
}
- poll_update(peer, hpoll);
- return;
}
}
}
- peer->outdate = current_time;
/*
- * Do not transmit if in broadcast cclient mode or access has
- * been denied.
+ * Do not transmit if in broadcast client mode.
*/
- if (peer->hmode == MODE_BCLIENT || peer->flash & TEST4) {
- poll_update(peer, hpoll);
- return;
-
- /*
- * Do not transmit in broadcast mode unless we are synchronized.
- */
- } else if (peer->hmode == MODE_BROADCAST && sys_peer == NULL) {
- poll_update(peer, hpoll);
- return;
- }
- peer_xmit(peer);
+ if (peer->hmode != MODE_BCLIENT)
+ peer_xmit(peer);
poll_update(peer, hpoll);
}
+
/*
* receive - Receive Procedure. See section 3.4.3 in the specification.
*/
@@ -306,15 +328,19 @@ receive(
{
register struct peer *peer; /* peer structure pointer */
register struct pkt *pkt; /* receive packet pointer */
+ int hisversion; /* packet version */
+ int hisleap; /* packet leap indicator */
int hismode; /* packet mode */
+ int hisstratum; /* packet stratum */
int restrict_mask; /* restrict bits */
int has_mac; /* length of MAC field */
int authlen; /* offset of MAC field */
- int is_authentic; /* cryptosum ok */
+ int is_authentic = 0; /* 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_org; /* origin timestamp */
+ l_fp p_rec; /* receive timestamp */
l_fp p_xmt; /* transmit timestamp */
#ifdef OPENSSL
keyid_t tkeyid = 0; /* temporary key ID */
@@ -323,6 +349,7 @@ receive(
int rval; /* cookie snatcher */
#endif /* OPENSSL */
int retcode = AM_NOMATCH;
+ int at_listhead;
/*
* Monitor the packet and get restrictions. Note that the packet
@@ -343,20 +370,24 @@ receive(
sys_badlength++;
return; /* bogus port */
}
- ntp_monitor(rbufp);
- restrict_mask = restrictions(&rbufp->recv_srcadr);
+ at_listhead = ntp_monitor(rbufp);
+ restrict_mask = restrictions(&rbufp->recv_srcadr, at_listhead);
#ifdef DEBUG
if (debug > 1)
- printf("receive: at %ld %s<-%s restrict %03x\n",
+ printf("receive: at %ld %s<-%s flags %x restrict %03x\n",
current_time, stoa(&rbufp->dstadr->sin),
- stoa(&rbufp->recv_srcadr), restrict_mask);
+ stoa(&rbufp->recv_srcadr),
+ rbufp->dstadr->flags, restrict_mask);
#endif
if (restrict_mask & RES_IGNORE) {
sys_restricted++;
- return; /* no anything */
+ return; /* ignore everything */
}
pkt = &rbufp->recv_pkt;
+ hisversion = PKT_VERSION(pkt->li_vn_mode);
+ hisleap = PKT_LEAP(pkt->li_vn_mode);
hismode = (int)PKT_MODE(pkt->li_vn_mode);
+ hisstratum = PKT_TO_STRATUM(pkt->stratum);
if (hismode == MODE_PRIVATE) {
if (restrict_mask & RES_NOQUERY) {
sys_restricted++;
@@ -387,10 +418,10 @@ receive(
* Version check must be after the query packets, since they
* intentionally use early version.
*/
- if (PKT_VERSION(pkt->li_vn_mode) == NTP_VERSION) {
+ if (hisversion == NTP_VERSION) {
sys_newversionpkt++; /* new version */
- } else if (!(restrict_mask & RES_VERSION) &&
- PKT_VERSION(pkt->li_vn_mode) >= NTP_OLDVERSION) {
+ } else if (!(restrict_mask & RES_VERSION) && hisversion >=
+ NTP_OLDVERSION) {
sys_oldversionpkt++; /* previous version */
} else {
sys_unknownversion++;
@@ -404,7 +435,7 @@ receive(
* would interpret as client mode.
*/
if (hismode == MODE_UNSPEC) {
- if (PKT_VERSION(pkt->li_vn_mode) == NTP_OLDVERSION) {
+ if (hisversion == NTP_OLDVERSION) {
hismode = MODE_CLIENT;
} else {
sys_badlength++;
@@ -413,35 +444,15 @@ receive(
}
/*
- * Discard broadcast if not enabled as broadcast client. If
- * Autokey, the wildcard interface cannot be used, so dump
- * packets gettiing off the bus at that stop as well. This means
- * that some systems with broken interface code, specifically
- * Linux, will not work with Autokey.
- */
- if (hismode == MODE_BROADCAST) {
- if (!sys_bclient || restrict_mask & RES_NOPEER) {
- sys_restricted++;
- return; /* no client */
- }
-#ifdef OPENSSL
- if (crypto_flags && rbufp->dstadr == any_interface) {
- sys_restricted++;
- return; /* no client */
- }
-#endif /* OPENSSL */
- }
-
- /*
* Parse the extension field if present. We figure out whether
* an extension field is present by measuring the MAC size. If
- * the number of words following the packet header is 0 or 1, no
- * MAC is present and the packet is not authenticated. If 1, the
- * packet is a reply to a previous request that failed to
- * authenticate. If 3, the packet is authenticated with DES; if
- * 5, the packet is authenticated with MD5. If greater than 5,
- * an extension field is present. If 2 or 4, the packet is a
- * runt and goes poof! with a brilliant flash.
+ * the number of words following the packet header is 0, no MAC
+ * is present and the packet is not authenticated. If 1, the
+ * packet is a crypto-NAK; if 3, the packet is authenticated
+ * with DES; if 5, the packet is authenticated with MD5. If 2 or
+ * 4, the packet is a runt and discarded forthwith. If greater
+ * than 5, an extension field is present, so we subtract the
+ * length of the field and go around again.
*/
authlen = LEN_PKT_NOMAC;
has_mac = rbufp->recv_length - authlen;
@@ -491,21 +502,58 @@ receive(
* address used to construct the autokey is the unicast address
* of the interface. However, if the sender is a broadcaster,
* the interface broadcast address is used instead.
- * Notwithstanding this technobabble, if the sender is a
+ & Notwithstanding this technobabble, if the sender is a
* multicaster, the broadcast address is null, so we use the
* unicast address anyway. Don't ask.
*/
- peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, rbufp->fd,
- hismode, &retcode);
- is_authentic = 0;
+ peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, hismode,
+ &retcode);
dstadr_sin = &rbufp->dstadr->sin;
+ NTOHL_FP(&pkt->org, &p_org);
+ NTOHL_FP(&pkt->rec, &p_rec);
+ NTOHL_FP(&pkt->xmt, &p_xmt);
+
+ /*
+ * Authentication is conditioned by three switches:
+ *
+ * NOPEER (RES_NOPEER) do not mobilize an association unless
+ * authenticated
+ * NOTRUST (RES_DONTTRUST) do not allow access unless
+ * authenticated (implies NOPEER)
+ * enable (sys_authenticate) master NOPEER switch, by default
+ * on
+ *
+ * The NOPEER and NOTRUST can be specified on a per-client basis
+ * using the restrict command. The enable switch if on implies
+ * NOPEER for all clients. There are four outcomes:
+ *
+ * NONE The packet has no MAC.
+ * OK the packet has a MAC and authentication succeeds
+ * ERROR the packet has a MAC and authentication fails
+ * CRYPTO crypto-NAK. The MAC has four octets only.
+ *
+ * Note: The AUTH(x, y) macro is used to filter outcomes. If x
+ * is zero, acceptable outcomes of y are NONE and OK. If x is
+ * one, the only acceptable outcome of y is OK.
+ */
if (has_mac == 0) {
+ is_authentic = AUTH_NONE; /* not required */
#ifdef DEBUG
if (debug)
- printf("receive: at %ld %s<-%s mode %d code %d\n",
- current_time, stoa(&rbufp->dstadr->sin),
- stoa(&rbufp->recv_srcadr), hismode,
- retcode);
+ printf("receive: at %ld %s<-%s mode %d code %d auth %d\n",
+ current_time, stoa(dstadr_sin),
+ stoa(&rbufp->recv_srcadr), hismode, retcode,
+ is_authentic);
+#endif
+ } else if (has_mac == 4) {
+ is_authentic = AUTH_CRYPTO; /* crypto-NAK */
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
+ current_time, stoa(dstadr_sin),
+ stoa(&rbufp->recv_srcadr), hismode, retcode,
+ skeyid, authlen, has_mac, is_authentic);
#endif
} else {
#ifdef OPENSSL
@@ -548,8 +596,14 @@ receive(
* broadcast address when available;
* otherwise, use the unicast address
* found when the association was
- * mobilized.
+ * mobilized. However, if this is from
+ * the wildcard interface, game over.
*/
+ if (crypto_flags && rbufp->dstadr ==
+ any_interface) {
+ sys_restricted++;
+ return; /* no wildcard */
+ }
pkeyid = 0;
if (!SOCKNUL(&rbufp->dstadr->bcast))
dstadr_sin =
@@ -588,15 +642,15 @@ receive(
* Compute the cryptosum. Note a clogging attack may
* succeed in bloating the key cache. If an autokey,
* purge it immediately, since we won't be needing it
- * again. If the packet is authentic, it may mobilize an
- * association.
+ * again. If the packet is authentic, it can mobilize an
+ * association. Note that there is no key zero.
*/
- if (authdecrypt(skeyid, (u_int32 *)pkt, authlen,
+ if (!authdecrypt(skeyid, (u_int32 *)pkt, authlen,
has_mac)) {
- is_authentic = 1;
- restrict_mask &= ~RES_DONTTRUST;
- } else {
+ is_authentic = AUTH_ERROR;
sys_badauth++;
+ } else {
+ is_authentic = AUTH_OK;
}
#ifdef OPENSSL
if (skeyid > NTP_MAXKEY)
@@ -608,97 +662,114 @@ receive(
"receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
current_time, stoa(dstadr_sin),
stoa(&rbufp->recv_srcadr), hismode, retcode,
- skeyid, authlen, has_mac,
- is_authentic);
+ skeyid, authlen, has_mac, is_authentic);
#endif
}
/*
* The association matching rules are implemented by a set of
- * routines and a table in ntp_peer.c. A packet matching an
- * association is processed by that association. If not and
- * certain conditions prevail, then an ephemeral association is
- * mobilized: a broadcast packet mobilizes a broadcast client
+ * routines and an association table. A packet matching an
+ * association is processed by the peer process for that
+ * association. If there are no errors, an ephemeral association
+ * is mobilized: a broadcast packet mobilizes a broadcast client
* aassociation; a manycast server packet mobilizes a manycast
* client association; a symmetric active packet mobilizes a
- * symmetric passive association. And, the adventure
- * continues...
+ * symmetric passive association.
*/
switch (retcode) {
+
+ /*
+ * This is a client mode packet not matching any association. If
+ * an ordinary client, simply toss a server mode packet back
+ * over the fence. If a manycast client, we have to work a
+ * little harder.
+ */
case AM_FXMIT:
/*
- * This is a client mode packet not matching a known
- * association. If from a manycast client we run a few
- * sanity checks before deciding to send a unicast
- * server response. Otherwise, it must be a client
- * request, so send a server response and go home.
+ * The vanilla case is when this is not a multicast
+ * interface. If authentication succeeds, return a
+ * server mode packet; if not and the key ID is nonzero,
+ * return a crypto-NAK.
*/
- if (sys_manycastserver && (rbufp->dstadr->flags &
- INT_MULTICAST)) {
-
- /*
- * There is no reason to respond to a request if
- * our time is worse than the manycaster or it
- * has already synchronized to us.
- */
- if (sys_peer == NULL ||
- PKT_TO_STRATUM(pkt->stratum) <
- sys_stratum || (sys_cohort &&
- PKT_TO_STRATUM(pkt->stratum) ==
- sys_stratum) ||
- rbufp->dstadr->addr_refid == pkt->refid)
- return; /* manycast dropped */
+ if (!(rbufp->dstadr->flags & INT_MCASTOPEN)) {
+ if (AUTH(restrict_mask & RES_DONTTRUST,
+ is_authentic))
+ fast_xmit(rbufp, MODE_SERVER, skeyid,
+ restrict_mask);
+ else if (is_authentic == AUTH_ERROR)
+ fast_xmit(rbufp, MODE_SERVER, 0,
+ restrict_mask);
+ return; /* hooray */
}
/*
- * Note that we don't require an authentication check
- * here, since we can't set the system clock; but, we do
- * send a crypto-NAK to tell the caller about this.
+ * This must be manycast. Do not respond if not
+ * configured as a manycast server.
*/
- if (has_mac && !is_authentic)
- fast_xmit(rbufp, MODE_SERVER, 0, restrict_mask);
- else
- fast_xmit(rbufp, MODE_SERVER, skeyid,
- restrict_mask);
- return;
+ if (!sys_manycastserver) {
+ sys_restricted++;
+ return; /* not enabled */
+ }
- case AM_MANYCAST:
+ /*
+ * Do not respond if unsynchronized or stratum is below
+ * the floor or at or above the ceiling.
+ */
+ if (sys_leap == LEAP_NOTINSYNC || sys_stratum <
+ sys_floor || sys_stratum >= sys_ceiling)
+ return; /* bad stratum */
/*
- * This is a server mode packet returned in response to
- * a client mode packet sent to a multicast group
- * address. The originate timestamp is a good nonce to
- * reliably associate the reply with what was sent. If
- * there is no match, that's curious and could be an
- * intruder attempting to clog, so we just ignore it.
- *
- * First, make sure the packet is authentic and not
- * restricted. If so and the manycast association is
- * found, we mobilize a client association and copy
- * pertinent variables from the manycast association to
- * the new client association.
- *
- * There is an implosion hazard at the manycast client,
- * since the manycast servers send the server packet
- * immediately. If the guy is already here, don't fire
- * up a duplicate.
+ * Do not respond if our stratum is greater than the
+ * manycaster or it has already synchronized to us.
*/
- if (restrict_mask & RES_DONTTRUST) {
- sys_restricted++;
- return; /* no trust */
- }
+ if (sys_peer == NULL || hisstratum < sys_stratum ||
+ (sys_cohort && hisstratum == sys_stratum) ||
+ rbufp->dstadr->addr_refid == pkt->refid)
+ return; /* no help */
- if (sys_authenticate && !is_authentic)
- return; /* bad auth */
+ /*
+ * Respond only if authentication succeeds. Don't do a
+ * crypto-NAK, as that would not be useful.
+ */
+ if (AUTH(restrict_mask & RES_DONTTRUST, is_authentic))
+ fast_xmit(rbufp, MODE_SERVER, skeyid,
+ restrict_mask);
- if ((peer2 = findmanycastpeer(rbufp)) == NULL)
- return; /* no assoc match */
+ return; /* hooray */
- if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
- MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, FLAG_IBURST, MDF_UCAST |
- MDF_ACLNT, 0, skeyid)) == NULL)
+ /*
+ * This is a server mode packet returned in response to a client
+ * mode packet sent to a multicast group address. The origin
+ * timestamp is a good nonce to reliably associate the reply
+ * with what was sent. If there is no match, that's curious and
+ * could be an intruder attempting to clog, so we just ignore
+ * it.
+ *
+ * If the packet is authentic and the manycast association is
+ * found, we mobilize a client association and copy pertinent
+ * variables from the manycast association to the new client
+ * association. If not, just ignore the packet.
+ *
+ * There is an implosion hazard at the manycast client, since
+ * the manycast servers send the server packet immediately. If
+ * the guy is already here, don't fire up a duplicate.
+ */
+ case AM_MANYCAST:
+ if (!AUTH(sys_authenticate | (restrict_mask &
+ (RES_NOPEER | RES_DONTTRUST)), is_authentic))
+ return; /* bad auth */
+
+ if ((peer2 = findmanycastpeer(rbufp)) == NULL) {
+ sys_restricted++;
+ return; /* not enabled */
+ }
+ if ((peer = newpeer(&rbufp->recv_srcadr,
+ rbufp->dstadr, MODE_CLIENT,
+ hisversion, NTP_MINDPOLL, NTP_MAXDPOLL,
+ FLAG_IBURST | FLAG_PREEMPT, MDF_UCAST | MDF_ACLNT,
+ 0, skeyid)) == NULL)
return; /* system error */
/*
@@ -707,260 +778,223 @@ receive(
peer->ttl = peer2->ttl;
break;
- case AM_NEWPASS:
+ /*
+ * This is the first packet received from a broadcast server. If
+ * the packet is authentic and we are enabled as broadcast
+ * client, mobilize a broadcast client association. We don't
+ * kiss any frogs here.
+ */
+ case AM_NEWBCL:
+ if (!AUTH(sys_authenticate | (restrict_mask &
+ (RES_NOPEER | RES_DONTTRUST)), is_authentic))
+ return; /* bad auth */
/*
- * This is the first packet received from a symmetric
- * active peer. First, make sure it is authentic and not
- * restricted. If so, mobilize a passive association.
- * If authentication fails send a crypto-NAK; otherwise,
- * kiss the frog.
+ * Do not respond if unsynchronized or stratum is below
+ * the floor or at or above the ceiling.
*/
- if (restrict_mask & RES_DONTTRUST) {
- sys_restricted++;
- return; /* no trust */
- }
- if (sys_authenticate && !is_authentic) {
- fast_xmit(rbufp, MODE_PASSIVE, 0,
- restrict_mask);
- return; /* bad auth */
- }
- if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
- MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_UCAST, 0,
- skeyid)) == NULL)
- return; /* system error */
-
- break;
+ if (hisleap == LEAP_NOTINSYNC || hisstratum <
+ sys_floor || hisstratum >= sys_ceiling)
+ return; /* bad stratum */
- case AM_NEWBCL:
+ switch (sys_bclient) {
/*
- * This is the first packet received from a broadcast
- * server. First, make sure it is authentic and not
- * restricted and that we are a broadcast client. If so,
- * mobilize a broadcast client association. We don't
- * kiss any frogs here.
+ * If not enabled, just skedaddle.
*/
- if (restrict_mask & RES_DONTTRUST) {
+ case 0:
sys_restricted++;
- return; /* no trust */
- }
- if (sys_authenticate && !is_authentic)
- return; /* bad auth */
-
- if (!sys_bclient)
- return; /* not a client */
+ return; /* not enabled */
- if ((peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
- MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, FLAG_MCAST |
- FLAG_IBURST, MDF_BCLNT, 0, skeyid)) == NULL)
- return; /* system error */
-#ifdef OPENSSL
/*
- * Danger looms. If this is autokey, go process the
- * extension fields. If something goes wrong, abandon
- * ship and don't trust subsequent packets.
+ * Execute the initial volley in order to calibrate the
+ * propagation delay and run the Autokey protocol, if
+ * enabled.
*/
- 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
- }
- }
+ case 1:
+ if ((peer = newpeer(&rbufp->recv_srcadr,
+ rbufp->dstadr, MODE_CLIENT, hisversion,
+ NTP_MINDPOLL, NTP_MAXDPOLL, FLAG_MCAST |
+ FLAG_IBURST, MDF_BCLNT, 0, skeyid)) ==
+ NULL)
+ return; /* system error */
+#ifdef OPENSSL
+ if (skeyid > NTP_MAXKEY)
+ crypto_recv(peer, rbufp);
#endif /* OPENSSL */
- return;
-
- case AM_POSSBCL:
+ return; /* hooray */
- /*
- * This is a broadcast packet received in client mode.
- * It could happen if the initial client/server volley
- * is not complete before the next broadcast packet is
- * received. Be liberal in what we accept.
- */
- case AM_PROCPKT:
/*
- * This is a symmetric mode packet received in symmetric
- * mode, a server packet received in client mode or a
- * broadcast packet received in broadcast client mode.
- * If it is restricted, this is very strange because it
- * is rude to send a packet to a restricted address. If
- * anyway, flash a restrain kiss and skedaddle to
- * Seattle. If not authentic, leave a light on and
- * continue.
+ * Do not execute the initial volley.
*/
- 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 */
+ case 2:
+#ifdef OPENSSL
+ /*
+ * If a two-way exchange is not possible,
+ * neither is Autokey.
+ */
+ if (skeyid > NTP_MAXKEY) {
+ msyslog(LOG_INFO,
+ "receive: autokey requires two-way communication");
+ return; /* no autokey */
+ }
+#endif /* OPENSSL */
+ if ((peer = newpeer(&rbufp->recv_srcadr,
+ rbufp->dstadr, MODE_BCLIENT, hisversion,
+ NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_BCLNT, 0,
+ skeyid)) == NULL)
+ return; /* system error */
}
- if (has_mac && !is_authentic)
- peer->flash |= TEST5; /* bad auth */
break;
- default:
+ /*
+ * This is the first packet received from a symmetric active
+ * peer. If the packet is authentic and the first he sent,
+ * mobilize a passive association. If not, kiss the frog.
+ */
+ case AM_NEWPASS:
/*
- * 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 the inbound packet is correctly authenticated and
+ * enabled, a symmetric passive association is
+ * mobilized. If not but correctly authenticated, a
+ * symmetric active response is sent. If authentication
+ * fails, send a crypto-NAK packet.
*/
- if (has_mac && hismode == MODE_PASSIVE)
- fast_xmit(rbufp, MODE_ACTIVE, 0, restrict_mask);
-#ifdef DEBUG
- if (debug)
- printf("receive: bad protocol %d\n", retcode);
-#endif
- return;
- }
+ if (!AUTH(restrict_mask & RES_DONTTRUST, is_authentic))
+ {
+ if (is_authentic == AUTH_ERROR)
+ fast_xmit(rbufp, MODE_ACTIVE, 0,
+ restrict_mask);
+ return; /* bad auth */
+ }
+ if (!AUTH(sys_authenticate | (restrict_mask &
+ RES_NOPEER), is_authentic)) {
+ fast_xmit(rbufp, MODE_ACTIVE, skeyid,
+ restrict_mask);
+ return; /* hooray */
+ }
+
+ /*
+ * Do not respond if stratum is below the floor.
+ */
+ if (hisstratum < sys_floor)
+ return; /* bad stratum */
+
+ if ((peer = newpeer(&rbufp->recv_srcadr,
+ rbufp->dstadr, MODE_PASSIVE, hisversion,
+ NTP_MINDPOLL, NTP_MAXDPOLL, 0, MDF_UCAST, 0,
+ skeyid)) == NULL)
+ return; /* system error */
+ break;
/*
- * 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.
+ * Process regular packet. Nothing special.
*/
- peer->timereceived = current_time;
- peer->received++;
- if (peer->flash & TEST5)
- peer->flags &= ~FLAG_AUTHENTIC;
- else
- peer->flags |= FLAG_AUTHENTIC;
- NTOHL_FP(&pkt->org, &p_org);
- NTOHL_FP(&pkt->xmt, &p_xmt);
+ case AM_PROCPKT:
+ break;
/*
- * If the packet is an old duplicate, we let it through so the
- * extension fields will be processed.
+ * A passive packet matches a passive association. This is
+ * usually the result of reconfiguring a client on the fly. As
+ * this association might be legitamate and this packet an
+ * attempt to deny service, just ignore it.
*/
- if (L_ISEQU(&peer->org, &p_xmt)) { /* test 1 */
- peer->flash |= TEST1; /* dupe */
- /* fall through */
+ case AM_ERR:
+ return;
/*
- * 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.
+ * For everything else there is the bit bucket.
*/
- } 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 */
+ default:
+ return;
+ }
+ peer->flash &= ~PKT_TEST_MASK;
/*
- * 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.
+ * Next comes a rigorous schedule of timestamp checking. If the
+ * transmit timestamp is zero, the server is horribly broken.
*/
- } else if (L_ISZERO(&peer->xmt)) {
- /* fall through */
+ if (L_ISZERO(&p_xmt)) {
+ return; /* read rfc1305 */
/*
- * 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.
+ * If the transmit timestamp duplicates a previous one, the
+ * packet is a replay. This prevents the bad guys from replaying
+ * the most recent packet, authenticated or not.
*/
- } else if (!L_ISZERO(&p_org)) {
- if (peer->cast_flags & MDF_ACLNT)
- return; /* not a client */
+ } else if (L_ISEQU(&peer->org, &p_xmt)) {
+ peer->flash |= TEST1;
+ peer->oldpkt++;
+ return; /* duplicate packet */
+
- peer->flash |= TEST2;
- /* fall through */
+ /*
+ * If this is a broadcast mode packet, skip further checking.
+ */
+ } else if (hismode != MODE_BROADCAST) {
+ if (L_ISZERO(&p_org))
+ peer->flash |= TEST3; /* protocol unsynch */
+ else if (!L_ISEQU(&p_org, &peer->xmt))
+ peer->flash |= TEST2; /* bogus packet */
+ }
/*
- * 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.
+ * Update the origin and destination timestamps. If
+ * unsynchronized or bogus abandon ship. If the crypto machine
+ * breaks, light the crypto bit and plaint the log.
*/
- } else if (L_ISZERO(&peer->org)) {
- /* fall through */
+ peer->org = p_xmt;
+ peer->rec = rbufp->recv_time;
+ if (peer->flash & PKT_TEST_MASK) {
+#ifdef OPENSSL
+ if (crypto_flags && (peer->flags & FLAG_SKEY)) {
+ rval = crypto_recv(peer, rbufp);
+ if (rval != XEVNT_OK) {
+ peer_clear(peer, "CRYP");
+ peer->flash |= TEST9; /* crypto error */
+ }
+ }
+#endif /* OPENSSL */
+ return; /* unsynch */
+ }
/*
- * 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.
+ * The timestamps are valid and the receive packet matches the
+ * last one sent. If the packet is a crypto-NAK, the server
+ * might have just changed keys. We reset the association
+ * and restart the protocol.
*/
- } else {
- if (hismode == MODE_ACTIVE)
- fast_xmit(rbufp, MODE_PASSIVE, 0,
- restrict_mask);
- else if (hismode == MODE_PASSIVE)
+ if (is_authentic == AUTH_CRYPTO) {
+ peer_clear(peer, "AUTH");
+ return; /* crypto-NAK */
+
+ /*
+ * If the association is authenticated, the key ID is nonzero
+ * and received packets must be authenticated. This is designed
+ * to avoid a bait-and-switch attack, which was possible in past
+ * versions. If symmetric modes, return a crypto-NAK. The peer
+ * should restart the protocol.
+ */
+ } else if (!AUTH(peer->keyid || (restrict_mask & RES_DONTTRUST),
+ is_authentic)) {
+ peer->flash |= TEST5;
+ if (hismode == MODE_ACTIVE || hismode == MODE_PASSIVE)
fast_xmit(rbufp, MODE_ACTIVE, 0, restrict_mask);
-#if DEBUG
- if (debug)
- printf("receive: dropped %03x\n", peer->flash);
-#endif
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "DROP");
- else
- unpeer(peer);
- return;
- }
- if (peer->flash & ~TEST2) {
- return;
+ return; /* bad auth */
}
+ /*
+ * That was hard and I am sweaty, but the packet is squeaky
+ * clean. Get on with real work.
+ */
+ peer->received++;
+ peer->timereceived = current_time;
+ if (is_authentic == AUTH_OK)
+ peer->flags |= FLAG_AUTHENTIC;
+ else
+ peer->flags &= ~FLAG_AUTHENTIC;
#ifdef OPENSSL
/*
* More autokey dance. The rules of the cha-cha are as follows:
@@ -981,17 +1015,27 @@ receive(
* 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.
+ *
+ * In case of crypto error, fire the orchestra and stop dancing.
+ * This is considered a permanant error, so light the crypto bit
+ * to suppress further requests. If preemptable or ephemeral,
+ * scuttle the ship.
*/
if (crypto_flags && (peer->flags & FLAG_SKEY)) {
- peer->flash |= TEST10;
+ peer->flash |= TEST8;
rval = crypto_recv(peer, rbufp);
if (rval != XEVNT_OK) {
- /* fall through */
+ peer_clear(peer, "CRYP");
+ peer->flash |= TEST9; /* crypto error */
+ if (peer->flags & FLAG_PREEMPT ||
+ !(peer->flags & FLAG_CONFIG))
+ unpeer(peer);
+ return;
} else if (hismode == MODE_SERVER) {
if (skeyid == peer->keyid)
- peer->flash &= ~TEST10;
- } else if (!peer->flash & TEST10) {
+ peer->flash &= ~TEST8;
+ } else if (!(peer->flash & TEST8)) {
peer->pkeyid = skeyid;
} else if ((ap = (struct autokey *)peer->recval.ptr) !=
NULL) {
@@ -1000,7 +1044,7 @@ receive(
for (i = 0; ; i++) {
if (tkeyid == peer->pkeyid ||
tkeyid == ap->key) {
- peer->flash &= ~TEST10;
+ peer->flash &= ~TEST8;
peer->pkeyid = skeyid;
break;
}
@@ -1011,8 +1055,8 @@ receive(
tkeyid, pkeyid, 0);
}
}
- if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 11 */
- peer->flash |= TEST11; /* not proventic */
+ if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 9 */
+ peer->flash |= TEST8; /* not proventic */
/*
* If the transmit queue is nonempty, clamp the host
@@ -1020,65 +1064,28 @@ receive(
*/
if (peer->cmmd != 0) {
peer->ppoll = pkt->ppoll;
- poll_update(peer, 0);
- }
-
- /*
- * If the return code from extension field processing is
- * not okay, we scrub the association and start over.
- */
- if (rval != XEVNT_OK) {
-
- /*
- * If the return code is bad, the crypto machine
- * may be jammed or an intruder may lurk. First,
- * we demobilize the association, then see if
- * the error is recoverable.
- */
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "CRYP");
- else
- unpeer(peer);
-#ifdef DEBUG
- if (debug)
- printf("packet: bad exten %x\n", rval);
-#endif
- return;
- }
-
- /*
- * If TEST10 is lit, the autokey sequence has broken,
- * which probably means the server has refreshed its
- * private value. We reset the poll interval to the
- & minimum and scrub the association clean.
- */
- if (peer->flash & TEST10 && peer->crypto &
- CRYPTO_FLAG_AUTO) {
- poll_update(peer, peer->minpoll);
-#ifdef DEBUG
- if (debug)
- printf(
- "packet: bad auto %03x\n",
- peer->flash);
-#endif
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "AUTO");
- else
- unpeer(peer);
- return;
+ poll_update(peer, peer->hpoll);
}
}
#endif /* OPENSSL */
/*
- * We have survived the gaunt. Forward to the packet routine. If
- * a symmetric passive association has been mobilized and the
- * association doesn't deserve to live, it will die in the
- * transmit routine if not reachable after timeout. However, if
- * either symmetric mode and the crypto code has something
- * urgent to say, we expedite the response.
+ * The dance is complete and the flash bits have been lit. Toss
+ * the packet over the fence for processing, which may light up
+ * more flashers.
*/
- process_packet(peer, pkt, &rbufp->recv_time);
+ process_packet(peer, pkt);
+
+ /*
+ * Well, that was nice. If TEST4 is lit, either the crypto
+ * machine jammed or a kiss-o'-death packet flew in, either of
+ * which is fatal.
+ */
+ if (peer->flash & TEST4) {
+ msyslog(LOG_INFO, "receive: fatal error %04x for %s",
+ peer->flash, stoa(&peer->srcadr));
+ return;
+ }
}
@@ -1091,23 +1098,15 @@ receive(
void
process_packet(
register struct peer *peer,
- register struct pkt *pkt,
- l_fp *recv_ts
+ register struct pkt *pkt
)
{
- l_fp t34, t21;
+ double t34, t21;
double p_offset, p_del, p_disp;
- double dtemp;
l_fp p_rec, p_xmt, p_org, p_reftime;
l_fp ci;
u_char pmode, pleap, pstratum;
- /*
- * Swap header fields and keep the books. The books amount to
- * the receive timestamp and poll interval in the header. We
- * need these even if there are other problems in order to crank
- * up the state machine.
- */
sys_processed++;
peer->processed++;
p_del = FPTOD(NTOHS_FP(pkt->rootdelay));
@@ -1124,106 +1123,97 @@ process_packet(
pstratum = PKT_TO_STRATUM(pkt->stratum);
/*
- * Test for unsynchronized server.
+ * Test for kiss-o'death packet)
*/
- if (L_ISHIS(&peer->org, &p_xmt)) /* count old packets */
- peer->oldpkt++;
- if (pmode != MODE_BROADCAST && (L_ISZERO(&p_rec) ||
- L_ISZERO(&p_org))) /* test 3 */
- peer->flash |= TEST3; /* unsynch */
- if (L_ISZERO(&p_xmt)) /* test 3 */
- peer->flash |= TEST3; /* unsynch */
+ if (pleap == LEAP_NOTINSYNC && pstratum == STRATUM_UNSPEC) {
+ if (memcmp(&pkt->refid, "DENY", 4) == 0) {
+ peer_clear(peer, "DENY");
+ peer->flash |= TEST4; /* access denied */
+ }
+ }
/*
- * 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.
+ * Capture the header values.
*/
- peer->org = p_xmt;
- peer->rec = *recv_ts;
- if (peer->flash) {
-#ifdef DEBUG
- if (debug)
- printf("packet: bad data %03x from address: %s\n",
- peer->flash, stoa(&peer->srcadr));
-#endif
- return;
- }
+ record_raw_stats(&peer->srcadr, peer->dstadr ? &peer->dstadr->sin : NULL, &p_org,
+ &p_rec, &p_xmt, &peer->rec);
peer->leap = pleap;
- peer->stratum = pstratum;
- peer->refid = pkt->refid;
+ peer->stratum = min(pstratum, STRATUM_UNSPEC);
+ peer->pmode = pmode;
+ peer->ppoll = pkt->ppoll;
+ peer->precision = pkt->precision;
+ peer->rootdelay = p_del;
+ peer->rootdispersion = p_disp;
+ peer->refid = pkt->refid; /* network byte order */
+ peer->reftime = p_reftime;
/*
- * Test for valid peer data (tests 6-8)
+ * Verify the server is synchronized; that is, the leap bits and
+ * stratum are valid, the root delay and root dispersion are
+ * valid and the reference timestamp is not later than the
+ * transmit timestamp.
*/
- ci = p_xmt;
- L_SUB(&ci, &p_reftime);
- LFPTOD(&ci, dtemp);
if (pleap == LEAP_NOTINSYNC || /* test 6 */
- pstratum >= STRATUM_UNSPEC || dtemp < 0)
- peer->flash |= TEST6; /* bad synch */
- if (!(peer->flags & FLAG_CONFIG) && sys_peer != NULL) { /* test 7 */
- if (pstratum > sys_stratum && pmode != MODE_ACTIVE)
- peer->flash |= TEST7; /* bad stratum */
- }
- if (p_del < 0 || p_disp < 0 || p_del / /* test 8 */
- 2 + p_disp >= MAXDISPERSE)
- peer->flash |= TEST8; /* bad peer values */
+ pstratum < sys_floor || pstratum >= sys_ceiling)
+ peer->flash |= TEST6; /* peer not synch */
+ if (p_del < 0 || p_disp < 0 || p_del / /* test 7 */
+ 2 + p_disp >= MAXDISPERSE || !L_ISHIS(&p_xmt, &p_reftime))
+ peer->flash |= TEST7; /* bad header */
/*
* If any tests fail at this point, the packet is discarded.
+ * Note that some flashers may have already been set in the
+ * receive() routine.
*/
- if (peer->flash) {
+ if (peer->flash & PKT_TEST_MASK) {
#ifdef DEBUG
if (debug)
- printf("packet: bad header %03x\n",
+ printf("packet: flash header %04x\n",
peer->flash);
#endif
return;
}
-
- /*
- * The header is valid. Capture the remaining header values and
- * mark as reachable.
- */
- record_raw_stats(&peer->srcadr, &peer->dstadr->sin, &p_org,
- &p_rec, &p_xmt, &peer->rec);
- peer->pmode = pmode;
- peer->ppoll = pkt->ppoll;
- peer->precision = pkt->precision;
- peer->rootdelay = p_del;
- peer->rootdispersion = p_disp;
- peer->reftime = p_reftime;
if (!(peer->reach)) {
report_event(EVNT_REACH, peer);
peer->timereachable = current_time;
}
+ poll_update(peer, peer->hpoll);
peer->reach |= 1;
- peer->unreach = 0;
- poll_update(peer, 0);
/*
- * If running in a client/server association, calculate the
- * clock offset c, roundtrip delay d and dispersion e. We use
- * the equations (reordered from those in the spec). Note that,
- * in a broadcast association, org has been set to the time of
- * last reception. Note the computation of dispersion includes
- * the system precision plus that due to the frequency error
- * since the originate time.
+ * For a client/server association, calculate the clock offset,
+ * roundtrip delay and dispersion. The equations are reordered
+ * from the spec for more efficient use of temporaries. For a
+ * broadcast association, offset the last measurement by the
+ * computed delay during the client/server volley. Note that
+ * org has been set to the time of last reception. Note the
+ * computation of dispersion includes the system precision plus
+ * that due to the frequency error since the origin time.
+ *
+ * It is very important to respect the hazards of overflow. The
+ * only permitted operation on raw timestamps is subtraction,
+ * where the result is a signed quantity spanning from 68 years
+ * in the past to 68 years in the future. To avoid loss of
+ * precision, these calculations are done using 64-bit integer
+ * arithmetic. However, the offset and delay calculations are
+ * sums and differences of these first-order differences, which
+ * if done using 64-bit integer arithmetic, would be valid over
+ * only half that span. Since the typical first-order
+ * differences are usually very small, they are converted to 64-
+ * bit doubles and all remaining calculations done in floating-
+ * point arithmetic. This preserves the accuracy while retaining
+ * the 68-year span.
*
* Let t1 = p_org, t2 = p_rec, t3 = p_xmt, t4 = peer->rec:
*/
- t34 = p_xmt; /* t3 - t4 */
- L_SUB(&t34, &peer->rec);
- t21 = p_rec; /* t2 - t1 */
- L_SUB(&t21, &p_org);
+ ci = p_xmt; /* t3 - t4 */
+ L_SUB(&ci, &peer->rec);
+ LFPTOD(&ci, t34);
+ ci = p_rec; /* t2 - t1 */
+ L_SUB(&ci, &p_org);
+ LFPTOD(&ci, t21);
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
@@ -1234,48 +1224,29 @@ 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) {
+ p_offset = t34;
if (peer->flags & FLAG_MCAST) {
- LFPTOD(&ci, p_offset);
peer->estbdelay = peer->offset - p_offset;
if (peer->hmode == MODE_CLIENT)
return;
- peer->flags &= ~FLAG_MCAST;
+ peer->flags &= ~(FLAG_MCAST | FLAG_BURST);
}
- DTOLFP(peer->estbdelay, &t34);
- L_ADD(&ci, &t34);
+ p_offset += peer->estbdelay;
p_del = peer->delay;
+ p_disp = 0;
} else {
- L_ADD(&ci, &t21); /* (t2 - t1) + (t3 - t4) */
- L_RSHIFT(&ci);
- L_SUB(&t21, &t34); /* (t2 - t1) - (t3 - t4) */
- LFPTOD(&t21, p_del);
+ p_offset = (t21 + t34) / 2.;
+ p_del = t21 - t34;
+ LFPTOD(&ci, p_disp);
+ p_disp = LOGTOD(sys_precision) +
+ LOGTOD(peer->precision) + clock_phi * p_disp;
}
p_del = max(p_del, LOGTOD(sys_precision));
- LFPTOD(&ci, p_offset);
- if ((peer->rootdelay + p_del) / 2. + peer->rootdispersion +
- p_disp >= MAXDISPERSE) /* test 9 */
- peer->flash |= TEST9; /* bad root distance */
-
- /*
- * If any flasher bits remain set at this point, abandon ship.
- * Otherwise, forward to the clock filter.
- */
- if (peer->flash) {
-#ifdef DEBUG
- if (debug)
- printf("packet: bad packet data %03x\n",
- peer->flash);
-#endif
- return;
- }
clock_filter(peer, p_offset, p_del, p_disp);
- clock_select();
record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
- peer->offset, peer->delay, peer->disp,
- SQRT(peer->jitter));
+ peer->offset, peer->delay, peer->disp, peer->jitter);
}
@@ -1285,18 +1256,23 @@ process_packet(
static void
clock_update(void)
{
- u_char oleap;
- u_char ostratum;
+ u_char oleap;
+ u_char ostratum;
+ double dtemp;
/*
- * Reset/adjust the system clock. Do this only if there is a
- * system peer and the peer epoch is not older than the last
- * update.
+ * There must be a system peer at this point. If we just changed
+ * the system peer, but have a newer sample from the old one,
+ * wait until newer data are available.
*/
- if (sys_peer == NULL)
- return;
- if (sys_peer->epoch <= last_time)
+ if (sys_poll < sys_peer->minpoll)
+ sys_poll = sys_peer->minpoll;
+ if (sys_poll > sys_peer->maxpoll)
+ sys_poll = sys_peer->maxpoll;
+ poll_update(sys_peer, sys_poll);
+ if (sys_peer->epoch <= sys_clocktime)
return;
+
#ifdef DEBUG
if (debug)
printf("clock_update: at %ld assoc %d \n", current_time,
@@ -1304,53 +1280,85 @@ clock_update(void)
#endif
oleap = sys_leap;
ostratum = sys_stratum;
- switch (local_clock(sys_peer, sys_offset, sys_syserr)) {
+ switch (local_clock(sys_peer, sys_offset)) {
/*
- * Clock is too screwed up. Just exit for now.
+ * Clock exceeds panic threshold. Life as we know it ends.
*/
case -1:
report_event(EVNT_SYSFAULT, NULL);
exit (-1);
- /*NOTREACHED*/
+ /* not reached */
/*
* Clock was stepped. Flush all time values of all peers.
*/
- case 1:
+ case 2:
clear_all();
- sys_peer = NULL;
+ sys_leap = LEAP_NOTINSYNC;
sys_stratum = STRATUM_UNSPEC;
- memcpy(&sys_refid, "STEP", 4);
- sys_poll = NTP_MINPOLL;
+ sys_peer = NULL;
+ sys_rootdelay = 0;
+ sys_rootdispersion = 0;
+ memcpy(&sys_refid, "STEP", 4);
report_event(EVNT_CLOCKRESET, NULL);
-#ifdef OPENSSL
- if (oleap != LEAP_NOTINSYNC)
- expire_all();
-#endif /* OPENSSL */
break;
/*
- * Update the system stratum, leap bits, root delay, root
- * dispersion, reference ID and reference time. We also update
- * select dispersion and max frequency error. If the leap
- * changes, we gotta reroll the keys.
+ * Clock was slewed. Update the system stratum, leap bits, root
+ * delay, root dispersion, reference ID and reference time. If
+ * the leap changes, we gotta reroll the keys. Except for
+ * reference clocks, the minimum dispersion increment is not
+ * less than sys_mindisp.
*/
- default:
- sys_stratum = (u_char) (sys_peer->stratum + 1);
- if (sys_stratum == 1 || sys_stratum == STRATUM_UNSPEC)
- sys_refid = sys_peer->refid;
- else
- sys_refid = sys_peer_refid;
+ case 1:
+ sys_leap = leap_next;
+ sys_stratum = min(sys_peer->stratum + 1,
+ STRATUM_UNSPEC);
sys_reftime = sys_peer->rec;
- sys_rootdelay = sys_peer->rootdelay + sys_peer->delay;
- sys_leap = leap_consensus;
+
+ /*
+ * In orphan mode the stratum defaults to the orphan
+ * stratum. The root delay is set to a random value
+ * generated at startup. The root dispersion is set from
+ * the peer dispersion; the peer root dispersion is
+ * ignored.
+ */
+ dtemp = sys_peer->disp + clock_phi * (current_time -
+ sys_peer->update) + sys_jitter +
+ fabs(sys_peer->offset);
+#ifdef REFCLOCK
+ if (!(sys_peer->flags & FLAG_REFCLOCK) && dtemp <
+ sys_mindisp)
+ dtemp = sys_mindisp;
+#else
+ if (dtemp < sys_mindisp)
+ dtemp = sys_mindisp;
+#endif /* REFCLOCK */
+ if (sys_stratum >= sys_orphan) {
+ sys_stratum = sys_orphan;
+ sys_rootdelay = sys_peer->delay;
+ sys_rootdispersion = dtemp;
+ } else {
+ sys_rootdelay = sys_peer->delay +
+ sys_peer->rootdelay;
+ sys_rootdispersion = dtemp +
+ sys_peer->rootdispersion;
+ }
if (oleap == LEAP_NOTINSYNC) {
report_event(EVNT_SYNCCHG, NULL);
#ifdef OPENSSL
expire_all();
+ crypto_update();
#endif /* OPENSSL */
}
+ break;
+ /*
+ * Popcorn spike or step threshold exceeded. Pretend it never
+ * happened.
+ */
+ default:
+ break;
}
if (ostratum != sys_stratum)
report_event(EVNT_PEERSTCHG, NULL);
@@ -1363,110 +1371,114 @@ clock_update(void)
void
poll_update(
struct peer *peer,
- int hpoll
+ int mpoll
)
{
-#ifdef OPENSSL
- int oldpoll;
-#endif /* OPENSSL */
+ int hpoll;
+
+ /*
+ * This routine figures out when the next poll should be sent.
+ * That turns out to be wickedly complicated. The big problem is
+ * that sometimes the time for the next poll is in the past.
+ * Watch out for races here between the receive process and the
+ * poll process. The key assertion is that, if nextdate equals
+ * current_time, the call is from the poll process; otherwise,
+ * it is from the receive process.
+ *
+ * First, bracket the poll interval according to the type of
+ * association and options. If a fixed interval is configured,
+ * use minpoll. This primarily is for reference clocks, but
+ * works for any association.
+ */
+ if (peer->flags & FLAG_FIXPOLL) {
+ hpoll = peer->minpoll;
/*
- * A little foxtrot to determine what controls the poll
- * interval. If the peer is reachable, but the last four polls
- * have not been answered, use the minimum. If declared
- * truechimer, use the system poll interval. This allows each
- * association to ramp up the poll interval for useless sources
- * and to clamp it to the minimum when first starting up.
+ * The ordinary case; clamp the poll interval between minpoll
+ * and maxpoll.
*/
+ } else {
+ hpoll = max(min(peer->maxpoll, mpoll), peer->minpoll);
+ }
#ifdef OPENSSL
- oldpoll = peer->kpoll;
+ /*
+ * Bit of crass arrogance at this point. If the poll interval
+ * has changed and we have a keylist, the lifetimes in the
+ * keylist are probably bogus. In this case purge the keylist
+ * and regenerate it later.
+ */
+ if (hpoll != peer->hpoll)
+ key_expire(peer);
#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;
- }
+ peer->hpoll = hpoll;
/*
- * Bit of adventure here. If during a burst and not a poll, just
- * slink away. If a poll, figure what the next poll should be.
- * If a burst is pending and a reference clock or a pending
- * crypto response, delay for one second. If the first sent in a
- * burst, delay ten seconds for the modem to come up. For others
- * in the burst, delay two seconds.
- *
- * In case of manycast server, make the poll interval, which is
- * axtually the manycast beacon interval, eight times the system
- * poll interval. Normally when the host poll interval settles
- * up to 1024 s, the beacon interval settles up to 2.3 hours.
+ * Now we figure out if there is an override. If during the
+ * crypto protocol and a message is pending, make it wait not
+ * more than two seconds.
*/
#ifdef OPENSSL
if (peer->cmmd != NULL && (sys_leap != LEAP_NOTINSYNC ||
peer->crypto)) {
peer->nextdate = current_time + RESP_DELAY;
+
+ /*
+ * If we get called from the receive routine while a burst is
+ * pending, just slink away. If from the poll routine and a
+ * reference clock or a pending crypto response, delay for one
+ * second. If this is the first sent in a burst, wait for the
+ * modem to come up. For others in the burst, delay two seconds.
+ */
} else if (peer->burst > 0) {
#else /* OPENSSL */
if (peer->burst > 0) {
#endif /* OPENSSL */
- if (hpoll == 0 && peer->nextdate != current_time)
+ if (peer->nextdate != current_time)
return;
#ifdef REFCLOCK
else if (peer->flags & FLAG_REFCLOCK)
peer->nextdate += RESP_DELAY;
-#endif
+#endif /* REFCLOCK */
else if (peer->flags & (FLAG_IBURST | FLAG_BURST) &&
peer->burst == NTP_BURST)
peer->nextdate += sys_calldelay;
else
peer->nextdate += BURST_DELAY;
- } else if (peer->cast_flags & MDF_ACAST) {
- if (sys_survivors >= sys_minclock || peer->ttl >=
- sys_ttlmax)
- peer->kpoll = (u_char) (peer->hpoll + 3);
- else
- peer->kpoll = peer->hpoll;
- peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
+ /*
+ * The ordinary case; use the minimum of the host and peer
+ * intervals, but not less than minpoll. In other words,
+ * oversampling is okay but understampling is evil.
+ */
} else {
- peer->kpoll = (u_char) max(min(peer->ppoll,
- peer->hpoll), peer->minpoll);
- peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
+ peer->nextdate = peer->outdate +
+ RANDPOLL(max(min(peer->ppoll, hpoll),
+ peer->minpoll));
}
- if (peer->nextdate < current_time)
- peer->nextdate = current_time;
-#ifdef OPENSSL
+
/*
- * Bit of crass arrogance at this point. If the poll interval
- * has changed and we have a keylist, the lifetimes in the
- * keylist are probably bogus. In this case purge the keylist
- * and regenerate it later.
+ * If the time for the next poll has already happened, bring it
+ * up to the next second after this one. This way the only way
+ * to get nexdate == current time is from the poll routine.
*/
- if (peer->kpoll != oldpoll)
- key_expire(peer);
-#endif /* OPENSSL */
+ if (peer->nextdate <= current_time)
+ peer->nextdate = current_time + 1;
#ifdef DEBUG
if (debug > 1)
printf("poll_update: at %lu %s flags %04x poll %d burst %d last %lu next %lu\n",
current_time, ntoa(&peer->srcadr), peer->flags,
- peer->kpoll, peer->burst, peer->outdate,
+ peer->hpoll, peer->burst, peer->outdate,
peer->nextdate);
#endif
}
-
/*
- * clear - clear peer filter registers. See Section 3.4.8 of the spec.
+ * peer_crypto_clear - discard crypto information
*/
void
-peer_clear(
- struct peer *peer, /* peer structure */
- char *ident /* tally lights */
- )
+peer_crypto_clear(
+ struct peer *peer
+ )
{
- u_char oreach, i;
-
/*
* If cryptographic credentials have been acquired, toss them to
* Valhalla. Note that autokeys are ephemeral, in that they are
@@ -1476,41 +1488,88 @@ peer_clear(
* purged, too. This makes it much harder to sneak in some
* unauthenticated data in the clock filter.
*/
- oreach = peer->reach;
+ DPRINTF(1, ("peer_crypto_clear: at %ld next %ld assoc ID %d\n",
+ current_time, peer->nextdate, peer->associd));
+
#ifdef OPENSSL
- key_expire(peer);
+ peer->assoc = 0;
+ peer->crypto = 0;
+
if (peer->pkey != NULL)
EVP_PKEY_free(peer->pkey);
- if (peer->ident_pkey != NULL)
- EVP_PKEY_free(peer->ident_pkey);
+ peer->pkey = NULL;
+
+ peer->digest = NULL; /* XXX MEMLEAK? check whether this needs to be freed in any way - never was freed */
+
if (peer->subject != NULL)
free(peer->subject);
+ peer->subject = NULL;
+
if (peer->issuer != NULL)
free(peer->issuer);
+ peer->issuer = NULL;
+
+ peer->pkeyid = 0;
+
+ peer->pcookie = 0;
+
+ if (peer->ident_pkey != NULL)
+ EVP_PKEY_free(peer->ident_pkey);
+ peer->ident_pkey = NULL;
+
+ memset(&peer->fstamp, 0, sizeof(peer->fstamp));
+
if (peer->iffval != NULL)
BN_free(peer->iffval);
+ peer->iffval = NULL;
+
if (peer->grpkey != NULL)
BN_free(peer->grpkey);
- if (peer->cmmd != NULL)
- free(peer->cmmd);
+ peer->grpkey = NULL;
+
value_free(&peer->cookval);
value_free(&peer->recval);
- value_free(&peer->tai_leap);
+
+ if (peer->cmmd != NULL) {
+ free(peer->cmmd);
+ peer->cmmd = NULL;
+ }
+
+ key_expire(peer);
+
value_free(&peer->encrypt);
- value_free(&peer->sndval);
#endif /* OPENSSL */
+}
+
+/*
+ * peer_clear - clear peer filter registers. See Section 3.4.8 of the spec.
+ */
+void
+peer_clear(
+ struct peer *peer, /* peer structure */
+ char *ident /* tally lights */
+ )
+{
+ int i;
+
+ peer_crypto_clear(peer);
+
+ if (peer == sys_peer)
+ sys_peer = NULL;
/*
* Wipe the association clean and initialize the nonzero values.
*/
memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
- if (peer == sys_peer)
- sys_peer = NULL;
peer->estbdelay = sys_bdelay;
- peer->hpoll = peer->kpoll = peer->minpoll;
peer->ppoll = peer->maxpoll;
- peer->jitter = MAXDISPERSE;
- peer->epoch = current_time;
+ peer->hpoll = peer->minpoll;
+ peer->disp = MAXDISPERSE;
+ peer->jitter = LOGTOD(sys_precision);
+ for (i = 0; i < NTP_SHIFT; i++) {
+ peer->filter_order[i] = i;
+ peer->filter_disp[i] = MAXDISPERSE;
+ }
#ifdef REFCLOCK
if (!(peer->flags & FLAG_REFCLOCK)) {
peer->leap = LEAP_NOTINSYNC;
@@ -1521,43 +1580,25 @@ peer_clear(
peer->leap = LEAP_NOTINSYNC;
peer->stratum = STRATUM_UNSPEC;
memcpy(&peer->refid, ident, 4);
-#endif
- for (i = 0; i < NTP_SHIFT; i++) {
- peer->filter_order[i] = i;
- peer->filter_disp[i] = MAXDISPERSE;
- peer->filter_epoch[i] = current_time;
- }
+#endif /* REFCLOCK */
/*
- * If he dies as a broadcast client, he comes back to life as
- * a broadcast client in client mode in order to recover the
- * initial autokey values.
- */
- if (peer->cast_flags & MDF_BCLNT) {
- peer->flags |= FLAG_MCAST;
- peer->hmode = MODE_CLIENT;
- }
-
- /*
- * Randomize the first poll to avoid bunching, but only if the
- * rascal has never been heard. During initialization use the
- * association count to spread out the polls at one-second
- * intervals.
+ * During initialization use the association count to spread out
+ * the polls at one-second intervals. Othersie, randomize over
+ * the minimum poll interval in order to avoid broadcast
+ * implosion.
*/
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;
+ if (initializing)
+ peer->nextdate += peer_associations;
+ else if (peer->hmode == MODE_PASSIVE)
+ peer->nextdate += RESP_DELAY;
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
+ peer->nextdate += (ntp_random() & ((1 << NTP_MINDPOLL) -
+ 1));
+
+ DPRINTF(1, ("peer_clear: at %ld next %ld assoc ID %d refid %s\n",
+ current_time, peer->nextdate, peer->associd, ident));
}
@@ -1576,7 +1617,7 @@ clock_filter(
double dst[NTP_SHIFT]; /* distance vector */
int ord[NTP_SHIFT]; /* index vector */
int i, j, k, m;
- double dsp, jit, dtemp, etemp;
+ double dtemp, etemp;
/*
* Shift the new sample into the register and discard the oldest
@@ -1587,14 +1628,13 @@ clock_filter(
* precision. The delay can sometimes swing negative due to
* frequency skew, so it is clamped non-negative.
*/
- dsp = min(LOGTOD(peer->precision) + LOGTOD(sys_precision) +
- sample_disp, MAXDISPERSE);
j = peer->filter_nextpt;
peer->filter_offset[j] = sample_offset;
peer->filter_delay[j] = max(0, sample_delay);
- peer->filter_disp[j] = dsp;
- j++; j %= NTP_SHIFT;
- peer->filter_nextpt = (u_short) j;
+ peer->filter_disp[j] = sample_disp;
+ peer->filter_epoch[j] = current_time;
+ j = (j + 1) % NTP_SHIFT;
+ peer->filter_nextpt = j;
/*
* Update dispersions since the last update and at the same
@@ -1614,26 +1654,31 @@ clock_filter(
dst[i] = MAXDISPERSE;
else if (peer->update - peer->filter_epoch[j] >
allan_xpt)
- dst[i] = MAXDISTANCE + peer->filter_disp[j];
+ dst[i] = sys_maxdist + peer->filter_disp[j];
else
dst[i] = peer->filter_delay[j];
ord[i] = j;
j++; j %= NTP_SHIFT;
}
- peer->filter_epoch[j] = current_time;
/*
- * Sort the samples in both lists by distance.
- */
- for (i = 1; i < NTP_SHIFT; i++) {
- for (j = 0; j < i; j++) {
- if (dst[j] > dst[i]) {
- k = ord[j];
- ord[j] = ord[i];
- ord[i] = k;
- etemp = dst[j];
- dst[j] = dst[i];
- dst[i] = etemp;
+ * If the clock discipline has stabilized, sort the samples in
+ * both lists by distance. Note, we do not displace a higher
+ * distance sample by a lower distance one unless lower by at
+ * least the precision.
+ */
+ if (state == 4) {
+ for (i = 1; i < NTP_SHIFT; i++) {
+ for (j = 0; j < i; j++) {
+ if (dst[j] > dst[i] +
+ LOGTOD(sys_precision)) {
+ k = ord[j];
+ ord[j] = ord[i];
+ ord[i] = k;
+ etemp = dst[j];
+ dst[j] = dst[i];
+ dst[i] = etemp;
+ }
}
}
}
@@ -1641,61 +1686,59 @@ clock_filter(
/*
* Copy the index list to the association structure so ntpq
* can see it later. Prune the distance list to samples less
- * than MAXDISTANCE, but keep at least two valid samples for
+ * than max distance, but keep at least two valid samples for
* jitter calculation.
*/
m = 0;
for (i = 0; i < NTP_SHIFT; i++) {
peer->filter_order[i] = (u_char) ord[i];
if (dst[i] >= MAXDISPERSE || (m >= 2 && dst[i] >=
- MAXDISTANCE))
+ sys_maxdist))
continue;
m++;
}
/*
- * Compute the dispersion and jitter squares. The dispersion
- * is weighted exponentially by NTP_FWEIGHT (0.5) so it is
- * normalized close to 1.0. The jitter is the mean of the square
- * differences relative to the lowest delay sample. If no
- * acceptable samples remain in the shift register, quietly
- * tiptoe home leaving only the dispersion.
+ * Compute the dispersion and jitter. The dispersion is weighted
+ * exponentially by NTP_FWEIGHT (0.5) so it is normalized close
+ * to 1.0. The jitter is the RMS differences relative to the
+ * lowest delay sample. If no acceptable samples remain in the
+ * shift register, quietly tiptoe home leaving only the
+ * dispersion.
*/
- jit = 0;
- peer->disp = 0;
+ peer->disp = peer->jitter = 0;
k = ord[0];
for (i = NTP_SHIFT - 1; i >= 0; i--) {
-
j = ord[i];
peer->disp = NTP_FWEIGHT * (peer->disp +
peer->filter_disp[j]);
if (i < m)
- jit += DIFF(peer->filter_offset[j],
+ peer->jitter += DIFF(peer->filter_offset[j],
peer->filter_offset[k]);
}
/*
* If no acceptable samples remain in the shift register,
* quietly tiptoe home leaving only the dispersion. Otherwise,
- * save the offset, delay and jitter average. Note the jitter
- * must not be less than the system precision.
+ * save the offset, delay and jitter. Note the jitter must not
+ * be less than the precision.
*/
if (m == 0)
return;
+
etemp = fabs(peer->offset - peer->filter_offset[k]);
- dtemp = sqrt(peer->jitter);
peer->offset = peer->filter_offset[k];
peer->delay = peer->filter_delay[k];
if (m > 1)
- jit /= m - 1;
- peer->jitter = max(jit, SQUARE(LOGTOD(sys_precision)));
+ peer->jitter /= m - 1;
+ peer->jitter = max(SQRT(peer->jitter), LOGTOD(sys_precision));
/*
* A new sample is useful only if it is younger than the last
- * one used, but only if the sucker has been synchronized.
+ * one used. Note the order is FIFO if the clock discipline has
+ * not stabilized.
*/
- if (peer->filter_epoch[k] <= peer->epoch && sys_leap !=
- LEAP_NOTINSYNC) {
+ if (peer->filter_epoch[k] <= peer->epoch) {
#ifdef DEBUG
if (debug)
printf("clock_filter: discard %lu\n",
@@ -1710,9 +1753,9 @@ clock_filter(
* last update is less than twice the system poll interval,
* consider the update a popcorn spike and ignore it.
*/
- if (m > 1 && etemp > CLOCK_SGATE * dtemp &&
- (long)(peer->filter_epoch[k] - peer->epoch) < (1 << (sys_poll +
- 1))) {
+ if (etemp > CLOCK_SGATE * peer->jitter && m > 1 &&
+ peer->filter_epoch[k] - peer->epoch < 2. *
+ ULOGTOD(sys_poll)) {
#ifdef DEBUG
if (debug)
printf("clock_filter: popcorn %.6f %.6f\n",
@@ -1723,7 +1766,7 @@ clock_filter(
/*
* The mitigated sample statistics are saved for later
- * processing.
+ * processing. If not in a burst, tickle the select.
*/
peer->epoch = peer->filter_epoch[k];
#ifdef DEBUG
@@ -1731,8 +1774,10 @@ clock_filter(
printf(
"clock_filter: n %d off %.6f del %.6f dsp %.6f jit %.6f, age %lu\n",
m, peer->offset, peer->delay, peer->disp,
- SQRT(peer->jitter), peer->update - peer->epoch);
+ peer->jitter, current_time - peer->epoch);
#endif
+ if (peer->burst == 0 || sys_leap == LEAP_NOTINSYNC)
+ clock_select();
}
@@ -1751,14 +1796,13 @@ clock_select(void)
int i, j, k, n;
int nlist, nl3;
- double d, e, f;
- int allow, sw, osurv;
+ int allow, osurv;
+ double d, e, f, g;
double high, low;
- double synch[NTP_MAXCLOCK], error[NTP_MAXCLOCK];
+ double synch[NTP_MAXASSOC], error[NTP_MAXASSOC];
struct peer *osys_peer;
struct peer *typeacts = NULL;
struct peer *typelocal = NULL;
- struct peer *typepps = NULL;
struct peer *typesystem = NULL;
static int list_alloc = 0;
@@ -1775,16 +1819,17 @@ clock_select(void)
*/
osys_peer = sys_peer;
sys_peer = NULL;
+ sys_pps = NULL;
+ sys_prefer = NULL;
osurv = sys_survivors;
sys_survivors = 0;
- sys_prefer = NULL;
#ifdef LOCKCLOCK
sys_leap = LEAP_NOTINSYNC;
sys_stratum = STRATUM_UNSPEC;
memcpy(&sys_refid, "DOWN", 4);
#endif /* LOCKCLOCK */
nlist = 0;
- for (n = 0; n < HASH_SIZE; n++)
+ for (n = 0; n < NTP_HASH_SIZE; n++)
nlist += peer_hash_count[n];
if (nlist > list_alloc) {
if (list_alloc > 0) {
@@ -1798,9 +1843,9 @@ clock_select(void)
indx_size += 5 * 3 * sizeof(*indx);
peer_list_size += 5 * sizeof(*peer_list);
}
- endpoint = emalloc(endpoint_size);
- indx = emalloc(indx_size);
- peer_list = emalloc(peer_list_size);
+ endpoint = (struct endpoint *)emalloc(endpoint_size);
+ indx = (int *)emalloc(indx_size);
+ peer_list = (struct peer **)emalloc(peer_list_size);
}
/*
@@ -1814,7 +1859,7 @@ clock_select(void)
* bucks and collectively crank the chimes.
*/
nlist = nl3 = 0; /* none yet */
- for (n = 0; n < HASH_SIZE; n++) {
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != NULL; peer =
peer->next) {
peer->flags &= ~FLAG_SYSPEER;
@@ -1834,6 +1879,7 @@ clock_select(void)
* nobody else is around. These guys are all
* configured, so we never throw them away.
*/
+#ifdef REFCLOCK
if (peer->refclktype == REFCLK_LOCALCLOCK
#if defined(VMS) && defined(VMS_LOCALUNIT)
/* wjm: VMS_LOCALUNIT taken seriously */
@@ -1842,11 +1888,9 @@ clock_select(void)
#endif /* VMS && VMS_LOCALUNIT */
) {
typelocal = peer;
+#ifndef LOCKCLOCK
if (!(peer->flags & FLAG_PREFER))
continue; /* no local clock */
-#ifdef LOCKCLOCK
- else
- sys_prefer = peer;
#endif /* LOCKCLOCK */
}
if (peer->sstclktype == CTL_SST_TS_TELEPHONE) {
@@ -1854,6 +1898,7 @@ clock_select(void)
if (!(peer->flags & FLAG_PREFER))
continue; /* no acts */
}
+#endif /* REFCLOCK */
/*
* If we get this far, the peer can stay on the
@@ -1873,6 +1918,7 @@ clock_select(void)
for (i = nl3 - 1; i >= 0; i--) {
if (e >= endpoint[indx[i]].val)
break;
+
indx[i + 3] = indx[i];
}
indx[i + 3] = nl3;
@@ -1883,6 +1929,7 @@ clock_select(void)
for (; i >= 0; i--) {
if (e >= endpoint[indx[i]].val)
break;
+
indx[i + 2] = indx[i];
}
indx[i + 2] = nl3;
@@ -1893,6 +1940,7 @@ clock_select(void)
for (; i >= 0; i--) {
if (e >= endpoint[indx[i]].val)
break;
+
indx[i + 1] = indx[i];
}
indx[i + 1] = nl3;
@@ -1925,7 +1973,9 @@ clock_select(void)
* correct synchronization is not possible.
*
* Here, nlist is the number of candidates and allow is the
- * number of falsetickers.
+ * number of falsetickers. Upon exit, the truechimers are the
+ * susvivors with offsets not less than low and not greater than
+ * high. There may be none of them.
*/
low = 1e9;
high = -1e9;
@@ -1976,31 +2026,76 @@ clock_select(void)
}
/*
+ * Clustering algorithm. Construct candidate list in order first
+ * by stratum then by root distance, but keep only the best
+ * NTP_MAXASSOC of them. Scan the list to find falsetickers, who
+ * leave the island immediately. The TRUE peer is always a
+ * truechimer. We must leave at least one peer to collect the
+ * million bucks. If in orphan mode, rascals found with lower
+ * stratum are guaranteed a seat on the bus.
+ */
+ j = 0;
+ for (i = 0; i < nlist; i++) {
+ peer = peer_list[i];
+ if (nlist > 1 && (peer->offset <= low || peer->offset >=
+ high) && !(peer->flags & FLAG_TRUE) &&
+ !(sys_stratum >= sys_orphan && peer->stratum <
+ sys_orphan))
+ continue;
+
+ peer->status = CTL_PST_SEL_DISTSYSPEER;
+
+ /*
+ * The order metric is formed from the stratum times
+ * max distance (1.) plus the root distance. It strongly
+ * favors the lowest stratum, but a higher stratum peer
+ * can capture the clock if the low stratum dominant
+ * hasn't been heard for awhile.
+ */
+ d = root_distance(peer) + peer->stratum * sys_maxdist;
+ if (j >= NTP_MAXASSOC) {
+ if (d >= synch[j - 1])
+ continue;
+ else
+ j--;
+ }
+ for (k = j; k > 0; k--) {
+ if (d >= synch[k - 1])
+ break;
+
+ peer_list[k] = peer_list[k - 1];
+ error[k] = error[k - 1];
+ synch[k] = synch[k - 1];
+ }
+ peer_list[k] = peer;
+ error[k] = peer->jitter;
+ synch[k] = d;
+ j++;
+ }
+ nlist = j;
+
+ /*
* If no survivors remain at this point, check if the local
* clock or modem drivers have been found. If so, nominate one
* of them as the only survivor. Otherwise, give up and leave
* the island to the rats.
*/
- if (high <= low) {
+ if (nlist == 0) {
if (typeacts != 0) {
- typeacts->status = CTL_PST_SEL_SANE;
+ typeacts->status = CTL_PST_SEL_DISTSYSPEER;
peer_list[0] = typeacts;
nlist = 1;
} else if (typelocal != 0) {
- typelocal->status = CTL_PST_SEL_SANE;
+ typelocal->status = CTL_PST_SEL_DISTSYSPEER;
peer_list[0] = typelocal;
nlist = 1;
} else {
if (osys_peer != NULL) {
- sys_poll = NTP_MINPOLL;
NLOG(NLOG_SYNCSTATUS)
msyslog(LOG_INFO,
"no servers reachable");
report_event(EVNT_PEERSTCHG, NULL);
}
- if (osurv > 0)
- resetmanycast();
- return;
}
}
@@ -2010,91 +2105,27 @@ clock_select(void)
* 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
+ * operators will tinker a higher value and use at least that
* number of synchronization sources.
*/
if (nlist < sys_minsane)
return;
- /*
- * Clustering algorithm. Construct candidate list in order first
- * by stratum then by root distance, but keep only the best
- * NTP_MAXCLOCK of them. Scan the list to find falsetickers, who
- * leave the island immediately. If a falseticker is not
- * configured, his association raft is drowned as well, but only
- * if at at least eight poll intervals have gone. We must leave
- * at least one peer to collect the million bucks.
- *
- * Note the hysteresis gimmick that increases the effective
- * distance for those rascals that have not made the final cut.
- * This is to discourage clockhopping. Note also the prejudice
- * against lower stratum peers if the floor is elevated.
- */
- j = 0;
- for (i = 0; i < nlist; i++) {
- peer = peer_list[i];
- if (nlist > 1 && (peer->offset <= low || peer->offset >=
- high)) {
- if (!(peer->flags & FLAG_CONFIG))
- unpeer(peer);
- continue;
- }
- peer->status = CTL_PST_SEL_DISTSYSPEER;
- d = peer->stratum;
- if (d < sys_floor)
- d += sys_floor;
- if (d > sys_ceiling)
- d = STRATUM_UNSPEC;
- d = root_distance(peer) + d * MAXDISTANCE;
- d *= 1. - peer->hyst;
- if (j >= NTP_MAXCLOCK) {
- if (d >= synch[j - 1])
- continue;
- else
- j--;
- }
- for (k = j; k > 0; k--) {
- if (d >= synch[k - 1])
- break;
- peer_list[k] = peer_list[k - 1];
- error[k] = error[k - 1];
- synch[k] = synch[k - 1];
- }
- peer_list[k] = peer;
- error[k] = peer->jitter;
- synch[k] = d;
- j++;
- }
- nlist = j;
- if (nlist == 0) {
-#ifdef DEBUG
- if (debug)
- printf("clock_select: empty intersection interval\n");
-#endif
- return;
- }
- for (i = 0; i < nlist; i++) {
+ for (i = 0; i < nlist; i++)
peer_list[i]->status = CTL_PST_SEL_SELCAND;
-#ifdef DEBUG
- if (debug > 2)
- printf("select: %s distance %.6f jitter %.6f\n",
- ntoa(&peer_list[i]->srcadr), synch[i],
- SQRT(error[i]));
-#endif
- }
-
/*
* Now, vote outlyers off the island by select jitter weighted
- * by root dispersion. Continue voting as long as there are more
- * than sys_minclock survivors and the minimum select jitter
- * squared is greater than the maximum peer jitter squared. Stop
- * if we are about to discard a prefer peer, who of course has
- * the immunity idol.
+ * by root distance. Continue voting as long as there are more
+ * than sys_minclock survivors and the minimum select jitter is
+ * greater than the maximum peer jitter. Stop if we are about to
+ * discard a TRUE or PREFER peer, who of course has the
+ * immunity idol.
*/
while (1) {
d = 1e9;
e = -1e9;
+ f = g = 0;
k = 0;
for (i = 0; i < nlist; i++) {
if (error[i] < d)
@@ -2104,28 +2135,24 @@ clock_select(void)
for (j = 0; j < nlist; j++)
f += DIFF(peer_list[j]->offset,
peer_list[i]->offset);
- f /= nlist - 1;
+ f = SQRT(f / (nlist - 1));
}
if (f * synch[i] > e) {
- sys_selerr = f;
+ g = f;
e = f * synch[i];
k = i;
}
}
- f = max(sys_selerr, SQUARE(LOGTOD(sys_precision)));
+ f = max(f, LOGTOD(sys_precision));
if (nlist <= sys_minclock || f <= d ||
- peer_list[k]->flags & FLAG_PREFER)
+ peer_list[k]->flags & (FLAG_TRUE | FLAG_PREFER))
break;
#ifdef DEBUG
if (debug > 2)
printf(
"select: drop %s select %.6f jitter %.6f\n",
- ntoa(&peer_list[k]->srcadr),
- SQRT(sys_selerr), SQRT(d));
+ ntoa(&peer_list[k]->srcadr), g, d);
#endif
- if (!(peer_list[k]->flags & FLAG_CONFIG) &&
- peer_list[k]->hmode == MODE_CLIENT)
- unpeer(peer_list[k]);
for (j = k + 1; j < nlist; j++) {
peer_list[j - 1] = peer_list[j];
error[j - 1] = error[j];
@@ -2137,158 +2164,178 @@ clock_select(void)
* What remains is a list usually not greater than sys_minclock
* peers. We want only a peer at the lowest stratum to become
* the system peer, although all survivors are eligible for the
- * combining algorithm. First record their order, diddle the
- * flags and clamp the poll intervals. Then, consider each peer
- * in turn and OR the leap bits on the assumption that, if some
- * of them honk nonzero bits, they must know what they are
- * doing. Check for prefer and pps peers at any stratum. Check
- * if the old system peer is among the peers at the lowest
- * stratum. Note that the head of the list is at the lowest
- * stratum and that unsynchronized peers cannot survive this
- * far.
- *
- * Fiddle for hysteresis. Pump it up for a peer only if the peer
- * stratum is at least the floor and there are enough survivors.
- * This minimizes the pain when tossing out rascals beneath the
- * floorboard. Don't count peers with stratum above the ceiling.
- * Manycast is sooo complicated.
- */
- leap_consensus = 0;
- for (i = nlist - 1; i >= 0; i--) {
+ * combining algorithm. 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. Note that the head of
+ * the list is at the lowest stratum and that unsynchronized
+ * peers cannot survive this far.
+ */
+ leap_next = 0;
+ for (i = 0; i < nlist; i++) {
peer = peer_list[i];
- leap_consensus |= peer->leap;
+ sys_survivors++;
+ leap_next |= peer->leap;
peer->status = CTL_PST_SEL_SYNCCAND;
- peer->rank++;
- peer->flags |= FLAG_SYSPEER;
- if (peer->stratum >= sys_floor && osurv >= sys_minclock)
- peer->hyst = HYST;
- else
- peer->hyst = 0;
- if (peer->stratum <= sys_ceiling)
- sys_survivors++;
if (peer->flags & FLAG_PREFER)
sys_prefer = peer;
- if (peer->refclktype == REFCLK_ATOM_PPS &&
- peer->stratum < STRATUM_UNSPEC)
- typepps = peer;
- if (peer->stratum == peer_list[0]->stratum && peer ==
- osys_peer)
+ if (peer == osys_peer)
typesystem = peer;
+#ifdef REFCLOCK
+ if (peer->refclktype == REFCLK_ATOM_PPS)
+ sys_pps = peer;
+#endif /* REFCLOCK */
+#if DEBUG
+ if (debug > 1)
+ printf("cluster: survivor %s metric %.6f\n",
+ ntoa(&peer_list[i]->srcadr), synch[i]);
+#endif
}
/*
- * 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.
+ * Anticlockhop provision. Keep the current system peer if it is
+ * a survivor but not first in the list. But do that only HOPPER
+ * times.
*/
- if (sys_survivors < sys_minclock && osurv >= sys_minclock)
- resetmanycast();
+ if (osys_peer == NULL || typesystem == NULL || typesystem ==
+ peer_list[0] || sys_hopper > sys_maxhop) {
+ typesystem = peer_list[0];
+ sys_hopper = 0;
+ } else {
+ peer->selbroken++;
+ }
/*
* Mitigation rules of the game. There are several types of
- * peers that make a difference here: (1) prefer local peers
- * (type REFCLK_LOCALCLOCK with FLAG_PREFER) or prefer modem
- * peers (type REFCLK_NIST_ATOM etc with FLAG_PREFER), (2) pps
- * peers (type REFCLK_ATOM_PPS), (3) remaining prefer peers
- * (flag FLAG_PREFER), (4) the existing system peer, if any, (5)
- * the head of the survivor list. Note that only one peer can be
- * declared prefer. The order of preference is in the order
- * stated. Note that all of these must be at the lowest stratum,
- * i.e., the stratum of the head of the survivor list.
- */
- if (sys_prefer)
- sw = sys_prefer->refclktype == REFCLK_LOCALCLOCK ||
- sys_prefer->sstclktype == CTL_SST_TS_TELEPHONE ||
- !typepps;
- else
- sw = 0;
- if (sw) {
- sys_peer = sys_prefer;
+ * peers that can be selected here: (1) orphan, (2) prefer peer
+ * (flag FLAG_PREFER) (3) pps peers (type REFCLK_ATOM_PPS), (4)
+ * the existing system peer, if any, and (5) the head of the
+ * survivor list.
+ */
+ if (typesystem->stratum >= sys_orphan) {
+
+ /*
+ * If in orphan mode, choose the system peer. If the
+ * lowest distance, we are the orphan parent and the
+ * offset is zero.
+ */
+ sys_peer = typesystem;
sys_peer->status = CTL_PST_SEL_SYSPEER;
- sys_offset = sys_peer->offset;
- sys_syserr = sys_peer->jitter;
+ if (sys_orphandelay < sys_peer->rootdelay) {
+ sys_offset = 0;
+ sys_refid = htonl(LOOPBACKADR);
+ } else {
+ sys_offset = sys_peer->offset;
+ sys_refid = addr2refid(&sys_peer->srcadr);
+ }
+ sys_jitter = LOGTOD(sys_precision);
#ifdef DEBUG
if (debug > 1)
- printf("select: prefer offset %.6f\n",
+ printf("select: orphan offset %.6f\n",
sys_offset);
#endif
- }
-#ifndef LOCKCLOCK
- else if (typepps) {
- sys_peer = typepps;
- sys_peer->status = CTL_PST_SEL_PPS;
- sys_offset = sys_peer->offset;
- sys_syserr = sys_peer->jitter;
- if (!pps_control)
- NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "pps sync enabled");
- pps_control = current_time;
+ } else if (sys_prefer) {
+
+ /*
+ * If a pps peer is present, choose it; otherwise,
+ * choose the prefer peer.
+ */
+ if (sys_pps) {
+ sys_peer = sys_pps;
+ sys_peer->status = CTL_PST_SEL_PPS;
+ sys_offset = sys_peer->offset;
+ if (!pps_control)
+ NLOG(NLOG_SYSEVENT)
+ msyslog(LOG_INFO,
+ "pps sync enabled");
+ pps_control = current_time;
#ifdef DEBUG
- if (debug > 1)
- printf("select: pps offset %.6f\n",
- sys_offset);
+ if (debug > 1)
+ printf("select: pps offset %.6f\n",
+ sys_offset);
#endif
- } else {
- if (typesystem)
- sys_peer = osys_peer;
+ } else {
+ sys_peer = sys_prefer;
+ sys_peer->status = CTL_PST_SEL_SYSPEER;
+ sys_offset = sys_peer->offset;
+#ifdef DEBUG
+ if (debug > 1)
+ printf("select: prefer offset %.6f\n",
+ sys_offset);
+#endif
+ }
+ if (sys_peer->stratum == STRATUM_REFCLOCK ||
+ sys_peer->stratum == STRATUM_UNSPEC)
+ sys_refid = sys_peer->refid;
else
- sys_peer = peer_list[0];
+ sys_refid = addr2refid(&sys_peer->srcadr);
+ sys_jitter = sys_peer->jitter;
+ } else {
+
+ /*
+ * Otherwise, choose the anticlockhopper.
+ */
+ sys_peer = typesystem;
sys_peer->status = CTL_PST_SEL_SYSPEER;
- sys_peer->rank++;
- sys_offset = clock_combine(peer_list, nlist);
- sys_syserr = sys_peer->jitter + sys_selerr;
+ clock_combine(peer_list, nlist);
+ if (sys_peer->stratum == STRATUM_REFCLOCK ||
+ sys_peer->stratum == STRATUM_UNSPEC)
+ sys_refid = sys_peer->refid;
+ else
+ sys_refid = addr2refid(&sys_peer->srcadr);
+ sys_jitter = SQRT(SQUARE(sys_peer->jitter) +
+ SQUARE(sys_jitter));
#ifdef DEBUG
if (debug > 1)
printf("select: combine offset %.6f\n",
sys_offset);
#endif
}
-#endif /* LOCKCLOCK */
+
+ /*
+ * We have found the alpha male.
+ */
+ sys_peer->flags |= FLAG_SYSPEER;
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))
+ if (sys_peer->flags & FLAG_REFCLOCK)
src = refnumtoa(&sys_peer->srcadr);
else
-#endif
+#endif /* REFCLOCK */
src = ntoa(&sys_peer->srcadr);
NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO, "synchronized to %s, stratum=%d", src,
- sys_peer->stratum);
+ msyslog(LOG_INFO, "synchronized to %s, stratum %d",
+ src, sys_peer->stratum);
}
clock_update();
}
+
/*
- * clock_combine - combine offsets from selected peers
+ * clock_combine - compute system offset and jitter from selected peers
*/
-static double
+static void
clock_combine(
- struct peer **peers,
- int npeers
+ struct peer **peers, /* survivor list */
+ int npeers /* number of survivors */
)
{
int i;
- double x, y, z;
+ double x, y, z, w;
- y = z = 0;
+ y = z = w = 0;
for (i = 0; i < npeers; i++) {
x = root_distance(peers[i]);
y += 1. / x;
z += peers[i]->offset / x;
+ w += SQUARE(peers[i]->offset - peers[0]->offset) / x;
}
- return (z / y);
+ sys_offset = z / y;
+ sys_jitter = SQRT(w / y);
}
/*
@@ -2299,14 +2346,22 @@ root_distance(
struct peer *peer
)
{
+ double dist;
+
/*
* Careful squeak here. The value returned must be greater than
- * zero blamed on the peer jitter, which must be at least the
- * square of sys_precision.
+ * the minimum root dispersion in order to avoid clockhop with
+ * highly precise reference clocks. In orphan mode lose the peer
+ * root delay, as that is used by the election algorithm.
*/
- return ((peer->rootdelay + peer->delay) / 2 +
+ if (peer->stratum >= sys_orphan)
+ dist = 0;
+ else
+ dist = peer->rootdelay;
+ dist += max(sys_mindisp, dist + peer->delay) / 2 +
peer->rootdispersion + peer->disp + clock_phi *
- (current_time - peer->update) + SQRT(peer->jitter));
+ (current_time - peer->update) + peer->jitter;
+ return (dist);
}
/*
@@ -2319,20 +2374,62 @@ peer_xmit(
{
struct pkt xpkt; /* transmit packet */
int sendlen, authlen;
- keyid_t xkeyid = 0; /* transmit key ID */
+ keyid_t xkeyid = 0; /* transmit key ID */
l_fp xmt_tx;
+ if (!peer->dstadr) /* don't bother with peers without interface */
+ return;
+
+ /*
+ * This is deliciously complicated. There are three cases.
+ *
+ * case leap stratum refid delay dispersion
+ *
+ * normal system system system system system
+ * orphan child 00 orphan system orphan system
+ * orphan parent 00 orphan loopbk 0 0
+ */
/*
- * Initialize transmit packet header fields.
+ * This is a normal packet. Use the system variables.
*/
- xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, peer->version,
- peer->hmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
+ if (sys_stratum < sys_orphan) {
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
+ peer->version, peer->hmode);
+ xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
+ xpkt.refid = sys_refid;
+ xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
+ xpkt.rootdispersion =
+ HTONS_FP(DTOUFP(sys_rootdispersion));
+
+ /*
+ * This is a orphan child packet. The host is synchronized to an
+ * orphan parent. Show leap synchronized, orphan stratum, system
+ * reference ID, orphan root delay and system root dispersion.
+ */
+ } else if (sys_peer != NULL) {
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
+ peer->version, peer->hmode);
+ xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
+ xpkt.refid = htonl(LOOPBACKADR);
+ xpkt.rootdelay = HTONS_FP(DTOFP(sys_orphandelay));
+ xpkt.rootdispersion =
+ HTONS_FP(DTOUFP(sys_rootdispersion));
+
+ /*
+ * This is an orphan parent. Show leap synchronized, orphan
+ * stratum, loopack reference ID and zero root delay and root
+ * dispersion.
+ */
+ } else {
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
+ peer->version, peer->hmode);
+ xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
+ xpkt.refid = sys_refid;
+ xpkt.rootdelay = 0;
+ xpkt.rootdispersion = 0;
+ }
xpkt.ppoll = peer->hpoll;
xpkt.precision = sys_precision;
- xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion));
- xpkt.refid = sys_refid;
HTONL_FP(&sys_reftime, &xpkt.reftime);
HTONL_FP(&peer->org, &xpkt.org);
HTONL_FP(&peer->rec, &xpkt.rec);
@@ -2342,23 +2439,25 @@ peer_xmit(
* is authenticated and contains a MAC. If not, the transmitted
* packet is not authenticated.
*
- * In the current I/O semantics the default interface is set
- * until after receiving a packet and setting the right
- * interface. So, the first packet goes out unauthenticated.
- * That's why the really icky test next is here.
+ * It is most important when autokey is in use that the local
+ * interface IP address be known before the first packet is
+ * sent. Otherwise, it is not possible to compute a correct MAC
+ * the recipient will accept. Thus, the I/O semantics have to do
+ * a little more work. In particular, the wildcard interface
+ * might not be usable.
*/
sendlen = LEN_PKT_NOMAC;
if (!(peer->flags & FLAG_AUTHENABLE)) {
get_systime(&peer->xmt);
HTONL_FP(&peer->xmt, &xpkt.xmt);
sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl],
- &xpkt, sendlen);
+ &xpkt, sendlen);
peer->sent++;
#ifdef DEBUG
if (debug)
printf("transmit: at %ld %s->%s mode %d\n",
- current_time, stoa(&peer->dstadr->sin),
- stoa(&peer->srcadr), peer->hmode);
+ current_time, peer->dstadr ? stoa(&peer->dstadr->sin) : "-",
+ stoa(&peer->srcadr), peer->hmode);
#endif
return;
}
@@ -2366,12 +2465,11 @@ peer_xmit(
/*
* The received packet contains a MAC, so the transmitted packet
* must be authenticated. If autokey is enabled, fuss with the
- * various modes; otherwise, private key cryptography is used.
+ * various modes; otherwise, symmetric key cryptography is used.
*/
#ifdef OPENSSL
if (crypto_flags && (peer->flags & FLAG_SKEY)) {
struct exten *exten; /* extension field */
- u_int opcode;
/*
* The Public Key Dance (PKD): Cryptographic credentials
@@ -2428,25 +2526,23 @@ peer_xmit(
key_expire(peer);
}
peer->keyid = xkeyid;
+ exten = NULL;
switch (peer->hmode) {
- /*
- * In broadcast server mode the autokey values are
- * required by the broadcast clients. Push them when a
- * new keylist is generated; otherwise, push the
- * association message so the client can request them at
- * other times.
- */
+ /*
+ * In broadcast server mode the autokey values are
+ * required by the broadcast clients. Push them when a
+ * new keylist is generated; otherwise, push the
+ * association message so the client can request them at
+ * other times.
+ */
case MODE_BROADCAST:
if (peer->flags & FLAG_ASSOC)
exten = crypto_args(peer, CRYPTO_AUTO |
- CRYPTO_RESP, NULL);
+ CRYPTO_RESP, NULL);
else
exten = crypto_args(peer, CRYPTO_ASSOC |
- CRYPTO_RESP, NULL);
- sendlen += crypto_xmit(&xpkt, &peer->srcadr,
- sendlen, exten, 0);
- free(exten);
+ CRYPTO_RESP, NULL);
break;
/*
@@ -2457,25 +2553,22 @@ peer_xmit(
* synchronized, so the agreement must be postponed
* until then. In any case, if a new keylist is
* generated, the autokey values are pushed.
+ *
+ * If the crypto bit is lit, don't send requests.
*/
case MODE_ACTIVE:
case MODE_PASSIVE:
- if (peer->cmmd != NULL) {
- peer->cmmd->associd =
- htonl(peer->associd);
- sendlen += crypto_xmit(&xpkt,
- &peer->srcadr, sendlen, peer->cmmd,
- 0);
- free(peer->cmmd);
- peer->cmmd = NULL;
- }
- exten = NULL;
+ if (peer->flash & TEST9)
+ break;
+ /*
+ * Parameter and certificate.
+ */
if (!peer->crypto)
exten = crypto_args(peer, CRYPTO_ASSOC,
- sys_hostname);
+ sys_hostname);
else if (!(peer->crypto & CRYPTO_FLAG_VALID))
exten = crypto_args(peer, CRYPTO_CERT,
- peer->issuer);
+ peer->issuer);
/*
* Identity. Note we have to sign the
@@ -2483,12 +2576,13 @@ peer_xmit(
* 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 (!(peer->crypto & CRYPTO_FLAG_VRFY))
+ exten = crypto_args(peer,
+ crypto_ident(peer), NULL);
else if (sys_leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_SIGN))
+ !(peer->crypto & CRYPTO_FLAG_SIGN))
exten = crypto_args(peer, CRYPTO_SIGN,
- sys_hostname);
+ sys_hostname);
/*
* Autokey. We request the cookie only when the
@@ -2501,32 +2595,27 @@ peer_xmit(
* the autokey values without being asked.
*/
else if (sys_leap != LEAP_NOTINSYNC &&
- peer->leap != LEAP_NOTINSYNC &&
- !(peer->crypto & CRYPTO_FLAG_AGREE))
+ peer->leap != LEAP_NOTINSYNC &&
+ !(peer->crypto & CRYPTO_FLAG_AGREE))
exten = crypto_args(peer, CRYPTO_COOK,
- NULL);
+ NULL);
else if (peer->flags & FLAG_ASSOC)
exten = crypto_args(peer, CRYPTO_AUTO |
- CRYPTO_RESP, NULL);
+ CRYPTO_RESP, NULL);
else if (!(peer->crypto & CRYPTO_FLAG_AUTO))
exten = crypto_args(peer, CRYPTO_AUTO,
- NULL);
+ 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))
+ 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);
- }
+ NULL);
break;
/*
@@ -2546,85 +2635,117 @@ peer_xmit(
* 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.
+ *
+ * If the crypto bit is lit, don't send requests.
*/
case MODE_CLIENT:
- if (peer->cmmd != NULL) {
- peer->cmmd->associd =
- htonl(peer->associd);
- sendlen += crypto_xmit(&xpkt,
- &peer->srcadr, sendlen, peer->cmmd,
- 0);
- free(peer->cmmd);
- peer->cmmd = NULL;
- }
- exten = NULL;
+ if (peer->flash & TEST9)
+ break;
+ /*
+ * Parameter and certificate.
+ */
if (!peer->crypto)
exten = crypto_args(peer, CRYPTO_ASSOC,
- sys_hostname);
+ sys_hostname);
else if (!(peer->crypto & CRYPTO_FLAG_VALID))
exten = crypto_args(peer, CRYPTO_CERT,
- peer->issuer);
+ peer->issuer);
/*
- * Identity.
+ * Identity
*/
- else if ((opcode = crypto_ident(peer)) != 0)
- exten = crypto_args(peer, opcode, NULL);
+ else if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+ exten = crypto_args(peer,
+ crypto_ident(peer), NULL);
/*
* Autokey
*/
else if (!(peer->crypto & CRYPTO_FLAG_AGREE))
exten = crypto_args(peer, CRYPTO_COOK,
- NULL);
+ NULL);
else if (!(peer->crypto & CRYPTO_FLAG_AUTO) &&
- (peer->cast_flags & MDF_BCLNT))
+ (peer->cast_flags & MDF_BCLNT))
exten = crypto_args(peer, CRYPTO_AUTO,
- NULL);
+ 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))
+ !(peer->crypto & CRYPTO_FLAG_SIGN))
exten = crypto_args(peer, CRYPTO_SIGN,
- sys_hostname);
+ sys_hostname);
else if (sys_leap != LEAP_NOTINSYNC &&
- peer->crypto & CRYPTO_FLAG_TAI &&
- !(peer->crypto & CRYPTO_FLAG_LEAP))
+ 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);
- }
+ NULL);
break;
}
/*
+ * Build the extension fields as directed. A response to
+ * a request is always sent, even if an error. If an
+ * error occurs when sending a request, the crypto
+ * machinery broke or was misconfigured. In that case
+ * light the crypto bit to suppress further requests.
+ */
+ 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;
+ }
+ if (exten != NULL) {
+ int ltemp = 0;
+
+ if (exten->opcode != 0) {
+ ltemp = crypto_xmit(&xpkt,
+ &peer->srcadr, sendlen, exten, 0);
+ if (ltemp == 0) {
+ peer->flash |= TEST9; /* crypto error */
+ free(exten);
+ return;
+ }
+ }
+ sendlen += ltemp;
+ free(exten);
+ }
+
+ /*
* If extension fields are present, we must use a
- * private value of zero and force min poll interval.
- * Most intricate.
+ * private cookie value of zero. Don't send if the
+ * crypto bit is set and no extension field is present,
+ * but in that case give back the key. Most intricate.
*/
- if (sendlen > LEN_PKT_NOMAC)
+ if (sendlen > LEN_PKT_NOMAC) {
session_key(&peer->dstadr->sin, &peer->srcadr,
xkeyid, 0, 2);
+ } else if (peer->flash & TEST9) {
+ authtrust(xkeyid, 0);
+ return;
+ }
}
#endif /* OPENSSL */
+
+ /*
+ * Stash the transmit timestamp corrected for the encryption
+ * delay. If autokey, give back the key, as we use keys only
+ * once. Check for errors such as missing keys, buffer overflow,
+ * etc.
+ */
xkeyid = peer->keyid;
get_systime(&peer->xmt);
L_ADD(&peer->xmt, &sys_authdelay);
HTONL_FP(&peer->xmt, &xpkt.xmt);
authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
if (authlen == 0) {
- msyslog(LOG_INFO,
- "transmit: encryption key %d not found", xkeyid);
- if (peer->flags & FLAG_CONFIG)
- peer_clear(peer, "NKEY");
- else
- unpeer(peer);
+ msyslog(LOG_INFO, "transmit: %s key %u not found",
+ stoa(&peer->srcadr), xkeyid);
+ peer->flash |= TEST9; /* no key found */
return;
}
sendlen += authlen;
@@ -2638,7 +2759,7 @@ peer_xmit(
exit (-1);
}
sendpkt(&peer->srcadr, peer->dstadr, sys_ttl[peer->ttl], &xpkt,
- sendlen);
+ sendlen);
/*
* Calculate the encryption delay. Keep the minimum over
@@ -2657,19 +2778,19 @@ peer_xmit(
#ifdef DEBUG
if (debug)
printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d index %d\n",
- current_time, ntoa(&peer->dstadr->sin),
- ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
- authlen, authlen, peer->keynumber);
+ "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d index %d\n",
+ current_time, peer->dstadr ? ntoa(&peer->dstadr->sin) : "-",
+ ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
+ authlen, authlen, peer->keynumber);
#endif
#else
#ifdef DEBUG
if (debug)
printf(
- "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
- current_time, ntoa(&peer->dstadr->sin),
- ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
- authlen, authlen);
+ "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
+ current_time, peer->dstadr ? ntoa(&peer->dstadr->sin) : "-",
+ ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen -
+ authlen, authlen);
#endif
#endif /* OPENSSL */
}
@@ -2699,54 +2820,91 @@ fast_xmit(
/*
* Initialize transmit packet header fields from the receive
* buffer provided. We leave some fields intact as received. If
- * the gazinta was from a multicast address, the gazouta must go
- * out another way.
+ * the gazinta was from a multicast address, the gazoutta must
+ * go out another way.
+ *
+ * The root delay field is special. If the system stratum is
+ * less than the orphan stratum, send the real root delay.
+ * Otherwise, if there is no system peer, send the orphan delay.
+ * Otherwise, we must be an orphan parent, so send zero.
*/
rpkt = &rbufp->recv_pkt;
- if (rbufp->dstadr->flags & INT_MULTICAST)
+ if (rbufp->dstadr->flags & INT_MCASTOPEN)
rbufp->dstadr = findinterface(&rbufp->recv_srcadr);
/*
- * If the packet has picked up a restriction due to either
- * access denied or rate exceeded, decide what to do with it.
+ * This is deliciously complicated. There are four cases.
+ *
+ * case leap stratum refid delay dispersion
+ *
+ * KoD 11 16 KISS system system
+ * normal system system system system system
+ * orphan child 00 orphan system orphan system
+ * orphan parent 00 orphan loopbk 0 0
*/
- 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.
- */
+ /*
+ * This is a kiss-of-death (KoD) packet. Show leap
+ * unsynchronized, stratum zero, reference ID the four-character
+ * kiss code and system root delay. 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 kiss.
+ */
+ if (mask & RES_LIMITED) {
+ sys_limitrejected++;
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 {
+ memcpy(&xpkt.refid, "RATE", 4);
+ xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
+ xpkt.rootdispersion =
+ HTONS_FP(DTOUFP(sys_rootdispersion));
+
+ /*
+ * This is a normal packet. Use the system variables.
+ */
+ } else if (sys_stratum < sys_orphan) {
xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
PKT_VERSION(rpkt->li_vn_mode), xmode);
xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
xpkt.refid = sys_refid;
+ xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
+ xpkt.rootdispersion =
+ HTONS_FP(DTOUFP(sys_rootdispersion));
+
+ /*
+ * This is a orphan child packet. The host is synchronized to an
+ * orphan parent. Show leap synchronized, orphan stratum, system
+ * reference ID and orphan root delay.
+ */
+ } else if (sys_peer != NULL) {
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
+ PKT_VERSION(rpkt->li_vn_mode), xmode);
+ xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
+ xpkt.refid = sys_refid;
+ xpkt.rootdelay = HTONS_FP(DTOFP(sys_orphandelay));
+ xpkt.rootdispersion =
+ HTONS_FP(DTOUFP(sys_rootdispersion));
+
+ /*
+ * This is an orphan parent. Show leap synchronized, orphan
+ * stratum, loopack reference ID and zero root delay.
+ */
+ } else {
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(LEAP_NOWARNING,
+ PKT_VERSION(rpkt->li_vn_mode), xmode);
+ xpkt.stratum = STRATUM_TO_PKT(sys_orphan);
+ xpkt.refid = htonl(LOOPBACKADR);
+ xpkt.rootdelay = HTONS_FP(DTOFP(0));
+ xpkt.rootdispersion = HTONS_FP(DTOFP(0));
}
xpkt.ppoll = rpkt->ppoll;
xpkt.precision = sys_precision;
- xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion =
- HTONS_FP(DTOUFP(sys_rootdispersion));
+ xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion));
HTONL_FP(&sys_reftime, &xpkt.reftime);
xpkt.org = rpkt->xmt;
HTONL_FP(&rbufp->recv_time, &xpkt.rec);
@@ -2773,11 +2931,11 @@ fast_xmit(
/*
* The received packet contains a MAC, so the transmitted packet
- * must be authenticated. For private-key cryptography, use the
- * predefined private keys to generate the cryptosum. For
- * autokey cryptography, use the server private value to
- * generate the cookie, which is unique for every source-
- * destination-key ID combination.
+ * must be authenticated. For symmetric key cryptography, use
+ * the predefined and trusted symmetric keys to generate the
+ * cryptosum. For autokey cryptography, use the server private
+ * value to generate the cookie, which is unique for every
+ * source-destination-key ID combination.
*/
#ifdef OPENSSL
if (xkeyid > NTP_MAXKEY) {
@@ -2794,8 +2952,8 @@ fast_xmit(
*/
cookie = session_key(&rbufp->recv_srcadr,
&rbufp->dstadr->sin, 0, sys_private, 0);
- if (rbufp->recv_length >= (int)(sendlen + MAX_MAC_LEN + 2 *
- sizeof(u_int32))) {
+ if (rbufp->recv_length >= (int)(sendlen + MAX_MAC_LEN +
+ 2 * sizeof(u_int32))) {
session_key(&rbufp->dstadr->sin,
&rbufp->recv_srcadr, xkeyid, 0, 2);
temp32 = CRYPTO_RESP;
@@ -2879,23 +3037,60 @@ key_expire(
* 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
+ * > TEST10 bad leap or stratum below floor or at or above ceiling
+ * > TEST11 root distance exceeded
+ * > TEST12 a direct or indirect synchronization loop would form
+ * > TEST13 unreachable or noselect
*/
-static int /* 0 if no, 1 if yes */
+int /* FALSE if fit, TRUE if unfit */
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 );
+ int rval = 0;
+
+ /*
+ * A stratum error occurs if (1) the server has never been
+ * synchronized, (2) the server stratum is below the floor or
+ * greater than or equal to the ceiling, (3) the system stratum
+ * is below the orphan stratum and the server stratum is greater
+ * than or equal to the orphan stratum.
+ */
+ if (peer->leap == LEAP_NOTINSYNC || peer->stratum < sys_floor ||
+ peer->stratum >= sys_ceiling || (sys_stratum < sys_orphan &&
+ peer->stratum >= sys_orphan))
+ rval |= TEST10; /* stratum out of bounds */
+
+ /*
+ * A distance error occurs if the root distance is greater than
+ * or equal to the distance threshold plus the increment due to
+ * one poll interval.
+ */
+ if (root_distance(peer) >= sys_maxdist + clock_phi *
+ ULOGTOD(sys_poll))
+ rval |= TEST11; /* distance exceeded */
+
+ /*
+ * A loop error occurs if the remote peer is synchronized to the
+ * local peer of if the remote peer is synchronized to the same
+ * server as the local peer, but only if the remote peer is not
+ * the orphan parent.
+ */
+ if (peer->stratum > 1 && peer->refid != htonl(LOOPBACKADR) &&
+ ((!peer->dstadr || peer->refid == peer->dstadr->addr_refid) ||
+ peer->refid == sys_refid))
+ rval |= TEST12; /* synch loop */
+
+ /*
+ * An unreachable error occurs if the server is unreachable or
+ * the noselect bit is set.
+ */
+ if (!peer->reach || peer->flags & FLAG_NOSELECT)
+ rval |= TEST13; /* unreachable */
+
+ peer->flash &= ~PEER_TEST_MASK;
+ peer->flash |= rval;
+ return (rval);
}
@@ -2908,7 +3103,7 @@ peer_unfit(
/*
* This routine calculates the system precision, defined as the minimum
- * of a sequency of differences between successive readings of the
+ * of a sequence 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.
@@ -2992,6 +3187,8 @@ init_proto(void)
sys_precision = (s_char)default_get_precision();
sys_jitter = LOGTOD(sys_precision);
sys_rootdelay = 0;
+ sys_orphandelay = (double)(ntp_random() & 0xffff) / 65536. *
+ sys_maxdist;
sys_rootdispersion = 0;
L_CLR(&sys_reftime);
sys_peer = NULL;
@@ -3074,14 +3271,21 @@ proto_config(
break;
/*
- * Turn on/off facility to listen to broadcasts.
+ * Turn on/off enable broadcasts.
*/
case PROTO_BROADCLIENT:
sys_bclient = (int)value;
- if (value)
- io_setbclient();
- else
+ if (sys_bclient == 0)
io_unsetbclient();
+ else
+ io_setbclient();
+ break;
+
+ /*
+ * Turn on/off PPS discipline.
+ */
+ case PROTO_PPS:
+ pps_enable = (int)value;
break;
/*
@@ -3090,6 +3294,7 @@ proto_config(
case PROTO_MULTICAST_ADD:
if (svalue)
io_multicast_add(*svalue);
+ sys_bclient = 1;
break;
/*
@@ -3115,60 +3320,97 @@ proto_config(
break;
/*
- * Require authentication to mobilize ephemeral associations.
+ * Turn on/off authentication to mobilize ephemeral
+ * associations.
*/
case PROTO_AUTHENTICATE:
sys_authenticate = (int)value;
break;
/*
- * Turn on/off PPS discipline.
+ * Set minimum number of survivors.
*/
- case PROTO_PPS:
- pps_enable = (int)value;
+ case PROTO_MINCLOCK:
+ sys_minclock = (int)dvalue;
break;
/*
- * Set the minimum number of survivors.
+ * Set maximum number of preemptable associations.
*/
- case PROTO_MINCLOCK:
- sys_minclock = (int)dvalue;
+ case PROTO_MAXCLOCK:
+ sys_maxclock = (int)dvalue;
break;
/*
- * Set the minimum number of candidates.
+ * Set minimum number of survivors.
*/
case PROTO_MINSANE:
sys_minsane = (int)dvalue;
break;
/*
- * Set the stratum floor.
+ * Set stratum floor.
*/
case PROTO_FLOOR:
sys_floor = (int)dvalue;
break;
/*
- * Set the stratum ceiling.
+ * Set stratum ceiling.
*/
case PROTO_CEILING:
sys_ceiling = (int)dvalue;
break;
/*
- * Set the cohort switch.
+ * Set orphan stratum.
+ */
+ case PROTO_ORPHAN:
+ sys_orphan = (int)dvalue;
+ break;
+
+ /*
+ * Set cohort switch.
*/
case PROTO_COHORT:
- sys_cohort= (int)dvalue;
+ sys_cohort = (int)dvalue;
+ break;
+
+ /*
+ * Set minimum dispersion increment.
+ */
+ case PROTO_MINDISP:
+ sys_mindisp = dvalue;
break;
+
/*
- * Set the adjtime() resolution (s).
+ * Set maximum distance (select threshold).
+ */
+ case PROTO_MAXDIST:
+ sys_maxdist = dvalue;
+ break;
+
+ /*
+ * Set anticlockhop threshold.
+ */
+ case PROTO_MAXHOP:
+ sys_maxhop = (int)dvalue;
+ break;
+
+ /*
+ * Set adjtime() resolution (s).
*/
case PROTO_ADJ:
sys_tick = dvalue;
break;
+ /*
+ * Set manycast beacon interval.
+ */
+ case PROTO_BEACON:
+ sys_beacon = (int)dvalue;
+ break;
+
#ifdef REFCLOCK
/*
* Turn on/off refclock calibrate
@@ -3176,15 +3418,15 @@ proto_config(
case PROTO_CAL:
cal_enable = (int)value;
break;
-#endif
+#endif /* REFCLOCK */
default:
/*
* Log this error.
*/
msyslog(LOG_INFO,
- "proto_config: illegal item %d, value %ld",
- item, value);
+ "proto_config: illegal item %d, value %ld", item,
+ value);
}
}
diff --git a/contrib/ntp/ntpd/ntp_refclock.c b/contrib/ntp/ntpd/ntp_refclock.c
index 172fbda..a29ef08 100644
--- a/contrib/ntp/ntpd/ntp_refclock.c
+++ b/contrib/ntp/ntpd/ntp_refclock.c
@@ -30,10 +30,6 @@
# endif
#endif /* TTYCLK */
-#ifdef HAVE_PPSCLOCK_H
-#include <sys/ppsclock.h>
-#endif /* HAVE_PPSCLOCK_H */
-
#ifdef KERNEL_PLL
#include "ntp_syscall.h"
#endif /* KERNEL_PLL */
@@ -63,18 +59,21 @@
* which is used for all peer-specific processing and contains a pointer
* to the refclockproc structure, which in turn containes a pointer to
* the unit structure, if used. The peer structure is identified by an
- * interface address in the dotted quad form 127.127.t.u (for now only IPv4
- * addresses are used, so we need to be sure the address is it), where t is
- * the clock type and u the unit. Some legacy drivers derive the
- * refclockproc structure pointer from the table typeunit[type][unit].
- * This interface is strongly discouraged and may be abandoned in
- * future.
+ * interface address in the dotted quad form 127.127.t.u (for now only
+ * IPv4 addresses are used, so we need to be sure the address is it),
+ * where t is the clock type and u the unit. Some legacy drivers derive
+ * the refclockproc structure pointer from the table
+ * typeunit[type][unit]. This interface is strongly discouraged and may
+ * be abandoned in future.
*/
#define MAXUNIT 4 /* max units */
#define FUDGEFAC .1 /* fudge correction factor */
+#define LF 0x0a /* ASCII LF */
-int fdpps; /* pps file descriptor */
-int cal_enable; /* enable refclock calibrate */
+#ifdef PPS
+int fdpps; /* ppsclock legacy */
+#endif /* PPS */
+int cal_enable; /* enable refclock calibrate */
/*
* Type/unit peer index. Used to find the peer structure for control and
@@ -93,6 +92,7 @@ static int refclock_cmpl_fp P((const double *, const double *));
#endif /* QSORT_USES_VOID_P */
static int refclock_sample P((struct refclockproc *));
+
/*
* refclock_report - note the occurance of an event
*
@@ -111,37 +111,60 @@ refclock_report(
pp = peer->procptr;
if (pp == NULL)
return;
- if (code == CEVNT_BADREPLY)
- pp->badformat++;
- if (code == CEVNT_BADTIME)
- pp->baddata++;
- if (code == CEVNT_TIMEOUT)
- pp->noreply++;
+
+ switch (code) {
+ case CEVNT_NOMINAL:
+ break;
+
+ case CEVNT_TIMEOUT:
+ pp->noreply++;
+ break;
+
+ case CEVNT_BADREPLY:
+ pp->badformat++;
+ break;
+
+ case CEVNT_FAULT:
+ break;
+
+ case CEVNT_PROP:
+ break;
+
+ case CEVNT_BADDATE:
+ case CEVNT_BADTIME:
+ pp->baddata++;
+ break;
+
+ default:
+ /* shouldn't happen */
+ break;
+ }
+
if (pp->currentstatus != code) {
pp->currentstatus = (u_char)code;
- pp->lastevent = (u_char)code;
+
+ /* RFC1305: copy only iff not CEVNT_NOMINAL */
+ if (code != CEVNT_NOMINAL)
+ pp->lastevent = (u_char)code;
+
if (code == CEVNT_FAULT)
msyslog(LOG_ERR,
- "clock %s event '%s' (0x%02x)",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
+ "clock %s event '%s' (0x%02x)",
+ refnumtoa(&peer->srcadr),
+ ceventstr(code), code);
else {
NLOG(NLOG_CLOCKEVENT)
- msyslog(LOG_INFO,
- "clock %s event '%s' (0x%02x)",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
+ msyslog(LOG_INFO,
+ "clock %s event '%s' (0x%02x)",
+ refnumtoa(&peer->srcadr),
+ ceventstr(code), code);
}
+
+ /* RFC1305: post peer clock event */
+ report_event(EVNT_PEERCLOCK, peer);
}
-#ifdef DEBUG
- if (debug)
- printf("clock %s event '%s' (0x%02x)\n",
- refnumtoa(&peer->srcadr),
- ceventstr(code), code);
-#endif
}
-
/*
* init_refclock - initialize the reference clock drivers
*
@@ -216,6 +239,7 @@ refclock_newpeer(
pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc));
if (pp == NULL)
return (0);
+
memset((char *)pp, 0, sizeof(struct refclockproc));
typeunit[clktype][unit] = peer;
peer->procptr = pp;
@@ -225,9 +249,10 @@ refclock_newpeer(
*/
peer->refclktype = clktype;
peer->refclkunit = (u_char)unit;
- peer->flags |= FLAG_REFCLOCK;
- peer->maxpoll = peer->minpoll;
+ peer->flags |= FLAG_REFCLOCK | FLAG_FIXPOLL;
+ peer->leap = LEAP_NOTINSYNC;
peer->stratum = STRATUM_REFCLOCK;
+ peer->ppoll = peer->maxpoll;
pp->type = clktype;
pp->timestarted = current_time;
@@ -252,8 +277,6 @@ refclock_newpeer(
refclock_unpeer(peer);
return (0);
}
- peer->hpoll = peer->minpoll;
- peer->ppoll = peer->maxpoll;
peer->refid = pp->refid;
return (1);
}
@@ -276,6 +299,7 @@ refclock_unpeer(
*/
if (!peer->procptr)
return;
+
clktype = peer->refclktype;
unit = peer->refclkunit;
if (refclock_conf[clktype]->clock_shutdown != noentry)
@@ -286,6 +310,24 @@ refclock_unpeer(
/*
+ * refclock_timer - called once per second for housekeeping.
+ */
+void
+refclock_timer(
+ struct peer *peer /* peer structure pointer */
+ )
+{
+ u_char clktype;
+ int unit;
+
+ clktype = peer->refclktype;
+ unit = peer->refclkunit;
+ if (refclock_conf[clktype]->clock_timer != noentry)
+ (refclock_conf[clktype]->clock_timer)(unit, peer);
+}
+
+
+/*
* refclock_transmit - simulate the transmit procedure
*
* This routine implements the NTP transmit procedure for a reference
@@ -300,18 +342,17 @@ refclock_transmit(
{
u_char clktype;
int unit;
- u_long next;
clktype = peer->refclktype;
unit = peer->refclkunit;
peer->sent++;
+ get_systime(&peer->xmt);
/*
* This is a ripoff of the peer transmit routine, but
* specialized for reference clocks. We do a little less
* protocol here and call the driver-specific transmit routine.
*/
- next = peer->outdate;
if (peer->burst == 0) {
u_char oreach;
#ifdef DEBUG
@@ -326,29 +367,26 @@ refclock_transmit(
*/
oreach = peer->reach;
peer->reach <<= 1;
+ peer->outdate = current_time;
if (!peer->reach) {
if (oreach) {
report_event(EVNT_UNREACH, peer);
peer->timereachable = current_time;
- peer_clear(peer, "NONE");
}
} else {
- if (!(oreach & 0x03)) {
+ if (!(oreach & 0x07)) {
clock_filter(peer, 0., 0., MAXDISPERSE);
clock_select();
}
if (peer->flags & FLAG_BURST)
peer->burst = NSTAGE;
}
- next = current_time;
+ } else {
+ peer->burst--;
}
- get_systime(&peer->xmt);
if (refclock_conf[clktype]->clock_poll != noentry)
(refclock_conf[clktype]->clock_poll)(unit, peer);
- peer->outdate = next;
- if (peer->burst > 0)
- peer->burst--;
- poll_update(peer, 0);
+ poll_update(peer, peer->hpoll);
}
@@ -367,10 +405,13 @@ refclock_cmpl_fp(
if (*dp1 < *dp2)
return (-1);
+
if (*dp1 > *dp2)
return (1);
+
return (0);
}
+
#else
static int
refclock_cmpl_fp(
@@ -380,8 +421,10 @@ refclock_cmpl_fp(
{
if (*dp1 < *dp2)
return (-1);
+
if (*dp1 > *dp2)
return (1);
+
return (0);
}
#endif /* QSORT_USES_VOID_P */
@@ -412,6 +455,7 @@ refclock_process_offset(
SAMPLE(doffset + fudge);
}
+
/*
* refclock_process - process a sample from the clock
*
@@ -420,7 +464,13 @@ refclock_process_offset(
* then constructs a new entry in the median filter circular buffer.
* Return success (1) if the data are correct and consistent with the
* converntional calendar.
-*/
+ *
+ * Important for PPS users: Normally, the pp->lastrec is set to the
+ * system time when the on-time character is received and the pp->year,
+ * ..., pp->second decoded and the seconds fraction pp->nsec in
+ * nanoseconds). When a PPS offset is available, pp->nsec is forced to
+ * zero and the fraction for pp->lastrec is set to the PPS offset.
+ */
int
refclock_process(
struct refclockproc *pp /* refclock structure pointer */
@@ -439,6 +489,7 @@ refclock_process(
if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui))
return (0);
+
offset.l_uf = 0;
DTOLFP(pp->nsec / 1e9, &ltemp);
L_ADD(&offset, &ltemp);
@@ -447,12 +498,13 @@ refclock_process(
return (1);
}
+
/*
* refclock_sample - process a pile of samples from the clock
*
* This routine implements a recursive median filter to suppress spikes
* in the data, as well as determine a performance statistic. It
- * calculates the mean offset and jitter (squares). A time adjustment
+ * calculates the mean offset and RMS jitter. A time adjustment
* fudgetime1 can be added to the final offset to compensate for various
* systematic errors. The routine returns the number of samples
* processed, which could be zero.
@@ -462,9 +514,9 @@ refclock_sample(
struct refclockproc *pp /* refclock structure pointer */
)
{
- int i, j, k, m, n;
- double offset;
- double off[MAXSTAGE];
+ int i, j, k, m, n;
+ double off[MAXSTAGE];
+ double offset;
/*
* Copy the raw offsets and sort into ascending order. Don't do
@@ -478,15 +530,22 @@ refclock_sample(
}
if (n == 0)
return (0);
+
if (n > 1)
- qsort((char *)off, (size_t)n, sizeof(double), refclock_cmpl_fp);
+ qsort(
+#ifdef QSORT_USES_VOID_P
+ (void *)
+#else
+ (char *)
+#endif
+ off, (size_t)n, sizeof(double), refclock_cmpl_fp);
/*
* Reject the furthest from the median of the samples until
* approximately 60 percent of the samples remain.
*/
i = 0; j = n;
- m = n - (n * 2) / NSTAGE;
+ m = n - (n * 4) / 10;
while ((j - i) > m) {
offset = off[(j + i) / 2];
if (off[j - 1] - offset < offset - off[i])
@@ -498,19 +557,20 @@ refclock_sample(
/*
* Determine the offset and jitter.
*/
- offset = 0;
- for (k = i; k < j; k++)
- offset += off[k];
- pp->offset = offset / m;
- if (m > 1)
- pp->jitter = SQUARE(off[i] - off[j - 1]);
- else
- pp->jitter = 0;
+ pp->offset = 0;
+ pp->jitter = 0;
+ for (k = i; k < j; k++) {
+ pp->offset += off[k];
+ if (k > i)
+ pp->jitter += SQUARE(off[k] - off[k - 1]);
+ }
+ pp->offset /= m;
+ pp->jitter = max(SQRT(pp->jitter / m), LOGTOD(sys_precision));
#ifdef DEBUG
if (debug)
printf(
"refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n",
- n, pp->offset, pp->disp, SQRT(pp->jitter));
+ n, pp->offset, pp->disp, pp->jitter);
#endif
return (n);
}
@@ -543,17 +603,17 @@ refclock_receive(
* the median filter samples and give the data to the clock
* filter.
*/
- peer->received++;
pp = peer->procptr;
- peer->processed++;
- peer->timereceived = current_time;
peer->leap = pp->leap;
- if (peer->leap == LEAP_NOTINSYNC) {
- refclock_report(peer, CEVNT_FAULT);
+ if (peer->leap == LEAP_NOTINSYNC)
return;
- }
- if (!peer->reach)
+
+ peer->received++;
+ peer->timereceived = current_time;
+ if (!peer->reach) {
report_event(EVNT_REACH, peer);
+ peer->timereachable = current_time;
+ }
peer->reach |= 1;
peer->reftime = pp->lastref;
peer->org = pp->lastrec;
@@ -561,11 +621,11 @@ refclock_receive(
get_systime(&peer->rec);
if (!refclock_sample(pp))
return;
+
clock_filter(peer, pp->offset, 0., pp->jitter);
- clock_select();
record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
peer->offset, peer->delay, clock_phi * (current_time -
- peer->epoch), SQRT(peer->jitter));
+ peer->epoch), peer->jitter);
if (cal_enable && last_offset < MINDISPERSE) {
#ifdef KERNEL_PLL
if (peer != sys_peer || pll_status & STA_PPSTIME)
@@ -578,28 +638,74 @@ refclock_receive(
}
}
+
/*
* refclock_gtlin - groom next input line and extract timestamp
*
* This routine processes the timecode received from the clock and
- * removes the parity bit and control characters. If a timestamp is
- * present in the timecode, as produced by the tty_clk STREAMS module,
- * it returns that as the timestamp; otherwise, it returns the buffer
- * timestamp. The routine return code is the number of characters in
- * the line.
+ * strips the parity bit and control characters. It returns the number
+ * of characters in the line followed by a NULL character ('\0'), which
+ * is not included in the count. In case of an empty line, the previous
+ * line is preserved.
*/
int
refclock_gtlin(
struct recvbuf *rbufp, /* receive buffer pointer */
- char *lineptr, /* current line pointer */
- int bmax, /* remaining characters in line */
- l_fp *tsptr /* pointer to timestamp returned */
+ char *lineptr, /* current line pointer */
+ int bmax, /* remaining characters in line */
+ l_fp *tsptr /* pointer to timestamp returned */
)
{
- char *dpt, *dpend, *dp;
- int i;
- l_fp trtmp, tstmp;
- char c;
+ char s[BMAX];
+ char *dpt, *dpend, *dp;
+
+ dpt = s;
+ dpend = s + refclock_gtraw(rbufp, s, BMAX - 1, tsptr);
+ if (dpend - dpt > bmax - 1)
+ dpend = dpt + bmax - 1;
+ for (dp = lineptr; dpt < dpend; dpt++) {
+ char c;
+
+ c = *dpt & 0x7f;
+ if (c >= 0x20 && c < 0x7f)
+ *dp++ = c;
+ }
+ if (dp == lineptr)
+ return (0);
+
+ *dp = '\0';
+ return (dp - lineptr);
+}
+
+
+/*
+ * refclock_gtraw - get next line/chunk of data
+ *
+ * This routine returns the raw data received from the clock in both
+ * canonical or raw modes. The terminal interface routines map CR to LF.
+ * In canonical mode this results in two lines, one containing data
+ * followed by LF and another containing only LF. In raw mode the
+ * interface routines can deliver arbitraty chunks of data from one
+ * character to a maximum specified by the calling routine. In either
+ * mode the routine returns the number of characters in the line
+ * followed by a NULL character ('\0'), which is not included in the
+ * count.
+ *
+ * If a timestamp is present in the timecode, as produced by the tty_clk
+ * STREAMS module, it returns that as the timestamp; otherwise, it
+ * returns the buffer timestamp.
+ */
+int
+refclock_gtraw(
+ struct recvbuf *rbufp, /* receive buffer pointer */
+ char *lineptr, /* current line pointer */
+ int bmax, /* remaining characters in line */
+ l_fp *tsptr /* pointer to timestamp returned */
+ )
+{
+ char *dpt, *dpend, *dp;
+ l_fp trtmp, tstmp;
+ int i;
/*
* Check for the presence of a timestamp left by the tty_clock
@@ -611,7 +717,6 @@ refclock_gtlin(
dpt = (char *)rbufp->recv_buffer;
dpend = dpt + rbufp->recv_length;
trtmp = rbufp->recv_time;
-
if (dpend >= dpt + 8) {
if (buftvtots(dpend - 8, &tstmp)) {
L_SUB(&trtmp, &tstmp);
@@ -620,10 +725,12 @@ refclock_gtlin(
if (debug > 1) {
printf(
"refclock_gtlin: fd %d ldisc %s",
- rbufp->fd, lfptoa(&trtmp, 6));
+ rbufp->fd, lfptoa(&trtmp,
+ 6));
get_systime(&trtmp);
L_SUB(&trtmp, &tstmp);
- printf(" sigio %s\n", lfptoa(&trtmp, 6));
+ printf(" sigio %s\n",
+ lfptoa(&trtmp, 6));
}
#endif
dpend -= 8;
@@ -634,34 +741,25 @@ refclock_gtlin(
}
/*
- * Edit timecode to remove control chars. Don't monkey with the
- * line buffer if the input buffer contains no ASCII printing
- * characters.
+ * Copy the raw buffer to the user string. The string is padded
+ * with a NULL, which is not included in the character count.
*/
if (dpend - dpt > bmax - 1)
dpend = dpt + bmax - 1;
- for (dp = lineptr; dpt < dpend; dpt++) {
- c = (char) (*dpt & 0x7f);
- if (c >= ' ')
- *dp++ = c;
- }
+ for (dp = lineptr; dpt < dpend; dpt++)
+ *dp++ = *dpt;
+ *dp = '\0';
i = dp - lineptr;
- if (i > 0)
- *dp = '\0';
#ifdef DEBUG
- if (debug > 1) {
- if (i > 0)
- printf("refclock_gtlin: fd %d time %s timecode %d %s\n",
- rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
- else
- printf("refclock_gtlin: fd %d time %s\n",
- rbufp->fd, ulfptoa(&trtmp, 6));
- }
+ if (debug > 1)
+ printf("refclock_gtraw: fd %d time %s timecode %d %s\n",
+ rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
#endif
*tsptr = trtmp;
return (i);
}
+
/*
* The following code does not apply to WINNT & VMS ...
*/
@@ -676,24 +774,17 @@ refclock_gtlin(
*/
int
refclock_open(
- char *dev, /* device name pointer */
- int speed, /* serial port speed (code) */
- int lflags /* line discipline flags */
+ char *dev, /* device name pointer */
+ u_int speed, /* serial port speed (code) */
+ u_int lflags /* line discipline flags */
)
{
- int fd, i;
- int flags;
- TTY ttyb, *ttyp;
-#ifdef TIOCMGET
- u_long ltemp;
-#endif /* TIOCMGET */
- int omode;
+ int fd;
+ int omode;
/*
* Open serial port and set default options
*/
- flags = lflags;
-
omode = O_RDWR;
#ifdef O_NONBLOCK
omode |= O_NONBLOCK;
@@ -703,38 +794,54 @@ refclock_open(
#endif
fd = open(dev, omode, 0777);
-
if (fd < 0) {
- msyslog(LOG_ERR, "refclock_open: %s: %m", dev);
+ msyslog(LOG_ERR, "refclock_open %s: %m", dev);
+ return (0);
+ }
+ if (!refclock_setup(fd, speed, lflags)) {
+ close(fd);
return (0);
}
+ if (!refclock_ioctl(fd, lflags)) {
+ close(fd);
+ return (0);
+ }
+ return (fd);
+}
- /*
- * This little jewel lights up the PPS file descriptor if the
- * device name matches the name in the pps line in the
- * configuration file. This is so the atom driver can glom onto
- * the right device. Very silly.
- */
- if (strcmp(dev, pps_device) == 0)
- fdpps = fd;
+/*
+ * refclock_setup - initialize terminal interface structure
+ */
+int
+refclock_setup(
+ int fd, /* file descriptor */
+ u_int speed, /* serial port speed (code) */
+ u_int lflags /* line discipline flags */
+ )
+{
+ int i;
+ TTY ttyb, *ttyp;
+#ifdef PPS
+ fdpps = fd; /* ppsclock legacy */
+#endif /* PPS */
/*
- * The following sections initialize the serial line port in
- * canonical (line-oriented) mode and set the specified line
- * speed, 8 bits and no parity. The modem control, break, erase
- * and kill functions are normally disabled. There is a
- * different section for each terminal interface, as selected at
- * compile time.
+ * By default, the serial line port is initialized in canonical
+ * (line-oriented) mode at specified line speed, 8 bits and no
+ * parity. LF ends the line and CR is mapped to LF. The break,
+ * erase and kill functions are disabled. There is a different
+ * section for each terminal interface, as selected at compile
+ * time. The flag bits can be used to set raw mode and echo.
*/
ttyp = &ttyb;
-
#ifdef HAVE_TERMIOS
+
/*
* POSIX serial line parameters (termios interface)
*/
if (tcgetattr(fd, ttyp) < 0) {
msyslog(LOG_ERR,
- "refclock_open: fd %d tcgetattr: %m", fd);
+ "refclock_setup fd %d tcgetattr: %m", fd);
return (0);
}
@@ -742,51 +849,55 @@ refclock_open(
* Set canonical mode and local connection; set specified speed,
* 8 bits and no parity; map CR to NL; ignore break.
*/
- ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
- ttyp->c_oflag = 0;
- ttyp->c_cflag = CS8 | CLOCAL | CREAD;
- (void)cfsetispeed(&ttyb, (u_int)speed);
- (void)cfsetospeed(&ttyb, (u_int)speed);
- ttyp->c_lflag = ICANON;
- for (i = 0; i < NCCS; ++i)
- {
- ttyp->c_cc[i] = '\0';
+ if (speed) {
+ u_int ltemp = 0;
+
+ ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
+ ttyp->c_oflag = 0;
+ ttyp->c_cflag = CS8 | CLOCAL | CREAD;
+ if (lflags & LDISC_7O1) {
+ /* HP Z3801A needs 7-bit, odd parity */
+ ttyp->c_cflag = CS7 | PARENB | PARODD | CLOCAL | CREAD;
+ }
+ cfsetispeed(&ttyb, speed);
+ cfsetospeed(&ttyb, speed);
+ for (i = 0; i < NCCS; ++i)
+ ttyp->c_cc[i] = '\0';
+
+#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
+
+ /*
+ * If we have modem control, check to see if modem leads
+ * are active; if so, set remote connection. This is
+ * necessary for the kernel pps mods to work.
+ */
+ if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
+ msyslog(LOG_ERR,
+ "refclock_setup fd %d TIOCMGET: %m", fd);
+#ifdef DEBUG
+ if (debug)
+ printf("refclock_setup fd %d modem status: 0x%x\n",
+ fd, ltemp);
+#endif
+ if (ltemp & TIOCM_DSR && lflags & LDISC_REMOTE)
+ ttyp->c_cflag &= ~CLOCAL;
+#endif /* TIOCMGET */
}
/*
- * Some special cases
+ * Set raw and echo modes. These can be changed on-fly.
*/
- if (flags & LDISC_RAW) {
- ttyp->c_iflag = 0;
+ ttyp->c_lflag = ICANON;
+ if (lflags & LDISC_RAW) {
ttyp->c_lflag = 0;
+ ttyp->c_iflag = 0;
ttyp->c_cc[VMIN] = 1;
}
-#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
- /*
- * If we have modem control, check to see if modem leads are
- * active; if so, set remote connection. This is necessary for
- * the kernel pps mods to work.
- */
- ltemp = 0;
- if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
- msyslog(LOG_ERR,
- "refclock_open: fd %d TIOCMGET failed: %m", fd);
-#ifdef DEBUG
- if (debug)
- printf("refclock_open: fd %d modem status 0x%lx\n",
- fd, ltemp);
-#endif
- if (ltemp & TIOCM_DSR)
- ttyp->c_cflag &= ~CLOCAL;
-#endif /* TIOCMGET */
+ if (lflags & LDISC_ECHO)
+ ttyp->c_lflag |= ECHO;
if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
msyslog(LOG_ERR,
- "refclock_open: fd %d TCSANOW failed: %m", fd);
- return (0);
- }
- if (tcflush(fd, TCIOFLUSH) < 0) {
- msyslog(LOG_ERR,
- "refclock_open: fd %d TCIOFLUSH failed: %m", fd);
+ "refclock_setup fd %d TCSANOW: %m", fd);
return (0);
}
#endif /* HAVE_TERMIOS */
@@ -799,7 +910,7 @@ refclock_open(
*/
if (ioctl(fd, TCGETA, ttyp) < 0) {
msyslog(LOG_ERR,
- "refclock_open: fd %d TCGETA failed: %m", fd);
+ "refclock_setup fd %d TCGETA: %m", fd);
return (0);
}
@@ -807,40 +918,47 @@ refclock_open(
* Set canonical mode and local connection; set specified speed,
* 8 bits and no parity; map CR to NL; ignore break.
*/
- ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
- ttyp->c_oflag = 0;
- ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
- ttyp->c_lflag = ICANON;
- ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+ if (speed) {
+ u_int ltemp = 0;
+
+ ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
+ ttyp->c_oflag = 0;
+ ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
+ for (i = 0; i < NCCS; ++i)
+ ttyp->c_cc[i] = '\0';
+
+#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
+
+ /*
+ * If we have modem control, check to see if modem leads
+ * are active; if so, set remote connection. This is
+ * necessary for the kernel pps mods to work.
+ */
+ if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
+ msyslog(LOG_ERR,
+ "refclock_setup fd %d TIOCMGET: %m", fd);
+#ifdef DEBUG
+ if (debug)
+ printf("refclock_setup fd %d modem status: %x\n",
+ fd, ltemp);
+#endif
+ if (ltemp & TIOCM_DSR)
+ ttyp->c_cflag &= ~CLOCAL;
+#endif /* TIOCMGET */
+ }
/*
- * Some special cases
+ * Set raw and echo modes. These can be changed on-fly.
*/
- if (flags & LDISC_RAW) {
- ttyp->c_iflag = 0;
+ ttyp->c_lflag = ICANON;
+ if (lflags & LDISC_RAW) {
ttyp->c_lflag = 0;
+ ttyp->c_iflag = 0;
+ ttyp->c_cc[VMIN] = 1;
}
-#ifdef TIOCMGET
- /*
- * If we have modem control, check to see if modem leads are
- * active; if so, set remote connection. This is necessary for
- * the kernel pps mods to work.
- */
- ltemp = 0;
- if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
- msyslog(LOG_ERR,
- "refclock_open: fd %d TIOCMGET failed: %m", fd);
-#ifdef DEBUG
- if (debug)
- printf("refclock_open: fd %d modem status %lx\n",
- fd, ltemp);
-#endif
- if (ltemp & TIOCM_DSR)
- ttyp->c_cflag &= ~CLOCAL;
-#endif /* TIOCMGET */
if (ioctl(fd, TCSETA, ttyp) < 0) {
msyslog(LOG_ERR,
- "refclock_open: fd %d TCSETA failed: %m", fd);
+ "refclock_setup fd %d TCSETA: %m", fd);
return (0);
}
#endif /* HAVE_SYSV_TTYS */
@@ -852,28 +970,24 @@ refclock_open(
*/
if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {
msyslog(LOG_ERR,
- "refclock_open: fd %d TIOCGETP %m", fd);
+ "refclock_setup fd %d TIOCGETP: %m", fd);
return (0);
}
- ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
+ if (speed)
+ ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
ttyp->sg_flags = EVENP | ODDP | CRMOD;
if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {
msyslog(LOG_ERR,
- "refclock_open: TIOCSETP failed: %m");
+ "refclock_setup TIOCSETP: %m");
return (0);
}
#endif /* HAVE_BSD_TTYS */
- if (!refclock_ioctl(fd, flags)) {
- (void)close(fd);
- msyslog(LOG_ERR,
- "refclock_open: fd %d ioctl failed: %m", fd);
- return (0);
- }
- return (fd);
+ return(1);
}
#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
#endif /* SYS_VXWORKS SYS_WINNT */
+
/*
* refclock_ioctl - set serial port control functions
*
@@ -885,68 +999,51 @@ refclock_open(
*/
int
refclock_ioctl(
- int fd, /* file descriptor */
- int flags /* line discipline flags */
+ int fd, /* file descriptor */
+ u_int lflags /* line discipline flags */
)
{
- /* simply return 1 if no UNIX line discipline is supported */
+ /*
+ * simply return 1 if no UNIX line discipline is supported
+ */
#if !defined SYS_VXWORKS && !defined SYS_WINNT
#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
-#ifdef TTYCLK
- TTY ttyb, *ttyp;
-#endif /* TTYCLK */
-
#ifdef DEBUG
if (debug)
- printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags);
+ printf("refclock_ioctl: fd %d flags 0x%x\n", fd,
+ lflags);
#endif
- if (flags == 0)
- return (1);
-#if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS))
- if (flags & (LDISC_CLK | LDISC_PPS | LDISC_ACTS)) {
- msyslog(LOG_ERR,
- "refclock_ioctl: unsupported terminal interface");
- return (0);
- }
-#endif /* HAVE_TERMIOS HAVE_BSD_TTYS */
#ifdef TTYCLK
- ttyp = &ttyb;
-#endif /* TTYCLK */
/*
- * The following features may or may not require System V
- * STREAMS support, depending on the particular implementation.
- */
-#if defined(TTYCLK)
- /*
* The TTYCLK option provides timestamping at the driver level.
* It requires the tty_clk streams module and System V STREAMS
* support. If not available, don't complain.
*/
- if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
+ if (lflags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
int rval = 0;
if (ioctl(fd, I_PUSH, "clk") < 0) {
msyslog(LOG_NOTICE,
- "refclock_ioctl: I_PUSH clk failed: %m");
+ "refclock_ioctl fd %d I_PUSH: %m", fd);
+ return (0);
+#ifdef CLK_SETSTR
} else {
char *str;
- if (flags & LDISC_CLKPPS)
+ if (lflags & LDISC_CLKPPS)
str = "\377";
- else if (flags & LDISC_ACTS)
+ else if (lflags & LDISC_ACTS)
str = "*";
else
str = "\n";
-#ifdef CLK_SETSTR
- if ((rval = ioctl(fd, CLK_SETSTR, str)) < 0)
+ if (ioctl(fd, CLK_SETSTR, str) < 0) {
msyslog(LOG_ERR,
- "refclock_ioctl: CLK_SETSTR failed: %m");
- if (debug)
- printf("refclock_ioctl: fd %d CLK_SETSTR %d str %s\n",
- fd, rval, str);
-#endif
+ "refclock_ioctl fd %d CLK_SETSTR: %m", fd);
+ return (0);
+ }
+#endif /*CLK_SETSTR */
}
}
#endif /* TTYCLK */
@@ -955,6 +1052,7 @@ refclock_ioctl(
return (1);
}
+
/*
* refclock_control - set and/or return clock values
*
@@ -981,17 +1079,22 @@ refclock_control(
*/
if (srcadr->ss_family != AF_INET)
return;
+
if (!ISREFCLOCKADR(srcadr))
return;
+
clktype = (u_char)REFCLOCKTYPE(srcadr);
unit = REFCLOCKUNIT(srcadr);
if (clktype >= num_refclock_conf || unit >= MAXUNIT)
return;
+
peer = typeunit[clktype][unit];
if (peer == NULL)
return;
+
if (peer->procptr == NULL)
return;
+
pp = peer->procptr;
/*
@@ -1003,16 +1106,9 @@ refclock_control(
if (in->haveflags & CLK_HAVETIME2)
pp->fudgetime2 = in->fudgetime2;
if (in->haveflags & CLK_HAVEVAL1)
- pp->stratum = (u_char) in->fudgeval1;
+ peer->stratum = pp->stratum = (u_char)in->fudgeval1;
if (in->haveflags & CLK_HAVEVAL2)
- pp->refid = in->fudgeval2;
- peer->stratum = pp->stratum;
- if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
- STRATUM_UNSPEC)
- peer->refid = pp->refid;
- else
- peer->refid = ((struct
- sockaddr_in*)&peer->srcadr)->sin_addr.s_addr;
+ peer->refid = pp->refid = in->fudgeval2;
if (in->haveflags & CLK_HAVEFLAG1) {
pp->sloppyclockflag &= ~CLK_FLAG1;
pp->sloppyclockflag |= in->flags & CLK_FLAG1;
@@ -1089,15 +1185,19 @@ refclock_buginfo(
*/
if (srcadr->ss_family != AF_INET)
return;
+
if (!ISREFCLOCKADR(srcadr))
return;
+
clktype = (u_char) REFCLOCKTYPE(srcadr);
unit = REFCLOCKUNIT(srcadr);
if (clktype >= num_refclock_conf || unit >= MAXUNIT)
return;
+
peer = typeunit[clktype][unit];
if (peer == NULL)
return;
+
pp = peer->procptr;
/*
diff --git a/contrib/ntp/ntpd/ntp_request.c b/contrib/ntp/ntpd/ntp_request.c
index eacba28..b1bc99d 100644
--- a/contrib/ntp/ntpd/ntp_request.c
+++ b/contrib/ntp/ntpd/ntp_request.c
@@ -98,7 +98,9 @@ static void req_clr_trap P((struct sockaddr_storage *, struct interface *, struc
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 *));
+static void get_ctl_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
+static void get_if_stats P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
+static void do_if_reload P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
#ifdef KERNEL_PLL
static void get_kernel_info P((struct sockaddr_storage *, struct interface *, struct req_pkt *));
#endif /* KERNEL_PLL */
@@ -171,6 +173,9 @@ static struct req_proc ntp_codes[] = {
{ REQ_GET_CLKBUGINFO, NOAUTH, sizeof(u_int32), sizeof(u_int32),
get_clkbug_info },
#endif
+ { REQ_IF_STATS, AUTH, 0, 0, get_if_stats },
+ { REQ_IF_RELOAD, AUTH, 0, 0, do_if_reload },
+
{ NO_REQUEST, NOAUTH, 0, 0, 0 }
};
@@ -495,17 +500,21 @@ process_private(
!(inpkt->implementation == IMPL_XNTPD &&
inpkt->request == REQ_CONFIG &&
temp_size == sizeof(struct old_conf_peer))) {
+#ifdef DEBUG
if (debug > 2)
printf("process_private: wrong item size, received %d, should be %d or %d\n",
temp_size, proc->sizeofitem, proc->v6_sizeofitem);
+#endif
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))) {
+#ifdef DEBUG
if (debug > 2)
printf("process_private: not enough data\n");
+#endif
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -650,7 +659,7 @@ peer_list(
ip = (struct info_peer_list *)prepare_pkt(srcadr, inter, inpkt,
v6sizeof(struct info_peer_list));
- for (i = 0; i < HASH_SIZE && ip != 0; i++) {
+ for (i = 0; i < NTP_HASH_SIZE && ip != 0; i++) {
pp = peer_hash[i];
while (pp != 0 && ip != 0) {
if (pp->srcadr.ss_family == AF_INET6) {
@@ -712,7 +721,7 @@ peer_list_sum(
#endif
ips = (struct info_peer_summary *)prepare_pkt(srcadr, inter, inpkt,
v6sizeof(struct info_peer_summary));
- for (i = 0; i < HASH_SIZE && ips != 0; i++) {
+ for (i = 0; i < NTP_HASH_SIZE && ips != 0; i++) {
pp = peer_hash[i];
while (pp != 0 && ips != 0) {
#ifdef DEBUG
@@ -727,7 +736,10 @@ peer_list_sum(
if (client_v6_capable) {
ips->srcadr6 = GET_INADDR6(pp->srcadr);
ips->v6_flag = 1;
- ips->dstadr6 = GET_INADDR6(pp->dstadr->sin);
+ if (pp->dstadr)
+ ips->dstadr6 = GET_INADDR6(pp->dstadr->sin);
+ else
+ memset(&ips->dstadr6, 0, sizeof(ips->dstadr6));
skip = 0;
} else {
skip = 1;
@@ -738,17 +750,22 @@ peer_list_sum(
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);
+
+ if (pp->dstadr)
+ 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);
+ else
+ memset(&ips->dstadr, 0, sizeof(ips->dstadr));
skip = 0;
}
+
if (!skip){
ips->srcport = NSRCPORT(&pp->srcadr);
ips->stratum = pp->stratum;
@@ -776,7 +793,7 @@ peer_list_sum(
ips->delay = HTONS_FP(DTOFP(pp->delay));
DTOLFP(pp->offset, &ltmp);
HTONL_FP(&ltmp, &ips->offset);
- ips->dispersion = HTONS_FP(DTOUFP(pp->disp));
+ ips->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
}
pp = pp->next;
ips = (struct info_peer_summary *)more_pkt();
@@ -828,21 +845,28 @@ peer_info (
if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
continue;
if (pp->srcadr.ss_family == AF_INET6) {
- ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
- GET_INADDR6(pp->dstadr->bcast) :
- GET_INADDR6(pp->dstadr->sin);
+ if (pp->dstadr)
+ ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
+ GET_INADDR6(pp->dstadr->bcast) :
+ GET_INADDR6(pp->dstadr->sin);
+ else
+ memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
+
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);
+ if (pp->dstadr)
+ 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);
+ else
+ memset(&ip->dstadr, 0, sizeof(ip->dstadr));
ip->srcadr = GET_INADDR(pp->srcadr);
if (client_v6_capable)
@@ -928,7 +952,10 @@ peer_stats (
struct sockaddr_storage addr;
extern struct peer *sys_peer;
- printf("peer_stats: called\n");
+#ifdef DEBUG
+ if (debug)
+ printf("peer_stats: called\n");
+#endif
items = INFO_NITEMS(inpkt->err_nitems);
ipl = (struct info_peer_list *) inpkt->data;
ip = (struct info_peer_stats *)prepare_pkt(srcadr, inter, inpkt,
@@ -946,30 +973,44 @@ peer_stats (
#ifdef HAVE_SA_LEN_IN_STRUCT_SOCKADDR
addr.ss_len = SOCKLEN(&addr);
#endif
- printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr),
+#ifdef DEBUG
+ if (debug)
+ printf("peer_stats: looking for %s, %d, %d\n", stoa(&addr),
ipl->port, ((struct sockaddr_in6 *)&addr)->sin6_port);
+#endif
ipl = (struct info_peer_list *)((char *)ipl +
INFO_ITEMSIZE(inpkt->mbz_itemsize));
if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
continue;
- printf("peer_stats: found %s\n", stoa(&addr));
+#ifdef DEBUG
+ if (debug)
+ printf("peer_stats: found %s\n", stoa(&addr));
+#endif
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;
+ if (pp->dstadr)
+ 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;
+ else
+ memset(&ip->dstadr, 0, sizeof(ip->dstadr));
+
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);
+ if (pp->dstadr)
+ ip->dstadr6 = pp->cast_flags == MDF_BCAST ?
+ GET_INADDR6(pp->dstadr->bcast):
+ GET_INADDR6(pp->dstadr->sin);
+ else
+ memset(&ip->dstadr6, 0, sizeof(ip->dstadr6));
+
ip->srcadr6 = GET_INADDR6(pp->srcadr);
ip->v6_flag = 1;
}
@@ -987,10 +1028,13 @@ peer_stats (
ip->flags |= INFO_FLAG_PREFER;
if (pp->flags & FLAG_BURST)
ip->flags |= INFO_FLAG_BURST;
+ if (pp->flags & FLAG_IBURST)
+ ip->flags |= INFO_FLAG_IBURST;
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->flags = htons(ip->flags);
ip->timereceived = htonl((u_int32)(current_time - pp->timereceived));
ip->timetosend = htonl(pp->nextdate - current_time);
ip->timereachable = htonl((u_int32)(current_time - pp->timereachable));
@@ -1020,24 +1064,6 @@ sys_info(
{
register struct info_sys *is;
- /*
- * Importations from the protocol module
- */
- extern u_char sys_leap;
- extern u_char sys_stratum;
- extern s_char sys_precision;
- extern double sys_rootdelay;
- extern double sys_rootdispersion;
- extern u_int32 sys_refid;
- extern l_fp sys_reftime;
- extern u_char sys_poll;
- extern struct peer *sys_peer;
- extern int sys_bclient;
- extern double sys_bdelay;
- extern l_fp sys_authdelay;
- extern double clock_stability;
- extern double sys_jitter;
-
is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
v6sizeof(struct info_sys));
@@ -1065,7 +1091,7 @@ sys_info(
is->rootdelay = htonl(DTOFP(sys_rootdelay));
is->rootdispersion = htonl(DTOUFP(sys_rootdispersion));
is->frequency = htonl(DTOFP(sys_jitter));
- is->stability = htonl(DTOUFP(clock_stability * 1e6));
+ is->stability = htonl(DTOUFP(clock_stability));
is->refid = sys_refid;
HTONL_FP(&sys_reftime, &is->reftime);
@@ -1147,7 +1173,7 @@ mem_stats(
/*
* Importations from the peer module
*/
- extern int peer_hash_count[HASH_SIZE];
+ extern int peer_hash_count[NTP_HASH_SIZE];
extern int peer_free_count;
extern u_long peer_timereset;
extern u_long findpeer_calls;
@@ -1165,7 +1191,7 @@ mem_stats(
ms->allocations = htonl((u_int32)peer_allocations);
ms->demobilizations = htonl((u_int32)peer_demobilizations);
- for (i = 0; i < HASH_SIZE; i++) {
+ for (i = 0; i < NTP_HASH_SIZE; i++) {
if (peer_hash_count[i] > 255)
ms->hashcount[i] = 255;
else
@@ -1266,7 +1292,7 @@ loop_info(
extern double last_offset;
extern double drift_comp;
extern int tc_counter;
- extern u_long last_time;
+ extern u_long sys_clocktime;
li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_loop));
@@ -1276,7 +1302,7 @@ loop_info(
DTOLFP(drift_comp * 1e6, &ltmp);
HTONL_FP(&ltmp, &li->drift_comp);
li->compliance = htonl((u_int32)(tc_counter));
- li->watchdog_timer = htonl((u_int32)(current_time - last_time));
+ li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime));
(void) more_pkt();
flush_pkt();
@@ -1319,7 +1345,7 @@ do_conf(
&& temp_cp.hmode != MODE_BROADCAST)
fl = 1;
if (temp_cp.flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
- | CONF_FLAG_BURST | CONF_FLAG_SKEY))
+ | CONF_FLAG_BURST | CONF_FLAG_IBURST | CONF_FLAG_SKEY))
fl = 1;
cp = (struct conf_peer *)
((char *)cp + INFO_ITEMSIZE(inpkt->mbz_itemsize));
@@ -1343,13 +1369,16 @@ do_conf(
fl = 0;
if (temp_cp.flags & CONF_FLAG_AUTHENABLE)
- fl |= FLAG_AUTHENABLE;
+ fl |= FLAG_AUTHENABLE;
if (temp_cp.flags & CONF_FLAG_PREFER)
- fl |= FLAG_PREFER;
+ fl |= FLAG_PREFER;
if (temp_cp.flags & CONF_FLAG_BURST)
fl |= FLAG_BURST;
+ if (temp_cp.flags & CONF_FLAG_IBURST)
+ fl |= FLAG_IBURST;
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;
@@ -1531,7 +1560,10 @@ do_unconf(
#endif
found = 0;
peer = (struct peer *)0;
- printf("searching for %s\n", stoa(&peeraddr));
+#ifdef DEBUG
+ if (debug)
+ printf("searching for %s\n", stoa(&peeraddr));
+#endif
while (!found) {
peer = findexistingpeer(&peeraddr, peer, -1);
if (peer == (struct peer *)0)
@@ -1620,7 +1652,9 @@ setclr_flags(
)
{
register u_int flags;
+ int prev_kern_enable;
+ prev_kern_enable = kern_enable;
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
@@ -1628,7 +1662,8 @@ setclr_flags(
}
flags = ((struct conf_sys_flags *)inpkt->data)->flags;
-
+ flags = ntohl(flags);
+
if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
SYS_FLAG_FILEGEN | SYS_FLAG_AUTH | SYS_FLAG_CAL)) {
@@ -1658,6 +1693,12 @@ setclr_flags(
if (flags & SYS_FLAG_CAL)
proto_config(PROTO_CAL, set, 0., NULL);
req_ack(srcadr, inter, inpkt, INFO_OKAY);
+
+ /* Reset the kernel ntp parameters if the kernel flag changed. */
+ if (prev_kern_enable && !kern_enable)
+ loop_config(LOOP_KERN_CLEAR, 0.0);
+ if (!prev_kern_enable && kern_enable)
+ loop_config(LOOP_DRIFTCOMP, drift_comp);
}
@@ -1780,6 +1821,8 @@ do_restrict(
cr = (struct conf_restrict *)inpkt->data;
bad = 0;
+ cr->flags = ntohs(cr->flags);
+ cr->mflags = ntohs(cr->mflags);
while (items-- > 0 && !bad) {
if (cr->mflags & ~(RESM_NTPONLY))
bad |= 1;
@@ -1926,7 +1969,7 @@ mon_getlist_1(
: GET_INADDR(md->interface->bcast))
: 4);
}
- im->flags = md->cast_flags;
+ im->flags = htonl(md->cast_flags);
im->port = md->rmtport;
im->mode = md->mode;
im->version = md->version;
@@ -1974,7 +2017,8 @@ reset_stats(
}
flags = ((struct reset_flags *)inpkt->data)->flags;
-
+ flags = ntohl(flags);
+
if (flags & ~RESET_ALLFLAGS) {
msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
flags & ~RESET_ALLFLAGS);
@@ -2754,3 +2798,91 @@ get_clkbug_info(
flush_pkt();
}
#endif
+
+/*
+ * receiver of interface structures
+ */
+static void
+fill_info_if_stats(void *data, interface_info_t *interface_info)
+{
+ struct info_if_stats **ifsp = (struct info_if_stats **)data;
+ struct info_if_stats *ifs = *ifsp;
+ struct interface *interface = interface_info->interface;
+
+ memset((char*)ifs, 0, sizeof(*ifs));
+
+ if (interface->sin.ss_family == AF_INET6) {
+ if (!client_v6_capable) {
+ return;
+ }
+ ifs->v6_flag = 1;
+ memcpy((char *)&ifs->unaddr.addr6, (char *)&CAST_V6(interface->sin)->sin6_addr, sizeof(struct in6_addr));
+ memcpy((char *)&ifs->unbcast.addr6, (char *)&CAST_V6(interface->bcast)->sin6_addr, sizeof(struct in6_addr));
+ memcpy((char *)&ifs->unmask.addr6, (char *)&CAST_V6(interface->mask)->sin6_addr, sizeof(struct in6_addr));
+ } else {
+ ifs->v6_flag = 0;
+ memcpy((char *)&ifs->unaddr.addr, (char *)&CAST_V4(interface->sin)->sin_addr, sizeof(struct in_addr));
+ memcpy((char *)&ifs->unbcast.addr, (char *)&CAST_V4(interface->bcast)->sin_addr, sizeof(struct in_addr));
+ memcpy((char *)&ifs->unmask.addr, (char *)&CAST_V4(interface->mask)->sin_addr, sizeof(struct in_addr));
+ }
+ ifs->v6_flag = htonl(ifs->v6_flag);
+ strcpy(ifs->name, interface->name);
+ ifs->family = htons(interface->family);
+ ifs->flags = htonl(interface->flags);
+ ifs->last_ttl = htonl(interface->last_ttl);
+ ifs->num_mcast = htonl(interface->num_mcast);
+ ifs->received = htonl(interface->received);
+ ifs->sent = htonl(interface->sent);
+ ifs->notsent = htonl(interface->notsent);
+ ifs->scopeid = htonl(interface->scopeid);
+ ifs->ifindex = htonl(interface->ifindex);
+ ifs->ifnum = htonl(interface->ifnum);
+ ifs->uptime = htonl(current_time - interface->starttime);
+ ifs->ignore_packets = interface->ignore_packets;
+ ifs->peercnt = htonl(interface->peercnt);
+ ifs->action = interface_info->action;
+
+ *ifsp = (struct info_if_stats *)more_pkt();
+}
+
+/*
+ * get_if_stats - get interface statistics
+ */
+static void
+get_if_stats(
+ struct sockaddr_storage *srcadr,
+ struct interface *inter,
+ struct req_pkt *inpkt
+ )
+{
+ struct info_if_stats *ifs;
+
+ DPRINTF(3, ("wants interface statistics\n"));
+
+ ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
+ v6sizeof(struct info_if_stats));
+
+ interface_enumerate(fill_info_if_stats, &ifs);
+
+ flush_pkt();
+}
+
+static void
+do_if_reload(
+ struct sockaddr_storage *srcadr,
+ struct interface *inter,
+ struct req_pkt *inpkt
+ )
+{
+ struct info_if_stats *ifs;
+
+ DPRINTF(3, ("wants interface reload\n"));
+
+ ifs = (struct info_if_stats *)prepare_pkt(srcadr, inter, inpkt,
+ v6sizeof(struct info_if_stats));
+
+ interface_update(fill_info_if_stats, &ifs);
+
+ flush_pkt();
+}
+
diff --git a/contrib/ntp/ntpd/ntp_restrict.c b/contrib/ntp/ntpd/ntp_restrict.c
index ede4225..473e2ce 100644
--- a/contrib/ntp/ntpd/ntp_restrict.c
+++ b/contrib/ntp/ntpd/ntp_restrict.c
@@ -112,9 +112,9 @@ init_restrict(void)
/*
* Zero the list and put all but one on the free list
*/
- resfree = 0;
+ resfree = NULL;
memset((char *)resinit, 0, sizeof resinit);
- resfree6 = 0;
+ resfree6 = NULL;
memset((char *)resinit6, 0, sizeof resinit6);
for (i = 1; i < INITRESLIST; i++) {
resinit[i].next = resfree;
@@ -158,7 +158,8 @@ init_restrict(void)
*/
int
restrictions(
- struct sockaddr_storage *srcadr
+ struct sockaddr_storage *srcadr,
+ int at_listhead
)
{
struct restrictlist *rl;
@@ -193,7 +194,7 @@ restrictions(
* Work our way down from there.
*/
match = restrictlist;
- for (rl = match->next; rl != 0 && rl->addr <= hostaddr;
+ for (rl = match->next; rl != NULL && rl->addr <= hostaddr;
rl = rl->next)
if ((hostaddr & rl->mask) == rl->addr) {
if ((rl->mflags & RESM_NTPONLY) &&
@@ -233,7 +234,7 @@ restrictions(
* Work our way down from there.
*/
match6 = restrictlist6;
- for (rl6 = match6->next; rl6 != 0 &&
+ for (rl6 = match6->next; rl6 != NULL &&
(memcmp(&(rl6->addr6), &hostaddr6,
sizeof(hostaddr6)) <= 0); rl6 = rl6->next) {
SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6,
@@ -260,7 +261,7 @@ restrictions(
* packet is greater than res_min_interval and the average is
* greater thatn res_avg_interval.
*/
- if (mon_enabled == MON_OFF) {
+ if (!at_listhead || mon_enabled == MON_OFF) {
flags &= ~RES_LIMITED;
} else {
struct mon_data *md;
@@ -323,14 +324,14 @@ hack_restrict(
* list. Else go searching for it.
*/
if (addr == 0) {
- rlprev = 0;
+ rlprev = NULL;
rl = restrictlist;
} else {
rlprev = restrictlist;
rl = rlprev->next;
- while (rl != 0) {
+ while (rl != NULL) {
if (rl->addr > addr) {
- rl = 0;
+ rl = NULL;
break;
} else if (rl->addr == addr) {
if (rl->mask == mask) {
@@ -342,11 +343,11 @@ hack_restrict(
if (!(mflags &
RESM_NTPONLY)) {
- rl = 0;
+ rl = NULL;
break;
}
} else if (rl->mask > mask) {
- rl = 0;
+ rl = NULL;
break;
}
}
@@ -361,16 +362,16 @@ hack_restrict(
SET_IPV6_ADDR_MASK(&addr6,
&GET_INADDR6(*resaddr), &mask6);
if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
- rlprev6 = 0;
+ rlprev6 = NULL;
rl6 = restrictlist6;
} else {
rlprev6 = restrictlist6;
rl6 = rlprev6->next;
- while (rl6 != 0) {
+ while (rl6 != NULL) {
addr_cmp = memcmp(&rl6->addr6, &addr6,
sizeof(addr6));
if (addr_cmp > 0) {
- rl6 = 0;
+ rl6 = NULL;
break;
} else if (addr_cmp == 0) {
mask_cmp = memcmp(&rl6->mask6,
@@ -384,11 +385,11 @@ hack_restrict(
if (!(mflags &
RESM_NTPONLY)) {
- rl6 = 0;
+ rl6 = NULL;
break;
}
} else if (mask_cmp > 0) {
- rl6 = 0;
+ rl6 = NULL;
break;
}
}
@@ -415,8 +416,8 @@ hack_restrict(
* Here we add bits to the flags. If this is a
* new restriction add it.
*/
- if (rl == 0) {
- if (numresfree == 0) {
+ if (rl == NULL) {
+ if (resfree == NULL) {
rl = (struct restrictlist *)
emalloc(INCRESLIST *
sizeof(struct
@@ -440,8 +441,13 @@ hack_restrict(
rl->mask = mask;
rl->mflags = (u_short)mflags;
- rl->next = rlprev->next;
- rlprev->next = rl;
+ if (rlprev == NULL) {
+ rl->next = restrictlist;
+ restrictlist = rl;
+ } else {
+ rl->next = rlprev->next;
+ rlprev->next = rl;
+ }
restrictcount++;
}
if ((rl->flags ^ (u_short)flags) &
@@ -457,7 +463,7 @@ hack_restrict(
* Remove some bits from the flags. If we didn't
* find this one, just return.
*/
- if (rl != 0) {
+ if (rl != NULL) {
if ((rl->flags ^ (u_short)flags) &
RES_LIMITED) {
res_limited_refcnt--;
@@ -469,15 +475,20 @@ hack_restrict(
break;
case RESTRICT_REMOVE:
+ case RESTRICT_REMOVEIF:
/*
* 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
+ if (rl != NULL
&& rl->addr != htonl(INADDR_ANY)
- && !(rl->mflags & RESM_INTERFACE)) {
- rlprev->next = rl->next;
+ && !(rl->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
+ if (rlprev != NULL) {
+ rlprev->next = rl->next;
+ } else {
+ restrictlist = rl->next;
+ }
restrictcount--;
if (rl->flags & RES_LIMITED) {
res_limited_refcnt--;
@@ -503,8 +514,8 @@ hack_restrict(
* Here we add bits to the flags. If this is a
* new restriction add it.
*/
- if (rl6 == 0) {
- if (numresfree6 == 0) {
+ if (rl6 == NULL) {
+ if (resfree6 == NULL) {
rl6 = (struct
restrictlist6 *)emalloc(
INCRESLIST * sizeof(struct
@@ -527,8 +538,13 @@ hack_restrict(
rl6->addr6 = addr6;
rl6->mask6 = mask6;
rl6->mflags = (u_short)mflags;
- rl6->next = rlprev6->next;
- rlprev6->next = rl6;
+ if (rlprev6 != NULL) {
+ rl6->next = rlprev6->next;
+ rlprev6->next = rl6;
+ } else {
+ rl6->next = restrictlist6;
+ restrictlist6 = rl6;
+ }
restrictcount6++;
}
if ((rl6->flags ^ (u_short)flags) &
@@ -544,7 +560,7 @@ hack_restrict(
* Remove some bits from the flags. If we didn't
* find this one, just return.
*/
- if (rl6 != 0) {
+ if (rl6 != NULL) {
if ((rl6->flags ^ (u_short)flags) &
RES_LIMITED) {
res_limited_refcnt6--;
@@ -556,15 +572,20 @@ hack_restrict(
break;
case RESTRICT_REMOVE:
+ case RESTRICT_REMOVEIF:
/*
* 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 &&
+ if (rl6 != NULL &&
!IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6)
- && !(rl6->mflags & RESM_INTERFACE)) {
- rlprev6->next = rl6->next;
+ && !(rl6->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
+ if (rlprev6 != NULL) {
+ rlprev6->next = rl6->next;
+ } else {
+ restrictlist6 = rl6->next;
+ }
restrictcount6--;
if (rl6->flags & RES_LIMITED) {
res_limited_refcnt6--;
diff --git a/contrib/ntp/ntpd/ntp_timer.c b/contrib/ntp/ntpd/ntp_timer.c
index 6f0f18b..fb6de70 100644
--- a/contrib/ntp/ntpd/ntp_timer.c
+++ b/contrib/ntp/ntpd/ntp_timer.c
@@ -34,6 +34,8 @@
* procedure to do cleanup and print a message.
*/
+volatile int interface_interval = 300; /* update interface every 5 minutes as default */
+
/*
* Alarm flag. The mainline code imports this.
*/
@@ -44,8 +46,9 @@ volatile int alarm_flag;
*/
static u_long adjust_timer; /* second timer */
static u_long keys_timer; /* minute timer */
-static u_long hourly_timer; /* hour timer */
+static u_long stats_timer; /* stats timer */
static u_long huffpuff_timer; /* huff-n'-puff timer */
+static u_long interface_timer; /* interface update timer */
#ifdef OPENSSL
static u_long revoke_timer; /* keys revoke timer */
u_char sys_revoke = KEY_REVOKE; /* keys revoke timeout (log2 s) */
@@ -138,7 +141,7 @@ void
init_timer(void)
{
# if defined SYS_WINNT & !defined(SYS_CYGWIN32)
- HANDLE hToken;
+ HANDLE hToken = INVALID_HANDLE_VALUE;
TOKEN_PRIVILEGES tkp;
# endif /* SYS_WINNT */
@@ -148,8 +151,9 @@ init_timer(void)
alarm_flag = 0;
alarm_overflow = 0;
adjust_timer = 1;
- hourly_timer = HOUR;
+ stats_timer = 0;
huffpuff_timer = 0;
+ interface_timer = 0;
current_time = 0;
timer_overflows = 0;
timer_xmtcalls = 0;
@@ -269,6 +273,15 @@ timer(void)
adjust_timer += 1;
adj_host_clock();
kod_proto();
+#ifdef REFCLOCK
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
+ for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
+ next_peer = peer->next;
+ if (peer->flags & FLAG_REFCLOCK)
+ refclock_timer(peer);
+ }
+ }
+#endif /* REFCLOCK */
}
/*
@@ -276,7 +289,7 @@ timer(void)
* here, since the peer structure might go away as the result of
* the call.
*/
- for (n = 0; n < HASH_SIZE; n++) {
+ for (n = 0; n < NTP_HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
if (peer->action && peer->nextaction <= current_time)
@@ -327,11 +340,24 @@ timer(void)
#endif /* OPENSSL */
/*
- * Finally, call the hourly routine.
+ * interface update timer
+ */
+ if (interface_interval && interface_timer <= current_time) {
+ timer_interfacetimeout(current_time + interface_interval);
+#ifdef DEBUG
+ if (debug)
+ printf("timer: interface update\n");
+#endif
+ interface_update(NULL, NULL);
+ }
+
+ /*
+ * Finally, periodically write stats.
*/
- if (hourly_timer <= current_time) {
- hourly_timer += HOUR;
- hourly_stats();
+ if (stats_timer <= current_time) {
+ if (stats_timer != 0)
+ write_stats();
+ stats_timer += stats_write_period;
}
}
@@ -363,6 +389,12 @@ alarming(
}
#endif /* SYS_WINNT */
+void
+timer_interfacetimeout(u_long timeout)
+{
+ interface_timer = timeout;
+}
+
/*
* timer_clr_stats - clear timer module stat counters
diff --git a/contrib/ntp/ntpd/ntp_util.c b/contrib/ntp/ntpd/ntp_util.c
index 135f9b3..91ff8a6 100644
--- a/contrib/ntp/ntpd/ntp_util.c
+++ b/contrib/ntp/ntpd/ntp_util.c
@@ -28,13 +28,13 @@
#endif
#ifdef DOSYNCTODR
-#if !defined(VMS)
-#include <sys/resource.h>
-#endif /* VMS */
+# if !defined(VMS)
+# include <sys/resource.h>
+# endif /* VMS */
#endif
#if defined(VMS)
-#include <descrip.h>
+# include <descrip.h>
#endif /* VMS */
/*
@@ -53,20 +53,23 @@ static char *key_file_name;
*/
static char *stats_drift_file;
static char *stats_temp_file;
+int stats_write_period = 3600; /* # of seconds between writes. */
+double stats_write_tolerance = 0;
+static double prev_drift_comp = 99999.;
/*
* Statistics file stuff
*/
#ifndef NTP_VAR
-#ifndef SYS_WINNT
-#define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */
-#else
-#define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */
-#endif /* SYS_WINNT */
+# ifndef SYS_WINNT
+# define NTP_VAR "/var/NTP/" /* NOTE the trailing '/' */
+# else
+# define NTP_VAR "c:\\var\\ntp\\" /* NOTE the trailing '\\' */
+# endif /* SYS_WINNT */
#endif
#ifndef MAXPATHLEN
-#define MAXPATHLEN 256
+# define MAXPATHLEN 256
#endif
static char statsdir[MAXPATHLEN] = NTP_VAR;
@@ -76,6 +79,9 @@ static FILEGEN loopstats;
static FILEGEN clockstats;
static FILEGEN rawstats;
static FILEGEN sysstats;
+#ifdef DEBUG_TIMING
+static FILEGEN timingstats;
+#endif
#ifdef OPENSSL
static FILEGEN cryptostats;
#endif /* OPENSSL */
@@ -87,6 +93,11 @@ static FILEGEN cryptostats;
int stats_control;
/*
+ * Initial frequency offset later passed to the loopfilter.
+ */
+double old_drift;
+
+/*
* init_util - initialize the utilities
*/
void
@@ -96,79 +107,23 @@ init_util(void)
stats_temp_file = 0;
key_file_name = 0;
-#define PEERNAME "peerstats"
-#define LOOPNAME "loopstats"
-#define CLOCKNAME "clockstats"
-#define RAWNAME "rawstats"
-#define STANAME "systats"
-#ifdef OPENSSL
-#define CRYPTONAME "cryptostats"
-#endif /* OPENSSL */
+ filegen_register(&statsdir[0], "peerstats", &peerstats);
- peerstats.fp = NULL;
- peerstats.prefix = &statsdir[0];
- peerstats.basename = (char*)emalloc(strlen(PEERNAME)+1);
- strcpy(peerstats.basename, PEERNAME);
- peerstats.id = 0;
- peerstats.type = FILEGEN_DAY;
- peerstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("peerstats", &peerstats);
-
- loopstats.fp = NULL;
- loopstats.prefix = &statsdir[0];
- loopstats.basename = (char*)emalloc(strlen(LOOPNAME)+1);
- strcpy(loopstats.basename, LOOPNAME);
- loopstats.id = 0;
- loopstats.type = FILEGEN_DAY;
- loopstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("loopstats", &loopstats);
-
- clockstats.fp = NULL;
- clockstats.prefix = &statsdir[0];
- clockstats.basename = (char*)emalloc(strlen(CLOCKNAME)+1);
- strcpy(clockstats.basename, CLOCKNAME);
- clockstats.id = 0;
- clockstats.type = FILEGEN_DAY;
- clockstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("clockstats", &clockstats);
-
- rawstats.fp = NULL;
- rawstats.prefix = &statsdir[0];
- rawstats.basename = (char*)emalloc(strlen(RAWNAME)+1);
- strcpy(rawstats.basename, RAWNAME);
- rawstats.id = 0;
- rawstats.type = FILEGEN_DAY;
- rawstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("rawstats", &rawstats);
-
- sysstats.fp = NULL;
- sysstats.prefix = &statsdir[0];
- sysstats.basename = (char*)emalloc(strlen(STANAME)+1);
- strcpy(sysstats.basename, STANAME);
- sysstats.id = 0;
- sysstats.type = FILEGEN_DAY;
- sysstats.flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
- filegen_register("sysstats", &sysstats);
+ filegen_register(&statsdir[0], "loopstats", &loopstats);
-#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 */
+ filegen_register(&statsdir[0], "clockstats", &clockstats);
+
+ filegen_register(&statsdir[0], "rawstats", &rawstats);
+
+ filegen_register(&statsdir[0], "sysstats", &sysstats);
-#undef PEERNAME
-#undef LOOPNAME
-#undef CLOCKNAME
-#undef RAWNAME
-#undef STANAME
#ifdef OPENSSL
-#undef CRYPTONAME
+ filegen_register(&statsdir[0], "cryptostats", &cryptostats);
#endif /* OPENSSL */
+
+#ifdef DEBUG_TIMING
+ filegen_register(&statsdir[0], "timingstats", &timingstats);
+#endif
}
@@ -176,7 +131,7 @@ init_util(void)
* hourly_stats - print some interesting stats
*/
void
-hourly_stats(void)
+write_stats(void)
{
FILE *fp;
@@ -260,6 +215,11 @@ hourly_stats(void)
record_sys_stats();
+ if ((u_long)(fabs(prev_drift_comp - drift_comp) * 1e9) <=
+ (u_long)(fabs(stats_write_tolerance * drift_comp) * 1e9)) {
+ return;
+ }
+ prev_drift_comp = drift_comp;
if (stats_drift_file != 0) {
if ((fp = fopen(stats_temp_file, "w")) == NULL) {
msyslog(LOG_ERR, "can't open %s: %m",
@@ -276,7 +236,7 @@ hourly_stats(void)
#ifndef NO_RENAME
(void) rename(stats_temp_file, stats_drift_file);
#else
- /* we have no rename NFS of ftp in use*/
+ /* we have no rename NFS of ftp in use */
if ((fp = fopen(stats_drift_file, "w")) == NULL) {
msyslog(LOG_ERR, "can't open %s: %m",
stats_drift_file);
@@ -305,12 +265,11 @@ hourly_stats(void)
void
stats_config(
int item,
- char *invalue /* only one type so far */
+ const char *invalue /* only one type so far */
)
{
FILE *fp;
- char *value;
- double old_drift;
+ const char *value;
int len;
/*
@@ -381,21 +340,21 @@ stats_config(
* missing or contains errors, tell the loop to reset.
*/
if ((fp = fopen(stats_drift_file, "r")) == NULL) {
- loop_config(LOOP_DRIFTCOMP, 1e9);
+ old_drift = 1e9;
break;
}
if (fscanf(fp, "%lf", &old_drift) != 1) {
msyslog(LOG_ERR, "Frequency format error in %s",
stats_drift_file);
- loop_config(LOOP_DRIFTCOMP, 1e9);
+ old_drift = 1e9;
fclose(fp);
break;
}
fclose(fp);
+ prev_drift_comp = old_drift / 1e6;
msyslog(LOG_INFO,
"frequency initialized %.3f PPM from %s",
old_drift, stats_drift_file);
- loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
break;
case STATS_STATSDIR:
@@ -505,6 +464,7 @@ record_peer_stats(
fflush(peerstats.fp);
}
}
+
/*
* record_loop_stats - write loop filter statistics to file
*
@@ -535,7 +495,7 @@ record_loop_stats(
day = now.l_ui / 86400 + MJD_1900;
now.l_ui %= 86400;
if (loopstats.fp != NULL) {
- fprintf(loopstats.fp, "%lu %s %.9f %.6f %.9f %.6f %d\n",
+ fprintf(loopstats.fp, "%lu %s %.9f %.3f %.9f %.6f %d\n",
day, ulfptoa(&now, 3), offset, freq * 1e6, jitter,
stability * 1e6, spoll);
fflush(loopstats.fp);
@@ -606,9 +566,9 @@ record_raw_stats(
now.l_ui %= 86400;
if (rawstats.fp != NULL) {
fprintf(rawstats.fp, "%lu %s %s %s %s %s %s %s\n",
- day, ulfptoa(&now, 3), stoa(srcadr), stoa(dstadr),
- ulfptoa(t1, 9), ulfptoa(t2, 9), ulfptoa(t3, 9),
- ulfptoa(t4, 9));
+ day, ulfptoa(&now, 3), stoa(srcadr), dstadr ? stoa(dstadr) : "-",
+ ulfptoa(t1, 9), ulfptoa(t2, 9), ulfptoa(t3, 9),
+ ulfptoa(t4, 9));
fflush(rawstats.fp);
}
}
@@ -695,13 +655,45 @@ record_crypto_stats(
}
#endif /* OPENSSL */
+#ifdef DEBUG_TIMING
+/*
+ * record_crypto_stats - write crypto statistics to file
+ *
+ * file format:
+ * day (mjd)
+ * time (s past midnight)
+ * text message
+ */
+void
+record_timing_stats(
+ const char *text
+ )
+{
+ static unsigned int flshcnt;
+ l_fp now;
+ u_long day;
+
+ if (!stats_control)
+ return;
+ get_systime(&now);
+ filegen_setup(&timingstats, now.l_ui);
+ day = now.l_ui / 86400 + MJD_1900;
+ now.l_ui %= 86400;
+ if (timingstats.fp != NULL) {
+ fprintf(timingstats.fp, "%lu %s %s\n",
+ day, lfptoa(&now, 3), text);
+ if (++flshcnt % 100 == 0)
+ fflush(timingstats.fp);
+ }
+}
+#endif
/*
* getauthkeys - read the authentication keys from the specified file
*/
void
getauthkeys(
- char *keyfile
+ const char *keyfile
)
{
int len;
@@ -795,3 +787,15 @@ sock_hash(
return hashVal;
}
+
+#if notyet
+/*
+ * ntp_exit - document explicitly that ntpd has exited
+ */
+void
+ntp_exit(int retval)
+{
+ msyslog(LOG_ERR, "EXITING with return code %d", retval);
+ exit(retval);
+}
+#endif
diff --git a/contrib/ntp/ntpd/ntpd-opts.c b/contrib/ntp/ntpd/ntpd-opts.c
new file mode 100644
index 0000000..eae28cb
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpd-opts.c
@@ -0,0 +1,1021 @@
+/*
+ * EDIT THIS FILE WITH CAUTION (ntpd-opts.c)
+ *
+ * It has been AutoGen-ed Sunday August 17, 2008 at 05:20:10 AM EDT
+ * From the definitions ntpd-opts.def
+ * and the template file options
+ *
+ * Generated from AutoOpts 29:0:4 templates.
+ */
+
+/*
+ * This file was produced by an AutoOpts template. AutoOpts is a
+ * copyrighted work. This source file is not encumbered by AutoOpts
+ * licensing, but is provided under the licensing terms chosen by the
+ * ntpd author or copyright holder. AutoOpts is licensed under
+ * the terms of the LGPL. The redistributable library (``libopts'') is
+ * licensed under the terms of either the LGPL or, at the users discretion,
+ * the BSD license. See the AutoOpts and/or libopts sources for details.
+ *
+ * This source file is copyrighted and licensed under the following terms:
+ *
+ * ntpd copyright 1970-2008 David L. Mills and/or others - all rights reserved
+ *
+ * see html/copyright.html
+ */
+
+
+#include <limits.h>
+
+#define OPTION_CODE_COMPILE 1
+#include "ntpd-opts.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+ "ntpd copyright (c) 1970-2008 David L. Mills and/or others, all rights reserved";
+tSCC zCopyrightNotice[] =
+
+/* extracted from ../include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ * global included definitions
+ */
+#ifdef __windows
+ extern int atoi(const char*);
+#else
+# include <stdlib.h>
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+/*
+ * Ipv4 option description:
+ */
+tSCC zIpv4Text[] =
+ "Force IPv4 DNS name resolution";
+tSCC zIpv4_NAME[] = "IPV4";
+tSCC zIpv4_Name[] = "ipv4";
+#define IPV4_FLAGS (OPTST_DISABLED)
+
+/*
+ * Ipv6 option description:
+ */
+tSCC zIpv6Text[] =
+ "Force IPv6 DNS name resolution";
+tSCC zIpv6_NAME[] = "IPV6";
+tSCC zIpv6_Name[] = "ipv6";
+#define IPV6_FLAGS (OPTST_DISABLED)
+
+/*
+ * Authreq option description with
+ * "Must also have options" and "Incompatible options":
+ */
+tSCC zAuthreqText[] =
+ "Require crypto authentication";
+tSCC zAuthreq_NAME[] = "AUTHREQ";
+tSCC zAuthreq_Name[] = "authreq";
+static const int
+ aAuthreqCantList[] = {
+ INDEX_OPT_AUTHNOREQ, NO_EQUIVALENT };
+#define AUTHREQ_FLAGS (OPTST_DISABLED)
+
+/*
+ * Authnoreq option description with
+ * "Must also have options" and "Incompatible options":
+ */
+tSCC zAuthnoreqText[] =
+ "Do not require crypto authentication";
+tSCC zAuthnoreq_NAME[] = "AUTHNOREQ";
+tSCC zAuthnoreq_Name[] = "authnoreq";
+static const int
+ aAuthnoreqCantList[] = {
+ INDEX_OPT_AUTHREQ, NO_EQUIVALENT };
+#define AUTHNOREQ_FLAGS (OPTST_DISABLED)
+
+/*
+ * Bcastsync option description:
+ */
+tSCC zBcastsyncText[] =
+ "Allow us to sync to broadcast servers";
+tSCC zBcastsync_NAME[] = "BCASTSYNC";
+tSCC zBcastsync_Name[] = "bcastsync";
+#define BCASTSYNC_FLAGS (OPTST_DISABLED)
+
+/*
+ * Configfile option description:
+ */
+tSCC zConfigfileText[] =
+ "configuration file name";
+tSCC zConfigfile_NAME[] = "CONFIGFILE";
+tSCC zConfigfile_Name[] = "configfile";
+#define CONFIGFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Debug_Level option description:
+ */
+#ifdef DEBUG
+tSCC zDebug_LevelText[] =
+ "Increase output debug message level";
+tSCC zDebug_Level_NAME[] = "DEBUG_LEVEL";
+tSCC zDebug_Level_Name[] = "debug-level";
+#define DEBUG_LEVEL_FLAGS (OPTST_DISABLED)
+
+#else /* disable Debug_Level */
+#define VALUE_OPT_DEBUG_LEVEL NO_EQUIVALENT
+#define DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zDebug_LevelText NULL
+#define zDebug_Level_NAME NULL
+#define zDebug_Level_Name NULL
+#endif /* DEBUG */
+
+/*
+ * Set_Debug_Level option description:
+ */
+#ifdef DEBUG
+tSCC zSet_Debug_LevelText[] =
+ "Set the output debug message level";
+tSCC zSet_Debug_Level_NAME[] = "SET_DEBUG_LEVEL";
+tSCC zSet_Debug_Level_Name[] = "set-debug-level";
+#define SET_DEBUG_LEVEL_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else /* disable Set_Debug_Level */
+#define VALUE_OPT_SET_DEBUG_LEVEL NO_EQUIVALENT
+#define SET_DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zSet_Debug_LevelText NULL
+#define zSet_Debug_Level_NAME NULL
+#define zSet_Debug_Level_Name NULL
+#endif /* DEBUG */
+
+/*
+ * Driftfile option description:
+ */
+tSCC zDriftfileText[] =
+ "frequency drift file name";
+tSCC zDriftfile_NAME[] = "DRIFTFILE";
+tSCC zDriftfile_Name[] = "driftfile";
+#define DRIFTFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Panicgate option description:
+ */
+tSCC zPanicgateText[] =
+ "Allow the first adjustment to be Big";
+tSCC zPanicgate_NAME[] = "PANICGATE";
+tSCC zPanicgate_Name[] = "panicgate";
+#define PANICGATE_FLAGS (OPTST_DISABLED)
+
+/*
+ * Jaildir option description:
+ */
+tSCC zJaildirText[] =
+ "Jail directory";
+tSCC zJaildir_NAME[] = "JAILDIR";
+tSCC zJaildir_Name[] = "jaildir";
+#define JAILDIR_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Interface option description:
+ */
+tSCC zInterfaceText[] =
+ "Listen on interface";
+tSCC zInterface_NAME[] = "INTERFACE";
+tSCC zInterface_Name[] = "interface";
+#define INTERFACE_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Keyfile option description:
+ */
+tSCC zKeyfileText[] =
+ "path to symmetric keys";
+tSCC zKeyfile_NAME[] = "KEYFILE";
+tSCC zKeyfile_Name[] = "keyfile";
+#define KEYFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Logfile option description:
+ */
+tSCC zLogfileText[] =
+ "path to the log file";
+tSCC zLogfile_NAME[] = "LOGFILE";
+tSCC zLogfile_Name[] = "logfile";
+#define LOGFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Novirtualips option description:
+ */
+tSCC zNovirtualipsText[] =
+ "Do not listen to virtual IPs";
+tSCC zNovirtualips_NAME[] = "NOVIRTUALIPS";
+tSCC zNovirtualips_Name[] = "novirtualips";
+#define NOVIRTUALIPS_FLAGS (OPTST_DISABLED)
+
+/*
+ * Modifymmtimer option description:
+ */
+#ifdef SYS_WINNT
+tSCC zModifymmtimerText[] =
+ "Modify Multimedia Timer (Windows only)";
+tSCC zModifymmtimer_NAME[] = "MODIFYMMTIMER";
+tSCC zModifymmtimer_Name[] = "modifymmtimer";
+#define MODIFYMMTIMER_FLAGS (OPTST_DISABLED)
+
+#else /* disable Modifymmtimer */
+#define VALUE_OPT_MODIFYMMTIMER NO_EQUIVALENT
+#define MODIFYMMTIMER_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zModifymmtimerText NULL
+#define zModifymmtimer_NAME NULL
+#define zModifymmtimer_Name NULL
+#endif /* SYS_WINNT */
+
+/*
+ * Nofork option description:
+ */
+tSCC zNoforkText[] =
+ "Do not fork";
+tSCC zNofork_NAME[] = "NOFORK";
+tSCC zNofork_Name[] = "nofork";
+#define NOFORK_FLAGS (OPTST_DISABLED)
+
+/*
+ * Nice option description:
+ */
+tSCC zNiceText[] =
+ "Run at high priority";
+tSCC zNice_NAME[] = "NICE";
+tSCC zNice_Name[] = "nice";
+#define NICE_FLAGS (OPTST_DISABLED)
+
+/*
+ * Pidfile option description:
+ */
+tSCC zPidfileText[] =
+ "path to the PID file";
+tSCC zPidfile_NAME[] = "PIDFILE";
+tSCC zPidfile_Name[] = "pidfile";
+#define PIDFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Priority option description:
+ */
+tSCC zPriorityText[] =
+ "Process priority";
+tSCC zPriority_NAME[] = "PRIORITY";
+tSCC zPriority_Name[] = "priority";
+#define PRIORITY_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ * Quit option description:
+ */
+tSCC zQuitText[] =
+ "Set the time and quit";
+tSCC zQuit_NAME[] = "QUIT";
+tSCC zQuit_Name[] = "quit";
+#define QUIT_FLAGS (OPTST_DISABLED)
+
+/*
+ * Propagationdelay option description:
+ */
+tSCC zPropagationdelayText[] =
+ "Broadcast/propagation delay";
+tSCC zPropagationdelay_NAME[] = "PROPAGATIONDELAY";
+tSCC zPropagationdelay_Name[] = "propagationdelay";
+#define PROPAGATIONDELAY_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Updateinterval option description:
+ */
+tSCC zUpdateintervalText[] =
+ "interval in seconds between scans for new or dropped interfaces";
+tSCC zUpdateinterval_NAME[] = "UPDATEINTERVAL";
+tSCC zUpdateinterval_Name[] = "updateinterval";
+#define UPDATEINTERVAL_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ * Statsdir option description:
+ */
+tSCC zStatsdirText[] =
+ "Statistics file location";
+tSCC zStatsdir_NAME[] = "STATSDIR";
+tSCC zStatsdir_Name[] = "statsdir";
+#define STATSDIR_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Trustedkey option description:
+ */
+tSCC zTrustedkeyText[] =
+ "Trusted key number";
+tSCC zTrustedkey_NAME[] = "TRUSTEDKEY";
+tSCC zTrustedkey_Name[] = "trustedkey";
+#define TRUSTEDKEY_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * User option description:
+ */
+tSCC zUserText[] =
+ "Run as userid (or userid:groupid)";
+tSCC zUser_NAME[] = "USER";
+tSCC zUser_Name[] = "user";
+#define USER_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Var option description:
+ */
+tSCC zVarText[] =
+ "make ARG an ntp variable (RW)";
+tSCC zVar_NAME[] = "VAR";
+tSCC zVar_Name[] = "var";
+#define VAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Dvar option description:
+ */
+tSCC zDvarText[] =
+ "make ARG an ntp variable (RW|DEF)";
+tSCC zDvar_NAME[] = "DVAR";
+tSCC zDvar_Name[] = "dvar";
+#define DVAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Slew option description:
+ */
+tSCC zSlewText[] =
+ "Slew up to 600 seconds";
+tSCC zSlew_NAME[] = "SLEW";
+tSCC zSlew_Name[] = "slew";
+#define SLEW_FLAGS (OPTST_DISABLED)
+
+/*
+ * Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[] = "Display usage information and exit";
+tSCC zHelp_Name[] = "help";
+
+tSCC zMore_HelpText[] = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[] = "Output version information and exit";
+tSCC zVersion_Name[] = "version";
+/*
+ * Declare option callback procedures
+ */
+#ifdef DEBUG
+ static tOptProc doOptSet_Debug_Level;
+#else /* not DEBUG */
+# define doOptSet_Debug_Level NULL
+#endif /* def/not DEBUG */
+#if defined(TEST_NTPD_OPTS)
+/*
+ * Under test, omit argument processing, or call optionStackArg,
+ * if multiple copies are allowed.
+ */
+extern tOptProc
+ optionNumericVal, optionPagedUsage, optionStackArg,
+ optionVersionStderr;
+static tOptProc
+ doUsageOpt;
+
+/*
+ * #define map the "normal" callout procs to the test ones...
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_NTPD_OPTS */
+/*
+ * When not under test, there are different procs to use
+ */
+extern tOptProc
+ optionNumericVal, optionPagedUsage, optionPrintVersion, optionStackArg;
+static tOptProc
+ doUsageOpt;
+
+/*
+ * #define map the "normal" callout procs
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#endif /* defined(TEST_NTPD_OPTS) */
+#ifdef TEST_NTPD_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_NTPD_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Define the Ntpd Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+ { /* entry idx, value */ 0, VALUE_OPT_IPV4,
+ /* equiv idx, value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ IPV4_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 1, VALUE_OPT_IPV6,
+ /* equiv idx, value */ NOLIMIT, NOLIMIT,
+ /* equivalenced to */ INDEX_OPT_IPV4,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ IPV6_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 2, VALUE_OPT_AUTHREQ,
+ /* equiv idx, value */ 2, VALUE_OPT_AUTHREQ,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ AUTHREQ_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, aAuthreqCantList,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zAuthreqText, zAuthreq_NAME, zAuthreq_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+ /* equiv idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ AUTHNOREQ_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, aAuthnoreqCantList,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zAuthnoreqText, zAuthnoreq_NAME, zAuthnoreq_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 4, VALUE_OPT_BCASTSYNC,
+ /* equiv idx, value */ 4, VALUE_OPT_BCASTSYNC,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ BCASTSYNC_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zBcastsyncText, zBcastsync_NAME, zBcastsync_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 5, VALUE_OPT_CONFIGFILE,
+ /* equiv idx, value */ 5, VALUE_OPT_CONFIGFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ CONFIGFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zConfigfileText, zConfigfile_NAME, zConfigfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 6, VALUE_OPT_DEBUG_LEVEL,
+ /* equiv idx, value */ 6, VALUE_OPT_DEBUG_LEVEL,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ DEBUG_LEVEL_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 7, VALUE_OPT_SET_DEBUG_LEVEL,
+ /* equiv idx, value */ 7, VALUE_OPT_SET_DEBUG_LEVEL,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ SET_DEBUG_LEVEL_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ SET_DEBUG_LEVEL_OPT_PROC,
+ /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 8, VALUE_OPT_DRIFTFILE,
+ /* equiv idx, value */ 8, VALUE_OPT_DRIFTFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ DRIFTFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zDriftfileText, zDriftfile_NAME, zDriftfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 9, VALUE_OPT_PANICGATE,
+ /* equiv idx, value */ 9, VALUE_OPT_PANICGATE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PANICGATE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPanicgateText, zPanicgate_NAME, zPanicgate_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 10, VALUE_OPT_JAILDIR,
+ /* equiv idx, value */ 10, VALUE_OPT_JAILDIR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ JAILDIR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zJaildirText, zJaildir_NAME, zJaildir_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 11, VALUE_OPT_INTERFACE,
+ /* equiv idx, value */ 11, VALUE_OPT_INTERFACE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ INTERFACE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zInterfaceText, zInterface_NAME, zInterface_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 12, VALUE_OPT_KEYFILE,
+ /* equiv idx, value */ 12, VALUE_OPT_KEYFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ KEYFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zKeyfileText, zKeyfile_NAME, zKeyfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 13, VALUE_OPT_LOGFILE,
+ /* equiv idx, value */ 13, VALUE_OPT_LOGFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ LOGFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zLogfileText, zLogfile_NAME, zLogfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 14, VALUE_OPT_NOVIRTUALIPS,
+ /* equiv idx, value */ 14, VALUE_OPT_NOVIRTUALIPS,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ NOVIRTUALIPS_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zNovirtualipsText, zNovirtualips_NAME, zNovirtualips_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 15, VALUE_OPT_MODIFYMMTIMER,
+ /* equiv idx, value */ 15, VALUE_OPT_MODIFYMMTIMER,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ MODIFYMMTIMER_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zModifymmtimerText, zModifymmtimer_NAME, zModifymmtimer_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 16, VALUE_OPT_NOFORK,
+ /* equiv idx, value */ 16, VALUE_OPT_NOFORK,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ NOFORK_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zNoforkText, zNofork_NAME, zNofork_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 17, VALUE_OPT_NICE,
+ /* equiv idx, value */ 17, VALUE_OPT_NICE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ NICE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zNiceText, zNice_NAME, zNice_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 18, VALUE_OPT_PIDFILE,
+ /* equiv idx, value */ 18, VALUE_OPT_PIDFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PIDFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPidfileText, zPidfile_NAME, zPidfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 19, VALUE_OPT_PRIORITY,
+ /* equiv idx, value */ 19, VALUE_OPT_PRIORITY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PRIORITY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionNumericVal,
+ /* desc, NAME, name */ zPriorityText, zPriority_NAME, zPriority_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 20, VALUE_OPT_QUIT,
+ /* equiv idx, value */ 20, VALUE_OPT_QUIT,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ QUIT_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zQuitText, zQuit_NAME, zQuit_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 21, VALUE_OPT_PROPAGATIONDELAY,
+ /* equiv idx, value */ 21, VALUE_OPT_PROPAGATIONDELAY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PROPAGATIONDELAY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPropagationdelayText, zPropagationdelay_NAME, zPropagationdelay_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 22, VALUE_OPT_UPDATEINTERVAL,
+ /* equiv idx, value */ 22, VALUE_OPT_UPDATEINTERVAL,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ UPDATEINTERVAL_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionNumericVal,
+ /* desc, NAME, name */ zUpdateintervalText, zUpdateinterval_NAME, zUpdateinterval_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 23, VALUE_OPT_STATSDIR,
+ /* equiv idx, value */ 23, VALUE_OPT_STATSDIR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ STATSDIR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zStatsdirText, zStatsdir_NAME, zStatsdir_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 24, VALUE_OPT_TRUSTEDKEY,
+ /* equiv idx, value */ 24, VALUE_OPT_TRUSTEDKEY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ TRUSTEDKEY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zTrustedkeyText, zTrustedkey_NAME, zTrustedkey_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 25, VALUE_OPT_USER,
+ /* equiv idx, value */ 25, VALUE_OPT_USER,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ USER_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zUserText, zUser_NAME, zUser_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 26, VALUE_OPT_VAR,
+ /* equiv idx, value */ 26, VALUE_OPT_VAR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ VAR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zVarText, zVar_NAME, zVar_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 27, VALUE_OPT_DVAR,
+ /* equiv idx, value */ 27, VALUE_OPT_DVAR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ DVAR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zDvarText, zDvar_NAME, zDvar_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 28, VALUE_OPT_SLEW,
+ /* equiv idx, value */ 28, VALUE_OPT_SLEW,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ SLEW_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zSlewText, zSlew_NAME, zSlew_Name,
+ /* disablement strs */ NULL, NULL },
+
+#ifdef NO_OPTIONAL_OPT_ARGS
+# define VERSION_OPT_FLAGS OPTST_IMM | OPTST_NO_INIT
+#else
+# define VERSION_OPT_FLAGS OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
+ OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT
+#endif
+
+ { /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ VERSION_OPT_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ DOVERPROC,
+ /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+ /* disablement strs */ NULL, NULL },
+
+#undef VERSION_OPT_FLAGS
+
+
+ { /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ doUsageOpt,
+ /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionPagedUsage,
+ /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+ /* disablement strs */ NULL, NULL }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Define the Ntpd Option Environment
+ */
+tSCC zPROGNAME[] = "NTPD";
+tSCC zUsageTitle[] =
+"ntpd - NTP daemon program - Ver. 4.2.4p5\n\
+USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+#define zRcName NULL
+#define apzHomeList NULL
+
+tSCC zBugsAddr[] = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC zDetail[] = "\n\n";
+tSCC zFullVersion[] = NTPD_FULL_VERSION;
+/* extracted from /usr/local/gnu/share/autogen/optcode.tpl near line 408 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+ static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions ntpdOptions = {
+ OPTIONS_STRUCT_VERSION,
+ 0, NULL, /* original argc + argv */
+ ( OPTPROC_BASE
+ + OPTPROC_ERRSTOP
+ + OPTPROC_SHORTOPT
+ + OPTPROC_LONGOPT
+ + OPTPROC_NO_REQ_OPT
+ + OPTPROC_ENVIRON
+ + OPTPROC_NO_ARGS ),
+ 0, NULL, /* current option index, current option */
+ NULL, NULL, zPROGNAME,
+ zRcName, zCopyright, zCopyrightNotice,
+ zFullVersion, apzHomeList, zUsageTitle,
+ zExplain, zDetail, optDesc,
+ zBugsAddr, /* address to send bugs to */
+ NULL, NULL, /* extensions/saved state */
+ optionUsage, /* usage procedure */
+ translate_option_strings, /* translation procedure */
+ /*
+ * Indexes to special options
+ */
+ { INDEX_OPT_MORE_HELP,
+ 0 /* no option state saving */,
+ NO_EQUIVALENT /* index of '-#' option */,
+ NO_EQUIVALENT /* index of default opt */
+ },
+ 32 /* full option count */, 29 /* user option count */
+};
+
+/*
+ * Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+ tOptions* pOptions,
+ tOptDesc* pOptDesc )
+{
+ USAGE( EXIT_SUCCESS );
+}
+
+#if ! defined(TEST_NTPD_OPTS)
+
+/* * * * * * *
+ *
+ * For the set-debug-level option, when DEBUG is #define-d.
+ */
+#ifdef DEBUG
+static void
+doOptSet_Debug_Level(
+ tOptions* pOptions,
+ tOptDesc* pOptDesc )
+{
+ /* extracted from ../include/debug-opt.def, line 29 */
+DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
+}
+#endif /* defined DEBUG */
+
+#endif /* defined(TEST_NTPD_OPTS) */
+
+/* extracted from /usr/local/gnu/share/autogen/optmain.tpl near line 92 */
+
+#if defined(TEST_NTPD_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+ int res = EXIT_SUCCESS;
+ (void)optionProcess( &ntpdOptions, argc, argv );
+ {
+ void optionPutShell( tOptions* );
+ optionPutShell( &ntpdOptions );
+ }
+ return res;
+}
+#endif /* defined TEST_NTPD_OPTS */
+/* extracted from /usr/local/gnu/share/autogen/optcode.tpl near line 514 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char* AO_gettext( char const* pz );
+static void coerce_it(void** s);
+
+static char*
+AO_gettext( char const* pz )
+{
+ char* pzRes;
+ if (pz == NULL)
+ return NULL;
+ pzRes = _(pz);
+ if (pzRes == pz)
+ return pzRes;
+ pzRes = strdup( pzRes );
+ if (pzRes == NULL) {
+ fputs( _("No memory for duping translated strings\n"), stderr );
+ exit( EXIT_FAILURE );
+ }
+ return pzRes;
+}
+
+static void coerce_it(void** s) { *s = AO_gettext(*s); }
+#define COERSION(_f) \
+ coerce_it((void*)&(ntpdOptions._f))
+
+/*
+ * This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+ /*
+ * Guard against re-translation. It won't work. The strings will have
+ * been changed by the first pass through this code. One shot only.
+ */
+ if (option_usage_text.field_ct == 0)
+ return;
+ /*
+ * Do the translations. The first pointer follows the field count field.
+ * The field count field is the size of a pointer.
+ */
+ {
+ char** ppz = (char**)(void*)&(option_usage_text);
+ int ix = option_usage_text.field_ct;
+
+ do {
+ ppz++;
+ *ppz = AO_gettext(*ppz);
+ } while (--ix > 0);
+ }
+ option_usage_text.field_ct = 0;
+
+ {
+ tOptDesc* pOD = ntpdOptions.pOptDesc;
+ int ix = ntpdOptions.optCt;
+
+ for (;;) {
+ pOD->pzText = AO_gettext(pOD->pzText);
+ pOD->pz_NAME = AO_gettext(pOD->pz_NAME);
+ pOD->pz_Name = AO_gettext(pOD->pz_Name);
+ pOD->pz_DisableName = AO_gettext(pOD->pz_DisableName);
+ pOD->pz_DisablePfx = AO_gettext(pOD->pz_DisablePfx);
+ if (--ix <= 0)
+ break;
+ pOD++;
+ }
+ }
+ COERSION(pzCopyright);
+ COERSION(pzCopyNotice);
+ COERSION(pzFullVersion);
+ COERSION(pzUsageTitle);
+ COERSION(pzExplain);
+ COERSION(pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef __cplusplus
+}
+#endif
+/* ntpd-opts.c ends here */
diff --git a/contrib/ntp/ntpd/ntpd-opts.def b/contrib/ntp/ntpd/ntpd-opts.def
new file mode 100644
index 0000000..7266e1b
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpd-opts.def
@@ -0,0 +1,13 @@
+/* -*- Mode: Text -*- */
+
+autogen definitions options;
+
+#include copyright.def
+
+prog-name = "ntpd";
+prog-title = "NTP daemon program";
+
+#include ntpdbase-opts.def
+
+detail = <<- _END_DETAIL
+ _END_DETAIL;
diff --git a/contrib/ntp/ntpd/ntpd-opts.h b/contrib/ntp/ntpd/ntpd-opts.h
new file mode 100644
index 0000000..45d0de5
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpd-opts.h
@@ -0,0 +1,351 @@
+/*
+ * EDIT THIS FILE WITH CAUTION (ntpd-opts.h)
+ *
+ * It has been AutoGen-ed Sunday August 17, 2008 at 05:20:09 AM EDT
+ * From the definitions ntpd-opts.def
+ * and the template file options
+ *
+ * Generated from AutoOpts 29:0:4 templates.
+ */
+
+/*
+ * This file was produced by an AutoOpts template. AutoOpts is a
+ * copyrighted work. This header file is not encumbered by AutoOpts
+ * licensing, but is provided under the licensing terms chosen by the
+ * ntpd author or copyright holder. AutoOpts is licensed under
+ * the terms of the LGPL. The redistributable library (``libopts'') is
+ * licensed under the terms of either the LGPL or, at the users discretion,
+ * the BSD license. See the AutoOpts and/or libopts sources for details.
+ *
+ * This source file is copyrighted and licensed under the following terms:
+ *
+ * ntpd copyright 1970-2008 David L. Mills and/or others - all rights reserved
+ *
+ * see html/copyright.html
+ */
+/*
+ * This file contains the programmatic interface to the Automated
+ * Options generated for the ntpd program.
+ * These macros are documented in the AutoGen info file in the
+ * "AutoOpts" chapter. Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_NTPD_OPTS_H_GUARD
+#define AUTOOPTS_NTPD_OPTS_H_GUARD
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ * Ensure that the library used for compiling this generated header is at
+ * least as new as the version current when the header template was released
+ * (not counting patch version increments). Also ensure that the oldest
+ * tolerable version is at least as old as what was current when the header
+ * template was released.
+ */
+#define AO_TEMPLATE_VERSION 118784
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+ Choke Me.
+#endif
+
+/*
+ * Enumeration of each option:
+ */
+typedef enum {
+ INDEX_OPT_IPV4 = 0,
+ INDEX_OPT_IPV6 = 1,
+ INDEX_OPT_AUTHREQ = 2,
+ INDEX_OPT_AUTHNOREQ = 3,
+ INDEX_OPT_BCASTSYNC = 4,
+ INDEX_OPT_CONFIGFILE = 5,
+ INDEX_OPT_DEBUG_LEVEL = 6,
+ INDEX_OPT_SET_DEBUG_LEVEL = 7,
+ INDEX_OPT_DRIFTFILE = 8,
+ INDEX_OPT_PANICGATE = 9,
+ INDEX_OPT_JAILDIR = 10,
+ INDEX_OPT_INTERFACE = 11,
+ INDEX_OPT_KEYFILE = 12,
+ INDEX_OPT_LOGFILE = 13,
+ INDEX_OPT_NOVIRTUALIPS = 14,
+ INDEX_OPT_MODIFYMMTIMER = 15,
+ INDEX_OPT_NOFORK = 16,
+ INDEX_OPT_NICE = 17,
+ INDEX_OPT_PIDFILE = 18,
+ INDEX_OPT_PRIORITY = 19,
+ INDEX_OPT_QUIT = 20,
+ INDEX_OPT_PROPAGATIONDELAY = 21,
+ INDEX_OPT_UPDATEINTERVAL = 22,
+ INDEX_OPT_STATSDIR = 23,
+ INDEX_OPT_TRUSTEDKEY = 24,
+ INDEX_OPT_USER = 25,
+ INDEX_OPT_VAR = 26,
+ INDEX_OPT_DVAR = 27,
+ INDEX_OPT_SLEW = 28,
+ INDEX_OPT_VERSION = 29,
+ INDEX_OPT_HELP = 30,
+ INDEX_OPT_MORE_HELP = 31
+} teOptIndex;
+
+#define OPTION_CT 32
+#define NTPD_VERSION "4.2.4p5"
+#define NTPD_FULL_VERSION "ntpd - NTP daemon program - Ver. 4.2.4p5"
+
+/*
+ * Interface defines for all options. Replace "n" with the UPPER_CASED
+ * option name (as in the teOptIndex enumeration above).
+ * e.g. HAVE_OPT( IPV4 )
+ */
+#define DESC(n) (ntpdOptions.pOptDesc[INDEX_OPT_## n])
+#define HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define OPT_ARG(n) (DESC(n).optArg.argString)
+#define STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define COUNT_OPT(n) (DESC(n).optOccCt)
+#define ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define CLEAR_OPT(n) STMTS( \
+ DESC(n).fOptState &= OPTST_PERSISTENT_MASK; \
+ if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+ DESC(n).fOptState |= OPTST_DISABLED; \
+ DESC(n).optCookie = NULL )
+
+/*
+ * Make sure there are no #define name conflicts with the option names
+ */
+#ifndef NO_OPTION_NAME_WARNINGS
+# ifdef IPV4
+# warning undefining IPV4 due to option name conflict
+# undef IPV4
+# endif
+# ifdef IPV6
+# warning undefining IPV6 due to option name conflict
+# undef IPV6
+# endif
+# ifdef AUTHREQ
+# warning undefining AUTHREQ due to option name conflict
+# undef AUTHREQ
+# endif
+# ifdef AUTHNOREQ
+# warning undefining AUTHNOREQ due to option name conflict
+# undef AUTHNOREQ
+# endif
+# ifdef BCASTSYNC
+# warning undefining BCASTSYNC due to option name conflict
+# undef BCASTSYNC
+# endif
+# ifdef CONFIGFILE
+# warning undefining CONFIGFILE due to option name conflict
+# undef CONFIGFILE
+# endif
+# ifdef DEBUG_LEVEL
+# warning undefining DEBUG_LEVEL due to option name conflict
+# undef DEBUG_LEVEL
+# endif
+# ifdef SET_DEBUG_LEVEL
+# warning undefining SET_DEBUG_LEVEL due to option name conflict
+# undef SET_DEBUG_LEVEL
+# endif
+# ifdef DRIFTFILE
+# warning undefining DRIFTFILE due to option name conflict
+# undef DRIFTFILE
+# endif
+# ifdef PANICGATE
+# warning undefining PANICGATE due to option name conflict
+# undef PANICGATE
+# endif
+# ifdef JAILDIR
+# warning undefining JAILDIR due to option name conflict
+# undef JAILDIR
+# endif
+# ifdef INTERFACE
+# warning undefining INTERFACE due to option name conflict
+# undef INTERFACE
+# endif
+# ifdef KEYFILE
+# warning undefining KEYFILE due to option name conflict
+# undef KEYFILE
+# endif
+# ifdef LOGFILE
+# warning undefining LOGFILE due to option name conflict
+# undef LOGFILE
+# endif
+# ifdef NOVIRTUALIPS
+# warning undefining NOVIRTUALIPS due to option name conflict
+# undef NOVIRTUALIPS
+# endif
+# ifdef MODIFYMMTIMER
+# warning undefining MODIFYMMTIMER due to option name conflict
+# undef MODIFYMMTIMER
+# endif
+# ifdef NOFORK
+# warning undefining NOFORK due to option name conflict
+# undef NOFORK
+# endif
+# ifdef NICE
+# warning undefining NICE due to option name conflict
+# undef NICE
+# endif
+# ifdef PIDFILE
+# warning undefining PIDFILE due to option name conflict
+# undef PIDFILE
+# endif
+# ifdef PRIORITY
+# warning undefining PRIORITY due to option name conflict
+# undef PRIORITY
+# endif
+# ifdef QUIT
+# warning undefining QUIT due to option name conflict
+# undef QUIT
+# endif
+# ifdef PROPAGATIONDELAY
+# warning undefining PROPAGATIONDELAY due to option name conflict
+# undef PROPAGATIONDELAY
+# endif
+# ifdef UPDATEINTERVAL
+# warning undefining UPDATEINTERVAL due to option name conflict
+# undef UPDATEINTERVAL
+# endif
+# ifdef STATSDIR
+# warning undefining STATSDIR due to option name conflict
+# undef STATSDIR
+# endif
+# ifdef TRUSTEDKEY
+# warning undefining TRUSTEDKEY due to option name conflict
+# undef TRUSTEDKEY
+# endif
+# ifdef USER
+# warning undefining USER due to option name conflict
+# undef USER
+# endif
+# ifdef VAR
+# warning undefining VAR due to option name conflict
+# undef VAR
+# endif
+# ifdef DVAR
+# warning undefining DVAR due to option name conflict
+# undef DVAR
+# endif
+# ifdef SLEW
+# warning undefining SLEW due to option name conflict
+# undef SLEW
+# endif
+#else /* NO_OPTION_NAME_WARNINGS */
+# undef IPV4
+# undef IPV6
+# undef AUTHREQ
+# undef AUTHNOREQ
+# undef BCASTSYNC
+# undef CONFIGFILE
+# undef DEBUG_LEVEL
+# undef SET_DEBUG_LEVEL
+# undef DRIFTFILE
+# undef PANICGATE
+# undef JAILDIR
+# undef INTERFACE
+# undef KEYFILE
+# undef LOGFILE
+# undef NOVIRTUALIPS
+# undef MODIFYMMTIMER
+# undef NOFORK
+# undef NICE
+# undef PIDFILE
+# undef PRIORITY
+# undef QUIT
+# undef PROPAGATIONDELAY
+# undef UPDATEINTERVAL
+# undef STATSDIR
+# undef TRUSTEDKEY
+# undef USER
+# undef VAR
+# undef DVAR
+# undef SLEW
+#endif /* NO_OPTION_NAME_WARNINGS */
+
+/*
+ * Interface defines for specific options.
+ */
+#define VALUE_OPT_IPV4 '4'
+#define WHICH_OPT_IPV4 (DESC(IPV4).optActualValue)
+#define WHICH_IDX_IPV4 (DESC(IPV4).optActualIndex)
+#define VALUE_OPT_IPV6 '6'
+#define VALUE_OPT_AUTHREQ 'a'
+#define VALUE_OPT_AUTHNOREQ 'A'
+#define VALUE_OPT_BCASTSYNC 'b'
+#define VALUE_OPT_CONFIGFILE 'c'
+#ifdef DEBUG
+#define VALUE_OPT_DEBUG_LEVEL 'd'
+#endif /* DEBUG */
+#ifdef DEBUG
+#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
+#endif /* DEBUG */
+#define VALUE_OPT_DRIFTFILE 'f'
+#define VALUE_OPT_PANICGATE 'g'
+#define VALUE_OPT_JAILDIR 'i'
+#define VALUE_OPT_INTERFACE 'I'
+#define VALUE_OPT_KEYFILE 'k'
+#define VALUE_OPT_LOGFILE 'l'
+#define VALUE_OPT_NOVIRTUALIPS 'L'
+#ifdef SYS_WINNT
+#define VALUE_OPT_MODIFYMMTIMER 'M'
+#endif /* SYS_WINNT */
+#define VALUE_OPT_NOFORK 'n'
+#define VALUE_OPT_NICE 'N'
+#define VALUE_OPT_PIDFILE 'p'
+#define VALUE_OPT_PRIORITY 'P'
+#define OPT_VALUE_PRIORITY (DESC(PRIORITY).optArg.argInt)
+#define VALUE_OPT_QUIT 'q'
+#define VALUE_OPT_PROPAGATIONDELAY 'r'
+#define VALUE_OPT_UPDATEINTERVAL 'U'
+#define OPT_VALUE_UPDATEINTERVAL (DESC(UPDATEINTERVAL).optArg.argInt)
+#define VALUE_OPT_STATSDIR 's'
+#define VALUE_OPT_TRUSTEDKEY 't'
+#define VALUE_OPT_USER 'u'
+#define VALUE_OPT_VAR 'v'
+#define VALUE_OPT_DVAR 'V'
+#define VALUE_OPT_SLEW 'x'
+
+#define VALUE_OPT_VERSION 'v'
+#define VALUE_OPT_HELP '?'
+#define VALUE_OPT_MORE_HELP '!'
+/*
+ * Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR STMTS( ntpdOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR STMTS( ntpdOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n) STMTS( \
+ ntpdOptions.curOptIdx = (n); \
+ ntpdOptions.pzCurOpt = NULL )
+#define START_OPT RESTART_OPT(1)
+#define USAGE(c) (*ntpdOptions.pUsageProc)( &ntpdOptions, c )
+/* extracted from /usr/local/gnu/share/autogen/opthead.tpl near line 360 */
+
+/* * * * * *
+ *
+ * Declare the ntpd option descriptor.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern tOptions ntpdOptions;
+
+#ifndef _
+# if ENABLE_NLS
+# include <stdio.h>
+ static inline char* aoGetsText( char const* pz ) {
+ if (pz == NULL) return NULL;
+ return (char*)gettext( pz );
+ }
+# define _(s) aoGetsText(s)
+# else /* ENABLE_NLS */
+# define _(s) s
+# endif /* ENABLE_NLS */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_NTPD_OPTS_H_GUARD */
+/* ntpd-opts.h ends here */
diff --git a/contrib/ntp/ntpd/ntpd-opts.menu b/contrib/ntp/ntpd/ntpd-opts.menu
new file mode 100644
index 0000000..3425d82
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpd-opts.menu
@@ -0,0 +1 @@
+* ntpd Invocation:: Invoking ntpd
diff --git a/contrib/ntp/ntpd/ntpd-opts.texi b/contrib/ntp/ntpd/ntpd-opts.texi
new file mode 100644
index 0000000..5a99b58
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpd-opts.texi
@@ -0,0 +1,489 @@
+@node ntpd Invocation
+@section Invoking ntpd
+@pindex ntpd
+@cindex NTP daemon program
+@ignore
+#
+# EDIT THIS FILE WITH CAUTION (ntpd-opts.texi)
+#
+# It has been AutoGen-ed Sunday August 17, 2008 at 05:20:12 AM EDT
+# From the definitions ntpd-opts.def
+# and the template file aginfo.tpl
+@end ignore
+This program has no explanation.
+
+
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{ntpd} program. It documents the ntpd usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* ntpd usage:: ntpd usage help (-?)
+* ntpd authnoreq:: authnoreq option (-A)
+* ntpd authreq:: authreq option (-a)
+* ntpd bcastsync:: bcastsync option (-b)
+* ntpd configfile:: configfile option (-c)
+* ntpd debug-level:: debug-level option (-d)
+* ntpd driftfile:: driftfile option (-f)
+* ntpd dvar:: dvar option (-V)
+* ntpd interface:: interface option (-I)
+* ntpd ipv4:: ipv4 option (-4)
+* ntpd ipv6:: ipv6 option (-6)
+* ntpd jaildir:: jaildir option (-i)
+* ntpd keyfile:: keyfile option (-k)
+* ntpd logfile:: logfile option (-l)
+* ntpd modifymmtimer:: modifymmtimer option (-M)
+* ntpd nice:: nice option (-N)
+* ntpd nofork:: nofork option (-n)
+* ntpd novirtualips:: novirtualips option (-L)
+* ntpd panicgate:: panicgate option (-g)
+* ntpd pidfile:: pidfile option (-p)
+* ntpd priority:: priority option (-P)
+* ntpd propagationdelay:: propagationdelay option (-r)
+* ntpd quit:: quit option (-q)
+* ntpd set-debug-level:: set-debug-level option (-D)
+* ntpd slew:: slew option (-x)
+* ntpd statsdir:: statsdir option (-s)
+* ntpd trustedkey:: trustedkey option (-t)
+* ntpd updateinterval:: updateinterval option (-U)
+* ntpd user:: user option (-u)
+* ntpd var:: var option (-v)
+@end menu
+
+@node ntpd usage
+@subsection ntpd usage help (-?)
+@cindex ntpd usage
+
+This is the automatically generated usage text for ntpd:
+
+@exampleindent 0
+@example
+ntpd - NTP daemon program - Ver. 4.2.5p113
+USAGE: ntpd [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
+ Flg Arg Option-Name Description
+ -4 no ipv4 Force IPv4 DNS name resolution
+ -6 no ipv6 Force IPv6 DNS name resolution
+ - an alternate for ipv4
+ -a no authreq Require crypto authentication
+ - prohibits these options:
+ authnoreq
+ -A no authnoreq Do not require crypto authentication
+ - prohibits these options:
+ authreq
+ -b no bcastsync Allow us to sync to broadcast servers
+ -c Str configfile configuration file name
+ -d no debug-level Increase output debug message level
+ - may appear multiple times
+ -D Str set-debug-level Set the output debug message level
+ - may appear multiple times
+ -f Str driftfile frequency drift file name
+ -g no panicgate Allow the first adjustment to be Big
+ -I Str interface Listen on the specified interface or IP
+ - may appear multiple times
+ -k Str keyfile path to symmetric keys
+ -l Str logfile path to the log file
+ -L no novirtualips Do not listen to virtual IPs
+ -n no nofork Do not fork
+ -N no nice Run at high priority
+ -p Str pidfile path to the PID file
+ -P Num priority Process priority
+ -q no quit Set the time and quit
+ -r Str propagationdelay Broadcast/propagation delay
+ -s Str statsdir Statistics file location
+ -t Str trustedkey Trusted key number
+ - may appear multiple times
+ -U Num updateinterval interval in seconds between scans for new or dropped interfaces
+ Str var make ARG an ntp variable (RW)
+ - may appear multiple times
+ Str dvar make ARG an ntp variable (RW|DEF)
+ - may appear multiple times
+ -x no slew Slew up to 600 seconds
+ opt version Output version information and exit
+ -? no help Display usage information and exit
+ -! no more-help Extended usage information passed thru pager
+
+Options are specified by doubled hyphens and their name
+or by a single hyphen and the flag character.
+
+The following option preset mechanisms are supported:
+ - examining environment variables named NTPD_*
+
+
+
+please send bug reports to: http://bugs.ntp.org, bugs@@ntp.org
+@end example
+@exampleindent 4
+
+@node ntpd ipv4
+@subsection ipv4 option (-4)
+@cindex ntpd-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node ntpd ipv6
+@subsection ipv6 option (-6)
+@cindex ntpd-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node ntpd authreq
+@subsection authreq option (-a)
+@cindex ntpd-authreq
+
+This is the ``require crypto authentication'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authnoreq.
+@end itemize
+
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+
+@node ntpd authnoreq
+@subsection authnoreq option (-A)
+@cindex ntpd-authnoreq
+
+This is the ``do not require crypto authentication'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authreq.
+@end itemize
+
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+
+@node ntpd bcastsync
+@subsection bcastsync option (-b)
+@cindex ntpd-bcastsync
+
+This is the ``allow us to sync to broadcast servers'' option.
+
+
+@node ntpd configfile
+@subsection configfile option (-c)
+@cindex ntpd-configfile
+
+This is the ``configuration file name'' option.
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+
+@node ntpd debug-level
+@subsection debug-level option (-d)
+@cindex ntpd-debug-level
+
+This is the ``increase output debug message level'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@item
+must be compiled in by defining @code{DEBUG} during the compilation.
+@end itemize
+
+Increase the debugging message output level.
+
+@node ntpd set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntpd-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@item
+must be compiled in by defining @code{DEBUG} during the compilation.
+@end itemize
+
+Set the output debugging level. Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntpd driftfile
+@subsection driftfile option (-f)
+@cindex ntpd-driftfile
+
+This is the ``frequency drift file name'' option.
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the
+/etc/ntp.conf
+file.
+
+@node ntpd panicgate
+@subsection panicgate option (-g)
+@cindex ntpd-panicgate
+
+This is the ``allow the first adjustment to be big'' option.
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+
+@node ntpd jaildir
+@subsection jaildir option (-i)
+@cindex ntpd-jaildir
+
+This is the ``jail directory'' option.
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+
+@node ntpd interface
+@subsection interface option (-I)
+@cindex ntpd-interface
+
+This is the ``listen on interface'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpd keyfile
+@subsection keyfile option (-k)
+@cindex ntpd-keyfile
+
+This is the ``path to symmetric keys'' option.
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+
+@node ntpd logfile
+@subsection logfile option (-l)
+@cindex ntpd-logfile
+
+This is the ``path to the log file'' option.
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+
+@node ntpd novirtualips
+@subsection novirtualips option (-L)
+@cindex ntpd-novirtualips
+
+This is the ``do not listen to virtual ips'' option.
+Do not listen to virtual IPs. The default is to listen.
+
+@node ntpd modifymmtimer
+@subsection modifymmtimer option (-M)
+@cindex ntpd-modifymmtimer
+
+This is the ``modify multimedia timer (windows only)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{SYS_WINNT} during the compilation.
+@end itemize
+
+Set the Windows Multimedia Timer to highest resolution.
+
+@node ntpd nofork
+@subsection nofork option (-n)
+@cindex ntpd-nofork
+
+This is the ``do not fork'' option.
+
+
+@node ntpd nice
+@subsection nice option (-N)
+@cindex ntpd-nice
+
+This is the ``run at high priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+
+@node ntpd pidfile
+@subsection pidfile option (-p)
+@cindex ntpd-pidfile
+
+This is the ``path to the pid file'' option.
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+
+@node ntpd priority
+@subsection priority option (-P)
+@cindex ntpd-priority
+
+This is the ``process priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+
+@node ntpd quit
+@subsection quit option (-q)
+@cindex ntpd-quit
+
+This is the ``set the time and quit'' option.
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+
+@node ntpd propagationdelay
+@subsection propagationdelay option (-r)
+@cindex ntpd-propagationdelay
+
+This is the ``broadcast/propagation delay'' option.
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+
+@node ntpd updateinterval
+@subsection updateinterval option (-U)
+@cindex ntpd-updateinterval
+
+This is the ``interval in seconds between scans for new or dropped interfaces'' option.
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning.
+
+@node ntpd statsdir
+@subsection statsdir option (-s)
+@cindex ntpd-statsdir
+
+This is the ``statistics file location'' option.
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+
+@node ntpd trustedkey
+@subsection trustedkey option (-t)
+@cindex ntpd-trustedkey
+
+This is the ``trusted key number'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Add a key number to the trusted key list.
+
+@node ntpd user
+@subsection user option (-u)
+@cindex ntpd-user
+
+This is the ``run as userid (or userid:groupid)'' option.
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+
+@node ntpd var
+@subsection var option (-v)
+@cindex ntpd-var
+
+This is the ``make arg an ntp variable (rw)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpd dvar
+@subsection dvar option (-V)
+@cindex ntpd-dvar
+
+This is the ``make arg an ntp variable (rw|def)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpd slew
+@subsection slew option (-x)
+@cindex ntpd-slew
+
+This is the ``slew up to 600 seconds'' option.
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
diff --git a/contrib/ntp/ntpd/ntpd.1 b/contrib/ntp/ntpd/ntpd.1
new file mode 100644
index 0000000..25aee41
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpd.1
@@ -0,0 +1,296 @@
+.TH NTPD 1 2008-08-17 "( 4.2.4p5)" "Programmer's Manual"
+.\" EDIT THIS FILE WITH CAUTION (ntpd.1)
+.\"
+.\" It has been AutoGen-ed Sunday August 17, 2008 at 05:20:11 AM EDT
+.\" From the definitions ntpd-opts.def
+.\" and the template file agman1.tpl
+.\"
+.SH NAME
+ntpd \- NTP daemon program
+.SH SYNOPSIS
+.B ntpd
+.\" Mixture of short (flag) options and long options
+.RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \--\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
+.PP
+All arguments must be options.
+.SH "DESCRIPTION"
+This manual page documents, briefly, the \fBntpd\fP command.
+
+.SH OPTIONS
+.TP
+.BR \-4 ", " \--ipv4
+Force IPv4 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+.TP
+.BR \-6 ", " \--ipv6
+Force IPv6 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+.TP
+.BR \-a ", " \--authreq
+Require crypto authentication.
+This option must not appear in combination with any of the following options:
+authnoreq.
+.sp
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+.TP
+.BR \-A ", " \--authnoreq
+Do not require crypto authentication.
+This option must not appear in combination with any of the following options:
+authreq.
+.sp
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+.TP
+.BR \-b ", " \--bcastsync
+Allow us to sync to broadcast servers.
+.sp
+
+.TP
+.BR \-c " \fIstring\fP, " \--configfile "=" \fIstring\fP
+configuration file name.
+.sp
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+.TP
+.BR \-d ", " \--debug-level
+Increase output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Increase the debugging message output level.
+.TP
+.BR \-D " \fIstring\fP, " \--set-debug-level "=" \fIstring\fP
+Set the output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Set the output debugging level. Can be supplied multiple times,
+but each overrides the previous value(s).
+.TP
+.BR \-f " \fIstring\fP, " \--driftfile "=" \fIstring\fP
+frequency drift file name.
+.sp
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the
+/etc/ntp.conf
+file.
+.TP
+.BR \-g ", " \--panicgate
+Allow the first adjustment to be Big.
+.sp
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+.TP
+.BR \-i " \fIstring\fP, " \--jaildir "=" \fIstring\fP
+Jail directory.
+.sp
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+.TP
+.BR \-I " \fIiface\fP, " \--interface "=" \fIiface\fP
+Listen on interface.
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR \-k " \fIstring\fP, " \--keyfile "=" \fIstring\fP
+path to symmetric keys.
+.sp
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+.TP
+.BR \-l " \fIstring\fP, " \--logfile "=" \fIstring\fP
+path to the log file.
+.sp
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+.TP
+.BR \-L ", " \--novirtualips
+Do not listen to virtual IPs.
+.sp
+Do not listen to virtual IPs. The default is to listen.
+.TP
+.BR \-M ", " \--modifymmtimer
+Modify Multimedia Timer (Windows only).
+.sp
+Set the Windows Multimedia Timer to highest resolution.
+.TP
+.BR \-n ", " \--nofork
+Do not fork.
+.sp
+
+.TP
+.BR \-N ", " \--nice
+Run at high priority.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+.TP
+.BR \-p " \fIstring\fP, " \--pidfile "=" \fIstring\fP
+path to the PID file.
+.sp
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+.TP
+.BR \-P " \fInumber\fP, " \--priority "=" \fInumber\fP
+Process priority.
+This option takes an integer number as its argument.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+.TP
+.BR \-q ", " \--quit
+Set the time and quit.
+.sp
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR \-r " \fIstring\fP, " \--propagationdelay "=" \fIstring\fP
+Broadcast/propagation delay.
+.sp
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+.TP
+.BR \-U " \fInumber\fP, " \--updateinterval "=" \fInumber\fP
+interval in seconds between scans for new or dropped interfaces.
+This option takes an integer number as its argument.
+.sp
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning.
+.TP
+.BR \-s " \fIstring\fP, " \--statsdir "=" \fIstring\fP
+Statistics file location.
+.sp
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+.TP
+.BR \-t " \fItkey\fP, " \--trustedkey "=" \fItkey\fP
+Trusted key number.
+This option may appear an unlimited number of times.
+.sp
+Add a key number to the trusted key list.
+.TP
+.BR \-u " \fIstring\fP, " \--user "=" \fIstring\fP
+Run as userid (or userid:groupid).
+.sp
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+.TP
+.BR \-v " \fInvar\fP, " \--var "=" \fInvar\fP
+make ARG an ntp variable (RW).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR \-V " \fIndvar\fP, " \--dvar "=" \fIndvar\fP
+make ARG an ntp variable (RW|DEF).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR \-x ", " \--slew
+Slew up to 600 seconds.
+.sp
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR \-? , " \--help"
+Display usage information and exit.
+.TP
+.BR \-! , " \--more-help"
+Extended usage information passed thru pager.
+.TP
+.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+Output version of program and exit. The default mode is `v', a simple
+version. The `c' mode will print copyright information and `n' will
+print the full copyright notice.
+.SH OPTION PRESETS
+Any option that is not marked as \fInot presettable\fP may be preset
+by loading values from environment variables named:
+.nf
+ \fBNTPD_<option-name>\fP or \fBNTPD\fP
+.fi
+.aj
+.SH AUTHOR
+David L. Mills and/or others
+.br
+Please send bug reports to: http://bugs.ntp.isc.org, bugs@ntp.org
+
+.PP
+.nf
+.na
+see html/copyright.html
+.fi
+.ad
+.PP
+This manual page was \fIAutoGen\fP-erated from the \fBntpd\fP
+option definitions.
diff --git a/contrib/ntp/ntpd/ntpd.c b/contrib/ntp/ntpd/ntpd.c
index 0b05253..04e0d07 100644
--- a/contrib/ntp/ntpd/ntpd.c
+++ b/contrib/ntp/ntpd/ntpd.c
@@ -10,9 +10,13 @@
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_stdlib.h"
+#include <ntp_random.h>
#ifdef SIM
-#include "ntpsim.h"
+# include "ntpsim.h"
+# include "ntpdsim-opts.h"
+#else
+# include "ntpd-opts.h"
#endif
#ifdef HAVE_UNISTD_H
@@ -43,9 +47,8 @@
# include <signal.h>
# include <process.h>
# include <io.h>
-# include "../libntp/log.h"
# include <clockstuff.h>
-# include <crtdbg.h>
+#include "ntp_iocompletionport.h"
#endif /* SYS_WINNT */
#if defined(HAVE_RTPRIO)
# ifdef HAVE_SYS_RESOURCE_H
@@ -104,10 +107,14 @@
# include <sys/ci/ciioctl.h>
#endif
-#ifdef HAVE_CLOCKCTL
+#ifdef HAVE_DROPROOT
# include <ctype.h>
# include <grp.h>
# include <pwd.h>
+#ifdef HAVE_LINUX_CAPABILITIES
+# include <sys/capability.h>
+# include <sys/prctl.h>
+#endif
#endif
/*
@@ -126,18 +133,10 @@
# define SIGDIE4 SIGTERM
#endif /* SYS_WINNT */
-#if defined SYS_WINNT
-/* handles for various threads, process, and objects */
-HANDLE ResolverThreadHandle = NULL;
-/* variables used to inform the Service Control Manager of our current state */
-BOOL NoWinService = FALSE;
-SERVICE_STATUS ssStatus;
-SERVICE_STATUS_HANDLE sshStatusHandle;
-HANDLE WaitHandles[3] = { NULL, NULL, NULL };
-char szMsgPath[255];
-static BOOL WINAPI OnConsoleEvent(DWORD dwCtrlType);
-BOOL init_randfile();
-#endif /* SYS_WINNT */
+#ifdef HAVE_DNSREGISTRATION
+#include <dns_sd.h>
+DNSServiceRef mdns;
+#endif
/*
* Scheduling priority we run at
@@ -149,22 +148,23 @@ int priority_done = 2; /* 0 - Set priority */
/* 2 - Don't set priority */
/* 1 and 2 are pretty much the same */
+#ifdef DEBUG
/*
* Debugging flag
*/
-volatile int debug;
+volatile int debug = 0; /* No debugging by default */
+#endif
-/*
- * Set the processing not to be in the forground
- */
-int forground_process = FALSE;
+int listen_to_virtual_ips = 1;
+const char *specific_interface = NULL; /* interface name or IP address to bind to */
/*
* No-fork flag. If set, we do not become a background daemon.
*/
-int nofork;
+int nofork = 0; /* Fork by default */
-#ifdef HAVE_CLOCKCTL
+#ifdef HAVE_DROPROOT
+int droproot = 0;
char *user = NULL; /* User to switch to */
char *group = NULL; /* group to switch to */
char *chrootdir = NULL; /* directory to chroot to */
@@ -173,7 +173,7 @@ int sw_gid;
char *endp;
struct group *gr;
struct passwd *pw;
-#endif /* HAVE_CLOCKCTL */
+#endif /* HAVE_DROPROOT */
/*
* Initializing flag. All async routines watch this and only do their
@@ -186,6 +186,8 @@ int initializing;
*/
extern const char *Version;
+char const *progname;
+
int was_alarmed;
#ifdef DECL_SYSCALL
@@ -211,6 +213,86 @@ static RETSIGTYPE no_debug P((int));
int ntpdmain P((int, char **));
static void set_process_priority P((void));
+static void init_logging P((char const *));
+static void setup_logfile P((void));
+
+/*
+ * Initialize the logging
+ */
+void
+init_logging(char const *name)
+{
+ const char *cp;
+
+ /*
+ * Logging. This may actually work on the gizmo board. Find a name
+ * to log with by using the basename
+ */
+ cp = strrchr(name, '/');
+ if (cp == 0)
+ cp = name;
+ else
+ cp++;
+
+#if !defined(VMS)
+
+# ifndef LOG_DAEMON
+ openlog(cp, LOG_PID);
+# else /* LOG_DAEMON */
+
+# ifndef LOG_NTP
+# define LOG_NTP LOG_DAEMON
+# endif
+ openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
+# ifdef DEBUG
+ if (debug)
+ setlogmask(LOG_UPTO(LOG_DEBUG));
+ else
+# endif /* DEBUG */
+ setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
+# endif /* LOG_DAEMON */
+#endif /* !SYS_WINNT && !VMS */
+
+ NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
+ msyslog(LOG_NOTICE, "%s", Version);
+}
+
+
+/*
+ * See if we should redirect the logfile
+ */
+
+void
+setup_logfile(
+ void
+ )
+{
+ if (HAVE_OPT( LOGFILE )) {
+ const char *my_optarg = OPT_ARG( LOGFILE );
+ FILE *new_file;
+
+ if(strcmp(my_optarg, "stderr") == 0)
+ new_file = stderr;
+ else if(strcmp(my_optarg, "stdout") == 0)
+ new_file = stdout;
+ else
+ new_file = fopen(my_optarg, "a");
+ if (new_file != NULL) {
+ NLOG(NLOG_SYSINFO)
+ msyslog(LOG_NOTICE, "logging to file %s", my_optarg);
+ if (syslog_file != NULL &&
+ fileno(syslog_file) != fileno(new_file))
+ (void)fclose(syslog_file);
+
+ syslog_file = new_file;
+ syslogit = 0;
+ }
+ else
+ msyslog(LOG_ERR,
+ "Cannot open log file %s",
+ my_optarg);
+ }
+}
#ifdef SIM
int
@@ -225,6 +307,7 @@ main(
#ifdef NO_MAIN_ALLOWED
CALL(ntpd,"ntpd",ntpdmain);
#else
+#ifndef SYS_WINNT
int
main(
int argc,
@@ -233,7 +316,8 @@ main(
{
return ntpdmain(argc, argv);
}
-#endif
+#endif /* SYS_WINNT */
+#endif /* NO_MAIN_ALLOWED */
#endif /* SIM */
#ifdef _AIX
@@ -371,16 +455,30 @@ ntpdmain(
)
{
l_fp now;
- char *cp;
- struct recvbuf *rbuflist;
struct recvbuf *rbuf;
#ifdef _AIX /* HMS: ifdef SIGDANGER? */
struct sigaction sa;
#endif
+ progname = argv[0];
+
initializing = 1; /* mark that we are initializing */
- debug = 0; /* no debugging by default */
- nofork = 0; /* will fork by default */
+
+ {
+ int optct = optionProcess(
+#ifdef SIM
+ &ntpdsimOptions
+#else
+ &ntpdOptions
+#endif
+ , argc, argv);
+ argc -= optct;
+ argv += optct;
+ }
+
+ /* HMS: is this lame? Should we process -l first? */
+
+ init_logging(progname); /* Open the log file */
#ifdef HAVE_UMASK
{
@@ -402,45 +500,102 @@ ntpdmain(
if (uid)
{
msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
+ printf("must be run as root, not uid %ld", (long)uid);
exit(1);
}
}
#endif
-#ifdef SYS_WINNT
- /* Set the Event-ID message-file name. */
- if (!GetModuleFileName(NULL, szMsgPath, sizeof(szMsgPath))) {
- msyslog(LOG_ERR, "GetModuleFileName(PGM_EXE_FILE) failed: %m\n");
+#ifdef OPENSSL
+ if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
+ msyslog(LOG_ERR,
+ "ntpd: OpenSSL version mismatch. Built against %lx, you have %lx\n",
+ OPENSSL_VERSION_NUMBER, SSLeay());
exit(1);
}
- addSourceToRegistry("NTP", szMsgPath);
#endif
- getstartup(argc, argv); /* startup configuration, may set debug */
+ /* getstartup(argc, argv); / * startup configuration, may set debug */
+
+#ifdef DEBUG
+ debug = DESC(DEBUG_LEVEL).optOccCt;
if (debug)
printf("%s\n", Version);
+#endif
+
+/*
+ * Enable the Multi-Media Timer for Windows?
+ */
+#ifdef SYS_WINNT
+ if (HAVE_OPT( MODIFYMMTIMER ))
+ set_mm_timer(MM_TIMER_HIRES);
+#endif
+
+ if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT ))
+ nofork = 1;
+
+ if (HAVE_OPT( NOVIRTUALIPS ))
+ listen_to_virtual_ips = 0;
+ if (HAVE_OPT( INTERFACE )) {
+#if 0
+ int ifacect = STACKCT_OPT( INTERFACE );
+ char** ifaces = STACKLST_OPT( INTERFACE );
+
+ /* malloc space for the array of names */
+ while (ifacect-- > 0) {
+ next_iface = *ifaces++;
+ }
+#else
+ specific_interface = OPT_ARG( INTERFACE );
+#endif
+ }
+
+ if (HAVE_OPT( NICE ))
+ priority_done = 0;
+
+#if defined(HAVE_SCHED_SETSCHEDULER)
+ if (HAVE_OPT( PRIORITY )) {
+ config_priority = OPT_VALUE_PRIORITY;
+ config_priority_override = 1;
+ priority_done = 0;
+ }
+#endif
+
+#ifdef SYS_WINNT
/*
- * Initialize random generator and public key pair
+ * Initialize the time structures and variables
*/
-#ifdef SYS_WINNT
- /* Initialize random file before OpenSSL checks */
- if(!init_randfile())
- msyslog(LOG_ERR, "Unable to initialize .rnd file\n");
+ init_winnt_time();
#endif
+
+ setup_logfile();
+
+ /*
+ * Initialize random generator and public key pair
+ */
get_systime(&now);
- SRANDOM((int)(now.l_i * now.l_uf));
+
+ ntp_srandom((int)(now.l_i * now.l_uf));
+
+#ifdef HAVE_DNSREGISTRATION
+ /* HMS: does this have to happen this early? */
+ msyslog(LOG_INFO, "Attemping to register mDNS");
+ if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
+ msyslog(LOG_ERR, "Unable to register mDNS");
+ }
+#endif
#if !defined(VMS)
# ifndef NODETACH
/*
* Detach us from the terminal. May need an #ifndef GIZMO.
*/
+ if (
# ifdef DEBUG
- if (!debug && !nofork)
-# else /* DEBUG */
- if (!nofork)
+ !debug &&
# endif /* DEBUG */
+ !nofork)
{
# ifndef SYS_WINNT
# ifdef HAVE_DAEMON
@@ -522,131 +677,12 @@ ntpdmain(
#endif /* _AIX */
}
# endif /* not HAVE_DAEMON */
-# else /* SYS_WINNT */
-
- {
- if (NoWinService == FALSE) {
- SERVICE_TABLE_ENTRY dispatchTable[] = {
- { TEXT("NetworkTimeProtocol"), (LPSERVICE_MAIN_FUNCTION)service_main },
- { NULL, NULL }
- };
-
- /* daemonize */
- if (!StartServiceCtrlDispatcher(dispatchTable))
- {
- msyslog(LOG_ERR, "StartServiceCtrlDispatcher: %m");
- ExitProcess(2);
- }
- }
- else {
- service_main(argc, argv);
- return 0;
- }
- }
# endif /* SYS_WINNT */
}
# endif /* NODETACH */
-# if defined(SYS_WINNT) && !defined(NODETACH)
- else
- service_main(argc, argv);
- return 0; /* must return a value */
-} /* end main */
-
-/*
- * If this runs as a service under NT, the main thread will block at
- * StartServiceCtrlDispatcher() and another thread will be started by the
- * Service Control Dispatcher which will begin execution at the routine
- * specified in that call (viz. service_main)
- */
-void
-service_main(
- DWORD argc,
- LPTSTR *argv
- )
-{
- char *cp;
- struct recvbuf *rbuflist;
- struct recvbuf *rbuf;
-
- if(!debug && NoWinService == FALSE)
- {
- /* register our service control handler */
- sshStatusHandle = RegisterServiceCtrlHandler( TEXT("NetworkTimeProtocol"),
- (LPHANDLER_FUNCTION)service_ctrl);
- if(sshStatusHandle == 0)
- {
- msyslog(LOG_ERR, "RegisterServiceCtrlHandler failed: %m");
- return;
- }
-
- /* report pending status to Service Control Manager */
- ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- ssStatus.dwCurrentState = SERVICE_START_PENDING;
- ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- ssStatus.dwServiceSpecificExitCode = 0;
- ssStatus.dwCheckPoint = 1;
- ssStatus.dwWaitHint = 5000;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- ssStatus.dwCurrentState = SERVICE_STOPPED;
- SetServiceStatus(sshStatusHandle, &ssStatus);
- return;
- }
-
- } /* debug */
-# endif /* defined(SYS_WINNT) && !defined(NODETACH) */
#endif /* VMS */
- /*
- * Logging. This may actually work on the gizmo board. Find a name
- * to log with by using the basename of argv[0]
- */
- cp = strrchr(argv[0], '/');
- if (cp == 0)
- cp = argv[0];
- else
- cp++;
-
- debug = 0; /* will be immediately re-initialized 8-( */
- getstartup(argc, argv); /* startup configuration, catch logfile this time */
-
-#if !defined(VMS)
-
-# ifndef LOG_DAEMON
- openlog(cp, LOG_PID);
-# else /* LOG_DAEMON */
-
-# ifndef LOG_NTP
-# define LOG_NTP LOG_DAEMON
-# endif
- openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
-# ifdef DEBUG
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
- else
-# endif /* DEBUG */
- setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
-# endif /* LOG_DAEMON */
-#endif /* !SYS_WINNT && !VMS */
-
- NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "%s", Version);
-
-#ifdef SYS_WINNT
- /* GMS 1/18/1997
- * TODO: lock the process in memory using SetProcessWorkingSetSize() and VirtualLock() functions
- *
- process_handle = GetCurrentProcess();
- if (SetProcessWorkingSetSize(process_handle, 2097152 , 4194304 ) == TRUE) {
- if (VirtualLock(0 , 4194304) == FALSE)
- msyslog(LOG_ERR, "VirtualLock() failed: %m");
- } else {
- msyslog(LOG_ERR, "SetProcessWorkingSetSize() failed: %m");
- }
- */
-#endif /* SYS_WINNT */
+ setup_logfile(); /* We lost any redirect when we daemonized */
#ifdef SCO5_CLOCK
/*
@@ -659,7 +695,7 @@ service_main(
if (fd >= 0) {
int zero = 0;
if (ioctl(fd, ACPU_LOCK, &zero) < 0)
- msyslog(LOG_ERR, "cannot lock to base CPU: %m\n");
+ msyslog(LOG_ERR, "cannot lock to base CPU: %m");
close( fd );
} /* else ...
* If we can't open the device, this probably just isn't
@@ -677,8 +713,9 @@ service_main(
{
struct rlimit rl;
+ /* HMS: must make the rlim_cur amount configurable */
if (getrlimit(RLIMIT_STACK, &rl) != -1
- && (rl.rlim_cur = 20 * 4096) < rl.rlim_max)
+ && (rl.rlim_cur = 50 * 4096) < rl.rlim_max)
{
if (setrlimit(RLIMIT_STACK, &rl) == -1)
{
@@ -686,6 +723,18 @@ service_main(
"Cannot adjust stack limit for mlockall: %m");
}
}
+# ifdef RLIMIT_MEMLOCK
+ /*
+ * The default RLIMIT_MEMLOCK is very low on Linux systems.
+ * Unless we increase this limit malloc calls are likely to
+ * fail if we drop root privlege. To be useful the value
+ * has to be larger than the largest ntpd resident set size.
+ */
+ rl.rlim_cur = rl.rlim_max = 32*1024*1024;
+ if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) {
+ msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
+ }
+# endif /* RLIMIT_MEMLOCK */
}
# endif /* HAVE_SETRLIMIT */
/*
@@ -699,7 +748,7 @@ service_main(
# ifdef _AIX
/*
* set the stack limit for AIX for plock().
- * see get_aix_stack for more info.
+ * see get_aix_stack() for more info.
*/
if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
{
@@ -762,26 +811,20 @@ service_main(
(void) signal_no_reset(SIGPIPE, SIG_IGN);
#endif /* SIGPIPE */
-#if defined SYS_WINNT
- if (!SetConsoleCtrlHandler(OnConsoleEvent, TRUE)) {
- msyslog(LOG_ERR, "Can't set console control handler: %m");
- }
-#endif
-
/*
* Call the init_ routines to initialize the data structures.
+ *
+ * Exactly what command-line options are we expecting here?
*/
-#if defined (HAVE_IO_COMPLETION_PORT)
- init_io_completion_port();
- init_winnt_time();
-#endif
init_auth();
init_util();
init_restrict();
init_mon();
init_timer();
+#if defined (HAVE_IO_COMPLETION_PORT)
+ init_io_completion_port();
+#endif
init_lib();
- init_random();
init_request();
init_control();
init_peer();
@@ -796,102 +839,137 @@ service_main(
/* turn off in config if unwanted */
/*
- * Get configuration. This (including argument list parsing) is
- * done in a separate module since this will definitely be different
- * for the gizmo board. While at it, save the host name for later
- * along with the length. The crypto needs this.
+ * Get the configuration. This is done in a separate module
+ * since this will definitely be different for the gizmo board.
*/
-#ifdef DEBUG
- debug = 0;
-#endif
+
getconfig(argc, argv);
+
+ loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
#ifdef OPENSSL
crypto_setup();
#endif /* OPENSSL */
initializing = 0;
-#if defined(SYS_WINNT) && !defined(NODETACH)
-# if defined(DEBUG)
- if(!debug)
- {
-# endif
- if (NoWinService == FALSE) {
- /* report to the service control manager that the service is running */
- ssStatus.dwCurrentState = SERVICE_RUNNING;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- if (ResolverThreadHandle != NULL)
- CloseHandle(ResolverThreadHandle);
- ssStatus.dwCurrentState = SERVICE_STOPPED;
- SetServiceStatus(sshStatusHandle, &ssStatus);
- return;
- }
- }
-# if defined(DEBUG)
- }
-# endif
-#endif
+#ifdef HAVE_DROPROOT
+ if( droproot ) {
+ /* Drop super-user privileges and chroot now if the OS supports this */
-#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 {
+#ifdef HAVE_LINUX_CAPABILITIES
+ /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
+ if( prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1 ) {
+ msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
+ exit(-1);
+ }
+#else
+ /* we need a user to switch to */
+ if( user == NULL ) {
+ msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
+ exit(-1);
+ }
+#endif /* HAVE_LINUX_CAPABILITIES */
+
+ 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 {
+ 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);
- }
+ if ((gr = getgrnam(group)) != NULL) {
+ sw_gid = gr->gr_gid;
+ } else {
+ errno = 0;
+ msyslog(LOG_ERR, "Cannot find group `%s'", group);
+ exit (-1);
+ }
+ }
+ }
+
+ if( chrootdir ) {
+ /* make sure cwd is inside the jail: */
+ if( chdir(chrootdir) ) {
+ msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
+ exit (-1);
+ }
+ if( 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);
+ }
+
+#ifndef HAVE_LINUX_CAPABILITIES
+ /*
+ * for now assume that the privilege to bind to privileged ports
+ * is associated with running with uid 0 - should be refined on
+ * ports that allow binding to NTP_PORT with uid != 0
+ */
+ disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */
#endif
+
+ if (disable_dynamic_updates && interface_interval) {
+ interface_interval = 0;
+ msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
+ }
+
+#ifdef HAVE_LINUX_CAPABILITIES
+ do {
+ /*
+ * We may be running under non-root uid now, but we still hold full root privileges!
+ * We drop all of them, except for the crucial one or two: cap_sys_time and
+ * cap_net_bind_service if doing dynamic interface tracking.
+ */
+ cap_t caps;
+ char *captext = interface_interval ?
+ "cap_sys_time,cap_net_bind_service=ipe" :
+ "cap_sys_time=ipe";
+ if( ! ( caps = cap_from_text( captext ) ) ) {
+ msyslog( LOG_ERR, "cap_from_text() failed: %m" );
+ exit(-1);
+ }
+ if( cap_set_proc( caps ) == -1 ) {
+ msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" );
+ exit(-1);
+ }
+ cap_free( caps );
+ } while(0);
+#endif /* HAVE_LINUX_CAPABILITIES */
+
+ } /* if( droproot ) */
+#endif /* HAVE_DROPROOT */
+
/*
* Report that we're up to any trappers
*/
@@ -913,48 +991,13 @@ getgroup:
* yet to learn about anything else that is.
*/
#if defined(HAVE_IO_COMPLETION_PORT)
- WaitHandles[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* exit reques */
- WaitHandles[1] = get_timer_handle();
- WaitHandles[2] = get_io_event();
-
- for (;;) {
- DWORD Index = WaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, FALSE, 1000, TRUE);
- switch (Index) {
- case WAIT_OBJECT_0 + 0 : /* exit request */
- exit(0);
- break;
-
- case WAIT_OBJECT_0 + 1 : /* timer */
- timer();
- break;
-
- case WAIT_OBJECT_0 + 2 : /* Io event */
-# ifdef DEBUG
- if ( debug > 3 )
- {
- printf( "IoEvent occurred\n" );
- }
-# endif
- break;
-
- case WAIT_IO_COMPLETION : /* loop */
- case WAIT_TIMEOUT :
- break;
- case WAIT_FAILED:
- msyslog(LOG_ERR, "ntpdc: WaitForMultipleObjectsEx Failed: Error: %m");
- break;
-
- /* For now do nothing if not expected */
- default:
- break;
-
- } /* switch */
- rbuflist = getrecvbufs(); /* get received buffers */
+ for (;;) {
+ int tot_full_recvbufs = GetReceivedBuffers();
#else /* normal I/O */
+ BLOCK_IO_AND_ALARM();
was_alarmed = 0;
- rbuflist = (struct recvbuf *)0;
for (;;)
{
# if !defined(HAVE_SIGNALED_IO)
@@ -963,18 +1006,15 @@ getgroup:
fd_set rdfdes;
int nfound;
-# elif defined(HAVE_SIGNALED_IO)
- block_io_and_alarm();
# endif
- rbuflist = getrecvbufs(); /* get received buffers */
if (alarm_flag) /* alarmed? */
{
was_alarmed = 1;
alarm_flag = 0;
}
- if (!was_alarmed && rbuflist == (struct recvbuf *)0)
+ if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE)
{
/*
* Nothing to do. Wait for something.
@@ -1003,10 +1043,10 @@ getgroup:
(void)input_handler(&ts);
}
else if (nfound == -1 && errno != EINTR)
- msyslog(LOG_ERR, "select() error: %m");
+ netsyslog(LOG_ERR, "select() error: %m");
# ifdef DEBUG
- else if (debug > 2)
- msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
+ else if (debug > 5)
+ netsyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
# endif /* DEBUG */
# else /* HAVE_SIGNALED_IO */
@@ -1017,50 +1057,87 @@ getgroup:
was_alarmed = 1;
alarm_flag = 0;
}
- rbuflist = getrecvbufs(); /* get received buffers */
}
-# ifdef HAVE_SIGNALED_IO
- unblock_io_and_alarm();
-# endif /* HAVE_SIGNALED_IO */
- /*
- * Out here, signals are unblocked. Call timer routine
- * to process expiry.
- */
if (was_alarmed)
{
+ UNBLOCK_IO_AND_ALARM();
+ /*
+ * Out here, signals are unblocked. Call timer routine
+ * to process expiry.
+ */
timer();
was_alarmed = 0;
+ BLOCK_IO_AND_ALARM();
}
#endif /* HAVE_IO_COMPLETION_PORT */
- /*
- * Call the data procedure to handle each received
- * packet.
- */
- while (rbuflist != (struct recvbuf *)0)
+
+#ifdef DEBUG_TIMING
{
- rbuf = rbuflist;
- rbuflist = rbuf->next;
- (rbuf->receiver)(rbuf);
- freerecvbuf(rbuf);
+ l_fp pts;
+ l_fp tsa, tsb;
+ int bufcount = 0;
+
+ get_systime(&pts);
+ tsa = pts;
+#endif
+ rbuf = get_full_recv_buffer();
+ while (rbuf != NULL)
+ {
+ if (alarm_flag)
+ {
+ was_alarmed = 1;
+ alarm_flag = 0;
+ }
+ UNBLOCK_IO_AND_ALARM();
+
+ if (was_alarmed)
+ { /* avoid timer starvation during lengthy I/O handling */
+ timer();
+ was_alarmed = 0;
+ }
+
+ /*
+ * Call the data procedure to handle each received
+ * packet.
+ */
+ if (rbuf->receiver != NULL) /* This should always be true */
+ {
+#ifdef DEBUG_TIMING
+ l_fp dts = pts;
+
+ L_SUB(&dts, &rbuf->recv_time);
+ DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
+ collect_timing(rbuf, "buffer processing delay", 1, &dts);
+ bufcount++;
+#endif
+ (rbuf->receiver)(rbuf);
+ } else {
+ msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING");
+ abort();
+ }
+
+ BLOCK_IO_AND_ALARM();
+ freerecvbuf(rbuf);
+ rbuf = get_full_recv_buffer();
+ }
+#ifdef DEBUG_TIMING
+ get_systime(&tsb);
+ L_SUB(&tsb, &tsa);
+ if (bufcount) {
+ collect_timing(NULL, "processing", bufcount, &tsb);
+ DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
+ }
}
-#if defined DEBUG && defined SYS_WINNT
- if (debug > 4)
- printf("getrecvbufs: %ld handler interrupts, %ld frames\n",
- handler_calls, handler_pkts);
#endif
/*
* Go around again
*/
}
-#ifndef SYS_WINNT
- exit(1); /* unreachable */
-#endif
-#ifndef SYS_WINNT
- return 1; /* DEC OSF cc braindamage */
-#endif
+ UNBLOCK_IO_AND_ALARM();
+ return 1;
}
@@ -1075,6 +1152,11 @@ finish(
{
msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
+ write_stats();
+#ifdef HAVE_DNSREGISTRATION
+ if (mdns != NULL)
+ DNSServiceRefDeallocate(mdns);
+#endif
switch (sig)
{
@@ -1131,7 +1213,8 @@ lessdebug(
}
#endif
#else /* not DEBUG */
-#ifndef SYS_WINNT/*
+#ifndef SYS_WINNT
+/*
* no_debug - We don't do the debug here.
*/
static RETSIGTYPE
@@ -1146,129 +1229,3 @@ no_debug(
}
#endif /* not SYS_WINNT */
#endif /* not DEBUG */
-
-#ifdef SYS_WINNT
-/* service_ctrl - control handler for NTP service
- * signals the service_main routine of start/stop requests
- * from the control panel or other applications making
- * win32API calls
- */
-void
-service_ctrl(
- DWORD dwCtrlCode
- )
-{
- DWORD dwState = SERVICE_RUNNING;
-
- /* Handle the requested control code */
- switch(dwCtrlCode)
- {
- case SERVICE_CONTROL_PAUSE:
- /* see no reason to support this */
- break;
-
- case SERVICE_CONTROL_CONTINUE:
- /* see no reason to support this */
- break;
-
- case SERVICE_CONTROL_STOP:
- dwState = SERVICE_STOP_PENDING;
- /*
- * Report the status, specifying the checkpoint and waithint,
- * before setting the termination event.
- */
- ssStatus.dwCurrentState = dwState;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- ssStatus.dwWaitHint = 3000;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- }
- if (WaitHandles[0] != NULL) {
- SetEvent(WaitHandles[0]);
- }
- return;
-
- case SERVICE_CONTROL_INTERROGATE:
- /* Update the service status */
- break;
-
- default:
- /* invalid control code */
- break;
-
- }
-
- ssStatus.dwCurrentState = dwState;
- ssStatus.dwWin32ExitCode = NO_ERROR;
- if (!SetServiceStatus(sshStatusHandle, &ssStatus))
- {
- msyslog(LOG_ERR, "SetServiceStatus: %m");
- }
-}
-
-static BOOL WINAPI
-OnConsoleEvent(
- DWORD dwCtrlType
- )
-{
- switch (dwCtrlType) {
- case CTRL_BREAK_EVENT :
- if (debug > 0) {
- debug <<= 1;
- }
- else {
- debug = 1;
- }
- if (debug > 8) {
- debug = 0;
- }
- printf("debug level %d\n", debug);
- break ;
-
- case CTRL_C_EVENT :
- case CTRL_CLOSE_EVENT :
- case CTRL_SHUTDOWN_EVENT :
- if (WaitHandles[0] != NULL) {
- SetEvent(WaitHandles[0]);
- }
- break;
-
- default :
- return FALSE;
-
-
- }
- return TRUE;;
-}
-
-
-/*
- * NT version of exit() - all calls to exit() should be routed to
- * this function.
- */
-void
-service_exit(
- int status
- )
-{
- if (!debug) { /* did not become a service, simply exit */
- /* service mode, need to have the service_main routine
- * register with the service control manager that the
- * service has stopped running, before exiting
- */
- ssStatus.dwCurrentState = SERVICE_STOPPED;
- SetServiceStatus(sshStatusHandle, &ssStatus);
-
- }
- uninit_io_completion_port();
- reset_winnt_time();
-
-# if defined _MSC_VER
- _CrtDumpMemoryLeaks();
-# endif
-#undef exit
- exit(status);
-}
-
-#endif /* SYS_WINNT */
diff --git a/contrib/ntp/ntpd/ntpdbase-opts.def b/contrib/ntp/ntpd/ntpdbase-opts.def
new file mode 100644
index 0000000..852af45
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpdbase-opts.def
@@ -0,0 +1,459 @@
+#include autogen-version.def
+
+test-main;
+
+flag = {
+ name = ipv4;
+ value = 4;
+ equivalence = ipv4;
+ descrip = "Force IPv4 DNS name resolution";
+ doc = <<- _EndOfDoc_
+ Force DNS resolution of following host names on the command line
+ to the IPv4 namespace.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = ipv6;
+ value = 6;
+ equivalence = ipv4;
+ descrip = "Force IPv6 DNS name resolution";
+ doc = <<- _EndOfDoc_
+ Force DNS resolution of following host names on the command line
+ to the IPv6 namespace.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = authreq;
+ value = a;
+ descrip = "Require crypto authentication";
+ flags-cant = authnoreq;
+ doc = <<- _EndOfDoc_
+ Require cryptographic authentication for broadcast client,
+ multicast client and symmetric passive associations.
+ This is the default.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = authnoreq;
+ value = A;
+ descrip = "Do not require crypto authentication";
+ flags-cant = authreq;
+ doc = <<- _EndOfDoc_
+ Do not require cryptographic authentication for broadcast client,
+ multicast client and symmetric passive associations.
+ This is almost never a good idea.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = bcastsync;
+ value = b;
+ descrip = "Allow us to sync to broadcast servers";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+
+#ifdef SIM
+flag = {
+ name = simbroadcastdelay;
+ value = B;
+ arg-type = string;
+ descrip = "Simulator broadcast delay";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+flag = {
+ name = configfile;
+ value = c;
+ arg-type = string;
+ descrip = "configuration file name";
+ doc = <<- _EndOfDoc_
+ The name and path of the configuration file,
+ /etc/ntp.conf
+ by default.
+ _EndOfDoc_;
+};
+
+#ifdef SIM
+flag = {
+ name = phasenoise;
+ value = C;
+ arg-type = string;
+ descrip = "Phase noise level";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+#include debug-opt.def
+
+flag = {
+ name = driftfile;
+ value = f;
+ arg-type = string;
+ descrip = "frequency drift file name";
+ doc = <<- _EndOfDoc_
+ The name and path of the frequency file,
+ /etc/ntp.drift
+ by default.
+ This is the same operation as the
+ driftfile driftfile
+ configuration specification in the
+ /etc/ntp.conf
+ file.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = panicgate;
+ value = g;
+ descrip = "Allow the first adjustment to be Big";
+ doc = <<- _EndOfDoc_
+ Normally,
+ ntpd
+ exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ ntpd
+ will exit with a message to the system log. This option can be used with the
+ -q
+ and
+ -x
+ options.
+ See the
+ tinker
+ configuration file directive for other options.
+ _EndOfDoc_;
+};
+
+#ifdef SIM
+flag = {
+ name = simslew;
+ value = H;
+ arg-type = string;
+ descrip = "Simuator slew";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+flag = {
+ name = jaildir;
+ value = i;
+ arg-type = string;
+ descrip = "Jail directory";
+ doc = <<- _EndOfDoc_
+ Chroot the server to the directory
+ jaildir
+ .
+ This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+ You may need to also specify a
+ -u
+ option.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = interface;
+ value = I;
+ arg-type = string;
+ descrip = "Listen on interface";
+ max = NOLIMIT;
+ arg-name = iface;
+ stack-arg;
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+
+flag = {
+ name = keyfile;
+ value = k;
+ arg-type = string;
+ descrip = "path to symmetric keys";
+ doc = <<- _EndOfDoc_
+ Specify the name and path of the symmetric key file.
+ /etc/ntp.keys
+ is the default.
+ This is the same operation as the
+ keys keyfile
+ configuration file directive.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = logfile;
+ value = l;
+ arg-type = string;
+ descrip = "path to the log file";
+ doc = <<- _EndOfDoc_
+ Specify the name and path of the log file.
+ The default is the system log file.
+ This is the same operation as the
+ logfile logfile
+ configuration file directive.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = novirtualips;
+ value = L;
+ descrip = "Do not listen to virtual IPs";
+ doc = <<- _EndOfDoc_
+ Do not listen to virtual IPs. The default is to listen.
+ _EndOfDoc_;
+};
+
+flag = {
+ ifdef = SYS_WINNT;
+ name = modifymmtimer;
+ value = M;
+ descrip = "Modify Multimedia Timer (Windows only)";
+ doc = <<- _EndOfDoc_
+ Set the Windows Multimedia Timer to highest resolution.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = nofork;
+ value = n;
+ descrip = "Do not fork";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+
+flag = {
+ name = nice;
+ value = N;
+ descrip = "Run at high priority";
+ doc = <<- _EndOfDoc_
+ To the extent permitted by the operating system, run
+ ntpd
+ at the highest priority.
+ _EndOfDoc_;
+};
+
+#ifdef SIM
+flag = {
+ name = servertime;
+ value = O;
+ arg-type = string;
+ descrip = "Server time";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+flag = {
+ name = pidfile;
+ value = p;
+ arg-type = string;
+ descrip = "path to the PID file";
+ doc = <<- _EndOfDoc_
+ Specify the name and path of the file used to record
+ ntpd's
+ process ID.
+ This is the same operation as the
+ pidfile pidfile
+ configuration file directive.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = priority;
+ value = P;
+ arg-type = number;
+ descrip = "Process priority";
+ doc = <<- _EndOfDoc_
+ To the extent permitted by the operating system, run
+ ntpd
+ at the specified
+ sched_setscheduler(SCHED_FIFO)
+ priority.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = quit;
+ value = q;
+ descrip = "Set the time and quit";
+ doc = <<- _EndOfDoc_
+ ntpd
+ will exit just after the first time the clock is set. This behavior mimics that of the
+ ntpdate
+ program, which is to be retired.
+ The
+ -g
+ and
+ -x
+ options can be used with this option.
+ Note: The kernel time discipline is disabled with this option.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = propagationdelay;
+ value = r;
+ arg-type = string;
+ descrip = "Broadcast/propagation delay";
+ doc = <<- _EndOfDoc_
+ Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = updateinterval;
+ value = U;
+ arg-type = number;
+ descrip = "interval in seconds between scans for new or dropped interfaces";
+ doc = <<- _EndOfDoc_
+ Give the time in seconds between two scans for new or dropped interfaces.
+ For systems with routing socket support the scans will be performed shortly after the interface change
+ has been detected by the system.
+ Use 0 to disable scanning.
+ _EndOfDoc_;
+};
+
+flag = {
+ name = statsdir;
+ value = s;
+ arg-type = string;
+ descrip = "Statistics file location";
+ doc = <<- _EndOfDoc_
+ Specify the directory path for files created by the statistics facility.
+ This is the same operation as the
+ statsdir statsdir
+ configuration file directive.
+ _EndOfDoc_;
+};
+
+#ifdef SIM
+flag = {
+ name = endsimtime;
+ value = S;
+ arg-type = string;
+ descrip = "Simulation end time";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+flag = {
+ name = trustedkey;
+ value = t;
+ arg-type = string;
+ descrip = "Trusted key number";
+ max = NOLIMIT;
+ arg-name = tkey;
+ stack-arg;
+ doc = <<- _EndOfDoc_
+ Add a key number to the trusted key list.
+ _EndOfDoc_;
+};
+
+#ifdef SIM
+flag = {
+ name = freqerr;
+ value = T;
+ arg-type = string;
+ descrip = "Simulation frequency error";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+#ifdef SIM
+flag = {
+ name = walknoise;
+ value = W;
+ arg-type = string;
+ descrip = "Simulation random walk noise";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+flag = {
+ name = user;
+ value = u;
+ arg-type = string;
+ descrip = "Run as userid (or userid:groupid)";
+ doc = <<- _EndOfDoc_
+ Specify a user, and optionally a group, to switch to.
+ This option is only available if the OS supports to run the server without full root privileges.
+ Currently, this option is supported under NetBSD (configure with
+ --enable-clockctl
+ ) and Linux (configure with
+ --enable-linuxcaps
+ ).
+ _EndOfDoc_;
+};
+
+flag = {
+ name = var;
+ value = v;
+ arg-type = string;
+ descrip = "make ARG an ntp variable (RW)";
+ max = NOLIMIT;
+ arg-name = nvar;
+ stack-arg;
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+
+flag = {
+ name = dvar;
+ value = V;
+ arg-type = string;
+ descrip = "make ARG an ntp variable (RW|DEF)";
+ max = NOLIMIT;
+ arg-name = ndvar;
+ stack-arg;
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+
+flag = {
+ name = slew;
+ value = x;
+ descrip = "Slew up to 600 seconds";
+ doc = <<- _EndOfDoc_
+ Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+ This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+ Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+ Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+ This option can be used with the
+ -g
+ and
+ -q
+ options.
+ See the
+ tinker
+ configuration file directive for other options.
+ Note: The kernel time discipline is disabled with this option.
+ _EndOfDoc_;
+};
+
+#ifdef SIM
+flag = {
+ name = ndelay;
+ value = Y;
+ arg-type = string;
+ descrip = "Simulation network delay";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
+
+#ifdef SIM
+flag = {
+ name = pdelay;
+ value = Z;
+ arg-type = string;
+ descrip = "Simulation processing delay";
+ doc = <<- _EndOfDoc_
+ _EndOfDoc_;
+};
+#endif
diff --git a/contrib/ntp/ntpd/ntpdsim-opts.c b/contrib/ntp/ntpd/ntpdsim-opts.c
new file mode 100644
index 0000000..4f09c0f
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpdsim-opts.c
@@ -0,0 +1,1262 @@
+/*
+ * EDIT THIS FILE WITH CAUTION (ntpdsim-opts.c)
+ *
+ * It has been AutoGen-ed Sunday August 17, 2008 at 05:20:14 AM EDT
+ * From the definitions ntpdsim-opts.def
+ * and the template file options
+ *
+ * Generated from AutoOpts 29:0:4 templates.
+ */
+
+/*
+ * This file was produced by an AutoOpts template. AutoOpts is a
+ * copyrighted work. This source file is not encumbered by AutoOpts
+ * licensing, but is provided under the licensing terms chosen by the
+ * ntpdsim author or copyright holder. AutoOpts is licensed under
+ * the terms of the LGPL. The redistributable library (``libopts'') is
+ * licensed under the terms of either the LGPL or, at the users discretion,
+ * the BSD license. See the AutoOpts and/or libopts sources for details.
+ *
+ * This source file is copyrighted and licensed under the following terms:
+ *
+ * ntpdsim copyright 1970-2008 David L. Mills and/or others - all rights reserved
+ *
+ * see html/copyright.html
+ */
+
+
+#include <limits.h>
+
+#define OPTION_CODE_COMPILE 1
+#include "ntpdsim-opts.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+ "ntpdsim copyright (c) 1970-2008 David L. Mills and/or others, all rights reserved";
+tSCC zCopyrightNotice[] =
+
+/* extracted from ../include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ * global included definitions
+ */
+#ifdef __windows
+ extern int atoi(const char*);
+#else
+# include <stdlib.h>
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+/*
+ * Ipv4 option description:
+ */
+tSCC zIpv4Text[] =
+ "Force IPv4 DNS name resolution";
+tSCC zIpv4_NAME[] = "IPV4";
+tSCC zIpv4_Name[] = "ipv4";
+#define IPV4_FLAGS (OPTST_DISABLED)
+
+/*
+ * Ipv6 option description:
+ */
+tSCC zIpv6Text[] =
+ "Force IPv6 DNS name resolution";
+tSCC zIpv6_NAME[] = "IPV6";
+tSCC zIpv6_Name[] = "ipv6";
+#define IPV6_FLAGS (OPTST_DISABLED)
+
+/*
+ * Authreq option description with
+ * "Must also have options" and "Incompatible options":
+ */
+tSCC zAuthreqText[] =
+ "Require crypto authentication";
+tSCC zAuthreq_NAME[] = "AUTHREQ";
+tSCC zAuthreq_Name[] = "authreq";
+static const int
+ aAuthreqCantList[] = {
+ INDEX_OPT_AUTHNOREQ, NO_EQUIVALENT };
+#define AUTHREQ_FLAGS (OPTST_DISABLED)
+
+/*
+ * Authnoreq option description with
+ * "Must also have options" and "Incompatible options":
+ */
+tSCC zAuthnoreqText[] =
+ "Do not require crypto authentication";
+tSCC zAuthnoreq_NAME[] = "AUTHNOREQ";
+tSCC zAuthnoreq_Name[] = "authnoreq";
+static const int
+ aAuthnoreqCantList[] = {
+ INDEX_OPT_AUTHREQ, NO_EQUIVALENT };
+#define AUTHNOREQ_FLAGS (OPTST_DISABLED)
+
+/*
+ * Bcastsync option description:
+ */
+tSCC zBcastsyncText[] =
+ "Allow us to sync to broadcast servers";
+tSCC zBcastsync_NAME[] = "BCASTSYNC";
+tSCC zBcastsync_Name[] = "bcastsync";
+#define BCASTSYNC_FLAGS (OPTST_DISABLED)
+
+/*
+ * Simbroadcastdelay option description:
+ */
+tSCC zSimbroadcastdelayText[] =
+ "Simulator broadcast delay";
+tSCC zSimbroadcastdelay_NAME[] = "SIMBROADCASTDELAY";
+tSCC zSimbroadcastdelay_Name[] = "simbroadcastdelay";
+#define SIMBROADCASTDELAY_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Configfile option description:
+ */
+tSCC zConfigfileText[] =
+ "configuration file name";
+tSCC zConfigfile_NAME[] = "CONFIGFILE";
+tSCC zConfigfile_Name[] = "configfile";
+#define CONFIGFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Phasenoise option description:
+ */
+tSCC zPhasenoiseText[] =
+ "Phase noise level";
+tSCC zPhasenoise_NAME[] = "PHASENOISE";
+tSCC zPhasenoise_Name[] = "phasenoise";
+#define PHASENOISE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Debug_Level option description:
+ */
+#ifdef DEBUG
+tSCC zDebug_LevelText[] =
+ "Increase output debug message level";
+tSCC zDebug_Level_NAME[] = "DEBUG_LEVEL";
+tSCC zDebug_Level_Name[] = "debug-level";
+#define DEBUG_LEVEL_FLAGS (OPTST_DISABLED)
+
+#else /* disable Debug_Level */
+#define VALUE_OPT_DEBUG_LEVEL NO_EQUIVALENT
+#define DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zDebug_LevelText NULL
+#define zDebug_Level_NAME NULL
+#define zDebug_Level_Name NULL
+#endif /* DEBUG */
+
+/*
+ * Set_Debug_Level option description:
+ */
+#ifdef DEBUG
+tSCC zSet_Debug_LevelText[] =
+ "Set the output debug message level";
+tSCC zSet_Debug_Level_NAME[] = "SET_DEBUG_LEVEL";
+tSCC zSet_Debug_Level_Name[] = "set-debug-level";
+#define SET_DEBUG_LEVEL_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else /* disable Set_Debug_Level */
+#define VALUE_OPT_SET_DEBUG_LEVEL NO_EQUIVALENT
+#define SET_DEBUG_LEVEL_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zSet_Debug_LevelText NULL
+#define zSet_Debug_Level_NAME NULL
+#define zSet_Debug_Level_Name NULL
+#endif /* DEBUG */
+
+/*
+ * Driftfile option description:
+ */
+tSCC zDriftfileText[] =
+ "frequency drift file name";
+tSCC zDriftfile_NAME[] = "DRIFTFILE";
+tSCC zDriftfile_Name[] = "driftfile";
+#define DRIFTFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Panicgate option description:
+ */
+tSCC zPanicgateText[] =
+ "Allow the first adjustment to be Big";
+tSCC zPanicgate_NAME[] = "PANICGATE";
+tSCC zPanicgate_Name[] = "panicgate";
+#define PANICGATE_FLAGS (OPTST_DISABLED)
+
+/*
+ * Simslew option description:
+ */
+tSCC zSimslewText[] =
+ "Simuator slew";
+tSCC zSimslew_NAME[] = "SIMSLEW";
+tSCC zSimslew_Name[] = "simslew";
+#define SIMSLEW_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Jaildir option description:
+ */
+tSCC zJaildirText[] =
+ "Jail directory";
+tSCC zJaildir_NAME[] = "JAILDIR";
+tSCC zJaildir_Name[] = "jaildir";
+#define JAILDIR_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Interface option description:
+ */
+tSCC zInterfaceText[] =
+ "Listen on interface";
+tSCC zInterface_NAME[] = "INTERFACE";
+tSCC zInterface_Name[] = "interface";
+#define INTERFACE_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Keyfile option description:
+ */
+tSCC zKeyfileText[] =
+ "path to symmetric keys";
+tSCC zKeyfile_NAME[] = "KEYFILE";
+tSCC zKeyfile_Name[] = "keyfile";
+#define KEYFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Logfile option description:
+ */
+tSCC zLogfileText[] =
+ "path to the log file";
+tSCC zLogfile_NAME[] = "LOGFILE";
+tSCC zLogfile_Name[] = "logfile";
+#define LOGFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Novirtualips option description:
+ */
+tSCC zNovirtualipsText[] =
+ "Do not listen to virtual IPs";
+tSCC zNovirtualips_NAME[] = "NOVIRTUALIPS";
+tSCC zNovirtualips_Name[] = "novirtualips";
+#define NOVIRTUALIPS_FLAGS (OPTST_DISABLED)
+
+/*
+ * Modifymmtimer option description:
+ */
+#ifdef SYS_WINNT
+tSCC zModifymmtimerText[] =
+ "Modify Multimedia Timer (Windows only)";
+tSCC zModifymmtimer_NAME[] = "MODIFYMMTIMER";
+tSCC zModifymmtimer_Name[] = "modifymmtimer";
+#define MODIFYMMTIMER_FLAGS (OPTST_DISABLED)
+
+#else /* disable Modifymmtimer */
+#define VALUE_OPT_MODIFYMMTIMER NO_EQUIVALENT
+#define MODIFYMMTIMER_FLAGS (OPTST_OMITTED | OPTST_NO_INIT)
+#define zModifymmtimerText NULL
+#define zModifymmtimer_NAME NULL
+#define zModifymmtimer_Name NULL
+#endif /* SYS_WINNT */
+
+/*
+ * Nofork option description:
+ */
+tSCC zNoforkText[] =
+ "Do not fork";
+tSCC zNofork_NAME[] = "NOFORK";
+tSCC zNofork_Name[] = "nofork";
+#define NOFORK_FLAGS (OPTST_DISABLED)
+
+/*
+ * Nice option description:
+ */
+tSCC zNiceText[] =
+ "Run at high priority";
+tSCC zNice_NAME[] = "NICE";
+tSCC zNice_Name[] = "nice";
+#define NICE_FLAGS (OPTST_DISABLED)
+
+/*
+ * Servertime option description:
+ */
+tSCC zServertimeText[] =
+ "Server time";
+tSCC zServertime_NAME[] = "SERVERTIME";
+tSCC zServertime_Name[] = "servertime";
+#define SERVERTIME_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Pidfile option description:
+ */
+tSCC zPidfileText[] =
+ "path to the PID file";
+tSCC zPidfile_NAME[] = "PIDFILE";
+tSCC zPidfile_Name[] = "pidfile";
+#define PIDFILE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Priority option description:
+ */
+tSCC zPriorityText[] =
+ "Process priority";
+tSCC zPriority_NAME[] = "PRIORITY";
+tSCC zPriority_Name[] = "priority";
+#define PRIORITY_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ * Quit option description:
+ */
+tSCC zQuitText[] =
+ "Set the time and quit";
+tSCC zQuit_NAME[] = "QUIT";
+tSCC zQuit_Name[] = "quit";
+#define QUIT_FLAGS (OPTST_DISABLED)
+
+/*
+ * Propagationdelay option description:
+ */
+tSCC zPropagationdelayText[] =
+ "Broadcast/propagation delay";
+tSCC zPropagationdelay_NAME[] = "PROPAGATIONDELAY";
+tSCC zPropagationdelay_Name[] = "propagationdelay";
+#define PROPAGATIONDELAY_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Updateinterval option description:
+ */
+tSCC zUpdateintervalText[] =
+ "interval in seconds between scans for new or dropped interfaces";
+tSCC zUpdateinterval_NAME[] = "UPDATEINTERVAL";
+tSCC zUpdateinterval_Name[] = "updateinterval";
+#define UPDATEINTERVAL_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ * Statsdir option description:
+ */
+tSCC zStatsdirText[] =
+ "Statistics file location";
+tSCC zStatsdir_NAME[] = "STATSDIR";
+tSCC zStatsdir_Name[] = "statsdir";
+#define STATSDIR_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Endsimtime option description:
+ */
+tSCC zEndsimtimeText[] =
+ "Simulation end time";
+tSCC zEndsimtime_NAME[] = "ENDSIMTIME";
+tSCC zEndsimtime_Name[] = "endsimtime";
+#define ENDSIMTIME_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Trustedkey option description:
+ */
+tSCC zTrustedkeyText[] =
+ "Trusted key number";
+tSCC zTrustedkey_NAME[] = "TRUSTEDKEY";
+tSCC zTrustedkey_Name[] = "trustedkey";
+#define TRUSTEDKEY_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Freqerr option description:
+ */
+tSCC zFreqerrText[] =
+ "Simulation frequency error";
+tSCC zFreqerr_NAME[] = "FREQERR";
+tSCC zFreqerr_Name[] = "freqerr";
+#define FREQERR_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Walknoise option description:
+ */
+tSCC zWalknoiseText[] =
+ "Simulation random walk noise";
+tSCC zWalknoise_NAME[] = "WALKNOISE";
+tSCC zWalknoise_Name[] = "walknoise";
+#define WALKNOISE_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * User option description:
+ */
+tSCC zUserText[] =
+ "Run as userid (or userid:groupid)";
+tSCC zUser_NAME[] = "USER";
+tSCC zUser_Name[] = "user";
+#define USER_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Var option description:
+ */
+tSCC zVarText[] =
+ "make ARG an ntp variable (RW)";
+tSCC zVar_NAME[] = "VAR";
+tSCC zVar_Name[] = "var";
+#define VAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Dvar option description:
+ */
+tSCC zDvarText[] =
+ "make ARG an ntp variable (RW|DEF)";
+tSCC zDvar_NAME[] = "DVAR";
+tSCC zDvar_Name[] = "dvar";
+#define DVAR_FLAGS (OPTST_DISABLED | OPTST_STACKED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Slew option description:
+ */
+tSCC zSlewText[] =
+ "Slew up to 600 seconds";
+tSCC zSlew_NAME[] = "SLEW";
+tSCC zSlew_Name[] = "slew";
+#define SLEW_FLAGS (OPTST_DISABLED)
+
+/*
+ * Ndelay option description:
+ */
+tSCC zNdelayText[] =
+ "Simulation network delay";
+tSCC zNdelay_NAME[] = "NDELAY";
+tSCC zNdelay_Name[] = "ndelay";
+#define NDELAY_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Pdelay option description:
+ */
+tSCC zPdelayText[] =
+ "Simulation processing delay";
+tSCC zPdelay_NAME[] = "PDELAY";
+tSCC zPdelay_Name[] = "pdelay";
+#define PDELAY_FLAGS (OPTST_DISABLED \
+ | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ * Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[] = "Display usage information and exit";
+tSCC zHelp_Name[] = "help";
+
+tSCC zMore_HelpText[] = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[] = "Output version information and exit";
+tSCC zVersion_Name[] = "version";
+
+/*
+ * Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[] = "Save the option state to a config file";
+tSCC zSave_Opts_Name[] = "save-opts";
+
+tSCC zLoad_OptsText[] = "Load options from a config file";
+tSCC zLoad_Opts_NAME[] = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[] = "no";
+#define zLoad_Opts_Name (zNotLoad_Opts_Name + 3)
+/*
+ * Declare option callback procedures
+ */
+#ifdef DEBUG
+ static tOptProc doOptSet_Debug_Level;
+#else /* not DEBUG */
+# define doOptSet_Debug_Level NULL
+#endif /* def/not DEBUG */
+#if defined(TEST_NTPDSIM_OPTS)
+/*
+ * Under test, omit argument processing, or call optionStackArg,
+ * if multiple copies are allowed.
+ */
+extern tOptProc
+ optionNumericVal, optionPagedUsage, optionStackArg,
+ optionVersionStderr;
+static tOptProc
+ doUsageOpt;
+
+/*
+ * #define map the "normal" callout procs to the test ones...
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_NTPDSIM_OPTS */
+/*
+ * When not under test, there are different procs to use
+ */
+extern tOptProc
+ optionNumericVal, optionPagedUsage, optionPrintVersion, optionStackArg;
+static tOptProc
+ doUsageOpt;
+
+/*
+ * #define map the "normal" callout procs
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#endif /* defined(TEST_NTPDSIM_OPTS) */
+#ifdef TEST_NTPDSIM_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_NTPDSIM_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Define the Ntpdsim Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+ { /* entry idx, value */ 0, VALUE_OPT_IPV4,
+ /* equiv idx, value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ IPV4_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 1, VALUE_OPT_IPV6,
+ /* equiv idx, value */ NOLIMIT, NOLIMIT,
+ /* equivalenced to */ INDEX_OPT_IPV4,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ IPV6_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 2, VALUE_OPT_AUTHREQ,
+ /* equiv idx, value */ 2, VALUE_OPT_AUTHREQ,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ AUTHREQ_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, aAuthreqCantList,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zAuthreqText, zAuthreq_NAME, zAuthreq_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+ /* equiv idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ AUTHNOREQ_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, aAuthnoreqCantList,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zAuthnoreqText, zAuthnoreq_NAME, zAuthnoreq_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 4, VALUE_OPT_BCASTSYNC,
+ /* equiv idx, value */ 4, VALUE_OPT_BCASTSYNC,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ BCASTSYNC_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zBcastsyncText, zBcastsync_NAME, zBcastsync_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 5, VALUE_OPT_SIMBROADCASTDELAY,
+ /* equiv idx, value */ 5, VALUE_OPT_SIMBROADCASTDELAY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ SIMBROADCASTDELAY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zSimbroadcastdelayText, zSimbroadcastdelay_NAME, zSimbroadcastdelay_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 6, VALUE_OPT_CONFIGFILE,
+ /* equiv idx, value */ 6, VALUE_OPT_CONFIGFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ CONFIGFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zConfigfileText, zConfigfile_NAME, zConfigfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 7, VALUE_OPT_PHASENOISE,
+ /* equiv idx, value */ 7, VALUE_OPT_PHASENOISE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PHASENOISE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPhasenoiseText, zPhasenoise_NAME, zPhasenoise_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 8, VALUE_OPT_DEBUG_LEVEL,
+ /* equiv idx, value */ 8, VALUE_OPT_DEBUG_LEVEL,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ DEBUG_LEVEL_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 9, VALUE_OPT_SET_DEBUG_LEVEL,
+ /* equiv idx, value */ 9, VALUE_OPT_SET_DEBUG_LEVEL,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ SET_DEBUG_LEVEL_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ SET_DEBUG_LEVEL_OPT_PROC,
+ /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 10, VALUE_OPT_DRIFTFILE,
+ /* equiv idx, value */ 10, VALUE_OPT_DRIFTFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ DRIFTFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zDriftfileText, zDriftfile_NAME, zDriftfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 11, VALUE_OPT_PANICGATE,
+ /* equiv idx, value */ 11, VALUE_OPT_PANICGATE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PANICGATE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPanicgateText, zPanicgate_NAME, zPanicgate_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 12, VALUE_OPT_SIMSLEW,
+ /* equiv idx, value */ 12, VALUE_OPT_SIMSLEW,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ SIMSLEW_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zSimslewText, zSimslew_NAME, zSimslew_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 13, VALUE_OPT_JAILDIR,
+ /* equiv idx, value */ 13, VALUE_OPT_JAILDIR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ JAILDIR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zJaildirText, zJaildir_NAME, zJaildir_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 14, VALUE_OPT_INTERFACE,
+ /* equiv idx, value */ 14, VALUE_OPT_INTERFACE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ INTERFACE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zInterfaceText, zInterface_NAME, zInterface_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 15, VALUE_OPT_KEYFILE,
+ /* equiv idx, value */ 15, VALUE_OPT_KEYFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ KEYFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zKeyfileText, zKeyfile_NAME, zKeyfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 16, VALUE_OPT_LOGFILE,
+ /* equiv idx, value */ 16, VALUE_OPT_LOGFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ LOGFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zLogfileText, zLogfile_NAME, zLogfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 17, VALUE_OPT_NOVIRTUALIPS,
+ /* equiv idx, value */ 17, VALUE_OPT_NOVIRTUALIPS,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ NOVIRTUALIPS_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zNovirtualipsText, zNovirtualips_NAME, zNovirtualips_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 18, VALUE_OPT_MODIFYMMTIMER,
+ /* equiv idx, value */ 18, VALUE_OPT_MODIFYMMTIMER,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ MODIFYMMTIMER_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zModifymmtimerText, zModifymmtimer_NAME, zModifymmtimer_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 19, VALUE_OPT_NOFORK,
+ /* equiv idx, value */ 19, VALUE_OPT_NOFORK,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ NOFORK_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zNoforkText, zNofork_NAME, zNofork_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 20, VALUE_OPT_NICE,
+ /* equiv idx, value */ 20, VALUE_OPT_NICE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ NICE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zNiceText, zNice_NAME, zNice_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 21, VALUE_OPT_SERVERTIME,
+ /* equiv idx, value */ 21, VALUE_OPT_SERVERTIME,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ SERVERTIME_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zServertimeText, zServertime_NAME, zServertime_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 22, VALUE_OPT_PIDFILE,
+ /* equiv idx, value */ 22, VALUE_OPT_PIDFILE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PIDFILE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPidfileText, zPidfile_NAME, zPidfile_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 23, VALUE_OPT_PRIORITY,
+ /* equiv idx, value */ 23, VALUE_OPT_PRIORITY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PRIORITY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionNumericVal,
+ /* desc, NAME, name */ zPriorityText, zPriority_NAME, zPriority_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 24, VALUE_OPT_QUIT,
+ /* equiv idx, value */ 24, VALUE_OPT_QUIT,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ QUIT_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zQuitText, zQuit_NAME, zQuit_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 25, VALUE_OPT_PROPAGATIONDELAY,
+ /* equiv idx, value */ 25, VALUE_OPT_PROPAGATIONDELAY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PROPAGATIONDELAY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPropagationdelayText, zPropagationdelay_NAME, zPropagationdelay_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 26, VALUE_OPT_UPDATEINTERVAL,
+ /* equiv idx, value */ 26, VALUE_OPT_UPDATEINTERVAL,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ UPDATEINTERVAL_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionNumericVal,
+ /* desc, NAME, name */ zUpdateintervalText, zUpdateinterval_NAME, zUpdateinterval_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 27, VALUE_OPT_STATSDIR,
+ /* equiv idx, value */ 27, VALUE_OPT_STATSDIR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ STATSDIR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zStatsdirText, zStatsdir_NAME, zStatsdir_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 28, VALUE_OPT_ENDSIMTIME,
+ /* equiv idx, value */ 28, VALUE_OPT_ENDSIMTIME,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ ENDSIMTIME_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zEndsimtimeText, zEndsimtime_NAME, zEndsimtime_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 29, VALUE_OPT_TRUSTEDKEY,
+ /* equiv idx, value */ 29, VALUE_OPT_TRUSTEDKEY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ TRUSTEDKEY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zTrustedkeyText, zTrustedkey_NAME, zTrustedkey_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 30, VALUE_OPT_FREQERR,
+ /* equiv idx, value */ 30, VALUE_OPT_FREQERR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ FREQERR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zFreqerrText, zFreqerr_NAME, zFreqerr_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 31, VALUE_OPT_WALKNOISE,
+ /* equiv idx, value */ 31, VALUE_OPT_WALKNOISE,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ WALKNOISE_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zWalknoiseText, zWalknoise_NAME, zWalknoise_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 32, VALUE_OPT_USER,
+ /* equiv idx, value */ 32, VALUE_OPT_USER,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ USER_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zUserText, zUser_NAME, zUser_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 33, VALUE_OPT_VAR,
+ /* equiv idx, value */ 33, VALUE_OPT_VAR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ VAR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zVarText, zVar_NAME, zVar_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 34, VALUE_OPT_DVAR,
+ /* equiv idx, value */ 34, VALUE_OPT_DVAR,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ DVAR_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionStackArg,
+ /* desc, NAME, name */ zDvarText, zDvar_NAME, zDvar_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 35, VALUE_OPT_SLEW,
+ /* equiv idx, value */ 35, VALUE_OPT_SLEW,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ SLEW_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zSlewText, zSlew_NAME, zSlew_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 36, VALUE_OPT_NDELAY,
+ /* equiv idx, value */ 36, VALUE_OPT_NDELAY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ NDELAY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zNdelayText, zNdelay_NAME, zNdelay_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ 37, VALUE_OPT_PDELAY,
+ /* equiv idx, value */ 37, VALUE_OPT_PDELAY,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ PDELAY_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zPdelayText, zPdelay_NAME, zPdelay_Name,
+ /* disablement strs */ NULL, NULL },
+
+#ifdef NO_OPTIONAL_OPT_ARGS
+# define VERSION_OPT_FLAGS OPTST_IMM | OPTST_NO_INIT
+#else
+# define VERSION_OPT_FLAGS OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
+ OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT
+#endif
+
+ { /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ VERSION_OPT_FLAGS, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ DOVERPROC,
+ /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+ /* disablement strs */ NULL, NULL },
+
+#undef VERSION_OPT_FLAGS
+
+
+ { /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ doUsageOpt,
+ /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ OPTST_IMM | OPTST_NO_INIT, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionPagedUsage,
+ /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, 1, 0,
+ /* opt state flags */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+ | OPTST_ARG_OPTIONAL | OPTST_NO_INIT, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ NULL,
+ /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+ /* disablement strs */ NULL, NULL },
+
+ { /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+ /* equiv idx value */ NO_EQUIVALENT, 0,
+ /* equivalenced to */ NO_EQUIVALENT,
+ /* min, max, act ct */ 0, NOLIMIT, 0,
+ /* opt state flags */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) \
+ | OPTST_DISABLE_IMM, 0,
+ /* last opt argumnt */ { NULL },
+ /* arg list/cookie */ NULL,
+ /* must/cannot opts */ NULL, NULL,
+ /* option proc */ optionLoadOpt,
+ /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+ /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * Define the Ntpdsim Option Environment
+ */
+tSCC zPROGNAME[] = "NTPDSIM";
+tSCC zUsageTitle[] =
+"ntpdsim - NTP daemon simulation program - Ver. 4.2.4p5\n\
+USAGE: %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+tSCC zRcName[] = ".ntprc";
+tSCC* apzHomeList[] = {
+ "$HOME",
+ ".",
+ NULL };
+
+tSCC zBugsAddr[] = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC zDetail[] = "\n\n";
+tSCC zFullVersion[] = NTPDSIM_FULL_VERSION;
+/* extracted from /usr/local/gnu/share/autogen/optcode.tpl near line 408 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+ static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions ntpdsimOptions = {
+ OPTIONS_STRUCT_VERSION,
+ 0, NULL, /* original argc + argv */
+ ( OPTPROC_BASE
+ + OPTPROC_ERRSTOP
+ + OPTPROC_SHORTOPT
+ + OPTPROC_LONGOPT
+ + OPTPROC_NO_REQ_OPT
+ + OPTPROC_ENVIRON
+ + OPTPROC_NO_ARGS
+ + OPTPROC_HAS_IMMED ),
+ 0, NULL, /* current option index, current option */
+ NULL, NULL, zPROGNAME,
+ zRcName, zCopyright, zCopyrightNotice,
+ zFullVersion, apzHomeList, zUsageTitle,
+ zExplain, zDetail, optDesc,
+ zBugsAddr, /* address to send bugs to */
+ NULL, NULL, /* extensions/saved state */
+ optionUsage, /* usage procedure */
+ translate_option_strings, /* translation procedure */
+ /*
+ * Indexes to special options
+ */
+ { INDEX_OPT_MORE_HELP,
+ INDEX_OPT_SAVE_OPTS,
+ NO_EQUIVALENT /* index of '-#' option */,
+ NO_EQUIVALENT /* index of default opt */
+ },
+ 43 /* full option count */, 38 /* user option count */
+};
+
+/*
+ * Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+ tOptions* pOptions,
+ tOptDesc* pOptDesc )
+{
+ USAGE( EXIT_SUCCESS );
+}
+
+#if ! defined(TEST_NTPDSIM_OPTS)
+
+/* * * * * * *
+ *
+ * For the set-debug-level option, when DEBUG is #define-d.
+ */
+#ifdef DEBUG
+static void
+doOptSet_Debug_Level(
+ tOptions* pOptions,
+ tOptDesc* pOptDesc )
+{
+ /* extracted from ../include/debug-opt.def, line 29 */
+DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
+}
+#endif /* defined DEBUG */
+
+#endif /* defined(TEST_NTPDSIM_OPTS) */
+
+/* extracted from /usr/local/gnu/share/autogen/optmain.tpl near line 92 */
+
+#if defined(TEST_NTPDSIM_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+ int res = EXIT_SUCCESS;
+ (void)optionProcess( &ntpdsimOptions, argc, argv );
+ {
+ void optionPutShell( tOptions* );
+ optionPutShell( &ntpdsimOptions );
+ }
+ return res;
+}
+#endif /* defined TEST_NTPDSIM_OPTS */
+/* extracted from /usr/local/gnu/share/autogen/optcode.tpl near line 514 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char* AO_gettext( char const* pz );
+static void coerce_it(void** s);
+
+static char*
+AO_gettext( char const* pz )
+{
+ char* pzRes;
+ if (pz == NULL)
+ return NULL;
+ pzRes = _(pz);
+ if (pzRes == pz)
+ return pzRes;
+ pzRes = strdup( pzRes );
+ if (pzRes == NULL) {
+ fputs( _("No memory for duping translated strings\n"), stderr );
+ exit( EXIT_FAILURE );
+ }
+ return pzRes;
+}
+
+static void coerce_it(void** s) { *s = AO_gettext(*s); }
+#define COERSION(_f) \
+ coerce_it((void*)&(ntpdsimOptions._f))
+
+/*
+ * This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+ /*
+ * Guard against re-translation. It won't work. The strings will have
+ * been changed by the first pass through this code. One shot only.
+ */
+ if (option_usage_text.field_ct == 0)
+ return;
+ /*
+ * Do the translations. The first pointer follows the field count field.
+ * The field count field is the size of a pointer.
+ */
+ {
+ char** ppz = (char**)(void*)&(option_usage_text);
+ int ix = option_usage_text.field_ct;
+
+ do {
+ ppz++;
+ *ppz = AO_gettext(*ppz);
+ } while (--ix > 0);
+ }
+ option_usage_text.field_ct = 0;
+
+ {
+ tOptDesc* pOD = ntpdsimOptions.pOptDesc;
+ int ix = ntpdsimOptions.optCt;
+
+ for (;;) {
+ pOD->pzText = AO_gettext(pOD->pzText);
+ pOD->pz_NAME = AO_gettext(pOD->pz_NAME);
+ pOD->pz_Name = AO_gettext(pOD->pz_Name);
+ pOD->pz_DisableName = AO_gettext(pOD->pz_DisableName);
+ pOD->pz_DisablePfx = AO_gettext(pOD->pz_DisablePfx);
+ if (--ix <= 0)
+ break;
+ pOD++;
+ }
+ }
+ COERSION(pzCopyright);
+ COERSION(pzCopyNotice);
+ COERSION(pzFullVersion);
+ COERSION(pzUsageTitle);
+ COERSION(pzExplain);
+ COERSION(pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef __cplusplus
+}
+#endif
+/* ntpdsim-opts.c ends here */
diff --git a/contrib/ntp/ntpd/ntpdsim-opts.def b/contrib/ntp/ntpd/ntpdsim-opts.def
new file mode 100644
index 0000000..093c325
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpdsim-opts.def
@@ -0,0 +1,15 @@
+/* -*- Mode: Text -*- */
+
+autogen definitions options;
+
+#include copyright.def
+#include homerc.def
+
+prog-name = "ntpdsim";
+prog-title = "NTP daemon simulation program";
+
+#define SIM
+#include ntpdbase-opts.def
+
+detail = <<- _END_DETAIL
+ _END_DETAIL;
diff --git a/contrib/ntp/ntpd/ntpdsim-opts.h b/contrib/ntp/ntpd/ntpdsim-opts.h
new file mode 100644
index 0000000..1c63654
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpdsim-opts.h
@@ -0,0 +1,422 @@
+/*
+ * EDIT THIS FILE WITH CAUTION (ntpdsim-opts.h)
+ *
+ * It has been AutoGen-ed Sunday August 17, 2008 at 05:20:13 AM EDT
+ * From the definitions ntpdsim-opts.def
+ * and the template file options
+ *
+ * Generated from AutoOpts 29:0:4 templates.
+ */
+
+/*
+ * This file was produced by an AutoOpts template. AutoOpts is a
+ * copyrighted work. This header file is not encumbered by AutoOpts
+ * licensing, but is provided under the licensing terms chosen by the
+ * ntpdsim author or copyright holder. AutoOpts is licensed under
+ * the terms of the LGPL. The redistributable library (``libopts'') is
+ * licensed under the terms of either the LGPL or, at the users discretion,
+ * the BSD license. See the AutoOpts and/or libopts sources for details.
+ *
+ * This source file is copyrighted and licensed under the following terms:
+ *
+ * ntpdsim copyright 1970-2008 David L. Mills and/or others - all rights reserved
+ *
+ * see html/copyright.html
+ */
+/*
+ * This file contains the programmatic interface to the Automated
+ * Options generated for the ntpdsim program.
+ * These macros are documented in the AutoGen info file in the
+ * "AutoOpts" chapter. Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_NTPDSIM_OPTS_H_GUARD
+#define AUTOOPTS_NTPDSIM_OPTS_H_GUARD
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ * Ensure that the library used for compiling this generated header is at
+ * least as new as the version current when the header template was released
+ * (not counting patch version increments). Also ensure that the oldest
+ * tolerable version is at least as old as what was current when the header
+ * template was released.
+ */
+#define AO_TEMPLATE_VERSION 118784
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+ Choke Me.
+#endif
+
+/*
+ * Enumeration of each option:
+ */
+typedef enum {
+ INDEX_OPT_IPV4 = 0,
+ INDEX_OPT_IPV6 = 1,
+ INDEX_OPT_AUTHREQ = 2,
+ INDEX_OPT_AUTHNOREQ = 3,
+ INDEX_OPT_BCASTSYNC = 4,
+ INDEX_OPT_SIMBROADCASTDELAY = 5,
+ INDEX_OPT_CONFIGFILE = 6,
+ INDEX_OPT_PHASENOISE = 7,
+ INDEX_OPT_DEBUG_LEVEL = 8,
+ INDEX_OPT_SET_DEBUG_LEVEL = 9,
+ INDEX_OPT_DRIFTFILE = 10,
+ INDEX_OPT_PANICGATE = 11,
+ INDEX_OPT_SIMSLEW = 12,
+ INDEX_OPT_JAILDIR = 13,
+ INDEX_OPT_INTERFACE = 14,
+ INDEX_OPT_KEYFILE = 15,
+ INDEX_OPT_LOGFILE = 16,
+ INDEX_OPT_NOVIRTUALIPS = 17,
+ INDEX_OPT_MODIFYMMTIMER = 18,
+ INDEX_OPT_NOFORK = 19,
+ INDEX_OPT_NICE = 20,
+ INDEX_OPT_SERVERTIME = 21,
+ INDEX_OPT_PIDFILE = 22,
+ INDEX_OPT_PRIORITY = 23,
+ INDEX_OPT_QUIT = 24,
+ INDEX_OPT_PROPAGATIONDELAY = 25,
+ INDEX_OPT_UPDATEINTERVAL = 26,
+ INDEX_OPT_STATSDIR = 27,
+ INDEX_OPT_ENDSIMTIME = 28,
+ INDEX_OPT_TRUSTEDKEY = 29,
+ INDEX_OPT_FREQERR = 30,
+ INDEX_OPT_WALKNOISE = 31,
+ INDEX_OPT_USER = 32,
+ INDEX_OPT_VAR = 33,
+ INDEX_OPT_DVAR = 34,
+ INDEX_OPT_SLEW = 35,
+ INDEX_OPT_NDELAY = 36,
+ INDEX_OPT_PDELAY = 37,
+ INDEX_OPT_VERSION = 38,
+ INDEX_OPT_HELP = 39,
+ INDEX_OPT_MORE_HELP = 40,
+ INDEX_OPT_SAVE_OPTS = 41,
+ INDEX_OPT_LOAD_OPTS = 42
+} teOptIndex;
+
+#define OPTION_CT 43
+#define NTPDSIM_VERSION "4.2.4p5"
+#define NTPDSIM_FULL_VERSION "ntpdsim - NTP daemon simulation program - Ver. 4.2.4p5"
+
+/*
+ * Interface defines for all options. Replace "n" with the UPPER_CASED
+ * option name (as in the teOptIndex enumeration above).
+ * e.g. HAVE_OPT( IPV4 )
+ */
+#define DESC(n) (ntpdsimOptions.pOptDesc[INDEX_OPT_## n])
+#define HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define OPT_ARG(n) (DESC(n).optArg.argString)
+#define STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define COUNT_OPT(n) (DESC(n).optOccCt)
+#define ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define CLEAR_OPT(n) STMTS( \
+ DESC(n).fOptState &= OPTST_PERSISTENT_MASK; \
+ if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+ DESC(n).fOptState |= OPTST_DISABLED; \
+ DESC(n).optCookie = NULL )
+
+/*
+ * Make sure there are no #define name conflicts with the option names
+ */
+#ifndef NO_OPTION_NAME_WARNINGS
+# ifdef IPV4
+# warning undefining IPV4 due to option name conflict
+# undef IPV4
+# endif
+# ifdef IPV6
+# warning undefining IPV6 due to option name conflict
+# undef IPV6
+# endif
+# ifdef AUTHREQ
+# warning undefining AUTHREQ due to option name conflict
+# undef AUTHREQ
+# endif
+# ifdef AUTHNOREQ
+# warning undefining AUTHNOREQ due to option name conflict
+# undef AUTHNOREQ
+# endif
+# ifdef BCASTSYNC
+# warning undefining BCASTSYNC due to option name conflict
+# undef BCASTSYNC
+# endif
+# ifdef SIMBROADCASTDELAY
+# warning undefining SIMBROADCASTDELAY due to option name conflict
+# undef SIMBROADCASTDELAY
+# endif
+# ifdef CONFIGFILE
+# warning undefining CONFIGFILE due to option name conflict
+# undef CONFIGFILE
+# endif
+# ifdef PHASENOISE
+# warning undefining PHASENOISE due to option name conflict
+# undef PHASENOISE
+# endif
+# ifdef DEBUG_LEVEL
+# warning undefining DEBUG_LEVEL due to option name conflict
+# undef DEBUG_LEVEL
+# endif
+# ifdef SET_DEBUG_LEVEL
+# warning undefining SET_DEBUG_LEVEL due to option name conflict
+# undef SET_DEBUG_LEVEL
+# endif
+# ifdef DRIFTFILE
+# warning undefining DRIFTFILE due to option name conflict
+# undef DRIFTFILE
+# endif
+# ifdef PANICGATE
+# warning undefining PANICGATE due to option name conflict
+# undef PANICGATE
+# endif
+# ifdef SIMSLEW
+# warning undefining SIMSLEW due to option name conflict
+# undef SIMSLEW
+# endif
+# ifdef JAILDIR
+# warning undefining JAILDIR due to option name conflict
+# undef JAILDIR
+# endif
+# ifdef INTERFACE
+# warning undefining INTERFACE due to option name conflict
+# undef INTERFACE
+# endif
+# ifdef KEYFILE
+# warning undefining KEYFILE due to option name conflict
+# undef KEYFILE
+# endif
+# ifdef LOGFILE
+# warning undefining LOGFILE due to option name conflict
+# undef LOGFILE
+# endif
+# ifdef NOVIRTUALIPS
+# warning undefining NOVIRTUALIPS due to option name conflict
+# undef NOVIRTUALIPS
+# endif
+# ifdef MODIFYMMTIMER
+# warning undefining MODIFYMMTIMER due to option name conflict
+# undef MODIFYMMTIMER
+# endif
+# ifdef NOFORK
+# warning undefining NOFORK due to option name conflict
+# undef NOFORK
+# endif
+# ifdef NICE
+# warning undefining NICE due to option name conflict
+# undef NICE
+# endif
+# ifdef SERVERTIME
+# warning undefining SERVERTIME due to option name conflict
+# undef SERVERTIME
+# endif
+# ifdef PIDFILE
+# warning undefining PIDFILE due to option name conflict
+# undef PIDFILE
+# endif
+# ifdef PRIORITY
+# warning undefining PRIORITY due to option name conflict
+# undef PRIORITY
+# endif
+# ifdef QUIT
+# warning undefining QUIT due to option name conflict
+# undef QUIT
+# endif
+# ifdef PROPAGATIONDELAY
+# warning undefining PROPAGATIONDELAY due to option name conflict
+# undef PROPAGATIONDELAY
+# endif
+# ifdef UPDATEINTERVAL
+# warning undefining UPDATEINTERVAL due to option name conflict
+# undef UPDATEINTERVAL
+# endif
+# ifdef STATSDIR
+# warning undefining STATSDIR due to option name conflict
+# undef STATSDIR
+# endif
+# ifdef ENDSIMTIME
+# warning undefining ENDSIMTIME due to option name conflict
+# undef ENDSIMTIME
+# endif
+# ifdef TRUSTEDKEY
+# warning undefining TRUSTEDKEY due to option name conflict
+# undef TRUSTEDKEY
+# endif
+# ifdef FREQERR
+# warning undefining FREQERR due to option name conflict
+# undef FREQERR
+# endif
+# ifdef WALKNOISE
+# warning undefining WALKNOISE due to option name conflict
+# undef WALKNOISE
+# endif
+# ifdef USER
+# warning undefining USER due to option name conflict
+# undef USER
+# endif
+# ifdef VAR
+# warning undefining VAR due to option name conflict
+# undef VAR
+# endif
+# ifdef DVAR
+# warning undefining DVAR due to option name conflict
+# undef DVAR
+# endif
+# ifdef SLEW
+# warning undefining SLEW due to option name conflict
+# undef SLEW
+# endif
+# ifdef NDELAY
+# warning undefining NDELAY due to option name conflict
+# undef NDELAY
+# endif
+# ifdef PDELAY
+# warning undefining PDELAY due to option name conflict
+# undef PDELAY
+# endif
+#else /* NO_OPTION_NAME_WARNINGS */
+# undef IPV4
+# undef IPV6
+# undef AUTHREQ
+# undef AUTHNOREQ
+# undef BCASTSYNC
+# undef SIMBROADCASTDELAY
+# undef CONFIGFILE
+# undef PHASENOISE
+# undef DEBUG_LEVEL
+# undef SET_DEBUG_LEVEL
+# undef DRIFTFILE
+# undef PANICGATE
+# undef SIMSLEW
+# undef JAILDIR
+# undef INTERFACE
+# undef KEYFILE
+# undef LOGFILE
+# undef NOVIRTUALIPS
+# undef MODIFYMMTIMER
+# undef NOFORK
+# undef NICE
+# undef SERVERTIME
+# undef PIDFILE
+# undef PRIORITY
+# undef QUIT
+# undef PROPAGATIONDELAY
+# undef UPDATEINTERVAL
+# undef STATSDIR
+# undef ENDSIMTIME
+# undef TRUSTEDKEY
+# undef FREQERR
+# undef WALKNOISE
+# undef USER
+# undef VAR
+# undef DVAR
+# undef SLEW
+# undef NDELAY
+# undef PDELAY
+#endif /* NO_OPTION_NAME_WARNINGS */
+
+/*
+ * Interface defines for specific options.
+ */
+#define VALUE_OPT_IPV4 '4'
+#define WHICH_OPT_IPV4 (DESC(IPV4).optActualValue)
+#define WHICH_IDX_IPV4 (DESC(IPV4).optActualIndex)
+#define VALUE_OPT_IPV6 '6'
+#define VALUE_OPT_AUTHREQ 'a'
+#define VALUE_OPT_AUTHNOREQ 'A'
+#define VALUE_OPT_BCASTSYNC 'b'
+#define VALUE_OPT_SIMBROADCASTDELAY 'B'
+#define VALUE_OPT_CONFIGFILE 'c'
+#define VALUE_OPT_PHASENOISE 'C'
+#ifdef DEBUG
+#define VALUE_OPT_DEBUG_LEVEL 'd'
+#endif /* DEBUG */
+#ifdef DEBUG
+#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
+#endif /* DEBUG */
+#define VALUE_OPT_DRIFTFILE 'f'
+#define VALUE_OPT_PANICGATE 'g'
+#define VALUE_OPT_SIMSLEW 'H'
+#define VALUE_OPT_JAILDIR 'i'
+#define VALUE_OPT_INTERFACE 'I'
+#define VALUE_OPT_KEYFILE 'k'
+#define VALUE_OPT_LOGFILE 'l'
+#define VALUE_OPT_NOVIRTUALIPS 'L'
+#ifdef SYS_WINNT
+#define VALUE_OPT_MODIFYMMTIMER 'M'
+#endif /* SYS_WINNT */
+#define VALUE_OPT_NOFORK 'n'
+#define VALUE_OPT_NICE 'N'
+#define VALUE_OPT_SERVERTIME 'O'
+#define VALUE_OPT_PIDFILE 'p'
+#define VALUE_OPT_PRIORITY 'P'
+#define OPT_VALUE_PRIORITY (DESC(PRIORITY).optArg.argInt)
+#define VALUE_OPT_QUIT 'q'
+#define VALUE_OPT_PROPAGATIONDELAY 'r'
+#define VALUE_OPT_UPDATEINTERVAL 'U'
+#define OPT_VALUE_UPDATEINTERVAL (DESC(UPDATEINTERVAL).optArg.argInt)
+#define VALUE_OPT_STATSDIR 's'
+#define VALUE_OPT_ENDSIMTIME 'S'
+#define VALUE_OPT_TRUSTEDKEY 't'
+#define VALUE_OPT_FREQERR 'T'
+#define VALUE_OPT_WALKNOISE 'W'
+#define VALUE_OPT_USER 'u'
+#define VALUE_OPT_VAR 'v'
+#define VALUE_OPT_DVAR 'V'
+#define VALUE_OPT_SLEW 'x'
+#define VALUE_OPT_NDELAY 'Y'
+#define VALUE_OPT_PDELAY 'Z'
+
+#define VALUE_OPT_VERSION 'v'
+#define VALUE_OPT_HELP '?'
+#define VALUE_OPT_MORE_HELP '!'
+#define VALUE_OPT_SAVE_OPTS '>'
+#define VALUE_OPT_LOAD_OPTS '<'
+#define SET_OPT_SAVE_OPTS(a) STMTS( \
+ DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT_MASK; \
+ DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+ DESC(SAVE_OPTS).optArg.argString = (char const*)(a) )
+/*
+ * Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR STMTS( ntpdsimOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR STMTS( ntpdsimOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n) STMTS( \
+ ntpdsimOptions.curOptIdx = (n); \
+ ntpdsimOptions.pzCurOpt = NULL )
+#define START_OPT RESTART_OPT(1)
+#define USAGE(c) (*ntpdsimOptions.pUsageProc)( &ntpdsimOptions, c )
+/* extracted from /usr/local/gnu/share/autogen/opthead.tpl near line 360 */
+
+/* * * * * *
+ *
+ * Declare the ntpdsim option descriptor.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern tOptions ntpdsimOptions;
+
+#ifndef _
+# if ENABLE_NLS
+# include <stdio.h>
+ static inline char* aoGetsText( char const* pz ) {
+ if (pz == NULL) return NULL;
+ return (char*)gettext( pz );
+ }
+# define _(s) aoGetsText(s)
+# else /* ENABLE_NLS */
+# define _(s) s
+# endif /* ENABLE_NLS */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_NTPDSIM_OPTS_H_GUARD */
+/* ntpdsim-opts.h ends here */
diff --git a/contrib/ntp/ntpd/ntpdsim-opts.menu b/contrib/ntp/ntpd/ntpdsim-opts.menu
new file mode 100644
index 0000000..c787458
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpdsim-opts.menu
@@ -0,0 +1 @@
+* ntpdsim Invocation:: Invoking ntpdsim
diff --git a/contrib/ntp/ntpd/ntpdsim-opts.texi b/contrib/ntp/ntpd/ntpdsim-opts.texi
new file mode 100644
index 0000000..49b5439
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpdsim-opts.texi
@@ -0,0 +1,509 @@
+@node ntpdsim Invocation
+@section Invoking ntpdsim
+@pindex ntpdsim
+@cindex NTP daemon simulation program
+@ignore
+#
+# EDIT THIS FILE WITH CAUTION (ntpdsim-opts.texi)
+#
+# It has been AutoGen-ed Sunday August 17, 2008 at 05:20:17 AM EDT
+# From the definitions ntpdsim-opts.def
+# and the template file aginfo.tpl
+@end ignore
+This program has no explanation.
+
+
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{ntpdsim} program. It documents the ntpdsim usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* ntpdsim usage:: ntpdsim usage help (-?)
+* ntpdsim authnoreq:: authnoreq option (-A)
+* ntpdsim authreq:: authreq option (-a)
+* ntpdsim bcastsync:: bcastsync option (-b)
+* ntpdsim configfile:: configfile option (-c)
+* ntpdsim debug-level:: debug-level option (-d)
+* ntpdsim driftfile:: driftfile option (-f)
+* ntpdsim dvar:: dvar option (-V)
+* ntpdsim endsimtime:: endsimtime option (-S)
+* ntpdsim freqerr:: freqerr option (-T)
+* ntpdsim interface:: interface option (-I)
+* ntpdsim ipv4:: ipv4 option (-4)
+* ntpdsim ipv6:: ipv6 option (-6)
+* ntpdsim jaildir:: jaildir option (-i)
+* ntpdsim keyfile:: keyfile option (-k)
+* ntpdsim logfile:: logfile option (-l)
+* ntpdsim modifymmtimer:: modifymmtimer option (-M)
+* ntpdsim ndelay:: ndelay option (-Y)
+* ntpdsim nice:: nice option (-N)
+* ntpdsim nofork:: nofork option (-n)
+* ntpdsim novirtualips:: novirtualips option (-L)
+* ntpdsim panicgate:: panicgate option (-g)
+* ntpdsim pdelay:: pdelay option (-Z)
+* ntpdsim phasenoise:: phasenoise option (-C)
+* ntpdsim pidfile:: pidfile option (-p)
+* ntpdsim priority:: priority option (-P)
+* ntpdsim propagationdelay:: propagationdelay option (-r)
+* ntpdsim quit:: quit option (-q)
+* ntpdsim servertime:: servertime option (-O)
+* ntpdsim set-debug-level:: set-debug-level option (-D)
+* ntpdsim simbroadcastdelay:: simbroadcastdelay option (-B)
+* ntpdsim simslew:: simslew option (-H)
+* ntpdsim slew:: slew option (-x)
+* ntpdsim statsdir:: statsdir option (-s)
+* ntpdsim trustedkey:: trustedkey option (-t)
+* ntpdsim updateinterval:: updateinterval option (-U)
+* ntpdsim user:: user option (-u)
+* ntpdsim var:: var option (-v)
+* ntpdsim walknoise:: walknoise option (-W)
+@end menu
+
+@node ntpdsim usage
+@subsection ntpdsim usage help (-?)
+@cindex ntpdsim usage
+
+This is the automatically generated usage text for ntpdsim:
+
+@exampleindent 0
+@example
+ntpdsim is unavailable - no --help
+@end example
+@exampleindent 4
+
+@node ntpdsim ipv4
+@subsection ipv4 option (-4)
+@cindex ntpdsim-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node ntpdsim ipv6
+@subsection ipv6 option (-6)
+@cindex ntpdsim-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node ntpdsim authreq
+@subsection authreq option (-a)
+@cindex ntpdsim-authreq
+
+This is the ``require crypto authentication'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authnoreq.
+@end itemize
+
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+
+@node ntpdsim authnoreq
+@subsection authnoreq option (-A)
+@cindex ntpdsim-authnoreq
+
+This is the ``do not require crypto authentication'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authreq.
+@end itemize
+
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+
+@node ntpdsim bcastsync
+@subsection bcastsync option (-b)
+@cindex ntpdsim-bcastsync
+
+This is the ``allow us to sync to broadcast servers'' option.
+
+
+@node ntpdsim simbroadcastdelay
+@subsection simbroadcastdelay option (-B)
+@cindex ntpdsim-simbroadcastdelay
+
+This is the ``simulator broadcast delay'' option.
+
+
+@node ntpdsim configfile
+@subsection configfile option (-c)
+@cindex ntpdsim-configfile
+
+This is the ``configuration file name'' option.
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+
+@node ntpdsim phasenoise
+@subsection phasenoise option (-C)
+@cindex ntpdsim-phasenoise
+
+This is the ``phase noise level'' option.
+
+
+@node ntpdsim debug-level
+@subsection debug-level option (-d)
+@cindex ntpdsim-debug-level
+
+This is the ``increase output debug message level'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@item
+must be compiled in by defining @code{DEBUG} during the compilation.
+@end itemize
+
+Increase the debugging message output level.
+
+@node ntpdsim set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntpdsim-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@item
+must be compiled in by defining @code{DEBUG} during the compilation.
+@end itemize
+
+Set the output debugging level. Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntpdsim driftfile
+@subsection driftfile option (-f)
+@cindex ntpdsim-driftfile
+
+This is the ``frequency drift file name'' option.
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the
+/etc/ntp.conf
+file.
+
+@node ntpdsim panicgate
+@subsection panicgate option (-g)
+@cindex ntpdsim-panicgate
+
+This is the ``allow the first adjustment to be big'' option.
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+
+@node ntpdsim simslew
+@subsection simslew option (-H)
+@cindex ntpdsim-simslew
+
+This is the ``simuator slew'' option.
+
+
+@node ntpdsim jaildir
+@subsection jaildir option (-i)
+@cindex ntpdsim-jaildir
+
+This is the ``jail directory'' option.
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+
+@node ntpdsim interface
+@subsection interface option (-I)
+@cindex ntpdsim-interface
+
+This is the ``listen on interface'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpdsim keyfile
+@subsection keyfile option (-k)
+@cindex ntpdsim-keyfile
+
+This is the ``path to symmetric keys'' option.
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+
+@node ntpdsim logfile
+@subsection logfile option (-l)
+@cindex ntpdsim-logfile
+
+This is the ``path to the log file'' option.
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+
+@node ntpdsim novirtualips
+@subsection novirtualips option (-L)
+@cindex ntpdsim-novirtualips
+
+This is the ``do not listen to virtual ips'' option.
+Do not listen to virtual IPs. The default is to listen.
+
+@node ntpdsim modifymmtimer
+@subsection modifymmtimer option (-M)
+@cindex ntpdsim-modifymmtimer
+
+This is the ``modify multimedia timer (windows only)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{SYS_WINNT} during the compilation.
+@end itemize
+
+Set the Windows Multimedia Timer to highest resolution.
+
+@node ntpdsim nofork
+@subsection nofork option (-n)
+@cindex ntpdsim-nofork
+
+This is the ``do not fork'' option.
+
+
+@node ntpdsim nice
+@subsection nice option (-N)
+@cindex ntpdsim-nice
+
+This is the ``run at high priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+
+@node ntpdsim servertime
+@subsection servertime option (-O)
+@cindex ntpdsim-servertime
+
+This is the ``server time'' option.
+
+
+@node ntpdsim pidfile
+@subsection pidfile option (-p)
+@cindex ntpdsim-pidfile
+
+This is the ``path to the pid file'' option.
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+
+@node ntpdsim priority
+@subsection priority option (-P)
+@cindex ntpdsim-priority
+
+This is the ``process priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+
+@node ntpdsim quit
+@subsection quit option (-q)
+@cindex ntpdsim-quit
+
+This is the ``set the time and quit'' option.
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+
+@node ntpdsim propagationdelay
+@subsection propagationdelay option (-r)
+@cindex ntpdsim-propagationdelay
+
+This is the ``broadcast/propagation delay'' option.
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+
+@node ntpdsim updateinterval
+@subsection updateinterval option (-U)
+@cindex ntpdsim-updateinterval
+
+This is the ``interval in seconds between scans for new or dropped interfaces'' option.
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning.
+
+@node ntpdsim statsdir
+@subsection statsdir option (-s)
+@cindex ntpdsim-statsdir
+
+This is the ``statistics file location'' option.
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+
+@node ntpdsim endsimtime
+@subsection endsimtime option (-S)
+@cindex ntpdsim-endsimtime
+
+This is the ``simulation end time'' option.
+
+
+@node ntpdsim trustedkey
+@subsection trustedkey option (-t)
+@cindex ntpdsim-trustedkey
+
+This is the ``trusted key number'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Add a key number to the trusted key list.
+
+@node ntpdsim freqerr
+@subsection freqerr option (-T)
+@cindex ntpdsim-freqerr
+
+This is the ``simulation frequency error'' option.
+
+
+@node ntpdsim walknoise
+@subsection walknoise option (-W)
+@cindex ntpdsim-walknoise
+
+This is the ``simulation random walk noise'' option.
+
+
+@node ntpdsim user
+@subsection user option (-u)
+@cindex ntpdsim-user
+
+This is the ``run as userid (or userid:groupid)'' option.
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+
+@node ntpdsim var
+@subsection var option (-v)
+@cindex ntpdsim-var
+
+This is the ``make arg an ntp variable (rw)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpdsim dvar
+@subsection dvar option (-V)
+@cindex ntpdsim-dvar
+
+This is the ``make arg an ntp variable (rw|def)'' option.
+
+This option has some usage constraints. It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpdsim slew
+@subsection slew option (-x)
+@cindex ntpdsim-slew
+
+This is the ``slew up to 600 seconds'' option.
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
+
+@node ntpdsim ndelay
+@subsection ndelay option (-Y)
+@cindex ntpdsim-ndelay
+
+This is the ``simulation network delay'' option.
+
+
+@node ntpdsim pdelay
+@subsection pdelay option (-Z)
+@cindex ntpdsim-pdelay
+
+This is the ``simulation processing delay'' option.
+
diff --git a/contrib/ntp/ntpd/ntpdsim.1 b/contrib/ntp/ntpd/ntpdsim.1
new file mode 100644
index 0000000..2a7ea46
--- /dev/null
+++ b/contrib/ntp/ntpd/ntpdsim.1
@@ -0,0 +1,357 @@
+.TH NTPDSIM 1 2008-08-17 "( 4.2.4p5)" "Programmer's Manual"
+.\" EDIT THIS FILE WITH CAUTION (ntpdsim.1)
+.\"
+.\" It has been AutoGen-ed Sunday August 17, 2008 at 05:20:16 AM EDT
+.\" From the definitions ntpdsim-opts.def
+.\" and the template file agman1.tpl
+.\"
+.SH NAME
+ntpdsim \- NTP daemon simulation program
+.SH SYNOPSIS
+.B ntpdsim
+.\" Mixture of short (flag) options and long options
+.RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \--\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
+.PP
+All arguments must be options.
+.SH "DESCRIPTION"
+This manual page documents, briefly, the \fBntpdsim\fP command.
+
+.SH OPTIONS
+.TP
+.BR \-4 ", " \--ipv4
+Force IPv4 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+.TP
+.BR \-6 ", " \--ipv6
+Force IPv6 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+.TP
+.BR \-a ", " \--authreq
+Require crypto authentication.
+This option must not appear in combination with any of the following options:
+authnoreq.
+.sp
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+.TP
+.BR \-A ", " \--authnoreq
+Do not require crypto authentication.
+This option must not appear in combination with any of the following options:
+authreq.
+.sp
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+.TP
+.BR \-b ", " \--bcastsync
+Allow us to sync to broadcast servers.
+.sp
+
+.TP
+.BR \-B " \fIstring\fP, " \--simbroadcastdelay "=" \fIstring\fP
+Simulator broadcast delay.
+.sp
+
+.TP
+.BR \-c " \fIstring\fP, " \--configfile "=" \fIstring\fP
+configuration file name.
+.sp
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+.TP
+.BR \-C " \fIstring\fP, " \--phasenoise "=" \fIstring\fP
+Phase noise level.
+.sp
+
+.TP
+.BR \-d ", " \--debug-level
+Increase output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Increase the debugging message output level.
+.TP
+.BR \-D " \fIstring\fP, " \--set-debug-level "=" \fIstring\fP
+Set the output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Set the output debugging level. Can be supplied multiple times,
+but each overrides the previous value(s).
+.TP
+.BR \-f " \fIstring\fP, " \--driftfile "=" \fIstring\fP
+frequency drift file name.
+.sp
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the
+/etc/ntp.conf
+file.
+.TP
+.BR \-g ", " \--panicgate
+Allow the first adjustment to be Big.
+.sp
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+.TP
+.BR \-H " \fIstring\fP, " \--simslew "=" \fIstring\fP
+Simuator slew.
+.sp
+
+.TP
+.BR \-i " \fIstring\fP, " \--jaildir "=" \fIstring\fP
+Jail directory.
+.sp
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+.TP
+.BR \-I " \fIiface\fP, " \--interface "=" \fIiface\fP
+Listen on interface.
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR \-k " \fIstring\fP, " \--keyfile "=" \fIstring\fP
+path to symmetric keys.
+.sp
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+.TP
+.BR \-l " \fIstring\fP, " \--logfile "=" \fIstring\fP
+path to the log file.
+.sp
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+.TP
+.BR \-L ", " \--novirtualips
+Do not listen to virtual IPs.
+.sp
+Do not listen to virtual IPs. The default is to listen.
+.TP
+.BR \-M ", " \--modifymmtimer
+Modify Multimedia Timer (Windows only).
+.sp
+Set the Windows Multimedia Timer to highest resolution.
+.TP
+.BR \-n ", " \--nofork
+Do not fork.
+.sp
+
+.TP
+.BR \-N ", " \--nice
+Run at high priority.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+.TP
+.BR \-O " \fIstring\fP, " \--servertime "=" \fIstring\fP
+Server time.
+.sp
+
+.TP
+.BR \-p " \fIstring\fP, " \--pidfile "=" \fIstring\fP
+path to the PID file.
+.sp
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+.TP
+.BR \-P " \fInumber\fP, " \--priority "=" \fInumber\fP
+Process priority.
+This option takes an integer number as its argument.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+.TP
+.BR \-q ", " \--quit
+Set the time and quit.
+.sp
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR \-r " \fIstring\fP, " \--propagationdelay "=" \fIstring\fP
+Broadcast/propagation delay.
+.sp
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+.TP
+.BR \-U " \fInumber\fP, " \--updateinterval "=" \fInumber\fP
+interval in seconds between scans for new or dropped interfaces.
+This option takes an integer number as its argument.
+.sp
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning.
+.TP
+.BR \-s " \fIstring\fP, " \--statsdir "=" \fIstring\fP
+Statistics file location.
+.sp
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+.TP
+.BR \-S " \fIstring\fP, " \--endsimtime "=" \fIstring\fP
+Simulation end time.
+.sp
+
+.TP
+.BR \-t " \fItkey\fP, " \--trustedkey "=" \fItkey\fP
+Trusted key number.
+This option may appear an unlimited number of times.
+.sp
+Add a key number to the trusted key list.
+.TP
+.BR \-T " \fIstring\fP, " \--freqerr "=" \fIstring\fP
+Simulation frequency error.
+.sp
+
+.TP
+.BR \-W " \fIstring\fP, " \--walknoise "=" \fIstring\fP
+Simulation random walk noise.
+.sp
+
+.TP
+.BR \-u " \fIstring\fP, " \--user "=" \fIstring\fP
+Run as userid (or userid:groupid).
+.sp
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+.TP
+.BR \-v " \fInvar\fP, " \--var "=" \fInvar\fP
+make ARG an ntp variable (RW).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR \-V " \fIndvar\fP, " \--dvar "=" \fIndvar\fP
+make ARG an ntp variable (RW|DEF).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR \-x ", " \--slew
+Slew up to 600 seconds.
+.sp
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR \-Y " \fIstring\fP, " \--ndelay "=" \fIstring\fP
+Simulation network delay.
+.sp
+
+.TP
+.BR \-Z " \fIstring\fP, " \--pdelay "=" \fIstring\fP
+Simulation processing delay.
+.sp
+
+.TP
+.BR \-? , " \--help"
+Display usage information and exit.
+.TP
+.BR \-! , " \--more-help"
+Extended usage information passed thru pager.
+.TP
+.BR \-> " [\fIrcfile\fP]," " \--save-opts" "[=\fIrcfile\fP]"
+Save the option state to \fIrcfile\fP. The default is the \fIlast\fP
+configuration file listed in the \fBOPTION PRESETS\fP section, below.
+.TP
+.BR \-< " \fIrcfile\fP," " \--load-opts" "=\fIrcfile\fP," " \--no-load-opts"
+Load options from \fIrcfile\fP.
+The \fIno-load-opts\fP form will disable the loading
+of earlier RC/INI files. \fI--no-load-opts\fP is handled early,
+out of order.
+.TP
+.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+Output version of program and exit. The default mode is `v', a simple
+version. The `c' mode will print copyright information and `n' will
+print the full copyright notice.
+.SH OPTION PRESETS
+Any option that is not marked as \fInot presettable\fP may be preset
+by loading values from configuration ("RC" or ".INI") file(s) and values from
+environment variables named:
+.nf
+ \fBNTPDSIM_<option-name>\fP or \fBNTPDSIM\fP
+.fi
+.aj
+The environmental presets take precedence (are processed later than)
+the configuration files.
+The \fIhomerc\fP files are "\fI$HOME\fP", and "\fI.\fP".
+If any of these are directories, then the file \fI.ntprc\fP
+is searched for within those directories.
+.SH AUTHOR
+David L. Mills and/or others
+.br
+Please send bug reports to: http://bugs.ntp.isc.org, bugs@ntp.org
+
+.PP
+.nf
+.na
+see html/copyright.html
+.fi
+.ad
+.PP
+This manual page was \fIAutoGen\fP-erated from the \fBntpdsim\fP
+option definitions.
diff --git a/contrib/ntp/ntpd/ntpsim.c b/contrib/ntp/ntpd/ntpsim.c
index 3fbae17..d5ed587 100644
--- a/contrib/ntp/ntpd/ntpsim.c
+++ b/contrib/ntp/ntpd/ntpsim.c
@@ -4,6 +4,7 @@
*/
#include "ntpd.h"
#include "ntpsim.h"
+#include "ntpdsim-opts.h"
/*
* Defines...
@@ -65,7 +66,6 @@ ntpsim(
init_mon();
init_timer();
init_lib();
- init_random();
init_request();
init_control();
init_peer();
@@ -73,14 +73,23 @@ ntpsim(
init_io();
init_loopfilter();
mon_start(MON_OFF);
+
+ {
+ int optct = optionProcess(&ntpdsimOptions, argc, argv);
+ argc -= optct;
+ argv += optct;
+ }
+
getconfig(argc, argv);
+
initializing = 0;
+ loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
/*
* Watch out here, we want the real time, not the silly stuff.
*/
gettimeofday(&seed, NULL);
- srand48(seed.tv_usec);
+ ntp_srandom(seed.tv_usec);
/*
* Push a beep and timer interrupt on the queue
@@ -202,11 +211,12 @@ ntptmr(
/*
* Process buffers received. They had better be in order by
- * receive timestamp.
+ * receive timestamp. Note that there are no additional buffers
+ * in the current implementation of ntpsim.
*/
while (n->rbuflist != NULL) {
rbuf = n->rbuflist;
- n->rbuflist = rbuf->next;
+ n->rbuflist = NULL;
(rbuf->receiver)(rbuf);
free(rbuf);
}
@@ -270,7 +280,6 @@ int srvr_rply(
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
@@ -306,20 +315,14 @@ netpkt(
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.
+ * the queue;
*/
if (obuf == NULL) {
n->rbuflist = rbuf;
- } else {
- while (obuf->next != NULL)
- obuf = obuf->next;
- obuf->next = rbuf;
}
}
diff --git a/contrib/ntp/ntpd/ppsapi_timepps.h b/contrib/ntp/ntpd/ppsapi_timepps.h
new file mode 100644
index 0000000..8adaf62
--- /dev/null
+++ b/contrib/ntp/ntpd/ppsapi_timepps.h
@@ -0,0 +1,26 @@
+/* ppsapi_timepps.h */
+
+/*
+ * This logic first tries to get the timepps.h file from a standard
+ * location, and then from our include/ subdirectory.
+ */
+
+#ifdef HAVE_TIMEPPS_H
+# include <timepps.h>
+#else
+# ifdef HAVE_SYS_TIMEPPS_H
+# include <sys/timepps.h>
+# else
+# ifdef HAVE_CIOGETEV
+# include "timepps-SunOS.h"
+# else
+# ifdef HAVE_TIOCGPPSEV
+# include "timepps-Solaris.h"
+# else
+# ifdef TIOCDCDTIMESTAMP
+# include "timepps-SCO.h"
+# endif
+# endif
+# endif
+# endif
+#endif
diff --git a/contrib/ntp/ntpd/refclock_acts.c b/contrib/ntp/ntpd/refclock_acts.c
index d26ceed..57f2ca7 100644
--- a/contrib/ntp/ntpd/refclock_acts.c
+++ b/contrib/ntp/ntpd/refclock_acts.c
@@ -1,8 +1,7 @@
/*
- * refclock_acts - clock driver for the NIST/PTB Automated Computer Time
- * Service aka Amalgamated Containerized Trash Service (ACTS)
+ * refclock_acts - clock driver for the NIST/USNO/PTB/NPL Computer Time
+ * Services
*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -22,342 +21,190 @@
# include <sys/ioctl.h>
#endif /* HAVE_SYS_IOCTL_H */
-/* MUST BE AFTER LAST #include <config.h> !!! */
-
-#if defined(CLOCK_ACTS) && defined(CLOCK_PTBACTS)
-# if defined(KEEPPTBACTS)
-# undef CLOCK_ACTS
-# else /* not KEEPPTBACTS */
-# undef CLOCK_PTBACTS
-# endif /* not KEEPPTBACTS */
-#endif /* CLOCK_ACTS && CLOCK_PTBACTS */
-
/*
- * This driver supports the NIST Automated Computer Time Service (ACTS).
- * It periodically dials a prespecified telephone number, receives the
- * NIST timecode data and calculates the local clock correction. It is
- * designed primarily for use as a backup when neither a radio clock nor
- * connectivity to Internet time servers is available. For the best
- * accuracy, the individual telephone line/modem delay needs to be
- * calibrated using outside sources.
- *
- * The ACTS is located at NIST Boulder, CO, telephone 303 494 4774. A
- * toll call from a residence telephone in Newark, DE, costs between 14
- * and 27 cents, depending on time of day, and from a campus telephone
- * between 3 and 4 cents, although it is not clear what carrier and time
- * of day discounts apply in this case. The modem dial string will
- * differ depending on local telephone configuration, etc., and is
- * specified by the phone command in the configuration file. The
- * argument to this command is an AT command for a Hayes compatible
- * modem.
- *
- * The accuracy produced by this driver should be in the range of a
- * millisecond or two, but may need correction due to the delay
- * characteristics of the individual modem involved. For undetermined
- * reasons, some modems work with the ACTS echo-delay measurement scheme
- * and some don't. This driver tries to do the best it can with what it
- * gets. Initial experiments with a Practical Peripherals 9600SA modem
- * here in Delaware suggest an accuracy of a millisecond or two can be
- * achieved without the scheme by using a fudge time1 value of 65.0 ms.
- * In either case, the dispersion for a single call involving ten
- * samples is about 1.3 ms.
- *
- * The driver can operate in either of three modes, as determined by
- * the mode parameter in the server configuration command. In mode 0
- * (automatic) the driver operates continuously at intervals depending
- * on the prediction error, as measured by the driver, usually in the
- * order of several hours. In mode 1 (backup) the driver is enabled in
- * automatic mode only when no other source of synchronization is
- * available and when more than MAXOUTAGE (3600 s) have elapsed since
- * last synchronized by other sources. In mode 2 (manual) the driver
- * operates only when enabled using a fudge flags switch, as described
- * below.
- *
- * For reliable call management, this driver requires a 1200-bps modem
- * with a Hayes-compatible command set and control over the modem data
- * terminal ready (DTR) control line. Present restrictions require the
- * use of a POSIX-compatible programming interface, although other
- * interfaces may work as well. The modem setup string is hard-coded in
- * the driver and may require changes for nonstandard modems or special
- * circumstances.
- *
- * Further information can be found in the README.refclock file in the
- * ntp - Version 3 distribution.
- *
- * Fudge Factors
- *
- * Ordinarily, the propagation time correction is computed automatically
- * by ACTS and the driver. When this is not possible or erratic due to
- * individual modem characteristics, the fudge flag2 switch should be
- * set to disable the ACTS echo-delay scheme. In any case, the fudge
- * time1 parameter can be used to adjust the propagation delay as
- * required.
- *
- * The ACTS call interval is determined in one of three ways. In manual
- * mode a call is initiated by setting fudge flag1 using ntpdc, either
- * manually or via a cron job. In AUTO mode this flag is set by the peer
- * timer, which is controlled by the sys_poll variable in response to
- * measured errors. In backup mode the driver is ordinarily asleep, but
- * awakes (in auto mode) if all other synchronization sources are lost.
- * In either auto or backup modes, the call interval increases as long
- * as the measured errors do not exceed the value of the fudge time2
- * parameter.
- *
- * When the fudge flag1 is set, the ACTS calling program is activated.
- * This program dials each number listed in the phones command of the
- * configuration file in turn. If a call attempt fails, the next number
- * in the list is dialed. The fudge flag1 and counter are reset and the
- * calling program terminated if (a) a valid clock update has been
- * determined, (b) no more numbers remain in the list, (c) a device
- * fault or timeout occurs or (d) fudge flag1 is reset manually using
- * ntpdc.
- *
- * In automatic and backup modes, the driver determines the call
- * interval using a procedure depending on the measured prediction
- * error and the fudge time2 parameter. If the error exceeds time2 for a
- * number of times depending on the current interval, the interval is
- * decreased, but not less than about 1000 s. If the error is less than
- * time2 for some number of times, the interval is increased, but not
- * more than about 18 h. With the default value of zero for fudge time2,
- * the interval will increase from 1000 s to the 4000-8000-s range, in
- * which the expected accuracy should be in the 1-2-ms range. Setting
- * fudge time2 to a large value, like 0.1 s, may result in errors of
- * that order, but increase the call interval to the maximum. The exact
- * value for each configuration will depend on the modem and operating
- * system involved, so some experimentation may be necessary.
+ * This driver supports the US (NIST, USNO) and European (PTB, NPL,
+ * etc.) modem time services, as well as Spectracom GPS and WWVB
+ * receivers connected via a modem. The driver periodically dials a
+ * number from a telephone list, receives the timecode data and
+ * calculates the local clock correction. It is designed primarily for
+ * use as backup when neither a radio clock nor connectivity to Internet
+ * time servers is available.
+ *
+ * This driver requires a modem with a Hayes-compatible command set and
+ * control over the modem data terminal ready (DTR) control line. The
+ * modem setup string is hard-coded in the driver and may require
+ * changes for nonstandard modems or special circumstances. For reasons
+ * unrelated to this driver, the data set ready (DSR) control line
+ * should not be set when this driver is first started.
+ *
+ * The calling program is initiated by setting fudge flag1, either
+ * manually or automatically. When flag1 is set, the calling program
+ * dials the first number in the phone command of the configuration
+ * file. If that call fails, the calling program dials the second number
+ * and so on. The number is specified by the Hayes ATDT prefix followed
+ * by the number itself, including the prefix and long-distance digits
+ * and delay code, if necessary. The flag1 is reset and the calling
+ * program terminated if (a) a valid clock update has been determined,
+ * (b) no more numbers remain in the list, (c) a device fault or timeout
+ * occurs or (d) fudge flag1 is reset manually.
+ *
+ * The driver is transparent to each of the modem time services and
+ * Spectracom radios. It selects the parsing algorithm depending on the
+ * message length. There is some hazard should the message be corrupted.
+ * However, the data format is checked carefully and only if all checks
+ * succeed is the message accepted. Corrupted lines are discarded
+ * without complaint.
+ *
+ * Fudge controls
+ *
+ * flag1 force a call in manual mode
+ * flag2 enable port locking (not verified)
+ * flag3 no modem; port is directly connected to device
+ * flag4 not used
+ *
+ * time1 offset adjustment (s)
+ *
+ * Ordinarily, the serial port is connected to a modem; however, it can
+ * be connected directly to a device or another computer for testing and
+ * calibration. In this case set fudge flag3 and the driver will send a
+ * single character 'T' at each poll event. In principle, fudge flag2
+ * enables port locking, allowing the modem to be shared when not in use
+ * by this driver. At least on Solaris with the current NTP I/O
+ * routines, this results only in lots of ugly error messages.
*/
-
/*
- * DESCRIPTION OF THE AUTOMATED COMPUTER TELEPHONE SERVICE (ACTS)
- * (reformatted from ACTS on-line computer help information)
+ * National Institute of Science and Technology (NIST)
*
- * The following is transmitted (at 1200 baud) following completion of
- * the telephone connection.
+ * Phone: (303) 494-4774 (Boulder, CO); (808) 335-4721 (Hawaii)
+ *
+ * Data Format
*
* National Institute of Standards and Technology
* Telephone Time Service, Generator 3B
* Enter question mark "?" for HELP
* D L D
* MJD YR MO DA H M S ST S UT1 msADV <OTM>
- * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) *
- * 47999 90-04-18 21:39:16 50 0 +.1 045.0 UTC(NIST) *
- * 47999 90-04-18 21:39:17 50 0 +.1 045.0 UTC(NIST) *
- * 47999 90-04-18 21:39:18 50 0 +.1 045.0 UTC(NIST) *
- * 47999 90-04-18 21:39:19 50 0 +.1 037.6 UTC(NIST) #
- * 47999 90-04-18 21:39:20 50 0 +.1 037.6 UTC(NIST) #
- * etc..etc...etc.......
- *
- * UTC = Universal Time Coordinated, the official world time referred to
- * the zero meridian.
+ * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) *<CR><LF>
+ * ...
*
- * DST Daylight savings time characters, valid for the continental
- * U.S., are set as follows:
+ * MJD, DST, DUT1 and UTC are not used by this driver. The "*" or "#" is
+ * the on-time markers echoed by the driver and used by NIST to measure
+ * and correct for the propagation delay.
*
- * 00 We are on standard time (ST).
- * 01-49 Now on DST, go to ST when your local time is 2:00 am and
- * the count is 01. The count is decremented daily at 00
- * (UTC).
- * 50 We are on DST.
- * 51-99 Now on ST, go to DST when your local time is 2:00 am and
- * the count is 51. The count is decremented daily at 00
- * (UTC).
+ * US Naval Observatory (USNO)
*
- * The two DST characters provide up to 48 days advance notice of a
- * change in time. The count remains at 00 or 50 at other times.
+ * Phone: (202) 762-1594 (Washington, DC); (719) 567-6742 (Boulder, CO)
*
- * LS Leap second flag is set to "1" to indicate that a leap second is
- * to be added as 23:59:60 (UTC) on the last day of the current UTC
- * month. The LS flag will be reset to "0" starting with 23:59:60
- * (UTC). The flag will remain on for the entire month before the
- * second is added. Leap seconds are added as needed at the end of
- * any month. Usually June and/or December are chosen.
+ * Data Format (two lines, repeating at one-second intervals)
*
- * The leap second flag will be set to a "2" to indicate that a
- * leap second is to be deleted at 23:59:58--00:00:00 on the last
- * day of the current month. (This latter provision is included per
- * international recommendation, however it is not likely to be
- * required in the near future.)
+ * jjjjj nnn hhmmss UTC<CR><LF>
+ * *<CR><LF>
*
- * DUT1 Approximate difference between earth rotation time (UT1) and
- * UTC, in steps of 0.1 second: DUT1 = UT1 - UTC.
+ * jjjjj modified Julian day number (not used)
+ * nnn day of year
+ * hhmmss second of day
+ * * on-time marker for previous timecode
+ * ...
*
- * MJD Modified Julian Date, often used to tag certain scientific data.
+ * USNO does not correct for the propagation delay. A fudge time1 of
+ * about .06 s is advisable.
*
- * The full time format is sent at 1200 baud, 8 bit, 1 stop, no parity.
- * The format at 300 Baud is also 8 bit, 1 stop, no parity. At 300 Baud
- * the MJD and DUT1 values are deleted and the time is transmitted only
- * on even seconds.
+ * European Services (PTB, NPL, etc.)
*
- * Maximum on line time will be 56 seconds. If all lines are busy at any
- * time, the oldest call will be terminated if it has been on line more
- * than 28 seconds, otherwise, the call that first reaches 28 seconds
- * will be terminated.
+ * PTB: +49 531 512038 (Germany)
+ * NPL: 0906 851 6333 (UK only)
*
- * Current time is valid at the "on-time" marker (OTM), either "*" or
- * "#". The nominal on-time marker (*) will be transmitted 45 ms early
- * to account for the 8 ms required to send 1 character at 1200 Baud,
- * plus an additional 7 ms for delay from NIST to the user, and
- * approximately 30 ms "scrambler" delay inherent in 1200 Baud modems.
- * If the caller echoes all characters, NIST will measure the round trip
- * delay and advance the on-time marker so that the midpoint of the stop
- * bit arrives at the user on time. The amount of msADV will reflect the
- * actual required advance in milliseconds and the OTM will be a "#".
+ * Data format (see the documentation for phone numbers and formats.)
*
- * (The NIST system requires 4 or 5 consecutive delay measurements which
- * are consistent before switching from "*" to "#". If the user has a
- * 1200 Baud modem with the same internal delay as that used by NIST,
- * then the "#" OTM should arrive at the user within +-2 ms of the
- * correct time.
+ * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500<CR><LF>
*
- * However, NIST has studied different brands of 1200 Baud modems and
- * found internal delays from 24 ms to 40 ms and offsets of the "#" OTM
- * of +-10 ms. For many computer users, +-10 ms accuracy should be more
- * than adequate since many computer internal clocks can only be set
- * with granularity of 20 to 50 ms. In any case, the repeatability of
- * the offset for the "#" OTM should be within +-2 ms, if the dial-up
- * path is reciprocal and the user doesn't change the brand or model of
- * modem used.
+ * Spectracom GPS and WWVB Receivers
*
- * This should be true even if the dial-up path on one day is a land-
- * line of less than 40 ms (one way) and on the next day is a satellite
- * link of 260 to 300 ms. In the rare event that the path is one way by
- * satellite and the other way by land line with a round trip
- * measurement in the range of 90 to 260 ms, the OTM will remain a "*"
- * indicating 45 ms advance.
- *
- * For user comments write:
- * NIST-ACTS
- * Time and Frequency Division
- * Mail Stop 847
- * 325 Broadway
- * Boulder, CO 80303
- *
- * Software for setting (PC)DOS compatable machines is available on a
- * 360-kbyte diskette for $35.00 from: NIST Office of Standard Reference
- * Materials B311-Chemistry Bldg, NIST, Gaithersburg, MD, 20899, (301)
- * 975-6776
- *
- * PTB timecode service (+49 531 512038)
- * The Physikalisch-Technische Bundesanstalt (Germany)
- * also supports a modem time service
- * as the data formats are very similar this driver can also be compiled for
- * utilizing the PTB time code service.
- *
- * Data format
- * 0000000000111111111122222222223333333333444444444455555555556666666666777777777 7
- * 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9
- * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500 *
- * A B C D EF G H IJ K L M N O P Q R S T U V W XY Z<CR><LF>
- *
- * A year
- * B month
- * C day
- * D hour
- * E : normally
- * A for DST to ST switch first hour
- * B for DST to ST switch second hour if not marked in H
- * F minute
- * G second
- * H timezone
- * I day of week
- * J week of year
- * K day of year
- * L month for next ST/DST changes
- * M day
- * N hour
- * O UTC year
- * P UTC month
- * Q UTC day
- * R UTC hour
- * S UTC minute
- * T modified julian day (MJD)
- * U DUT1
- * V direction and month if leap second
- * W signal delay (assumed/measured)
- * X sequence number for additional text line in Y
- * Y additional text
- * Z on time marker (* - assumed delay / # measured delay)
- * <CR>!<LF> ! is second change !
- *
- * This format is also used by the National Physical Laboratory (NPL)'s
- * TRUETIME service in the UK. In this case the timezone field is
- * UTC+0 or UTC+1 for standard and daylight saving time. The phone
- * number for this service (a premium rate number) is 0891 516 333.
- * It is not clear whether the echo check is implemented.
- *
- * For more detail, see http://www.npl.co.uk/npl/cetm/taf/truetime.html.
+ * If a modem is connected to a Spectracom receiver, this driver will
+ * call it up and retrieve the time in one of two formats. As this
+ * driver does not send anything, the radio will have to either be
+ * configured in continuous mode or be polled by another local driver.
*/
-
/*
* Interface definitions
*/
-#define SPEED232 B1200 /* uart speed (1200 cowardly baud) */
+#define DEVICE "/dev/acts%d" /* device name and unit */
+#define SPEED232 B9600 /* uart speed (9600 baud) */
#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#ifdef CLOCK_ACTS
-# define REFID "ACTS" /* reference ID */
-# define DESCRIPTION "NIST Automated Computer Time Service" /* WRU */
-# define LENCODE 50 /* length of valid timecode string */
-# define DEVICE "/dev/acts%d" /* device name and unit */
-# define REF_ENTRY refclock_acts
-#else /* not CLOCK_ACTS */
-# define REFID "TPTB" /* reference ID */
-# define DESCRIPTION "PTB Automated Computer Time Service"
-# define LENCODE 78 /* length of valid timecode string */
-# define DEVICE "/dev/ptb%d" /* device name and unit */
-# define REF_ENTRY refclock_ptb
-#endif /* not CLOCK_ACTS */
+#define LOCKFILE "/var/spool/locks/LCK..cua%d"
+#define DESCRIPTION "Automated Computer Time Service" /* WRU */
+#define REFID "NONE" /* default reference ID */
+#define MSGCNT 20 /* max message count */
+#define SMAX 256 /* max clockstats line length */
+
+/*
+ * Calling program modes
+ */
#define MODE_AUTO 0 /* automatic mode */
#define MODE_BACKUP 1 /* backup mode */
#define MODE_MANUAL 2 /* manual mode */
-#define MSGCNT 10 /* we need this many ACTS messages */
-#define SMAX 80 /* max token string length */
-#define ACTS_MINPOLL 10 /* log2 min poll interval (1024 s) */
-#define ACTS_MAXPOLL 18 /* log2 max poll interval (16384 s) */
-#define MAXOUTAGE 3600 /* max before ACTS kicks in (s) */
+/*
+ * Service identifiers.
+ */
+#define REFACTS "NIST" /* NIST reference ID */
+#define LENACTS 50 /* NIST format */
+#define REFUSNO "USNO" /* USNO reference ID */
+#define LENUSNO 20 /* USNO */
+#define REFPTB "PTB\0" /* PTB/NPL reference ID */
+#define LENPTB 78 /* PTB/NPL format */
+#define REFWWVB "WWVB" /* WWVB reference ID */
+#define LENWWVB0 22 /* WWVB format 0 */
+#define LENWWVB2 24 /* WWVB format 2 */
+#define LF 0x0a /* ASCII LF */
/*
- * Modem control strings. These may have to be changed for some modems.
+ * Modem setup strings. These may have to be changed for some modems.
*
* AT command prefix
- * B1 initiate call negotiation using Bell 212A
- * &C1 enable carrier detect
+ * B1 US answer tone
+ * &C0 disable carrier detect
* &D2 hang up and return to command mode on DTR transition
* E0 modem command echo disabled
* l1 set modem speaker volume to low level
- * M1 speaker enabled untill carrier detect
+ * M1 speaker enabled until carrier detect
* Q0 return result codes
* V1 return result codes as English words
*/
-#define MODEM_SETUP "ATB1&C1&D2E0L1M1Q0V1" /* modem setup */
-#define MODEM_HANGUP "ATH" /* modem disconnect */
+#define MODEM_SETUP "ATB1&C0&D2E0L1M1Q0V1\r" /* modem setup */
+#define MODEM_HANGUP "ATH\r" /* modem disconnect */
/*
- * Timeouts
+ * Timeouts (all in seconds)
*/
-#define IDLE 60 /* idle timeout (s) */
-#define WAIT 2 /* wait timeout (s) */
-#define ANSWER 30 /* answer timeout (s) */
-#define CONNECT 10 /* connect timeout (s) */
-#define TIMECODE 15 /* timecode timeout (s) */
+#define SETUP 3 /* setup timeout */
+#define DTR 1 /* DTR timeout */
+#define ANSWER 60 /* answer timeout */
+#define CONNECT 20 /* first valid message timeout */
+#define TIMECODE 30 /* all valid messages timeout */
/*
- * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
- * leap.
+ * State machine codes
*/
-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};
+#define S_IDLE 0 /* wait for poll */
+#define S_OK 1 /* wait for modem setup */
+#define S_DTR 2 /* wait for modem DTR */
+#define S_CONNECT 3 /* wait for answer*/
+#define S_FIRST 4 /* wait for first valid message */
+#define S_MSG 5 /* wait for all messages */
+#define S_CLOSE 6 /* wait after sending disconnect */
/*
* Unit control structure
*/
struct actsunit {
- int pollcnt; /* poll message counter */
+ int unit; /* unit number */
int state; /* the first one was Delaware */
- int run; /* call program run switch */
- int msgcnt; /* count of ACTS messages received */
- long redial; /* interval to next automatic call */
- double msADV; /* millisecond advance of last message */
+ int timer; /* timeout counter */
+ int retry; /* retry index */
+ int msgcnt; /* count of messages received */
+ l_fp tstamp; /* on-time timestamp */
+ char *bufptr; /* buffer pointer */
};
/*
@@ -366,77 +213,54 @@ struct actsunit {
static int acts_start P((int, struct peer *));
static void acts_shutdown P((int, struct peer *));
static void acts_receive P((struct recvbuf *));
+static void acts_message P((struct peer *));
+static void acts_timecode P((struct peer *, char *));
static void acts_poll P((int, struct peer *));
static void acts_timeout P((struct peer *));
static void acts_disc P((struct peer *));
-static int acts_write P((struct peer *, const char *));
+static void acts_timer P((int, struct peer *));
/*
* Transfer vector (conditional structure name)
*/
-struct refclock REF_ENTRY = {
+struct refclock refclock_acts = {
acts_start, /* start up driver */
acts_shutdown, /* shut down driver */
acts_poll, /* transmit poll message */
- noentry, /* not used (old acts_control) */
- noentry, /* not used (old acts_init) */
- noentry, /* not used (old acts_buginfo) */
- NOFLAGS /* not used */
+ noentry, /* not used */
+ noentry, /* not used */
+ noentry, /* not used */
+ acts_timer /* housekeeping timer */
};
+struct refclock refclock_ptb;
/*
- * acts_start - open the devices and initialize data for processing
+ * Initialize data for processing
*/
-
static int
acts_start (
- int unit,
+ int unit,
struct peer *peer
)
{
- register struct actsunit *up;
+ struct actsunit *up;
struct refclockproc *pp;
- int fd;
- char device[20];
- int dtr = TIOCM_DTR;
-
- /*
- * Open serial port. Use ACTS line discipline, if available. It
- * pumps a timestamp into the data stream at every on-time
- * character '*' found. Note: the port must have modem control
- * or deep pockets for the phone bill. HP-UX 9.03 users should
- * have very deep pockets.
- */
- (void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS)))
- return (0);
- if (ioctl(fd, TIOCMBIS, (char *)&dtr) < 0) {
- msyslog(LOG_ERR, "clock %s ACTS no modem control",
- ntoa(&peer->srcadr));
- return (0);
- }
/*
* Allocate and initialize unit structure
*/
- if (!(up = (struct actsunit *)
- emalloc(sizeof(struct actsunit)))) {
- (void) close(fd);
+ up = emalloc(sizeof(struct actsunit));
+ if (up == NULL)
return (0);
- }
- memset((char *)up, 0, sizeof(struct actsunit));
+
+ memset(up, 0, sizeof(struct actsunit));
+ up->unit = unit;
pp = peer->procptr;
+ pp->unitptr = (caddr_t)up;
pp->io.clock_recv = acts_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
- (void) close(fd);
- free(up);
- return (0);
- }
- pp->unitptr = (caddr_t)up;
/*
* Initialize miscellaneous variables
@@ -444,24 +268,9 @@ acts_start (
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
- peer->minpoll = ACTS_MINPOLL;
- peer->maxpoll = ACTS_MAXPOLL;
peer->sstclktype = CTL_SST_TS_TELEPHONE;
-
- /*
- * Initialize modem and kill DTR. We skedaddle if this comes
- * bum.
- */
- if (!acts_write(peer, MODEM_SETUP)) {
- (void) close(fd);
- free(up);
- return (0);
- }
-
- /*
- * Set up the driver timeout
- */
- peer->nextdate = current_time + WAIT;
+ peer->flags &= ~FLAG_FIXPOLL;
+ up->bufptr = pp->a_lastcode;
return (1);
}
@@ -471,16 +280,18 @@ acts_start (
*/
static void
acts_shutdown (
- int unit,
+ int unit,
struct peer *peer
)
{
- register struct actsunit *up;
+ struct actsunit *up;
struct refclockproc *pp;
+ /*
+ * Warning: do this only when a call is not in progress.
+ */
pp = peer->procptr;
up = (struct actsunit *)pp->unitptr;
- io_closeclock(&pp->io);
free(up);
}
@@ -493,254 +304,326 @@ acts_receive (
struct recvbuf *rbufp
)
{
- register struct actsunit *up;
+ struct actsunit *up;
struct refclockproc *pp;
struct peer *peer;
- char str[SMAX];
- int i;
- char hangup = '%'; /* ACTS hangup */
- int day; /* day of the month */
- int month; /* month of the year */
- u_long mjd; /* Modified Julian Day */
- double dut1; /* DUT adjustment */
- double msADV; /* ACTS transmit advance (ms) */
- char flag; /* calibration flag */
-#ifndef CLOCK_PTBACTS
- char utc[10]; /* this is NIST and you're not */
- u_int dst; /* daylight/standard time indicator */
- u_int leap; /* leap-second indicator */
-#else
- char leapdir; /* leap direction */
- u_int leapmonth; /* month of leap */
-#endif
+ char tbuf[BMAX];
+ char *tptr;
+
/*
- * Initialize pointers and read the timecode and timestamp. If
- * the OK modem status code, leave it where folks can find it.
+ * Initialize pointers and read the timecode and timestamp. Note
+ * we are in raw mode and victim of whatever the terminal
+ * interface kicks up; so, we have to reassemble messages from
+ * arbitrary fragments. Capture the timecode at the beginning of
+ * the message and at the '*' and '#' on-time characters.
*/
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct actsunit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
- &pp->lastrec);
- if (pp->lencode == 0) {
- if (strcmp(pp->a_lastcode, "OK") == 0)
- pp->lencode = 2;
- return;
+ pp->lencode = refclock_gtraw(rbufp, tbuf, BMAX - (up->bufptr -
+ pp->a_lastcode), &pp->lastrec);
+ for (tptr = tbuf; *tptr != '\0'; tptr++) {
+ if (*tptr == LF) {
+ if (up->bufptr == pp->a_lastcode) {
+ up->tstamp = pp->lastrec;
+ continue;
+
+ } else {
+ *up->bufptr = '\0';
+ acts_message(peer);
+ up->bufptr = pp->a_lastcode;
+ }
+ } else if (!iscntrl(*tptr)) {
+ *up->bufptr++ = *tptr;
+ if (*tptr == '*' || *tptr == '#') {
+ up->tstamp = pp->lastrec;
+ write(pp->io.fd, tptr, 1);
+ }
+ }
}
+}
+
+
+/*
+ * acts_message - process message
+ */
+void
+acts_message(
+ struct peer *peer
+ )
+{
+ struct actsunit *up;
+ struct refclockproc *pp;
+ int dtr = TIOCM_DTR;
+ char tbuf[SMAX];
#ifdef DEBUG
- if (debug)
- printf("acts: state %d timecode %d %*s\n", up->state,
- pp->lencode, pp->lencode, pp->a_lastcode);
+ u_int modem;
#endif
- switch (up->state) {
-
- case 0:
+ /*
+ * What to do depends on the state and the first token in the
+ * message. A NO token sends the message to the clockstats.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+#ifdef DEBUG
+ ioctl(pp->io.fd, TIOCMGET, (char *)&modem);
+ sprintf(tbuf, "acts: %04x (%d %d) %lu %s", modem, up->state,
+ up->timer, strlen(pp->a_lastcode), pp->a_lastcode);
+ if (debug)
+ printf("%s\n", tbuf);
+#endif
+ strncpy(tbuf, pp->a_lastcode, SMAX);
+ strtok(tbuf, " ");
+ if (strcmp(tbuf, "NO") == 0)
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ switch(up->state) {
- /*
- * State 0. We are not expecting anything. Probably
- * modem disconnect noise. Go back to sleep.
- */
+ /*
+ * We are waiting for the OK response to the modem setup
+ * command. When this happens, raise DTR and dial the number
+ * followed by \r.
+ */
+ case S_OK:
+ if (strcmp(tbuf, "OK") != 0) {
+ msyslog(LOG_ERR, "acts: setup error %s",
+ pp->a_lastcode);
+ acts_disc(peer);
+ return;
+ }
+ ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr);
+ up->state = S_DTR;
+ up->timer = DTR;
return;
- case 1:
-
- /*
- * State 1. We are waiting for the call to be answered.
- * All we care about here is CONNECT as the first token
- * in the string. If the modem signals BUSY, ERROR, NO
- * ANSWER, NO CARRIER or NO DIALTONE, we immediately
- * hang up the phone. If CONNECT doesn't happen after
- * ANSWER seconds, hang up the phone. If everything is
- * okay, start the connect timeout and slide into state
- * 2.
- */
- if( strcmp(pp->a_lastcode, " ") == 0) {
+ /*
+ * We are waiting for the call to be answered. All we care about
+ * here is token CONNECT. Send the message to the clockstats.
+ */
+ case S_CONNECT:
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ if (strcmp(tbuf, "CONNECT") != 0) {
acts_disc(peer);
return;
}
- if( strcmp(sys_phone[0],"DIRECT") != 0 ) {
- (void)strncpy(str, strtok(pp->a_lastcode, " "), SMAX);
- if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") ==
- 0 || strcmp(str, "NO") == 0) {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s ACTS modem status %s",
- ntoa(&peer->srcadr), pp->a_lastcode);
- acts_disc(peer);
- } else if (strcmp(str, "CONNECT") == 0) {
- peer->nextdate = current_time + CONNECT;
- up->msgcnt = 0;
- up->state++;
- }
- } else {
- (void) strncpy(str,"CONNECT",7);
- peer->nextdate = current_time + CONNECT;
- up->msgcnt = 0;
- up->state++;
- }
+ up->state = S_FIRST;
+ up->timer = CONNECT;
return;
- case 2:
-
- /*
- * State 2. The call has been answered and we are
- * waiting for the first ACTS message. If this doesn't
- * happen within the timecode timeout, hang up the
- * phone. We probably got a wrong number or ACTS is
- * down.
- */
- peer->nextdate = current_time + TIMECODE;
- up->state++;
- }
-
/*
- * Real yucky things here. Ignore everything except timecode
- * messages, as determined by the message length. We told the
- * terminal routines to end the line with '*' and the line
- * discipline to strike a timestamp on that character. However,
- * when the ACTS echo-delay scheme works, the '*' eventually
- * becomes a '#'. In this case the message is ended by the <CR>
- * that comes about 200 ms after the '#' and the '#' cannot be
- * echoed at the proper time. But, this may not be a lose, since
- * we already have good data from prior messages and only need
- * the millisecond advance calculated by ACTS. So, if the
- * message is long enough and has an on-time character at the
- * right place, we consider the message (but not neccesarily the
- * timestmap) to be valid.
+ * We are waiting for a timecode. Pass it to the parser.
*/
- if (pp->lencode != LENCODE)
- return;
+ case S_FIRST:
+ case S_MSG:
+ acts_timecode(peer, pp->a_lastcode);
+ break;
+ }
+}
+
+/*
+ * acts_timecode - identify the service and parse the timecode message
+ */
+void
+acts_timecode(
+ struct peer *peer, /* peer structure pointer */
+ char *str /* timecode string */
+ )
+{
+ struct actsunit *up;
+ struct refclockproc *pp;
+ int day; /* day of the month */
+ int month; /* month of the year */
+ u_long mjd; /* Modified Julian Day */
+ double dut1; /* DUT adjustment */
+
+ u_int dst; /* ACTS daylight/standard time */
+ u_int leap; /* ACTS leap indicator */
+ double msADV; /* ACTS transmit advance (ms) */
+ char utc[10]; /* ACTS timescale */
+ char flag; /* ACTS on-time character (* or #) */
+
+ char synchar; /* WWVB synchronized indicator */
+ char qualchar; /* WWVB quality indicator */
+ char leapchar; /* WWVB leap indicator */
+ char dstchar; /* WWVB daylight/savings indicator */
+ int tz; /* WWVB timezone */
+
+ u_int leapmonth; /* PTB/NPL month of leap */
+ char leapdir; /* PTB/NPL leap direction */
-#ifndef CLOCK_PTBACTS
/*
- * We apparently have a valid timecode message, so dismember it
- * with sscan(). This routine does a good job in spotting syntax
- * errors without becoming overly pedantic.
- *
- * D L D
- * MJD YR MO DA H M S ST S UT1 msADV OTM
- * 47222 88-03-02 21:39:15 83 0 +.3 045.0 UTC(NBS) *
+ * The parser selects the modem format based on the message
+ * length. Since the data are checked carefully, occasional
+ * errors due noise are forgivable.
*/
- if (sscanf(pp->a_lastcode,
- "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %s %c",
- &mjd, &pp->year, &month, &day, &pp->hour, &pp->minute,
- &pp->second, &dst, &leap, &dut1, &msADV, utc, &flag) != 13) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-#else
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ pp->nsec = 0;
+ switch(strlen(str)) {
+
/*
- * Data format
- * 0000000000111111111122222222223333333333444444444455555555556666666666777777777 7
- * 0123456789012345678901234567890123456789012345678901234567890123456789012345678 9
- * 1995-01-23 20:58:51 MEZ 10402303260219950123195849740+40000500 *
+ * For USNO format on-time character '*', which is on a line by
+ * itself. Be sure a timecode has been received.
*/
- if (sscanf(pp->a_lastcode,
- "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c",
- &pp->second, &pp->year, &month, &day, &pp->hour, &pp->minute, &mjd, &dut1, &leapdir, &leapmonth, &msADV, &flag) != 12) {
- refclock_report(peer, CEVNT_BADREPLY);
+ case 1:
+ if (*str == '*' && up->msgcnt > 0)
+ break;
+
return;
- }
-#endif
+
/*
- * Some modems can't be trusted (the Practical Peripherals
- * 9600SA comes to mind) and, even if they manage to unstick
- * ACTS, the millisecond advance is wrong, so we use CLK_FLAG2
- * to disable echoes, if neccessary.
+ * ACTS format: "jjjjj yy-mm-dd hh:mm:ss ds l uuu aaaaa
+ * UTC(NIST) *"
*/
- if ((flag == '*' || flag == '#') && !(pp->sloppyclockflag &
- CLK_FLAG2))
- (void)write(pp->io.fd, &flag, 1);
+ case LENACTS:
+ if (sscanf(str,
+ "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %9s %c",
+ &mjd, &pp->year, &month, &day, &pp->hour,
+ &pp->minute, &pp->second, &dst, &leap, &dut1,
+ &msADV, utc, &flag) != 13) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Wait until ACTS has calculated the roundtrip delay.
+ * We don't need to do anything, as ACTS adjusts the
+ * on-time epoch.
+ */
+ if (flag != '#')
+ return;
+
+ pp->day = ymd2yd(pp->year, month, day);
+ pp->leap = LEAP_NOWARNING;
+ if (leap == 1)
+ pp->leap = LEAP_ADDSECOND;
+ else if (pp->leap == 2)
+ pp->leap = LEAP_DELSECOND;
+ memcpy(&pp->refid, REFACTS, 4);
+ if (up->msgcnt == 0)
+ record_clock_stats(&peer->srcadr, str);
+ up->msgcnt++;
+ break;
/*
- * The ACTS timecode format croaks in 2000. Life is short.
- * Would only the timecode mavens resist the urge to express months
- * of the year and days of the month in favor of days of the year.
+ * USNO format: "jjjjj nnn hhmmss UTC"
*/
- if (month < 1 || month > 12 || day < 1) {
- refclock_report(peer, CEVNT_BADTIME);
+ case LENUSNO:
+ if (sscanf(str, "%5ld %3d %2d%2d%2d %3s",
+ &mjd, &pp->day, &pp->hour, &pp->minute,
+ &pp->second, utc) != 6) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Wait for the on-time character, which follows in a
+ * separate message. There is no provision for leap
+ * warning.
+ */
+ pp->leap = LEAP_NOWARNING;
+ memcpy(&pp->refid, REFUSNO, 4);
+ if (up->msgcnt == 0)
+ record_clock_stats(&peer->srcadr, str);
+ up->msgcnt++;
return;
- }
/*
- * Depending on the driver, at this point we have a two-digit year
- * or a four-digit year. Make sure we have a four-digit year.
+ * PTB/NPL format: "yyyy-mm-dd hh:mm:ss MEZ"
*/
- if ( pp->year < YEAR_PIVOT ) pp->year += 100; /* Y2KFixes */
- if ( pp->year < YEAR_BREAK ) pp->year += 1900; /* Y2KFixes */
- if ( !isleap_4(pp->year) ) { /* Y2KFixes */
- if (day > day1tab[month - 1]) {
- refclock_report(peer, CEVNT_BADTIME);
+ case LENPTB:
+ if (sscanf(str,
+ "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c",
+ &pp->second, &pp->year, &month, &day, &pp->hour,
+ &pp->minute, &mjd, &dut1, &leapdir, &leapmonth,
+ &msADV, &flag) != 12) {
+ refclock_report(peer, CEVNT_BADREPLY);
return;
}
- for (i = 0; i < month - 1; i++)
- day += day1tab[i];
- } else {
- if (day > day2tab[month - 1]) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
+ pp->leap = LEAP_NOWARNING;
+ if (leapmonth == month) {
+ if (leapdir == '+')
+ pp->leap = LEAP_ADDSECOND;
+ else if (leapdir == '-')
+ pp->leap = LEAP_DELSECOND;
}
- for (i = 0; i < month - 1; i++)
- day += day2tab[i];
- }
- pp->day = day;
+ pp->day = ymd2yd(pp->year, month, day);
+ memcpy(&pp->refid, REFPTB, 4);
+ if (up->msgcnt == 0)
+ record_clock_stats(&peer->srcadr, str);
+ up->msgcnt++;
+ break;
-#ifndef CLOCK_PTBACTS
- if (leap == 1)
- pp->leap = LEAP_ADDSECOND;
- else if (pp->leap == 2)
- pp->leap = LEAP_DELSECOND;
-#else
- if (leapmonth == month) {
- if (leapdir == '+')
- pp->leap = LEAP_ADDSECOND;
- else if (leapdir == '-')
- pp->leap = LEAP_DELSECOND;
- }
-#endif
/*
- * Colossal hack here. We process each sample in a trimmed-mean
- * filter and determine the reference clock offset and
- * dispersion. The fudge time1 value is added to each sample as
- * received. If we collect MSGCNT samples before the '#' on-time
- * character, we use the results of the filter as is. If the '#'
- * is found before that, the adjusted msADV is used to correct
- * the propagation delay.
+ * WWVB format 0: "I ddd hh:mm:ss DTZ=nn"
+ */
+ case LENWWVB0:
+ if (sscanf(str, "%c %3d %2d:%2d:%2d %cTZ=%2d",
+ &synchar, &pp->day, &pp->hour, &pp->minute,
+ &pp->second, &dstchar, &tz) != 7) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+ pp->leap = LEAP_NOWARNING;
+ if (synchar != ' ')
+ pp->leap = LEAP_NOTINSYNC;
+ memcpy(&pp->refid, REFWWVB, 4);
+ if (up->msgcnt == 0)
+ record_clock_stats(&peer->srcadr, str);
+ up->msgcnt++;
+ break;
+
+ /*
+ * WWVB format 2: "IQyy ddd hh:mm:ss.mmm LD"
*/
- up->msgcnt++;
- if (flag == '#') {
- pp->offset += (msADV - up->msADV) * 1000 * 1e-6;
- } else {
- up->msADV = msADV;
- if (!refclock_process(pp)) {
- refclock_report(peer, CEVNT_BADTIME);
+ case LENWWVB2:
+ if (sscanf(str, "%c%c%2d %3d %2d:%2d:%2d.%3ld%c%c%c",
+ &synchar, &qualchar, &pp->year, &pp->day,
+ &pp->hour, &pp->minute, &pp->second, &pp->nsec,
+ &dstchar, &leapchar, &dstchar) != 11) {
+ refclock_report(peer, CEVNT_BADREPLY);
return;
- } else if (up->msgcnt < MSGCNT)
- return;
+ }
+ pp->nsec *= 1000000;
+ pp->leap = LEAP_NOWARNING;
+ if (synchar != ' ')
+ pp->leap = LEAP_NOTINSYNC;
+ else if (leapchar == 'L')
+ pp->leap = LEAP_ADDSECOND;
+ memcpy(&pp->refid, REFWWVB, 4);
+ if (up->msgcnt == 0)
+ record_clock_stats(&peer->srcadr, str);
+ up->msgcnt++;
+ break;
+
+ /*
+ * None of the above. Just forget about it and wait for the next
+ * message or timeout.
+ */
+ default:
+ return;
}
/*
- * We have a filtered sample offset ready for peer processing.
- * We use lastrec as both the reference time and receive time in
- * order to avoid being cute, like setting the reference time
- * later than the receive time, which may cause a paranoid
- * protocol module to chuck out the data. Finaly, we unhook the
- * timeout, arm for the next call, fold the tent and go home.
- * The little dance with the '%' character is an undocumented
- * ACTS feature that hangs up the phone real quick without
- * waiting for carrier loss or long-space disconnect, but we do
- * these clumsy things anyway.
+ * We have a valid timecode. The fudge time1 value is added to
+ * each sample by the main line routines. Note that in current
+ * telephone networks the propatation time can be different for
+ * each call and can reach 200 ms for some calls.
*/
+ peer->refid = pp->refid;
+ pp->lastrec = up->tstamp;
+ if (!refclock_process(pp)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- pp->sloppyclockflag &= ~CLK_FLAG1;
- up->pollcnt = 0;
- (void)write(pp->io.fd, &hangup, 1);
- up->state = 0;
- acts_disc(peer);
+ if (peer->disp > MAXDISTANCE)
+ refclock_receive(peer);
+ if (up->state != S_MSG) {
+ up->state = S_MSG;
+ up->timer = TIMECODE;
+ }
}
@@ -749,234 +632,298 @@ acts_receive (
*/
static void
acts_poll (
- int unit,
+ int unit,
struct peer *peer
)
{
- register struct actsunit *up;
+ struct actsunit *up;
struct refclockproc *pp;
/*
- * If the driver is running, we set the enable flag (fudge
- * flag1), which causes the driver timeout routine to initiate a
- * call to ACTS. If not, the enable flag can be set using
- * ntpdc. If this is the sustem peer, then follow the system
- * poll interval.
+ * This routine is called at every system poll. All it does is
+ * set flag1 under certain conditions. The real work is done by
+ * the timeout routine and state machine.
*/
pp = peer->procptr;
up = (struct actsunit *)pp->unitptr;
+ switch (peer->ttl) {
- if (up->run) {
+ /*
+ * In manual mode the calling program is activated by the ntpdc
+ * program using the enable flag (fudge flag1), either manually
+ * or by a cron job.
+ */
+ case MODE_MANUAL:
+ /* fall through */
+ break;
+
+ /*
+ * In automatic mode the calling program runs continuously at
+ * intervals determined by the poll event or specified timeout.
+ */
+ case MODE_AUTO:
pp->sloppyclockflag |= CLK_FLAG1;
- if (peer == sys_peer)
- peer->hpoll = sys_poll;
- else
- peer->hpoll = peer->minpoll;
+ break;
+
+ /*
+ * In backup mode the calling program runs continuously as long
+ * as either no peers are available or this peer is selected.
+ */
+ case MODE_BACKUP:
+ if (sys_peer == NULL || sys_peer == peer)
+ pp->sloppyclockflag |= CLK_FLAG1;
+ break;
}
- acts_timeout (peer);
- return;
}
/*
- * acts_timeout - called by the timer interrupt
+ * acts_timer - called at one-second intervals
*/
static void
-acts_timeout (
+acts_timer(
+ int unit,
struct peer *peer
)
{
- register struct actsunit *up;
+ struct actsunit *up;
struct refclockproc *pp;
- int dtr = TIOCM_DTR;
/*
- * If a timeout occurs in other than state 0, the call has
- * failed. If in state 0, we just see if there is other work to
- * do.
+ * This routine implments a timeout which runs for a programmed
+ * interval. The counter is initialized by the state machine and
+ * counts down to zero. Upon reaching zero, the state machine is
+ * called. If flag1 is set while in S_IDLE state, force a
+ * timeout.
*/
pp = peer->procptr;
up = (struct actsunit *)pp->unitptr;
- if (up->state) {
- acts_disc(peer);
+ if (pp->sloppyclockflag & CLK_FLAG1 && up->state == S_IDLE) {
+ acts_timeout(peer);
return;
}
- switch (peer->ttl) {
+ if (up->timer == 0)
+ return;
+
+ up->timer--;
+ if (up->timer == 0)
+ acts_timeout(peer);
+}
+
+
+/*
+ * acts_timeout - called on timeout
+ */
+static void
+acts_timeout(
+ struct peer *peer
+ )
+{
+ struct actsunit *up;
+ struct refclockproc *pp;
+ int fd;
+ char device[20];
+ char lockfile[128], pidbuf[8];
+ char tbuf[BMAX];
+
+ /*
+ * The state machine is driven by messages from the modem, when
+ * first stated and at timeout.
+ */
+ pp = peer->procptr;
+ up = (struct actsunit *)pp->unitptr;
+ pp->sloppyclockflag &= ~CLK_FLAG1;
+ if (sys_phone[up->retry] == NULL && !(pp->sloppyclockflag &
+ CLK_FLAG3)) {
+ msyslog(LOG_ERR, "acts: no phones");
+ return;
+ }
+ switch(up->state) {
+
+ /*
+ * System poll event. Lock the modem port and open the device.
+ */
+ case S_IDLE:
/*
- * In manual mode the ACTS calling program is activated
- * by the ntpdc program using the enable flag (fudge
- * flag1), either manually or by a cron job.
+ * Lock the modem port. If busy, retry later. Note: if
+ * something fails between here and the close, the lock
+ * file may not be removed.
*/
- case MODE_MANUAL:
- up->run = 0;
- break;
+ if (pp->sloppyclockflag & CLK_FLAG2) {
+ sprintf(lockfile, LOCKFILE, up->unit);
+ fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL,
+ 0644);
+ if (fd < 0) {
+ msyslog(LOG_ERR, "acts: port busy");
+ return;
+ }
+ sprintf(pidbuf, "%d\n", (u_int)getpid());
+ write(fd, pidbuf, strlen(pidbuf));
+ close(fd);
+ }
/*
- * In automatic mode the ACTS calling program runs
- * continuously at intervals determined by the sys_poll
- * variable.
+ * Open the device in raw mode and link the I/O.
*/
- case MODE_AUTO:
- if (!up->run)
- pp->sloppyclockflag |= CLK_FLAG1;
- up->run = 1;
- break;
+ if (!pp->io.fd) {
+ sprintf(device, DEVICE, up->unit);
+ fd = refclock_open(device, SPEED232,
+ LDISC_ACTS | LDISC_RAW | LDISC_REMOTE);
+ if (fd == 0) {
+ return;
+ }
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+ msyslog(LOG_ERR,
+ "acts: addclock fails");
+ close(fd);
+ pp->io.fd = 0;
+ return;
+ }
+ }
/*
- * In backup mode the ACTS calling program is disabled,
- * unless no system peer has been selected for MAXOUTAGE
- * (3600 s). Once enabled, it runs until some other NTP
- * peer shows up.
+ * If the port is directly connected to the device, skip
+ * the modem business and send 'T' for Spectrabum.
*/
- case MODE_BACKUP:
- if (!up->run && sys_peer == 0) {
- if (current_time - last_time > MAXOUTAGE) {
- up->run = 1;
- peer->hpoll = peer->minpoll;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s ACTS backup started ",
- ntoa(&peer->srcadr));
+ if (pp->sloppyclockflag & CLK_FLAG3) {
+ if (write(pp->io.fd, "T", 1) < 0) {
+ msyslog(LOG_ERR, "acts: write %m");
+ return;
}
- } else if (up->run && sys_peer->sstclktype != CTL_SST_TS_TELEPHONE) {
- peer->hpoll = peer->minpoll;
- up->run = 0;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s ACTS backup stopped",
- ntoa(&peer->srcadr));
+ up->state = S_FIRST;
+ up->timer = CONNECT;
+ return;
}
- break;
- default:
- msyslog(LOG_ERR,
- "clock %s ACTS invalid mode", ntoa(&peer->srcadr));
- }
+ /*
+ * Initialize the modem. This works with Hayes commands.
+ */
+#ifdef DEBUG
+ if (debug)
+ printf("acts: setup %s\n", MODEM_SETUP);
+#endif
+ if (write(pp->io.fd, MODEM_SETUP, strlen(MODEM_SETUP)) <
+ 0) {
+ msyslog(LOG_ERR, "acts: write %m");
+ return;
+ }
+ up->state = S_OK;
+ up->timer = SETUP;
+ return;
/*
- * The fudge flag1 is used as an enable/disable; if set either
- * by the code or via ntpdc, the ACTS calling program is
- * started; if reset, the phones stop ringing.
+ * In OK state the modem did not respond to setup.
*/
- if (!(pp->sloppyclockflag & CLK_FLAG1)) {
- up->pollcnt = 0;
- peer->nextdate = current_time + IDLE;
- return;
- }
+ case S_OK:
+ msyslog(LOG_ERR, "acts: no modem");
+ break;
/*
- * Initiate a call to the ACTS service. If we wind up here in
- * other than state 0, a successful call could not be completed
- * within minpoll seconds. We advance to the next modem dial
- * string. If none are left, we log a notice and clear the
- * enable flag. For future enhancement: call the site RP and
- * leave an obscene message in his voicemail.
+ * In DTR state we are waiting for the modem to settle down
+ * before hammering it with a dial command.
*/
- if (sys_phone[up->pollcnt][0] == '\0') {
- refclock_report(peer, CEVNT_TIMEOUT);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s ACTS calling program terminated",
- ntoa(&peer->srcadr));
- pp->sloppyclockflag &= ~CLK_FLAG1;
+ case S_DTR:
+ sprintf(tbuf, "DIAL #%d %s", up->retry,
+ sys_phone[up->retry]);
+ record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
if (debug)
- printf("acts: calling program terminated\n");
+ printf("%s\n", tbuf);
#endif
- up->pollcnt = 0;
- peer->nextdate = current_time + IDLE;
+ write(pp->io.fd, sys_phone[up->retry],
+ strlen(sys_phone[up->retry]));
+ write(pp->io.fd, "\r", 1);
+ up->state = S_CONNECT;
+ up->timer = ANSWER;
return;
- }
/*
- * Raise DTR, call ACTS and start the answer timeout. We think
- * it strange if the OK status has not been received from the
- * modem, but plow ahead anyway.
+ * In CONNECT state the call did not complete.
*/
- if (strcmp(pp->a_lastcode, "OK") != 0)
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s ACTS no modem status",
- ntoa(&peer->srcadr));
- (void)ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr);
- (void)acts_write(peer, sys_phone[up->pollcnt]);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s ACTS calling %s\n",
- ntoa(&peer->srcadr), sys_phone[up->pollcnt]);
- up->state = 1;
- up->pollcnt++;
- pp->polls++;
- peer->nextdate = current_time + ANSWER;
- return;
-}
-
+ case S_CONNECT:
+ msyslog(LOG_ERR, "acts: no answer");
+ break;
-/*
- * acts_disc - disconnect the call and wait for the ruckus to cool
- */
-static void
-acts_disc (
- struct peer *peer
- )
-{
- register struct actsunit *up;
- struct refclockproc *pp;
- int dtr = TIOCM_DTR;
+ /*
+ * In FIRST state no messages were received.
+ */
+ case S_FIRST:
+ msyslog(LOG_ERR, "acts: no messages");
+ break;
/*
- * We should never get here other than in state 0, unless a call
- * has timed out. We drop DTR, which will reliably get the modem
- * off the air, even while ACTS is hammering away full tilt.
+ * In CLOSE state hangup is complete. Close the doors and
+ * windows and get some air.
*/
- pp = peer->procptr;
- up = (struct actsunit *)pp->unitptr;
- (void)ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr);
- if (up->state > 0) {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s ACTS call failed %d",
- ntoa(&peer->srcadr), up->state);
-#ifdef DEBUG
- if (debug)
- printf("acts: call failed %d\n", up->state);
-#endif
- up->state = 0;
+ case S_CLOSE:
+
+ /*
+ * Close the device and unlock a shared modem.
+ */
+ if (pp->io.fd) {
+ io_closeclock(&pp->io);
+ close(pp->io.fd);
+ if (pp->sloppyclockflag & CLK_FLAG2) {
+ sprintf(lockfile, LOCKFILE, up->unit);
+ unlink(lockfile);
+ }
+ pp->io.fd = 0;
+ }
+
+ /*
+ * If messages were received, fold the tent and wait for
+ * the next poll. If no messages and there are more
+ * numbers to dial, retry after a short wait.
+ */
+ up->bufptr = pp->a_lastcode;
+ up->timer = 0;
+ up->state = S_IDLE;
+ if ( up->msgcnt == 0) {
+ up->retry++;
+ if (sys_phone[up->retry] == NULL)
+ up->retry = 0;
+ else
+ up->timer = SETUP;
+ } else {
+ up->retry = 0;
+ }
+ up->msgcnt = 0;
+ return;
}
- peer->nextdate = current_time + WAIT;
+ acts_disc(peer);
}
/*
- * acts_write - write a message to the serial port
+ * acts_disc - disconnect the call and clean the place up.
*/
-static int
-acts_write (
- struct peer *peer,
- const char *str
+static void
+acts_disc (
+ struct peer *peer
)
{
- register struct actsunit *up;
+ struct actsunit *up;
struct refclockproc *pp;
- int len;
- int code;
- char cr = '\r';
+ int dtr = TIOCM_DTR;
/*
- * Not much to do here, other than send the message, handle
- * debug and report faults.
+ * We get here if the call terminated successfully or if an
+ * error occured. If the median filter has something in it,feed
+ * the data to the clock filter. If a modem port, drop DTR to
+ * force command mode and send modem hangup.
*/
pp = peer->procptr;
up = (struct actsunit *)pp->unitptr;
- len = strlen(str);
-#ifdef DEBUG
- if (debug)
- printf("acts: state %d send %d %s\n", up->state, len,
- str);
-#endif
- code = write(pp->io.fd, str, (unsigned)len) == len;
- code &= write(pp->io.fd, &cr, 1) == 1;
- if (!code)
- refclock_report(peer, CEVNT_FAULT);
- return (code);
+ if (up->msgcnt > 0)
+ refclock_receive(peer);
+ if (!(pp->sloppyclockflag & CLK_FLAG3)) {
+ ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr);
+ write(pp->io.fd, MODEM_HANGUP, strlen(MODEM_HANGUP));
+ }
+ up->timer = SETUP;
+ up->state = S_CLOSE;
}
#else
diff --git a/contrib/ntp/ntpd/refclock_arbiter.c b/contrib/ntp/ntpd/refclock_arbiter.c
index cf5f92f..88a3225 100644
--- a/contrib/ntp/ntpd/refclock_arbiter.c
+++ b/contrib/ntp/ntpd/refclock_arbiter.c
@@ -76,10 +76,13 @@
* ee = hardware errors
*
* If flag4 is set, an additional line consisting of the receiver
- * latitude (LA), longitude (LO) and elevation (LH) (meters) is written
- * to this file. If channel B is enabled for deviation mode and connected
- * to a 1-PPS signal, the last two numbers on the line are the deviation
- * and standard deviation averaged over the last 15 seconds.
+ * latitude (LA), longitude (LO), elevation (LH) (meters), and data
+ * buffer (DB) is written to this file. If channel B is enabled for
+ * deviation mode and connected to a 1-PPS signal, the last two numbers
+ * on the line are the deviation and standard deviation averaged over
+ * the last 15 seconds.
+ *
+ * PPS calibration fudge time1 .001240
*/
/*
@@ -88,12 +91,11 @@
#define DEVICE "/dev/gps%d" /* device name and unit */
#define SPEED232 B9600 /* uart speed (9600 baud) */
#define PRECISION (-20) /* precision assumed (about 1 us) */
-#define REFID "GPS " /* reference ID */
+#define REFID "GPS " /* reference ID */
#define DESCRIPTION "Arbiter 1088A/B GPS Receiver" /* WRU */
-
#define LENARB 24 /* format B5 timecode length */
-#define MAXSTA 30 /* max length of status string */
-#define MAXPOS 70 /* max length of position string */
+#define MAXSTA 40 /* max length of status string */
+#define MAXPOS 80 /* max length of position string */
/*
* ARB unit control structure
@@ -212,7 +214,8 @@ arb_receive(
struct peer *peer;
l_fp trtmp;
int temp;
- u_char syncchar; /* synchronization indicator */
+ u_char syncchar; /* synch indicator */
+ char tbuf[BMAX]; /* temp buffer */
/*
* Initialize pointers and read the timecode and timestamp
@@ -220,7 +223,7 @@ arb_receive(
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct arbunit *)pp->unitptr;
- temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
+ temp = refclock_gtlin(rbufp, tbuf, BMAX, &trtmp);
/*
* Note we get a buffer and timestamp for both a <cr> and <lf>,
@@ -238,49 +241,64 @@ arb_receive(
*/
if (temp == 0)
return;
+
pp->lastrec = up->laststamp;
up->laststamp = trtmp;
if (temp < 3)
return;
+
if (up->tcswitch == 0) {
/*
* Collect statistics. If nothing is recogized, just
* ignore; sometimes the clock doesn't stop spewing
- * timecodes for awhile after the B0 commant.
+ * timecodes for awhile after the B0 command.
+ *
+ * If flag4 is not set, send TQ, SR, B5. If flag4 is
+ * sset, send TQ, SR, LA, LO, LH, DB, B5. When the
+ * median filter is full, send B0.
*/
- if (!strncmp(pp->a_lastcode, "TQ", 2)) {
- up->qualchar = pp->a_lastcode[2];
+ if (!strncmp(tbuf, "TQ", 2)) {
+ up->qualchar = tbuf[2];
write(pp->io.fd, "SR", 2);
- } else if (!strncmp(pp->a_lastcode, "SR", 2)) {
- strcpy(up->status, pp->a_lastcode + 2);
+ return;
+
+ } else if (!strncmp(tbuf, "SR", 2)) {
+ strcpy(up->status, tbuf + 2);
if (pp->sloppyclockflag & CLK_FLAG4)
write(pp->io.fd, "LA", 2);
- else {
+ else
write(pp->io.fd, "B5", 2);
- up->tcswitch++;
- }
- } else if (!strncmp(pp->a_lastcode, "LA", 2)) {
- strcpy(up->latlon, pp->a_lastcode + 2);
+ return;
+
+ } else if (!strncmp(tbuf, "LA", 2)) {
+ strcpy(up->latlon, tbuf + 2);
write(pp->io.fd, "LO", 2);
- } else if (!strncmp(pp->a_lastcode, "LO", 2)) {
+ return;
+
+ } else if (!strncmp(tbuf, "LO", 2)) {
strcat(up->latlon, " ");
- strcat(up->latlon, pp->a_lastcode + 2);
+ strcat(up->latlon, tbuf + 2);
write(pp->io.fd, "LH", 2);
- } else if (!strncmp(pp->a_lastcode, "LH", 2)) {
+ return;
+
+ } else if (!strncmp(tbuf, "LH", 2)) {
strcat(up->latlon, " ");
- strcat(up->latlon, pp->a_lastcode + 2);
+ strcat(up->latlon, tbuf + 2);
write(pp->io.fd, "DB", 2);
- } else if (!strncmp(pp->a_lastcode, "DB", 2)) {
+ return;
+
+ } else if (!strncmp(tbuf, "DB", 2)) {
strcat(up->latlon, " ");
- strcat(up->latlon, pp->a_lastcode + 2);
+ strcat(up->latlon, tbuf + 2);
record_clock_stats(&peer->srcadr, up->latlon);
+#ifdef DEBUG
+ if (debug)
+ printf("arbiter: %s\n", up->latlon);
+#endif
write(pp->io.fd, "B5", 2);
- up->tcswitch++;
}
- return;
}
- pp->lencode = temp;
/*
* We get down to business, check the timecode format and decode
@@ -291,25 +309,25 @@ arb_receive(
* that the time quality character and receiver status string is
* tacked on the end for clockstats display.
*/
- if (pp->lencode == LENARB) {
- /*
- * Timecode format B5: "i yy ddd hh:mm:ss.000 "
- */
- pp->a_lastcode[LENARB - 2] = up->qualchar;
- strcat(pp->a_lastcode, up->status);
- syncchar = ' ';
- if (sscanf(pp->a_lastcode, "%c%2d %3d %2d:%2d:%2d",
- &syncchar, &pp->year, &pp->day, &pp->hour,
- &pp->minute, &pp->second) != 6) {
- refclock_report(peer, CEVNT_BADREPLY);
- write(pp->io.fd, "B0", 2);
- return;
- }
- } else {
+ up->tcswitch++;
+ if (up->tcswitch <= 1 || temp < LENARB)
+ return;
+
+ /*
+ * Timecode format B5: "i yy ddd hh:mm:ss.000 "
+ */
+ strncpy(pp->a_lastcode, tbuf, BMAX);
+ pp->a_lastcode[LENARB - 2] = up->qualchar;
+ strcat(pp->a_lastcode, up->status);
+ pp->lencode = strlen(pp->a_lastcode);
+ syncchar = ' ';
+ if (sscanf(pp->a_lastcode, "%c%2d %3d %2d:%2d:%2d",
+ &syncchar, &pp->year, &pp->day, &pp->hour,
+ &pp->minute, &pp->second) != 6) {
+ refclock_report(peer, CEVNT_BADREPLY);
write(pp->io.fd, "B0", 2);
return;
}
- up->tcswitch++;
/*
* We decode the clock dispersion from the time quality
@@ -319,6 +337,7 @@ arb_receive(
case '0': /* locked, max accuracy */
pp->disp = 1e-7;
+ pp->lastref = pp->lastrec;
break;
case '4': /* unlock accuracy < 1 us */
@@ -369,13 +388,6 @@ arb_receive(
pp->leap = LEAP_NOTINSYNC;
else
pp->leap = LEAP_NOWARNING;
-#ifdef DEBUG
- if (debug)
- printf("arbiter: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
- if (up->tcswitch >= NSTAGE)
- write(pp->io.fd, "B0", 2);
/*
* Process the new sample in the median filter and determine the
@@ -383,6 +395,12 @@ arb_receive(
*/
if (!refclock_process(pp))
refclock_report(peer, CEVNT_BADTIME);
+ else if (peer->disp > MAXDISTANCE)
+ refclock_receive(peer);
+
+ if (up->tcswitch >= MAXSTAGE) {
+ write(pp->io.fd, "B0", 2);
+ }
}
@@ -404,24 +422,30 @@ arb_poll(
* Transmission occurs once per second, unless turned off by a
* "B0". Note there is no checking on state, since this may not
* be the only customer reading the clock. Only one customer
- * need poll the clock; all others just listen in. If nothing is
- * heard from the clock for two polls, declare a timeout and
- * keep going.
+ * need poll the clock; all others just listen in.
*/
pp = peer->procptr;
up = (struct arbunit *)pp->unitptr;
+ pp->polls++;
up->tcswitch = 0;
- if (write(pp->io.fd, "TQ", 2) != 2) {
+ if (write(pp->io.fd, "TQ", 2) != 2)
refclock_report(peer, CEVNT_FAULT);
- } else
- pp->polls++;
+
+ /*
+ * Process median filter samples. If none received, declare a
+ * timeout and keep going.
+ */
if (pp->coderecv == pp->codeproc) {
refclock_report(peer, CEVNT_TIMEOUT);
return;
}
- pp->lastref = pp->lastrec;
refclock_receive(peer);
record_clock_stats(&peer->srcadr, pp->a_lastcode);
+#ifdef DEBUG
+ if (debug)
+ printf("arbiter: timecode %d %s\n",
+ pp->lencode, pp->a_lastcode);
+#endif
}
#else
diff --git a/contrib/ntp/ntpd/refclock_arc.c b/contrib/ntp/ntpd/refclock_arc.c
index f556da6..af80621 100644
--- a/contrib/ntp/ntpd/refclock_arc.c
+++ b/contrib/ntp/ntpd/refclock_arc.c
@@ -7,6 +7,7 @@
#endif
#if defined(REFCLOCK) && defined(CLOCK_ARCRON_MSF)
+
static const char arc_version[] = { "V1.3 2003/02/21" };
/* define PRE_NTP420 for compatibility to previous versions of NTP (at least
@@ -32,6 +33,7 @@ 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.
+Modifications by Nigel Roles <nigel@9fs.org>, 2003.
THIS CODE IS SUPPLIED AS IS, WITH NO WARRANTY OF ANY KIND. USE AT
@@ -47,6 +49,16 @@ reproduced.
-------------------------------------------------------------------------------
+Nigel's notes:
+
+1) Called tcgetattr() before modifying, so that fields correctly initialised
+ for all operating systems
+
+2) Altered parsing of timestamp line so that it copes with fields which are
+ not always ASCII digits (e.g. status field when battery low)
+
+-------------------------------------------------------------------------------
+
Christopher's notes:
MAJOR CHANGES SINCE V1.2
@@ -656,6 +668,8 @@ arc_start(
#ifdef HAVE_TERMIOS
+ tcgetattr(fd, &arg);
+
arg.c_iflag = IGNBRK | ISTRIP;
arg.c_oflag = 0;
arg.c_cflag = B300 | CS8 | CREAD | CLOCAL | CSTOPB;
@@ -804,12 +818,28 @@ send_slow(
}
/* Copy in the command to be sent. */
- while(*s) { up->cmdqueue[CMDQUEUELEN - spaceleft--] = *s++; }
+ while(*s && spaceleft > 0) { up->cmdqueue[CMDQUEUELEN - spaceleft--] = *s++; }
return(1);
}
+static int
+get2(char *p, int *val)
+{
+ if (!isdigit((int)p[0]) || !isdigit((int)p[1])) return 0;
+ *val = (p[0] - '0') * 10 + p[1] - '0';
+ return 1;
+}
+
+static int
+get1(char *p, int *val)
+{
+ if (!isdigit((int)p[0])) return 0;
+ *val = p[0] - '0';
+ return 1;
+}
+
/* Macro indicating action we will take for different quality values. */
#define quality_action(q) \
(((q) == QUALITY_UNKNOWN) ? "UNKNOWN, will use clock anyway" : \
@@ -1115,12 +1145,15 @@ arc_receive(
/* We don't use the nano-second part... */
pp->nsec = 0;
#endif
- n = sscanf(pp->a_lastcode, "o%2d%2d%2d%1d%2d%2d%2d%1d%1d",
- &pp->hour, &pp->minute, &pp->second,
- &wday, &pp->day, &month, &pp->year, &flags, &status);
-
/* Validate format and numbers. */
- if(n != 9) {
+ if (pp->a_lastcode[0] != 'o'
+ || !get2(pp->a_lastcode + 1, &pp->hour)
+ || !get2(pp->a_lastcode + 3, &pp->minute)
+ || !get2(pp->a_lastcode + 5, &pp->second)
+ || !get1(pp->a_lastcode + 7, &wday)
+ || !get2(pp->a_lastcode + 8, &pp->day)
+ || !get2(pp->a_lastcode + 10, &month)
+ || !get2(pp->a_lastcode + 12, &pp->year)) {
#ifdef DEBUG
/* Would expect to have caught major problems already... */
if(debug) { printf("arc: badly formatted data.\n"); }
@@ -1129,6 +1162,13 @@ arc_receive(
refclock_report(peer, CEVNT_BADREPLY);
return;
}
+ flags = pp->a_lastcode[14];
+ status = pp->a_lastcode[15];
+#ifdef DEBUG
+ if(debug) { printf("arc: status 0x%.2x flags 0x%.2x\n", flags, status); }
+#endif
+ n = 9;
+
/*
Validate received values at least enough to prevent internal
array-bounds problems, etc.
diff --git a/contrib/ntp/ntpd/refclock_atom.c b/contrib/ntp/ntpd/refclock_atom.c
index 51153ae..2e469ec 100644
--- a/contrib/ntp/ntpd/refclock_atom.c
+++ b/contrib/ntp/ntpd/refclock_atom.c
@@ -1,4 +1,3 @@
-
/*
* refclock_atom - clock driver for 1-pps signals
*/
@@ -18,13 +17,7 @@
#if defined(REFCLOCK) && defined(CLOCK_ATOM)
#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
+# include "ppsapi_timepps.h"
#endif /* HAVE_PPSAPI */
/*
@@ -48,7 +41,12 @@
* Systems, Version 1.0, RFC-2783 (PPSAPI). Implementations are
* available for FreeBSD, Linux, SunOS, Solaris and Alpha. However, at
* present only the Alpha implementation provides the full generality of
- * the API with multiple PPS drivers and multiple handles per driver.
+ * the API with multiple PPS drivers and multiple handles per driver. If
+ * the PPSAPI is normally implemented in the /usr/include/sys/timepps.h
+ * header file and kernel support specific to each operating system.
+ * However, this driver can operate without this interface if means are
+ * proviced to call the pps_sample() routine from another driver. Please
+ * note; if the PPSAPI interface is present, it must be used.
*
* In many configurations a single port is used for the radio timecode
* and PPS signal. In order to provide for this configuration and others
@@ -61,16 +59,20 @@
* configuration file.
*
* This driver normally uses the PLL/FLL clock discipline implemented in
- * the ntpd code. If kernel support is available, the kernel PLL/FLL
- * clock discipline is used instead. The default configuration is not to
- * use the kernel PPS discipline, if present. The kernel PPS discipline
- * can be enabled using the pps command.
+ * the ntpd code. Ordinarily, this is the most accurate means, as the
+ * median filter in the driver interface is much larger than in the
+ * kernel. However, if the systemic clock frequency error is large (tens
+ * to hundreds of PPM), it's better to used the kernel support, if
+ * available.
*
* Fudge Factors
*
- * There are no special fudge factors other than the generic. The fudge
- * time1 parameter can be used to compensate for miscellaneous device
- * driver and OS delays.
+ * If flag2 is dim (default), the on-time epoch is the assert edge of
+ * the PPS signal; if lit, the on-time epoch is the clear edge. If flag2
+ * is lit, the assert edge is used; if flag3 is dim (default), the
+ * kernel PPS support is disabled; if lit it is enabled. The time1
+ * parameter can be used to compensate for miscellaneous device driver
+ * and OS delays.
*/
/*
* Interface definitions
@@ -84,7 +86,6 @@
#define DESCRIPTION "PPS Clock Discipline" /* WRU */
#define NANOSECOND 1000000000 /* one second (ns) */
#define RANGEGATE 500000 /* range gate (ns) */
-#define ASTAGE 8 /* filter stages */
static struct peer *pps_peer; /* atom driver for PPS sources */
@@ -106,34 +107,38 @@ struct ppsunit {
*/
static int atom_start P((int, struct peer *));
static void atom_poll P((int, struct peer *));
-#ifdef HAVE_PPSAPI
static void atom_shutdown P((int, struct peer *));
+#ifdef HAVE_PPSAPI
static void atom_control P((int, struct refclockstat *, struct
refclockstat *, struct peer *));
-static int atom_pps P((struct peer *));
-static int atom_ppsapi P((struct peer *, int, int));
+static void atom_timer P((int, struct peer *));
+static int atom_ppsapi P((struct peer *, int));
#endif /* HAVE_PPSAPI */
/*
* Transfer vector
*/
+#ifdef HAVE_PPSAPI
struct refclock refclock_atom = {
atom_start, /* start up driver */
-#ifdef HAVE_PPSAPI
atom_shutdown, /* shut down driver */
-#else
- noentry, /* shut down driver */
-#endif /* HAVE_PPSAPI */
atom_poll, /* transmit poll message */
-#ifdef HAVE_PPSAPI
atom_control, /* fudge control */
-#else
- noentry, /* fudge control */
-#endif /* HAVE_PPSAPI */
- noentry, /* initialize driver */
- noentry, /* not used (old atom_buginfo) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* buginfo (not used) */
+ atom_timer, /* called once per second */
+};
+#else /* HAVE_PPSAPI */
+struct refclock refclock_atom = {
+ atom_start, /* start up driver */
+ atom_shutdown, /* shut down driver */
+ atom_poll, /* transmit poll message */
+ noentry, /* fudge control (not used) */
+ noentry, /* initialize driver (not used) */
+ noentry, /* buginfo (not used) */
NOFLAGS /* not used */
};
+#endif /* HAVE_PPPSAPI */
/*
@@ -148,7 +153,8 @@ atom_start(
struct refclockproc *pp;
#ifdef HAVE_PPSAPI
register struct ppsunit *up;
- char device[80];
+ char device[80];
+ int mode;
#endif /* HAVE_PPSAPI */
/*
@@ -160,23 +166,17 @@ atom_start(
pp->clockdesc = DESCRIPTION;
pp->stratum = STRATUM_UNSPEC;
memcpy((char *)&pp->refid, REFID, 4);
- peer->burst = ASTAGE;
#ifdef HAVE_PPSAPI
up = emalloc(sizeof(struct ppsunit));
memset(up, 0, sizeof(struct ppsunit));
pp->unitptr = (caddr_t)up;
/*
- * Open PPS device. If this fails and some driver has already
- * opened the associated radio device, fdpps has the file
- * descriptor for it.
+ * Open PPS device. This can be any serial or parallel port and
+ * not necessarily the port used for the associated radio.
*/
sprintf(device, DEVICE, unit);
up->fddev = open(device, O_RDWR, 0777);
- if (up->fddev <= 0 && fdpps > 0) {
- strcpy(device, pps_device);
- up->fddev = fdpps;
- }
if (up->fddev <= 0) {
msyslog(LOG_ERR,
"refclock_atom: %s: %m", device);
@@ -184,22 +184,55 @@ atom_start(
}
/*
- * Light off the PPSAPI interface. If this PPS device is shared
- * with the radio device, take the default options from the pps
- * command. This is for legacy purposes.
+ * Light off the PPSAPI interface.
*/
if (time_pps_create(up->fddev, &up->handle) < 0) {
msyslog(LOG_ERR,
"refclock_atom: time_pps_create failed: %m");
return (0);
}
- return (atom_ppsapi(peer, 0, 0));
+
+ /*
+ * If the mode is nonzero, use that for the time_pps_setparams()
+ * mode; otherwise, PPS_CAPTUREASSERT. Enable kernel PPS if
+ * flag3 is lit.
+ */
+ mode = peer->ttl;
+ if (mode == 0)
+ mode = PPS_CAPTUREASSERT;
+ return (atom_ppsapi(peer, mode));
#else /* HAVE_PPSAPI */
return (1);
#endif /* HAVE_PPSAPI */
}
+/*
+ * atom_shutdown - shut down the clock
+ */
+static void
+atom_shutdown(
+ int unit, /* unit number (not used) */
+ struct peer *peer /* peer structure pointer */
+ )
+{
+ struct refclockproc *pp;
+ register struct ppsunit *up;
+
+ pp = peer->procptr;
+ up = (struct ppsunit *)pp->unitptr;
+#ifdef HAVE_PPSAPI
+ if (up->fddev > 0)
+ close(up->fddev);
+ if (up->handle != 0)
+ time_pps_destroy(up->handle);
+#endif /* HAVE_PPSAPI */
+ if (pps_peer == peer)
+ pps_peer = NULL;
+ free(up);
+}
+
+
#ifdef HAVE_PPSAPI
/*
* atom_control - fudge control
@@ -213,10 +246,17 @@ atom_control(
)
{
struct refclockproc *pp;
+ int mode;
pp = peer->procptr;
- atom_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
- pp->sloppyclockflag & CLK_FLAG3);
+ if (peer->ttl != 0) /* all legal modes must be nonzero */
+ return;
+
+ if (pp->sloppyclockflag & CLK_FLAG2)
+ mode = PPS_CAPTURECLEAR;
+ else
+ mode = PPS_CAPTUREASSERT;
+ atom_ppsapi(peer, mode);
}
@@ -226,8 +266,7 @@ atom_control(
int
atom_ppsapi(
struct peer *peer, /* peer structure pointer */
- int enb_clear, /* clear enable */
- int enb_hardpps /* hardpps enable */
+ int mode /* mode */
)
{
struct refclockproc *pp;
@@ -236,29 +275,23 @@ atom_ppsapi(
pp = peer->procptr;
up = (struct ppsunit *)pp->unitptr;
+ if (up->handle == 0)
+ return (0);
+
if (time_pps_getcap(up->handle, &capability) < 0) {
msyslog(LOG_ERR,
"refclock_atom: time_pps_getcap failed: %m");
return (0);
}
memset(&up->pps_params, 0, sizeof(pps_params_t));
- if (enb_clear)
- up->pps_params.mode = capability & PPS_CAPTURECLEAR;
- else
- up->pps_params.mode = capability & PPS_CAPTUREASSERT;
- if (!up->pps_params.mode) {
- msyslog(LOG_ERR,
- "refclock_atom: invalid capture edge %d",
- enb_clear);
- return (0);
- }
- up->pps_params.mode |= PPS_TSFMT_TSPEC;
+ up->pps_params.api_version = PPS_API_VERS_1;
+ up->pps_params.mode = mode | PPS_TSFMT_TSPEC;
if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
msyslog(LOG_ERR,
"refclock_atom: time_pps_setparams failed: %m");
return (0);
}
- if (enb_hardpps) {
+ if (pp->sloppyclockflag & CLK_FLAG3) {
if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
up->pps_params.mode & ~PPS_TSFMT_TSPEC,
PPS_TSFMT_TSPEC) < 0) {
@@ -272,9 +305,9 @@ atom_ppsapi(
if (debug) {
time_pps_getparams(up->handle, &up->pps_params);
printf(
- "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x kern %d\n",
+ "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x\n",
up->fddev, capability, up->pps_params.api_version,
- up->pps_params.mode, enb_hardpps);
+ up->pps_params.mode);
}
#endif
return (1);
@@ -282,39 +315,16 @@ atom_ppsapi(
/*
- * atom_shutdown - shut down the clock
- */
-static void
-atom_shutdown(
- int unit, /* unit number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- register struct ppsunit *up;
-
- pp = peer->procptr;
- up = (struct ppsunit *)pp->unitptr;
- if (up->fddev > 0)
- close(up->fddev);
- if (up->handle != 0)
- time_pps_destroy(up->handle);
- if (pps_peer == peer)
- pps_peer = 0;
- free(up);
-}
-
-
-/*
- * atom_pps - receive data from the PPSAPI interface
+ * atom_timer - called once per second
*
* This routine is called once per second when the PPSAPI interface is
* present. It snatches the PPS timestamp from the kernel and saves the
* sign-extended fraction in a circular buffer for processing at the
* next poll event.
*/
-static int
-atom_pps(
+static void
+atom_timer(
+ int unit, /* unit number (not used) */
struct peer *peer /* peer structure pointer */
)
{
@@ -322,7 +332,9 @@ atom_pps(
struct refclockproc *pp;
pps_info_t pps_info;
struct timespec timeout, ts;
- double dtemp;
+ long sec, nsec;
+ double dtemp;
+ char tbuf[80]; /* monitor buffer */
/*
* Convert the timespec nanoseconds field to signed double and
@@ -334,34 +346,58 @@ atom_pps(
pp = peer->procptr;
up = (struct ppsunit *)pp->unitptr;
if (up->handle == 0)
- return (-1);
+ return;
+
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
- &timeout) < 0)
- return (-1);
+ &timeout) < 0) {
+ refclock_report(peer, CEVNT_FAULT);
+ return;
+ }
if (up->pps_params.mode & PPS_CAPTUREASSERT) {
- if (pps_info.assert_sequence ==
- up->pps_info.assert_sequence)
- return (1);
ts = up->pps_info.assert_timestamp;
} else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
- if (pps_info.clear_sequence ==
- up->pps_info.clear_sequence)
- return (1);
ts = up->pps_info.clear_timestamp;
} else {
- return (-1);
- }
- if (!((ts.tv_sec == up->ts.tv_sec && ts.tv_nsec -
- up->ts.tv_nsec > NANOSECOND - RANGEGATE) ||
- (ts.tv_sec - up->ts.tv_sec == 1 && ts.tv_nsec -
- up->ts.tv_nsec < RANGEGATE))) {
- up->ts = ts;
- return (1);
+ refclock_report(peer, CEVNT_FAULT);
+ return;
}
+
+ /*
+ * There can be zero, one or two PPS seconds between polls. If
+ * zero, either the poll clock is slightly faster than the PPS
+ * clock or the PPS clock has died. If the PPS clock advanced
+ * once between polls, we make sure the fraction time difference
+ * since the last sample is within the range gate of 5 ms (500
+ * PPM). If the PPS clock advanced twice since the last poll,
+ * the poll bracketed more than one second and the first second
+ * was lost to a slip. Since the interval since the last sample
+ * found is now two seconds, just widen the range gate. If the
+ * PPS clock advanced three or more times, either the signal has
+ * failed for a number of seconds or we have runts, in which
+ * case just ignore them.
+ *
+ * If flag4 is lit, record each second offset to clockstats.
+ * That's so we can make awesome Allan deviation plots.
+ */
+ sec = ts.tv_sec - up->ts.tv_sec;
+ nsec = ts.tv_nsec - up->ts.tv_nsec;
up->ts = ts;
+ if (nsec < 0) {
+ sec --;
+ nsec += NANOSECOND;
+ } else if (nsec >= NANOSECOND) {
+ sec++;
+ nsec -= NANOSECOND;
+ }
+ if (sec * NANOSECOND + nsec > NANOSECOND + RANGEGATE)
+ return;
+
+ else if (sec * NANOSECOND + nsec < NANOSECOND - RANGEGATE)
+ return;
+
pp->lastrec.l_ui = ts.tv_sec + JAN_1970;
dtemp = ts.tv_nsec * FRAC / 1e9;
if (dtemp >= FRAC)
@@ -371,11 +407,16 @@ atom_pps(
ts.tv_nsec -= NANOSECOND;
dtemp = -(double)ts.tv_nsec / NANOSECOND;
SAMPLE(dtemp + pp->fudgetime1);
+ if (pp->sloppyclockflag & CLK_FLAG4){
+ sprintf(tbuf, "%.9f", dtemp);
+ record_clock_stats(&peer->srcadr, tbuf);
+ }
#ifdef DEBUG
if (debug > 1)
- printf("atom_pps %f %f\n", dtemp, pp->fudgetime1);
+ printf("atom_timer: %lu %f %f\n", current_time,
+ dtemp, pp->fudgetime1);
#endif
- return (0);
+ return;
}
#endif /* HAVE_PPSAPI */
@@ -387,6 +428,9 @@ atom_pps(
* processes PPS information. It processes the PPS timestamp and saves
* the sign-extended fraction in a circular buffer for processing at the
* next poll event. This works only for a single PPS device.
+ *
+ * The routine should be used by another configured driver ONLY when
+ * this driver is configured as well and the PPSAPI is NOT in use.
*/
int
pps_sample(
@@ -399,8 +443,9 @@ pps_sample(
double doffset;
peer = pps_peer;
- if (peer == 0) /* nobody home */
+ if (peer == NULL)
return (1);
+
pp = peer->procptr;
/*
@@ -417,12 +462,9 @@ pps_sample(
return (0);
}
+
/*
* atom_poll - called by the transmit procedure
- *
- * This routine is called once per second when in burst mode to save PPS
- * sample offsets in the median filter. At the end of the burst period
- * the samples are processed as a heap and the clock filter updated.
*/
static void
atom_poll(
@@ -431,66 +473,37 @@ atom_poll(
)
{
struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
- int err;
-#endif /* HAVE_PPSAPI */
-
- /*
- * Accumulate samples in the median filter. If a noise sample,
- * return with no prejudice; if a protocol error, get mean;
- * otherwise, cool. At the end of each poll interval, do a
- * little bookeeping and process the surviving samples.
- */
pp = peer->procptr;
pp->polls++;
-#ifdef HAVE_PPSAPI
- err = atom_pps(peer);
- if (err < 0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
-#endif /* HAVE_PPSAPI */
/*
* Valid time is returned only if the prefer peer has survived
- * the intersection algorithm and within clock_max of local time
+ * the intersection algorithm and within 0.4 s of local time
* and not too long ago. This ensures the PPS time is within
- * +-0.5 s of the local time and the seconds numbering is
- * unambiguous. Note that the leap bits are set no-warning on
- * the first valid update and the stratum is set at the prefer
- * peer, unless overriden by a fudge command.
+ * 0.5 s of the local time and the seconds numbering is
+ * unambiguous. Note that the leap bits, stratum and refid are
+ * set from the prefer peer, unless overriden by a fudge
+ * command.
*/
- if (peer->burst > 0)
- return;
- peer->leap = LEAP_NOTINSYNC;
if (pp->codeproc == pp->coderecv) {
refclock_report(peer, CEVNT_TIMEOUT);
- peer->burst = ASTAGE;
return;
} else if (sys_prefer == NULL) {
pp->codeproc = pp->coderecv;
- peer->burst = ASTAGE;
return;
- } else if (fabs(sys_prefer->offset) > clock_max) {
+ } else if (fabs(sys_prefer->offset) >= 0.4) {
pp->codeproc = pp->coderecv;
- peer->burst = ASTAGE;
return;
}
- pp->leap = LEAP_NOWARNING;
+ pp->leap = sys_prefer->leap;
if (pp->stratum >= STRATUM_UNSPEC)
peer->stratum = sys_prefer->stratum;
else
peer->stratum = pp->stratum;
- if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
- STRATUM_UNSPEC)
- peer->refid = pp->refid;
- else
- peer->refid = addr2refid(&sys_prefer->srcadr);
pp->lastref = pp->lastrec;
refclock_receive(peer);
- peer->burst = ASTAGE;
}
#else
int refclock_atom_bs;
@@ -499,6 +512,6 @@ pps_sample(
l_fp *offset /* PPS offset */
)
{
- return 1;
+ return (1);
}
#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_bancomm.c b/contrib/ntp/ntpd/refclock_bancomm.c
index a63be44..9fc8c82 100644
--- a/contrib/ntp/ntpd/refclock_bancomm.c
+++ b/contrib/ntp/ntpd/refclock_bancomm.c
@@ -25,6 +25,21 @@
*
* Installation of the Datum/Bancomm driver creates the
* device file /dev/btfp0
+ *
+ * 04/28/2005 Rob Neal
+ * Modified to add support for Symmetricom bc637PCI-U Time &
+ * Frequency Processor.
+ * Card bus type (VME/VXI or PCI) and environment are specified via the
+ * "mode" keyword on the server command in ntp.conf.
+ * server 127.127.16.u prefer mode m (...)
+ * Modes currently supported are
+ * 1 : FreeBSD PCI 635/637.
+ * 2 : Linux or Windows PCI 635/637.
+ * not specified, or other number:
+ * : Assumed to be VME/VXI legacy Bancomm card on Solaris.
+ * Linux and Windows platforms require Symmetricoms' proprietary driver
+ * for the TFP card.
+ * Tested on FreeBSD 5.3 with a 637 card.
*/
#ifdef HAVE_CONFIG_H
@@ -49,7 +64,6 @@ struct btfp_time /* Structure for reading 5 time words */
{
unsigned short btfp_time[5]; /* Time words 0,1,2,3, and 4. (16bit)*/
};
-
/* SunOS5 ioctl commands definitions.*/
#define BTFPIOC ( 'b'<< 8 )
#define IOCIO( l, n ) ( BTFPIOC | n )
@@ -61,11 +75,16 @@ struct btfp_time /* Structure for reading 5 time words */
#define RUNLOCK IOCIOR(b, 19, int ) /* Release Capture Lockout */
#define RCR0 IOCIOR(b, 22, int ) /* Read control register zero.*/
#define WCR0 IOCIOWN(b, 23, int) /* Write control register zero*/
-
/***** Compound ioctl commands *****/
/* Read all 5 time words in one call. */
#define READTIME IOCIORN(b, 32, sizeof( struct btfp_time ))
+
+#if defined(__FreeBSD__)
+#undef READTIME
+#define READTIME _IOR('u', 5, struct btfp_time )
+#endif
+
#define VMEFD "/dev/btfp0"
struct vmedate { /* structure returned by get_vmetime.c */
@@ -74,11 +93,12 @@ struct vmedate { /* structure returned by get_vmetime.c */
unsigned short hr;
unsigned short mn;
unsigned short sec;
- unsigned long frac;
+ long frac;
unsigned short status;
};
/* END OF STUFF FROM RES */
+typedef void *SYMMT_PCI_HANDLE;
/*
* VME interface parameters.
@@ -99,7 +119,7 @@ extern u_long current_time; /* current time(s) */
/*
* Imported from ntpd module
*/
-extern int debug; /* global debug flag */
+extern volatile int debug; /* global debug flag */
/*
* VME unit control structure.
@@ -114,12 +134,20 @@ struct vmeunit {
/*
* Function prototypes
*/
-static void vme_init (void);
static int vme_start (int, struct peer *);
static void vme_shutdown (int, struct peer *);
static void vme_receive (struct recvbuf *);
static void vme_poll (int unit, struct peer *);
-struct vmedate *get_datumtime(struct vmedate *);
+struct vmedate *get_datumtime(struct vmedate *);
+void tvme_fill(struct vmedate *, uint32_t btm[2]);
+/*
+ * Define the bc*() functions as weak so we can compile/link without them.
+ * Only clients with the card will have the proprietary vendor device driver
+ * and interface library needed for use on Linux/Windows platforms.
+ */
+extern uint32_t __attribute__ ((weak)) bcReadBinTime(SYMMT_PCI_HANDLE, uint32_t *, uint32_t*, uint8_t*);
+extern SYMMT_PCI_HANDLE __attribute__ ((weak)) bcStartPci(void);
+extern void __attribute__ ((weak)) bcStopPci(SYMMT_PCI_HANDLE);
/*
* Transfer vector
@@ -136,6 +164,8 @@ struct refclock refclock_bancomm = {
int fd_vme; /* file descriptor for ioctls */
int regvalue;
+int tfp_type; /* mode selector, indicate platform and driver interface */
+SYMMT_PCI_HANDLE stfp_handle;
/*
@@ -151,7 +181,17 @@ vme_start(
struct refclockproc *pp;
int dummy;
char vmedev[20];
-
+
+ tfp_type = (int)(peer->ttl);
+ switch (tfp_type) {
+ case 1:
+ break;
+ case 2:
+ stfp_handle = bcStartPci(); /* init the card in lin/win */
+ break;
+ default:
+ break;
+ }
/*
* Open VME device
*/
@@ -163,13 +203,20 @@ vme_start(
msyslog(LOG_ERR, "vme_start: failed open of %s: %m", vmedev);
return (0);
}
- else { /* Release capture lockout in case it was set from before. */
- if( ioctl( fd_vme, RUNLOCK, &dummy ) )
- msyslog(LOG_ERR, "vme_start: RUNLOCK failed %m");
-
- regvalue = 0; /* More esoteric stuff to do... */
- if( ioctl( fd_vme, WCR0, &regvalue ) )
- msyslog(LOG_ERR, "vme_start: WCR0 failed %m");
+ else {
+ switch (tfp_type) {
+ case 1: break;
+ case 2: break;
+ default:
+ /* Release capture lockout in case it was set before. */
+ if( ioctl( fd_vme, RUNLOCK, &dummy ) )
+ msyslog(LOG_ERR, "vme_start: RUNLOCK failed %m");
+
+ regvalue = 0; /* More esoteric stuff to do... */
+ if( ioctl( fd_vme, WCR0, &regvalue ) )
+ msyslog(LOG_ERR, "vme_start: WCR0 failed %m");
+ break;
+ }
}
/*
@@ -222,6 +269,7 @@ vme_shutdown(
io_closeclock(&pp->io);
pp->unitptr = NULL;
free(vme);
+ if (tfp_type == 2) bcStopPci(stfp_handle);
}
@@ -275,7 +323,6 @@ vme_poll(
time(&tloc);
tadr = gmtime(&tloc);
tptr->year = (unsigned short)(tadr->tm_year + 1900);
-
sprintf(pp->a_lastcode,
"%3.3d %2.2d:%2.2d:%2.2d.%.6ld %1d",
@@ -292,13 +339,13 @@ vme_poll(
pp->hour = tptr->hr;
pp->minute = tptr->mn;
pp->second = tptr->sec;
- pp->usec = tptr->frac;
+ pp->nsec = tptr->frac;
#ifdef DEBUG
if (debug)
printf("pp: %3d %02d:%02d:%02d.%06ld %1x\n",
pp->day, pp->hour, pp->minute, pp->second,
- pp->usec, tptr->status);
+ pp->nsec, tptr->status);
#endif
if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */
refclock_report(peer, CEVNT_BADREPLY);
@@ -325,108 +372,95 @@ vme_poll(
struct vmedate *
get_datumtime(struct vmedate *time_vme)
{
- unsigned short status;
char cbuf[7];
struct btfp_time vts;
+ uint32_t btm[2];
+ uint8_t dmy;
if ( time_vme == (struct vmedate *)NULL) {
time_vme = (struct vmedate *)malloc(sizeof(struct vmedate ));
}
- if( ioctl(fd_vme, READTIME, &vts))
- msyslog(LOG_ERR, "get_datumtime error: %m");
-
- /* if you want to actually check the validity of these registers, do a
- define of CHECK above this. I didn't find it necessary. - RES
- */
-
-#ifdef CHECK
-
- /* Get day */
- sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
- ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
-
- if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2]) )
- time_vme->day = (unsigned short)atoi(cbuf);
- else
- time_vme->day = (unsigned short) 0;
-
- /* Get hour */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff);
-
- if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
- time_vme->hr = (unsigned short)atoi(cbuf);
- else
- time_vme->hr = (unsigned short) 0;
-
- /* Get minutes */
- sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8);
- if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
- time_vme->mn = (unsigned short)atoi(cbuf);
- else
- time_vme->mn = (unsigned short) 0;
-
- /* Get seconds */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff);
-
- if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
- time_vme->sec = (unsigned short)atoi(cbuf);
- else
- time_vme->sec = (unsigned short) 0;
-
- /* Get microseconds. Yes, we ignore the 0.1 microsecond digit so we can
- use the TVTOTSF function later on...*/
+ switch (tfp_type) {
+ case 1: /* BSD, PCI, 2 32bit time words */
+ if (ioctl(fd_vme, READTIME, &btm)) {
+ msyslog(LOG_ERR, "get_bc63x error: %m");
+ return(NULL);
+ }
+ tvme_fill(time_vme, btm);
+ break;
- sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ],
- vts.btfp_time[ 4 ]>>8);
+ case 2: /* Linux/Windows, PCI, 2 32bit time words */
+ if (bcReadBinTime(stfp_handle, &btm[1], &btm[0], &dmy) == 0) {
+ msyslog(LOG_ERR, "get_datumtime error: %m");
+ return(NULL);
+ }
+ tvme_fill(time_vme, btm);
+ break;
- if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2])
- && isdigit(cbuf[3]) && isdigit(cbuf[4]) && isdigit(cbuf[5]))
- time_vme->frac = (u_long) atoi(cbuf);
- else
- time_vme->frac = (u_long) 0;
-#else
+ default: /* legacy bancomm card */
- /* DONT CHECK just trust the card */
+ if (ioctl(fd_vme, READTIME, &vts)) {
+ msyslog(LOG_ERR, "get_datumtime error: %m");
+ return(NULL);
+ }
+ /* Get day */
+ sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
+ ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
+ time_vme->day = (unsigned short)atoi(cbuf);
- /* Get day */
- sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
- ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
- time_vme->day = (unsigned short)atoi(cbuf);
+ /* Get hour */
+ sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff);
- /* Get hour */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff);
+ time_vme->hr = (unsigned short)atoi(cbuf);
- time_vme->hr = (unsigned short)atoi(cbuf);
+ /* Get minutes */
+ sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8);
+ time_vme->mn = (unsigned short)atoi(cbuf);
- /* Get minutes */
- sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8);
- time_vme->mn = (unsigned short)atoi(cbuf);
+ /* Get seconds */
+ sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff);
+ time_vme->sec = (unsigned short)atoi(cbuf);
- /* Get seconds */
- sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff);
- time_vme->sec = (unsigned short)atoi(cbuf);
+ /* Get microseconds. Yes, we ignore the 0.1 microsecond digit so
+ we can use the TVTOTSF function later on...*/
- /* Get microseconds. Yes, we ignore the 0.1 microsecond digit so we can
- use the TVTOTSF function later on...*/
+ sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ],
+ vts.btfp_time[ 4 ]>>8);
- sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ],
- vts.btfp_time[ 4 ]>>8);
+ time_vme->frac = (u_long) atoi(cbuf);
- time_vme->frac = (u_long) atoi(cbuf);
+ /* Get status bit */
+ time_vme->status = (vts.btfp_time[0] & 0x0010) >>4;
-#endif /* CHECK */
+ break;
+ }
- /* Get status bit */
- status = (vts.btfp_time[0] & 0x0010) >>4;
- time_vme->status = status; /* Status=0 if locked to ref. */
- /* Status=1 if flywheeling */
- if (status) { /* lost lock ? */
+ if (time_vme->status)
return ((void *)NULL);
- }
else
return (time_vme);
}
+/* Assign values to time_vme struct. Mostly for readability */
+void
+tvme_fill(struct vmedate *time_vme, uint32_t btm[2])
+{
+ struct tm maj;
+ uint32_t dmaj, dmin;
+
+ dmaj = btm[1]; /* syntax sugar */
+ dmin = btm[0];
+
+ gmtime_r(&dmaj, &maj);
+ time_vme->day = maj.tm_yday+1;
+ time_vme->hr = maj.tm_hour;
+ time_vme->mn = maj.tm_min;
+ time_vme->sec = maj.tm_sec;
+ time_vme->frac = (dmin & 0x000fffff) * 1000;
+ time_vme->frac += ((dmin & 0x00f00000) >> 20) * 100;
+ time_vme->status = (dmin & 0x01000000) >> 24;
+ return;
+}
#else
int refclock_bancomm_bs;
diff --git a/contrib/ntp/ntpd/refclock_chu.c b/contrib/ntp/ntpd/refclock_chu.c
index e0c79e2..843e9aaa 100644
--- a/contrib/ntp/ntpd/refclock_chu.c
+++ b/contrib/ntp/ntpd/refclock_chu.c
@@ -208,12 +208,12 @@
#define BAUD 300 /* modulation rate (bps) */
#define OFFSET 128 /* companded sample offset */
#define SIZE 256 /* decompanding table size */
-#define MAXSIG 6000. /* maximum signal level */
+#define MAXAMP 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 DEVICE_AUDIO "/dev/audio" /* device name */
#define DESCRIPTION "CHU Audio/Modem Receiver" /* WRU */
#define AUDIO_BUFSIZ 240 /* audio buffer size (30 ms) */
#else
@@ -655,15 +655,15 @@ chu_audio_receive(
sample = up->comp[~*dpt++ & 0xff];
/*
- * Clip noise spikes greater than MAXSIG. If no clips,
+ * Clip noise spikes greater than MAXAMP. If no clips,
* increase the gain a tad; if the clips are too high,
* decrease a tad.
*/
- if (sample > MAXSIG) {
- sample = MAXSIG;
+ if (sample > MAXAMP) {
+ sample = MAXAMP;
up->clipcnt++;
- } else if (sample < -MAXSIG) {
- sample = -MAXSIG;
+ } else if (sample < -MAXAMP) {
+ sample = -MAXAMP;
up->clipcnt++;
}
chu_rf(peer, sample);
@@ -1112,7 +1112,7 @@ chu_b(
up->tstamp[up->ntstamp] = up->cstamp[i];
L_SUB(&up->tstamp[up->ntstamp], &offset);
L_ADD(&offset, &up->charstamp);
- if (up->ntstamp < MAXSTAGE)
+ if (up->ntstamp < MAXSTAGE - 1)
up->ntstamp++;
}
}
@@ -1216,7 +1216,7 @@ chu_a(
up->tstamp[up->ntstamp] = up->cstamp[i];
L_SUB(&up->tstamp[up->ntstamp], &offset);
L_ADD(&offset, &up->charstamp);
- if (up->ntstamp < MAXSTAGE)
+ if (up->ntstamp < MAXSTAGE - 1)
up->ntstamp++;
}
while (temp > up->prevsec) {
@@ -1231,7 +1231,7 @@ chu_a(
}
i = -(2 * k);
for (j = 0; j < nchar; j++) {
- if (i < 0 || i > 19) {
+ if (i < 0 || i > 18) {
i += 2;
continue;
}
diff --git a/contrib/ntp/ntpd/refclock_conf.c b/contrib/ntp/ntpd/refclock_conf.c
index 8a424f0..dc29d1e 100644
--- a/contrib/ntp/ntpd/refclock_conf.c
+++ b/contrib/ntp/ntpd/refclock_conf.c
@@ -24,7 +24,7 @@ extern struct refclock refclock_local;
#define refclock_local refclock_none
#endif
-#if defined(CLOCK_TRAK) && defined(PPS)
+#if 0 && defined(CLOCK_TRAK) && defined(PPS)
extern struct refclock refclock_trak;
#else
#define refclock_trak refclock_none
@@ -96,7 +96,7 @@ extern struct refclock refclock_irig;
#define refclock_irig refclock_none
#endif
-#if defined(CLOCK_MSFEES) && defined(PPS)
+#if 0 && defined(CLOCK_MSFEES) && defined(PPS)
extern struct refclock refclock_msfees;
#else
#define refclock_msfees refclock_none
@@ -144,18 +144,6 @@ extern struct refclock refclock_atom;
#define refclock_atom refclock_none
#endif
-#ifdef CLOCK_PTBACTS
-extern struct refclock refclock_ptb;
-#else
-#define refclock_ptb refclock_none
-#endif
-
-#ifdef CLOCK_USNO
-extern struct refclock refclock_usno;
-#else
-#define refclock_usno refclock_none
-#endif
-
#ifdef CLOCK_HPGPS
extern struct refclock refclock_hpgps;
#else
@@ -186,7 +174,7 @@ extern struct refclock refclock_palisade;
#define refclock_palisade refclock_none
#endif
-#if defined(CLOCK_ONCORE) && defined(HAVE_PPSAPI)
+#if defined(CLOCK_ONCORE)
extern struct refclock refclock_oncore;
#else
#define refclock_oncore refclock_none
@@ -279,7 +267,7 @@ extern struct refclock refclock_neoclock4x;
struct refclock *refclock_conf[] = {
&refclock_none, /* 0 REFCLK_NONE */
&refclock_local, /* 1 REFCLK_LOCAL */
- &refclock_trak, /* 2 REFCLK_GPS_TRAK */
+ &refclock_none, /* 2 deprecated: REFCLK_GPS_TRAK */
&refclock_pst, /* 3 REFCLK_WWV_PST */
&refclock_wwvb, /* 4 REFCLK_SPECTRACOM */
&refclock_true, /* 5 REFCLK_TRUETIME */
@@ -291,18 +279,18 @@ struct refclock *refclock_conf[] = {
&refclock_arbiter, /* 11 REFCLK_GPS_ARBITER */
&refclock_tpro, /* 12 REFCLK_IRIG_TPRO */
&refclock_leitch, /* 13 REFCLK_ATOM_LEITCH */
- &refclock_msfees, /* 14 REFCLK_MSF_EES */
- &refclock_true, /* 15 alias for REFCLK_TRUETIME */
+ &refclock_none, /* 14 deprecated: REFCLK_MSF_EES */
+ &refclock_none, /* 15 not used */
&refclock_bancomm, /* 16 REFCLK_IRIG_BANCOMM */
&refclock_datum, /* 17 REFCLK_GPS_DATUM */
- &refclock_acts, /* 18 REFCLK_NIST_ACTS */
+ &refclock_acts, /* 18 REFCLK_ACTS */
&refclock_heath, /* 19 REFCLK_WWV_HEATH */
&refclock_nmea, /* 20 REFCLK_GPS_NMEA */
&refclock_gpsvme, /* 21 REFCLK_GPS_VME */
&refclock_atom, /* 22 REFCLK_ATOM_PPS */
- &refclock_ptb, /* 23 REFCLK_PTB_ACTS */
- &refclock_usno, /* 24 REFCLK_USNO */
- &refclock_true, /* 25 alias for REFCLK_TRUETIME */
+ &refclock_none, /* 23 not used */
+ &refclock_none, /* 24 not used */
+ &refclock_none, /* 25 not used */
&refclock_hpgps, /* 26 REFCLK_GPS_HP */
&refclock_arc, /* 27 REFCLK_ARCRON_MSF */
&refclock_shm, /* 28 REFCLK_SHM */
diff --git a/contrib/ntp/ntpd/refclock_datum.c b/contrib/ntp/ntpd/refclock_datum.c
index 82b7369..b26fe73 100644
--- a/contrib/ntp/ntpd/refclock_datum.c
+++ b/contrib/ntp/ntpd/refclock_datum.c
@@ -119,6 +119,7 @@
#define REFID "DATM" /* reference id */
#define DATUM_DISPERSION 0 /* fixed dispersion = 0 ms */
#define DATUM_MAX_ERROR 0.100 /* limits on sigma squared */
+#define DATUM_DEV "/dev/datum" /* device name */
#define DATUM_MAX_ERROR2 (DATUM_MAX_ERROR*DATUM_MAX_ERROR)
@@ -233,6 +234,7 @@ datum_pts_start(
{
struct datum_pts_unit **temp_datum_pts_unit;
struct datum_pts_unit *datum_pts;
+ int fd;
#ifdef HAVE_TERMIOS
struct termios arg;
#endif
@@ -243,6 +245,16 @@ datum_pts_start(
#endif
/*
+ ** Open the Datum PTS device
+ */
+ fd = open(DATUM_DEV, O_RDWR);
+
+ if (fd < 0) {
+ msyslog(LOG_ERR, "Datum_PTS: open(\"%s\", O_RDWR) failed: %m", DATUM_DEV);
+ return 0;
+ }
+
+ /*
** Create the memory for the new unit
*/
@@ -260,11 +272,7 @@ datum_pts_start(
datum_pts->yearstart = 0; /* initialize the yearstart to 0 */
datum_pts->sigma2 = 0.0; /* initialize the sigma2 to 0 */
- /*
- ** Open the Datum PTS device
- */
-
- datum_pts->PTS_fd = open("/dev/datum",O_RDWR);
+ datum_pts->PTS_fd = fd;
fcntl(datum_pts->PTS_fd, F_SETFL, 0); /* clear the descriptor flags */
diff --git a/contrib/ntp/ntpd/refclock_fg.c b/contrib/ntp/ntpd/refclock_fg.c
index ebcf1b5..ce5085a 100644
--- a/contrib/ntp/ntpd/refclock_fg.c
+++ b/contrib/ntp/ntpd/refclock_fg.c
@@ -323,9 +323,6 @@ fg_receive(
printf ("fg: time is %04d/%03d %02d:%02d:%02d UTC\n",
pp->year, pp->day, pp->hour, pp->minute, pp->second);
#endif
-
- if (peer->stratum <= 1)
- peer->refid = pp->refid;
pp->disp = (10e-6);
pp->lastrec = rbufp->recv_time; /* Is it better than get_systime()? */
/* pp->leap = LEAP_NOWARNING; */
diff --git a/contrib/ntp/ntpd/refclock_gpsvme.c b/contrib/ntp/ntpd/refclock_gpsvme.c
index a7fcf5f..9f9e85c 100644
--- a/contrib/ntp/ntpd/refclock_gpsvme.c
+++ b/contrib/ntp/ntpd/refclock_gpsvme.c
@@ -1,622 +1,254 @@
-/*
- * refclock_gpsvme.c NTP clock driver for the TrueTime GPS-VME
- * R. Schmidt, Time Service, US Naval Obs. res@tuttle.usno.navy.mil
- *
- * The refclock type has been defined as 16 (until new id assigned).
- * These DEFS are included in the Makefile:
- * DEFS= -DHAVE_TERMIOS -DSYS_HPUX=9
- * DEFS_LOCAL= -DREFCLOCK
- * CLOCKDEFS= -DGPSVME
- * The file map_vme.c does the VME memory mapping, and includes vme_init().
- * map_vme.c is HP-UX specific, because HPUX cannot mmap() device files! Boo!
- * The file gps.h provides TrueTime register info.
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_GPSVME)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
-#include <stdio.h>
-#include <syslog.h>
-#include <ctype.h>
-
-#include "gps.h"
-#include "/etc/conf/h/io.h"
-
-/* GLOBAL STUFF BY RES */
-
-#include <time.h>
-
-#define PRIO 120 /* set the realtime priority */
-#define NREGS 7 /* number of registers we will use */
-
-extern int init_vme(); /* This is just a call to map_vme() */
- /* It doesn't have to be extern */
- /* the map_vme() call */
-extern unsigned short *greg[NREGS]; /* made extern to avoid being in both map_vme.c and this file */
-extern void *gps_base; /* mjb lmco 12/20/99 */
-
-extern caddr_t map_vme ();
-extern void unmap_vme(); /* Unmaps the VME space */
-
-struct vmedate { /* structure needed by ntp */
- unsigned short year; /* *tptr is a pointer to this */
- unsigned short doy;
- unsigned short hr;
- unsigned short mn;
- unsigned short sec;
- unsigned long frac;
- unsigned short status;
+/* refclock_psc.c: clock driver for Brandywine PCI-SyncClock32/HP-UX 11.X */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#if defined(REFCLOCK) && defined(CLOCK_GPSVME)
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_stdlib.h"
+
+#ifdef __hpux
+#include <sys/rtprio.h> /* may already be included above */
+#include <sys/lock.h> /* NEEDED for PROCLOCK */
+#endif /* __hpux */
+
+#ifdef __linux__
+#include <sys/ioctl.h> /* for _IOR, ioctl */
+#endif /* __linux__ */
+
+enum { /* constants */
+ BUFSIZE = 32,
+ PSC_SYNC_OK = 0x40, /* Sync status bit */
+ DP_LEAPSEC_DAY10DAY1 = 0x82, /* DP RAM address */
+ DP_LEAPSEC_DAY1000DAY100 = 0x83,
+ DELAY = 1,
+ NUNIT = 2 /* max UNITS */
};
-struct vmedate *get_gpsvme_time();
-struct vmedate * time_vme; /* added to emulate LM refclock_gpsvme
- (Made global per RES suggestion to fix mem leak DW lmco) mjb lmco 12/15/99 */
-
-/* END OF STUFF FROM RES */
-
-/*
- * Definitions
- */
-#define MAXUNITS 2 /* max number of VME units */
-#define BMAX 50 /* timecode buffer length */
-
-/*
- * VME interface parameters.
- */
-#define VMEPRECISION (-21) /* precision assumed (1 us) */
-#define USNOREFID "USNO\0" /* Or whatever? */
-#define VMEREFID "GPS" /* reference id */
-#define VMEDESCRIPTION "GPS" /* who we are */
-#define VMEHSREFID 0x7f7f1001 /* 127.127.16.01 refid hi strata */
-
-/* I'm using clock type 16 until one is assigned */
-/* This is set also in vme_control, below */
-
-
-#define GMT 0 /* hour offset from Greenwich */
-
-/*
- * VME unit control structure.
- */
-struct vmeunit {
- struct peer *peer; /* associated peer structure */
- struct refclockio io; /* given to the I/O handler */
- struct vmedate vmedata; /* data returned from vme read */
- l_fp lastrec; /* last local time */
- l_fp lastref; /* last timecode time */
- char lastcode[BMAX]; /* last timecode received */
- u_short lencode; /* length of last timecode */
- u_long lasttime; /* last time clock heard from */
- u_short unit; /* unit number for this guy */
- u_short status; /* clock status */
- u_short lastevent; /* last clock event */
- u_short year; /* year of eternity */
- u_short day; /* day of year */
- u_short hour; /* hour of day */
- u_short minute; /* minute of hour */
- u_short second; /* seconds of minute */
- u_long usec; /* microsecond of second */
- u_long yearstart; /* start of current year */
- u_short leap; /* leap indicators */
- /*
- * Status tallies
- */
- u_long polls; /* polls sent */
- u_long noreply; /* no replies to polls */
- u_long coderecv; /* timecodes received */
- u_long badformat; /* bad format */
- u_long baddata; /* bad data */
- u_long timestarted; /* time we started this */
+/* clock card registers */
+struct psc_regs {
+ uint32_t low_time; /* card base + 0x00 */
+ uint32_t high_time; /* card base + 0x04 */
+ uint32_t ext_low_time; /* card base + 0x08 */
+ uint32_t ext_high_time; /* card base + 0x0C */
+ uint8_t device_status; /* card base + 0x10 */
+ uint8_t device_control; /* card base + 0x11 */
+ uint8_t reserved0; /* card base + 0x12 */
+ uint8_t ext_100ns; /* card base + 0x13 */
+ uint8_t match_usec; /* card base + 0x14 */
+ uint8_t match_msec; /* card base + 0x15 */
+ uint8_t reserved1; /* card base + 0x16 */
+ uint8_t reserved2; /* card base + 0x17 */
+ uint8_t reserved3; /* card base + 0x18 */
+ uint8_t reserved4; /* card base + 0x19 */
+ uint8_t dp_ram_addr; /* card base + 0x1A */
+ uint8_t reserved5; /* card base + 0x1B */
+ uint8_t reserved6; /* card base + 0x1C */
+ uint8_t reserved7; /* card base + 0x1D */
+ uint8_t dp_ram_data; /* card base + 0x1E */
+ uint8_t reserved8; /* card base + 0x1F */
+} *volatile regp[NUNIT];
+
+#define PSC_REGS _IOR('K', 0, long) /* ioctl argument */
+
+/* Macros to swap byte order and convert BCD to binary */
+#define SWAP(val) ( ((val) >> 24) | (((val) & 0x00ff0000) >> 8) | \
+(((val) & 0x0000ff00) << 8) | (((val) & 0x000000ff) << 24) )
+#define BCD2INT2(val) ( ((val) >> 4 & 0x0f)*10 + ((val) & 0x0f) )
+#define BCD2INT3(val) ( ((val) >> 8 & 0x0f)*100 + ((val) >> 4 & 0x0f)*10 + \
+((val) & 0x0f) )
+
+/* PSC interface definitions */
+#define PRECISION (-20) /* precision assumed (1 us) */
+#define REFID "USNO" /* reference ID */
+#define DESCRIPTION "Brandywine PCI-SyncClock32"
+#define DEVICE "/dev/refclock%1d" /* device file */
+
+/* clock unit control structure */
+struct psc_unit {
+ short unit; /* NTP refclock unit number */
+ short last_hour; /* last hour (monitor leap sec) */
+ int msg_flag[2]; /* count error messages */
};
+int fd[NUNIT]; /* file descriptor */
-/*
- * Data space for the unit structures. Note that we allocate these on
- * the fly, but never give them back.
- */
-static struct vmeunit *vmeunits[MAXUNITS];
-static u_char unitinuse[MAXUNITS];
+/* Local function prototypes */
+static int psc_start(int, struct peer *);
+static void psc_shutdown(int, struct peer *);
+static void psc_poll(int, struct peer *);
+static void check_leap_sec(struct refclockproc *, int);
-/*
- * Keep the fudge factors separately so they can be set even
- * when no clock is configured.
- */
-static l_fp fudgefactor[MAXUNITS];
-static u_char stratumtouse[MAXUNITS];
-static u_char sloppyclockflag[MAXUNITS];
-
-/*
- * Function prototypes
- */
-static void vme_init (void);
-static int vme_start (int, struct peer *);
-static void vme_shutdown (int, struct peer *);
-static void vme_report_event (struct vmeunit *, int);
-static void vme_receive (struct recvbuf *);
-static void vme_poll (int unit, struct peer *);
-static void vme_control (int, struct refclockstat *, struct refclockstat *, struct peer *);
-static void vme_buginfo (int, struct refclockbug *, struct peer *);
-
-/*
- * Transfer vector
- */
-struct refclock refclock_gpsvme = {
- vme_start, vme_shutdown, vme_poll,
- vme_control, vme_init, vme_buginfo, NOFLAGS
+/* Transfer vector */
+struct refclock refclock_gpsvme = {
+ psc_start, psc_shutdown, psc_poll, noentry, noentry, noentry, NOFLAGS
};
-int fd_vme; /* file descriptor for ioctls */
-int regvalue;
-
-/*
- * vme_init - initialize internal vme driver data
- */
-static void
-vme_init(void)
-{
- register int i;
- /*
- * Just zero the data arrays
- */
- /*
- bzero((char *)vmeunits, sizeof vmeunits);
- bzero((char *)unitinuse, sizeof unitinuse);
- */
-
- /*
- * Initialize fudge factors to default.
- */
- for (i = 0; i < MAXUNITS; i++) {
- fudgefactor[i].l_ui = 0;
- fudgefactor[i].l_uf = 0;
- stratumtouse[i] = 0;
- sloppyclockflag[i] = 0;
- }
-}
-
-/*
- * vme_start - open the VME device and initialize data for processing
- */
+/* psc_start: open device and initialize data for processing */
static int
-vme_start(
- u_int unit,
- struct peer *peer
- )
+psc_start(
+ int unit,
+ struct peer *peer
+ )
{
- register struct vmeunit *vme;
- register int i;
- int dummy;
- char vmedev[20];
-
- /*
- * Check configuration info.
- */
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_start: unit %d invalid", unit);
- return (0);
- }
- if (unitinuse[unit]) {
- msyslog(LOG_ERR, "vme_start: unit %d in use", unit);
- return (0);
- }
-
- /*
- * Open VME device
- */
-#ifdef DEBUG
-
- printf("Opening VME DEVICE \n");
-#endif
- init_vme(); /* This is in the map_vme.c external file */
-
- /*
- * Allocate unit structure
- */
- if (vmeunits[unit] != 0) {
- vme = vmeunits[unit]; /* The one we want is okay */
- } else {
- for (i = 0; i < MAXUNITS; i++) {
- if (!unitinuse[i] && vmeunits[i] != 0)
- break;
- }
- if (i < MAXUNITS) {
- /*
- * Reclaim this one
- */
- vme = vmeunits[i];
- vmeunits[i] = 0;
- } else {
- vme = (struct vmeunit *)
- emalloc(sizeof(struct vmeunit));
- time_vme = (struct vmedate *)malloc(sizeof(struct vmedate)); /* Added to emulate LM's refclock_gpsvme
- (added to fix mem lead DW lmco) mjb lmco 12/22/99 */
- }
- }
- bzero((char *)vme, sizeof(struct vmeunit));
- vmeunits[unit] = vme;
-
- /*
- * Set up the structures
- */
- vme->peer = peer;
- vme->unit = (u_short)unit;
- vme->timestarted = current_time;
-
- vme->io.clock_recv = vme_receive;
- vme->io.srcclock = (caddr_t)vme;
- vme->io.datalen = 0;
- vme->io.fd = fd_vme;
-
- /*
- * All done. Initialize a few random peer variables, then
- * return success.
- */
- peer->precision = VMEPRECISION;
- peer->stratum = stratumtouse[unit];
- memcpy( (char *)&peer->refid, USNOREFID,4);
-
- /* peer->refid = htonl(VMEHSREFID); */
-
- unitinuse[unit] = 1;
- return (1);
-}
-
-
-/*
- * vme_shutdown - shut down a VME clock
- */
-static void
-vme_shutdown(
- int unit
- )
-{
- register struct vmeunit *vme;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_shutdown: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- msyslog(LOG_ERR, "vme_shutdown: unit %d not in use", unit);
- return;
- }
-
- /*
- * Tell the I/O module to turn us off. We're history.
- */
- unmap_vme();
- vme = vmeunits[unit];
- io_closeclock(&vme->io);
- unitinuse[unit] = 0;
+ char buf[BUFSIZE];
+ struct refclockproc *pp;
+ struct psc_unit *up = emalloc(sizeof *up);
+
+ if (unit < 0 || unit > 1) { /* support units 0 and 1 */
+ msyslog(LOG_ERR, "psc_start: bad unit: %d", unit);
+ return 0;
+ }
+
+ if (!up) {
+ msyslog(LOG_ERR, "psc_start: unit: %d, emalloc: %m", unit);
+ return 0;
+ }
+ memset(up, '\0', sizeof *up);
+
+ sprintf(buf, DEVICE, unit); /* dev file name */
+ fd[unit] = open(buf, O_RDONLY); /* open device file */
+ if (fd[unit] < 0) {
+ msyslog(LOG_ERR, "psc_start: unit: %d, open failed. %m", unit);
+ return 0;
+ }
+
+ /* get the address of the mapped regs */
+ if (ioctl(fd[unit], PSC_REGS, &regp[unit]) < 0) {
+ msyslog(LOG_ERR, "psc_start: unit: %d, ioctl failed. %m", unit);
+ return 0;
+ }
+
+ /* initialize peer variables */
+ pp = peer->procptr;
+ pp->io.clock_recv = noentry;
+ pp->io.srcclock = (caddr_t) peer;
+ pp->io.datalen = 0;
+ pp->io.fd = -1;
+ pp->unitptr = (caddr_t) up;
+ get_systime(&pp->lastrec);
+ memcpy((char *)&pp->refid, REFID, 4);
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ up->unit = unit;
+#ifdef __hpux
+ rtprio(0,120); /* set real time priority */
+ plock(PROCLOCK); /* lock process in memory */
+#endif /* __hpux */
+ return 1;
}
-/*
- * vme_report_event - note the occurance of an event
- *
- * This routine presently just remembers the report and logs it, but
- * does nothing heroic for the trap handler.
- */
+/* psc_shutdown: shut down the clock */
static void
-vme_report_event(
- struct vmeunit *vme,
- int code
- )
+psc_shutdown(
+ int unit,
+ struct peer *peer
+ )
{
- struct peer *peer;
-
- peer = vme->peer;
- if (vme->status != (u_short)code) {
- vme->status = (u_short)code;
- if (code != CEVNT_NOMINAL)
- vme->lastevent = (u_short)code;
- msyslog(LOG_INFO,
- "clock %s event %x", ntoa(&peer->srcadr), code);
- }
+ free(peer->procptr->unitptr);
+ close(fd[unit]);
}
-
-/*
- * vme_receive - receive data from the VME device.
- *
- * Note: This interface would be interrupt-driven. We don't use that
- * now, but include a dummy routine for possible future adventures.
- */
+/* psc_poll: read, decode, and record device time */
static void
-vme_receive(
- struct recvbuf *rbufp
- )
+psc_poll(
+ int unit,
+ struct peer *peer
+ )
{
+ struct refclockproc *pp = peer->procptr;
+ struct psc_unit *up;
+ unsigned tlo, thi;
+ unsigned char status;
+
+ up = (struct psc_unit *) pp->unitptr;
+ tlo = regp[unit]->low_time; /* latch and read first 4 bytes */
+ thi = regp[unit]->high_time; /* read 4 higher order bytes */
+ status = regp[unit]->device_status; /* read device status byte */
+
+ if (!(status & PSC_SYNC_OK)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ if (!up->msg_flag[unit]) { /* write once to system log */
+ msyslog(LOG_WARNING,
+ "SYNCHRONIZATION LOST on unit %1d, status %02x\n",
+ status, unit);
+ up->msg_flag[unit] = 1;
+ }
+ return;
+ }
+
+ get_systime(&pp->lastrec);
+ pp->polls++;
+
+ tlo = SWAP(tlo); /* little to big endian swap on */
+ thi = SWAP(thi); /* copy of data */
+ /* convert the BCD time to broken down time used by refclockproc */
+ pp->day = BCD2INT3((thi & 0x0FFF0000) >> 16);
+ pp->hour = BCD2INT2((thi & 0x0000FF00) >> 8);
+ pp->minute = BCD2INT2(thi & 0x000000FF);
+ pp->second = BCD2INT2(tlo >> 24);
+ /* ntp_process() in ntp_refclock.c appears to use usec as fraction of
+ second in microseconds if usec is nonzero. */
+ pp->nsec = 1000000*BCD2INT3((tlo & 0x00FFF000) >> 12) +
+ BCD2INT3(tlo & 0x00000FFF);
+
+ sprintf(pp->a_lastcode, "%3.3d %2.2d:%2.2d:%2.2d.%09ld %02x %08x %08x",
+ pp->day, pp->hour, pp->minute, pp->second, pp->nsec, status, thi,
+ tlo);
+ pp->lencode = strlen(pp->a_lastcode);
+
+ /* compute the timecode timestamp */
+ if (!refclock_process(pp)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ /* simulate the NTP receive and packet procedures */
+ refclock_receive(peer);
+ /* write clock statistics to file */
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+
+ /* With the first timecode beginning the day, check for a GPS
+ leap second notification. */
+ if (pp->hour < up->last_hour) {
+ check_leap_sec(pp, unit);
+ up->msg_flag[0] = up->msg_flag[1] = 0; /* reset flags */
+ }
+ up->last_hour = pp->hour;
}
-/*
- * vme_poll - called by the transmit procedure
- */
+/* check_leap_sec: read the Dual Port RAM leap second day registers. The
+ onboard GPS receiver should write the hundreds digit of day of year in
+ DP_LeapSec_Day1000Day100 and the tens and ones digits in
+ DP_LeapSec_Day10Day1. If these values are nonzero and today, we have
+ a leap second pending, so we set the pp->leap flag to LEAP_ADDSECOND.
+ If the BCD data are zero or a date other than today, set pp->leap to
+ LEAP_NOWARNING. */
static void
-vme_poll(
- int unit,
- struct peer *peer
- )
+check_leap_sec(struct refclockproc *pp, int unit)
{
- struct vmedate *tptr;
- struct vmeunit *vme;
- l_fp tstmp;
- time_t tloc;
- struct tm *tadr;
- long ltemp;
-
-
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_poll: unit %d invalid", unit);
- return;
- }
- if (!unitinuse[unit]) {
- msyslog(LOG_ERR, "vme_poll: unit %d not in use", unit);
- return;
- }
- vme = vmeunits[unit]; /* Here is the structure */
- vme->polls++;
-
- tptr = &vme->vmedata;
-
- if ((tptr = get_gpsvme_time()) == NULL ) {
- vme_report_event(vme, CEVNT_BADREPLY);
- return;
- }
-
- get_systime(&vme->lastrec);
- vme->lasttime = current_time;
-
- /*
- * Get VME time and convert to timestamp format.
- * The year must come from the system clock.
- */
- /*
- time(&tloc);
- tadr = gmtime(&tloc);
- tptr->year = (unsigned short)(tadr->tm_year + 1900);
- */
-
- sprintf(vme->lastcode,
- "%3.3d %2.2d:%2.2d:%2.2d.%.6d %1d\0",
- tptr->doy, tptr->hr, tptr->mn,
- tptr->sec, tptr->frac, tptr->status);
-
- record_clock_stats(&(vme->peer->srcadr), vme->lastcode);
- vme->lencode = (u_short) strlen(vme->lastcode);
-
- vme->day = tptr->doy;
- vme->hour = tptr->hr;
- vme->minute = tptr->mn;
- vme->second = tptr->sec;
- vme->nsec = tptr->frac * 1000;
-
-#ifdef DEBUG
- if (debug)
- printf("vme: %3d %02d:%02d:%02d.%06ld %1x\n",
- vme->day, vme->hour, vme->minute, vme->second,
- vme->nsec, tptr->status);
-#endif
- if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */
- vme_report_event(vme, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * Now, compute the reference time value. Use the heavy
- * machinery for the seconds and the millisecond field for the
- * fraction when present. If an error in conversion to internal
- * format is found, the program declares bad data and exits.
- * Note that this code does not yet know how to do the years and
- * relies on the clock-calendar chip for sanity.
- */
- if (!clocktime(vme->day, vme->hour, vme->minute,
- vme->second, GMT, vme->lastrec.l_ui,
- &vme->yearstart, &vme->lastref.l_ui)) {
- vme->baddata++;
- vme_report_event(vme, CEVNT_BADTIME);
- msyslog(LOG_ERR, "refclock_gpsvme: bad data!!");
- return;
- }
- vme->lastref.l_uf = 0;
- DTOLFP(vme->nsec / 1e9, &ltemp);
- L_ADD(&vme->lastrec, &ltemp);
- tstmp = vme->lastref;
-
- L_SUB(&tstmp, &vme->lastrec);
- vme->coderecv++;
-
- L_ADD(&tstmp, &(fudgefactor[vme->unit]));
- vme->lastref = vme->lastrec;
- refclock_receive(vme->peer);
-}
-
-/*
- * vme_control - set fudge factors, return statistics2
- */
-static void
-vme_control(
- u_int unit,
- struct refclockstat *in,
- struct refclockstat *out,
- struct peer * peer
- )
-{
- register struct vmeunit *vme;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_control: unit %d invalid)", unit);
- return;
- }
-
- if (in != 0) {
- if (in->haveflags & CLK_HAVETIME1)
- DTOLFP(in->fudgetime1, &fudgefactor[unit]); /* added mjb lmco 12/20/99 */
-
- if (in->haveflags & CLK_HAVEVAL1) {
- stratumtouse[unit] = (u_char)(in->fudgeval1 & 0xf);
- if (unitinuse[unit]) {
- struct peer *peer;
-
- /*
- * Should actually reselect clock, but
- * will wait for the next timecode
- */
- vme = vmeunits[unit];
- peer = vme->peer;
- peer->stratum = stratumtouse[unit];
- if (stratumtouse[unit] <= 1)
- memcpy( (char *)&peer->refid, USNOREFID,4);
- else
- peer->refid = htonl(VMEHSREFID);
- }
- }
- if (in->haveflags & CLK_HAVEFLAG1) {
- sloppyclockflag[unit] = in->flags & CLK_FLAG1;
- }
- }
-
- if (out != 0) {
- out->type = 16; /*set by RES SHOULD BE CHANGED */
- out->haveflags
- = CLK_HAVETIME1|CLK_HAVEVAL1|CLK_HAVEVAL2|CLK_HAVEFLAG1;
- out->clockdesc = VMEDESCRIPTION;
- LFPTOD(&fudgefactor[unit], out->fudgetime1); /* added mjb lmco 12/20/99 */
-
- out ->fudgetime2 = 0; /* should do what above was supposed to do mjb lmco 12/20/99 */
-
- out->fudgeval1 = (long)stratumtouse[unit]; /*changed from above LONG was not
- defined mjb lmco 12/15/99 */
-
- out->fudgeval2 = 0;
- out->flags = sloppyclockflag[unit];
- if (unitinuse[unit]) {
- vme = vmeunits[unit];
- out->lencode = vme->lencode;
- out->p_lastcode = vme->lastcode;
- out->timereset = current_time - vme->timestarted;
- out->polls = vme->polls;
- out->noresponse = vme->noreply;
- out->badformat = vme->badformat;
- out->baddata = vme->baddata;
- out->lastevent = vme->lastevent;
- out->currentstatus = vme->status;
- } else {
- out->lencode = 0;
- out->p_lastcode = "";
- out->polls = out->noresponse = 0;
- out->badformat = out->baddata = 0;
- out->timereset = 0;
- out->currentstatus = out->lastevent = CEVNT_NOMINAL;
- }
- }
-}
-
-/*
- * vme_buginfo - return clock dependent debugging info
- */
-static void
-vme_buginfo(
- int unit,
- register struct refclockbug *bug,
- struct peer * peer
- )
-{
- register struct vmeunit *vme;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_buginfo: unit %d invalid)", unit);
- return;
- }
-
- if (!unitinuse[unit])
- return;
- vme = vmeunits[unit];
-
- bug->nvalues = 11;
- bug->ntimes = 5;
- if (vme->lasttime != 0)
- bug->values[0] = current_time - vme->lasttime;
- else
- bug->values[0] = 0;
- bug->values[2] = (u_long)vme->year;
- bug->values[3] = (u_long)vme->day;
- bug->values[4] = (u_long)vme->hour;
- bug->values[5] = (u_long)vme->minute;
- bug->values[6] = (u_long)vme->second;
- bug->values[7] = (u_long)vme->nsec;
- bug->values[9] = vme->yearstart;
- bug->stimes = 0x1c;
- bug->times[0] = vme->lastref;
- bug->times[1] = vme->lastrec;
-}
-/* -------------------------------------------------------*/
-/* get_gpsvme_time() */
-/* R. Schmidt, USNO, 1995 */
-/* It's ugly, but hey, it works and its free */
-
-#include "gps.h" /* defines for TrueTime GPS-VME */
-
-#define PBIAS 193 /* 193 microsecs to read the GPS experimentally found */
-
-struct vmedate *
-get_gpsvme_time(void)
-{
- extern struct vmedate *time_vme;
- unsigned short set, hr, min, sec, ums, hms, status;
- int ret;
- char ti[3];
-
- long tloc ;
- time_t mktime(),time();
- struct tm *gmtime(), *gmt;
- char *gpsmicro;
- gpsmicro = (char *) malloc(7);
-
- *greg = (unsigned short *)malloc(sizeof(short) * NREGS);
-
-
- /* reference the freeze command address general register 1 */
- set = *greg[0];
- /* read the registers : */
- /* get year */
- time_vme->year = (unsigned short) *greg[6];
- /* Get doy */
- time_vme->doy = (unsigned short) (*greg[5] & MASKDAY);
- /* Get hour */
- time_vme->hr = (unsigned short) ((*greg[4] & MASKHI) >>8);
- /* Get minutes */
- time_vme->mn = (unsigned short) (*greg[4] & MASKLO);
- /* Get seconds */
- time_vme->sec = (unsigned short) (*greg[3] & MASKHI) >>8;
- /* get microseconds in 2 parts and put together */
- ums = *greg[2];
- hms = *greg[3] & MASKLO;
-
- time_vme->status = (unsigned short) *greg[5] >>13;
-
- /* reference the unfreeze command address general register 1 */
- set = *greg[1];
-
- sprintf(gpsmicro,"%2.2x%4.4x\0", hms, ums);
- time_vme->frac = (u_long) gpsmicro;
-
- /* unmap_vme(); */
-
- if (!status) {
- return (NULL); /* fixed mjb lmco 12/20/99 */
- }
- else
- return (time_vme);
+ unsigned char dhi, dlo;
+ int leap_day;
+
+ regp[unit]->dp_ram_addr = DP_LEAPSEC_DAY10DAY1;
+ usleep(DELAY);
+ dlo = regp[unit]->dp_ram_data;
+ regp[unit]->dp_ram_addr = DP_LEAPSEC_DAY1000DAY100;
+ usleep(DELAY);
+ dhi = regp[unit]->dp_ram_data;
+ leap_day = BCD2INT2(dlo) + 100*(dhi & 0x0F);
+
+ pp->leap = LEAP_NOWARNING; /* default */
+ if (leap_day && leap_day == pp->day) {
+ pp->leap = LEAP_ADDSECOND; /* leap second today */
+ msyslog(LOG_ERR, "LEAP_ADDSECOND flag set, day %d (%x %x).",
+ leap_day, dhi, dlo);
+ }
}
#else
-int refclock_gpsvme_bs;
-#endif /* REFCLOCK */
+int refclock_gpsvme_bs;
+#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_heath.c b/contrib/ntp/ntpd/refclock_heath.c
index c16cef3..a56b491 100644
--- a/contrib/ntp/ntpd/refclock_heath.c
+++ b/contrib/ntp/ntpd/refclock_heath.c
@@ -1,8 +1,10 @@
/*
- * refclock_heath - clock driver for Heath GC-1000 and and GC-1000 II
+ * refclock_heath - clock driver for Heath GC-1000
+ * (but no longer the GC-1001 Model II, which apparently never worked)
*/
+
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_HEATH)
@@ -32,17 +34,20 @@
* occasionally being rudely stepped when the offset exceeds the default
* clock_max of 128 ms.
*
- * There are two GC-1000 versions supported by this driver. The original
+ * There were two GC-1000 versions supported by this driver. The original
* GC-1000 with RS-232 output first appeared in 1983, but dissapeared
- * from the market a few years later. The GC-1000 II with RS-232 output
+ * from the market a few years later. The GC-1001 II with RS-232 output
* first appeared circa 1990, but apparently is no longer manufactured.
* The two models differ considerably, both in interface and commands.
* The GC-1000 has a pseudo-bipolar timecode output triggered by a RTS
* transition. The timecode includes both the day of year and time of
- * day. The GC-1000 II has a true bipolar output and a complement of
+ * day. The GC-1001 II has a true bipolar output and a complement of
* single character commands. The timecode includes only the time of
* day.
*
+ * The GC-1001 II was apparently never tested and, based on a Coverity
+ * scan, apparently never worked [Bug 689]. Related code has been disabled.
+ *
* GC-1000
*
* The internal DIPswitches should be set to operate in MANUAL mode. The
@@ -78,7 +83,7 @@
* established and hh:mm:ss.? once synchronization is established and
* then lost again for about a day.
*
- * GC-1000 II
+ * GC-1001 II
*
* Commands consist of a single letter and are case sensitive. When
* enterred in lower case, a description of the action performed is
@@ -161,7 +166,9 @@
#define DESCRIPTION "Heath GC-1000 Most Accurate Clock" /* WRU */
#define LENHEATH1 23 /* min timecode length */
+#if 0 /* BUG 689 */
#define LENHEATH2 13 /* min timecode length */
+#endif
/*
* Tables to compute the ddd of year form icky dd/mm timecode. Viva la
@@ -172,7 +179,7 @@ static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/*
* Baud rate table. The GC-1000 supports 1200, 2400 and 4800; the
- * GC-1000 II supports only 9600.
+ * GC-1001 II supports only 9600.
*/
static int speed[] = {B1200, B2400, B4800, B9600};
@@ -214,9 +221,10 @@ heath_start(
/*
* Open serial port
*/
- (void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, speed[peer->ttl & 0x3], 0)))
- return (0);
+ sprintf(device, DEVICE, unit);
+ if (!(fd = refclock_open(device, speed[peer->ttl & 0x3],
+ LDISC_REMOTE)))
+ return (0);
pp = peer->procptr;
pp->io.clock_recv = heath_receive;
pp->io.srcclock = (caddr_t)peer;
@@ -286,7 +294,7 @@ heath_receive(
/*
* GC-1000 timecode format: "hh:mm:ss.f AM mm/dd/yy"
- * GC-1000 II timecode format: "hh:mm:ss.f "
+ * GC-1001 II timecode format: "hh:mm:ss.f "
*/
case LENHEATH1:
if (sscanf(pp->a_lastcode,
@@ -298,16 +306,35 @@ heath_receive(
}
break;
+#if 0 /* BUG 689 */
/*
- * GC-1000 II timecode format: "hh:mm:ss.f "
+ * GC-1001 II timecode format: "hh:mm:ss.f "
*/
case LENHEATH2:
if (sscanf(pp->a_lastcode, "%2d:%2d:%2d.%c", &pp->hour,
&pp->minute, &pp->second, &dsec) != 4) {
refclock_report(peer, CEVNT_BADREPLY);
return;
+ } else {
+ struct tm *tm_time_p;
+ time_t now;
+
+ time(&now); /* we should grab 'now' earlier */
+ tm_time_p = gmtime(&now);
+ /*
+ * There is a window of time around midnight
+ * where this will Do The Wrong Thing.
+ */
+ if (tm_time_p) {
+ month = tm_time_p->tm_mon + 1;
+ day = tm_time_p->tm_mday;
+ } else {
+ refclock_report(peer, CEVNT_FAULT);
+ return;
+ }
}
break;
+#endif
default:
refclock_report(peer, CEVNT_BADREPLY);
@@ -385,12 +412,15 @@ heath_poll(
/*
* We toggle the RTS modem control lead (GC-1000) and sent a T
- * (GC-1000 II) to kick a timecode loose from the radio. This
+ * (GC-1001 II) to kick a timecode loose from the radio. This
* code works only for POSIX and SYSV interfaces. With bsd you
* are on your own. We take a timestamp between the up and down
* edges to lengthen the pulse, which should be about 50 usec on
* a Sun IPC. With hotshot CPUs, the pulse might get too short.
* Later.
+ *
+ * Bug 689: Even though we no longer support the GC-1001 II,
+ * I'm leaving the 'T' write in for timing purposes.
*/
if (ioctl(pp->io.fd, TIOCMBIC, (char *)&bits) < 0)
refclock_report(peer, CEVNT_FAULT);
diff --git a/contrib/ntp/ntpd/refclock_hopfpci.c b/contrib/ntp/ntpd/refclock_hopfpci.c
index 1b02319..81c186d 100644
--- a/contrib/ntp/ntpd/refclock_hopfpci.c
+++ b/contrib/ntp/ntpd/refclock_hopfpci.c
@@ -181,17 +181,11 @@ hopfpci_shutdown(
struct peer *peer
)
{
- struct refclockproc *pp;
- register struct hopfpciTime *up;
-
- pp = peer->procptr;
- up = (struct hopfpciTime *)pp->unitptr;
#ifndef SYS_WINNT
close(fd);
#else
CloseHopfDevice();
-/* UnmapViewOfFile (up); */
#endif
}
@@ -206,11 +200,9 @@ hopfpci_poll(
)
{
struct refclockproc *pp;
- register struct hopfpciTime *up;
HOPFTIME m_time;
pp = peer->procptr;
- up = (struct hopfpciTime *)pp->unitptr;
#ifndef SYS_WINNT
ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
diff --git a/contrib/ntp/ntpd/refclock_hopfser.c b/contrib/ntp/ntpd/refclock_hopfser.c
index 1d27333..94b660b 100644
--- a/contrib/ntp/ntpd/refclock_hopfser.c
+++ b/contrib/ntp/ntpd/refclock_hopfser.c
@@ -30,9 +30,11 @@
#if defined HAVE_SYS_MODEM_H
# include <sys/modem.h>
-# define TIOCMSET MCSETA
-# define TIOCMGET MCGETA
-# define TIOCM_RTS MRTS
+# ifndef __QNXNTO__
+# define TIOCMSET MCSETA
+# define TIOCMGET MCGETA
+# define TIOCM_RTS MRTS
+# endif
#endif
#ifdef HAVE_TERMIOS_H
diff --git a/contrib/ntp/ntpd/refclock_hpgps.c b/contrib/ntp/ntpd/refclock_hpgps.c
index 7c801bb..5efd19e 100644
--- a/contrib/ntp/ntpd/refclock_hpgps.c
+++ b/contrib/ntp/ntpd/refclock_hpgps.c
@@ -41,6 +41,13 @@
* than 1 usec. The accuracy when operating in holdover is typically better
* than 10 usec. per day.
*
+ * The same driver also handles the HP Z3801A which is available surplus
+ * from the cell phone industry. It's popular with hams.
+ * It needs a different line setup: 19200 baud, 7 data bits, odd parity
+ * That is selected by adding "mode 1" to the server line in ntp.conf
+ * HP Z3801A code from Jeff Mock added by Hal Murray, Sep 2005
+ *
+ *
* The receiver should be operated with factory default settings.
* Initial driver operation: expects the receiver to be already locked
* to GPS, configured and able to output timecode format 2 messages.
@@ -85,6 +92,7 @@
*/
#define DEVICE "/dev/hpgps%d" /* device name and unit */
#define SPEED232 B9600 /* uart speed (9600 baud) */
+#define SPEED232Z B19200 /* uart speed (19200 baud) */
#define PRECISION (-10) /* precision assumed (about 1 ms) */
#define REFID "GPS\0" /* reference ID */
#define DESCRIPTION "HP 58503A GPS Time and Frequency Reference Receiver"
@@ -152,11 +160,18 @@ hpgps_start(
/*
* Open serial port. Use CLK line discipline, if available.
+ * Default is HP 58503A, mode arg selects HP Z3801A
*/
(void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
- return (0);
-
+ /* mode parameter to server config line shares ttl slot */
+ if ((peer->ttl == 1)) {
+ if (!(fd = refclock_open(device, SPEED232Z,
+ LDISC_CLK | LDISC_7O1)))
+ return (0);
+ } else {
+ if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
+ return (0);
+ }
/*
* Allocate and initialize unit structure
*/
diff --git a/contrib/ntp/ntpd/refclock_irig.c b/contrib/ntp/ntpd/refclock_irig.c
index 0b35368..6be09d9 100644
--- a/contrib/ntp/ntpd/refclock_irig.c
+++ b/contrib/ntp/ntpd/refclock_irig.c
@@ -116,13 +116,14 @@
* timestamp in NTP format.
*
* The fraction part of the on-time timestamp is a good indicator of how
- * well the driver is doing. With an UltrSPARC 30 and Solaris 2.7, this
- * thing can keep the clock within a few tens of microseconds relative
- * to the IRIG-B signal. Accuracy with IRIG-E is about ten times worse.
- * Unfortunately, Sun broke the 2.7 audio driver in 2.8, which has a
- * 10-ms sawtooth modulation. The driver attempts to remove the
- * modulation by some clever estimation techniques which mostly work.
- * Your experience may vary.
+ * well the driver is doing. Once upon a time, an UltrSPARC 30 and
+ * Solaris 2.7 kept the clock within a few tens of microseconds relative
+ * to the IRIG-B signal. Accuracy with IRIG-E was 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. With the
+ * "mixerctl -o" command before starting the daemon, the jitter is down
+ * to about 100 microseconds. 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
@@ -132,13 +133,12 @@
* Fudge factors
*
* Fudge flag4 causes the dubugging output described above to be
- * recorded in the clockstats file. When the audio driver is compiled,
- * fudge flag2 selects the audio input port, where 0 is the mike port
- * (default) and 1 is the line-in port. It does not seem useful to
- * select the compact disc player port. Fudge flag3 enables audio
- * monitoring of the input signal. For this purpose, the monitor gain is
- * set to a default value. Fudgetime2 is used as a frequency vernier for
- * broken codec sample frequency.
+ * recorded in the clockstats file. Fudge flag2 selects the audio input
+ * port, where 0 is the mike port (default) and 1 is the line-in port.
+ * It does not seem useful to select the compact disc player port. Fudge
+ * flag3 enables audio monitoring of the input signal. For this purpose,
+ * the monitor gain is set to a default value. Fudgetime2 is used as a
+ * frequency vernier for broken codec sample frequency.
*/
/*
* Interface definitions
@@ -157,7 +157,7 @@
#define FIELD 10 /* subfields per field */
#define MINTC 2 /* min PLL time constant */
#define MAXTC 20 /* max PLL time constant max */
-#define MAXSIG 6000. /* maximum signal level */
+#define MAXAMP 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 */
@@ -442,15 +442,15 @@ irig_receive(
sample = up->comp[~*dpt++ & 0xff];
/*
- * Clip noise spikes greater than MAXSIG. If no clips,
+ * Clip noise spikes greater than MAXAMP. If no clips,
* increase the gain a tad; if the clips are too high,
* decrease a tad.
*/
- if (sample > MAXSIG) {
- sample = MAXSIG;
+ if (sample > MAXAMP) {
+ sample = MAXAMP;
up->clipcnt++;
- } else if (sample < -MAXSIG) {
- sample = -MAXSIG;
+ } else if (sample < -MAXAMP) {
+ sample = -MAXAMP;
up->clipcnt++;
}
@@ -690,6 +690,7 @@ irig_base(
*/
if (up->carphase != 7)
return;
+
env = (up->lastenv[2] - up->lastenv[6]) / 2.;
lope = (up->lastint[2] - up->lastint[6]) / 2.;
if (lope > up->intmax)
@@ -939,11 +940,8 @@ irig_decode(
else
pp->leap = LEAP_NOWARNING;
up->second = (up->second + up->decim) % 60;
- if (pp->year > 0) {
+ if (pp->year > 0)
pp->year += 2000;
- if (syncchar == '0')
- up->errflg |= IRIG_ERR_CHECK;
- }
if (pp->second != up->second)
up->errflg |= IRIG_ERR_CHECK;
up->second = pp->second;
@@ -993,6 +991,7 @@ irig_poll(
if (pp->coderecv == pp->codeproc) {
refclock_report(peer, CEVNT_TIMEOUT);
return;
+
} else {
refclock_receive(peer);
record_clock_stats(&peer->srcadr, pp->a_lastcode);
diff --git a/contrib/ntp/ntpd/refclock_jjy.c b/contrib/ntp/ntpd/refclock_jjy.c
index 2aa9d6a..9d1419a 100644
--- a/contrib/ntp/ntpd/refclock_jjy.c
+++ b/contrib/ntp/ntpd/refclock_jjy.c
@@ -4,7 +4,7 @@
/**********************************************************************/
/* */
-/* Copyright (C) 2001, Takao Abe. All rights reserved. */
+/* Copyright (C) 2001-2004, Takao Abe. All rights reserved. */
/* */
/* Permission to use, copy, modify, and distribute this software */
/* and its documentation for any purpose is hereby granted */
@@ -55,9 +55,25 @@
/* [Change] Log to clockstats even if bad reply */
/* [Fix] PRECISION = (-3) (about 100 ms) */
/* [Add] Support the C-DEX Co.Ltd. JJY receiver */
+/* */
/* 2001/12/04 */
/* [Fix] C-DEX JST2000 ( fukusima@goto.info.waseda.ac.jp ) */
/* */
+/* 2002/07/12 */
+/* [Fix] Portability for FreeBSD ( patched by the user ) */
+/* */
+/* 2004/10/31 */
+/* [Change] Command send timing for the Tristate Ltd. JJY receiver */
+/* JJY-01 ( Firmware version 2.01 ) */
+/* Thanks to Andy Taki for testing under FreeBSD */
+/* */
+/* 2004/11/28 */
+/* [Add] Support the Echo Keisokuki LT-2000 receiver */
+/* */
+/* 2006/11/04 */
+/* [Fix] C-DEX JST2000 */
+/* Thanks to Hideo Kuramatsu for the patch */
+/* */
/**********************************************************************/
#ifdef HAVE_CONFIG_H
@@ -103,6 +119,18 @@
/* <ENQ>1J<ETX> <STX>JYYMMDD HHMMSSS<ETX> */
/* */
/**********************************************************************/
+/* */
+/* The Echo Keisokuki Co. Ltd. JJY receiver LT2000 */
+/* */
+/* Command Response Remarks */
+/* ------------ ---------------------- --------------------- */
+/* # Mode 1 (Request&Send) */
+/* T YYMMDDWHHMMSS<BCC1><BCC2><CR> */
+/* C Mode 2 (Continuous) */
+/* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
+/* <SUB> Second signal */
+/* */
+/**********************************************************************/
/*
* Interface definitions
@@ -117,7 +145,8 @@
* JJY unit control structure
*/
struct jjyunit {
- char unittype ; /* UNITTYPE_XXXXXXXXXX */
+ char unittype ; /* UNITTYPE_XXXXXXXXXX */
+ short operationmode ; /* Echo Keisokuki LT-2000 : 1 or 2 */
short version ;
short linediscipline ; /* LDISC_CLK or LDISC_RAW */
int linecount ;
@@ -134,6 +163,7 @@ struct jjyunit {
#define UNITTYPE_TRISTATE_JJY01 1
#define UNITTYPE_CDEX_JST2000 2
+#define UNITTYPE_ECHOKEISOKUKI_LT2000 3
/*
* Function prototypes
@@ -143,9 +173,11 @@ static void jjy_shutdown P((int, struct peer *));
static void jjy_poll P((int, struct peer *));
static void jjy_poll_tristate_jjy01 P((int, struct peer *));
static void jjy_poll_cdex_jst2000 P((int, struct peer *));
+static void jjy_poll_echokeisokuki_lt2000 P((int, struct peer *));
static void jjy_receive P((struct recvbuf *));
static int jjy_receive_tristate_jjy01 P((struct recvbuf *));
static int jjy_receive_cdex_jst2000 P((struct recvbuf *));
+static int jjy_receive_echokeisokuki_lt2000 P((struct recvbuf *));
/*
* Transfer vector
@@ -208,6 +240,7 @@ jjy_start ( int unit, struct peer *peer )
case 0 :
case 1 : iDiscipline = LDISC_CLK ; break ;
case 2 : iDiscipline = LDISC_RAW ; break ;
+ case 3 : iDiscipline = LDISC_CLK ; break ;
default :
msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
ntoa(&peer->srcadr), peer->ttl ) ;
@@ -253,6 +286,19 @@ jjy_start ( int unit, struct peer *peer )
up->lineexpect = 1 ;
up->charexpect[0] = 15 ; /* <STX>JYYMMDD HHMMSSS<ETX> */
break ;
+ case 3 :
+ up->unittype = UNITTYPE_ECHOKEISOKUKI_LT2000 ;
+ up->operationmode = 2 ; /* Mode 2 : Continuous mode */
+ up->lineexpect = 1 ;
+ switch ( up->operationmode ) {
+ case 1 :
+ up->charexpect[0] = 15 ; /* YYMMDDWHHMMSS<BCC1><BCC2><CR> */
+ break ;
+ case 2 :
+ up->charexpect[0] = 17 ; /* YYMMDDWHHMMSS<ST1><ST2><ST3><ST4><CR> */
+ break ;
+ }
+ break ;
default :
msyslog ( LOG_ERR, "JJY receiver [ %s mode %d ] : Unsupported mode",
ntoa(&peer->srcadr), peer->ttl ) ;
@@ -384,6 +430,10 @@ jjy_receive ( struct recvbuf *rbufp )
rc = jjy_receive_cdex_jst2000 ( rbufp ) ;
break ;
+ case UNITTYPE_ECHOKEISOKUKI_LT2000 :
+ rc = jjy_receive_echokeisokuki_lt2000 ( rbufp ) ;
+ break ;
+
default :
rc = 0 ;
break ;
@@ -438,10 +488,10 @@ jjy_receive ( struct recvbuf *rbufp )
}
#ifdef DEBUG
if ( debug ) {
- printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d JST ",
- up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
- printf ( "( %04d/%03d %02d:%02d:%02d UTC )\n",
- pp->year, pp->day, pp->hour, pp->minute, pp->second ) ;
+ printf ( "jjy_receive (refclock_jjy.c) : %04d/%02d/%02d %02d:%02d:%02d.%1d JST ",
+ up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
+ printf ( "( %04d/%03d %02d:%02d:%02d.%1d UTC )\n",
+ pp->year, pp->day, pp->hour, pp->minute, pp->second, (int)(pp->nsec/100000000) ) ;
}
#endif
@@ -449,19 +499,19 @@ jjy_receive ( struct recvbuf *rbufp )
* Process the new sample in the median filter and determine the
* timecode timestamp.
*/
+
+ sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d.%1d JST",
+ up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond/100 ) ;
+ record_clock_stats ( &peer->srcadr, sLogText ) ;
+
if ( ! refclock_process ( pp ) ) {
refclock_report(peer, CEVNT_BADTIME);
- sprintf ( sLogText, "BAD TIME %04d/%02d/%02d %02d:%02d:%02d JST",
- up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
- record_clock_stats ( &peer->srcadr, sLogText ) ;
return ;
}
- sprintf ( sLogText, "%04d/%02d/%02d %02d:%02d:%02d JST",
- up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
pp->lastref = pp->lastrec;
refclock_receive(peer);
- record_clock_stats ( &peer->srcadr, sLogText ) ;
+
}
/**************************************************************************************************/
@@ -470,6 +520,8 @@ static int
jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
{
+ static char *sFunctionName = "jjy_receive_tristate_jjy01" ;
+
struct jjyunit *up ;
struct refclockproc *pp ;
struct peer *peer;
@@ -495,27 +547,82 @@ jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
switch ( up->linecount ) {
- case 1 : /* YYYY/MM/DD */
+ case 1 : /* YYYY/MM/DD WWW */
- if ( iLen < 10 ) {
+ if ( iLen != 14 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
+ }
+#endif
up->lineerror = 1 ;
break ;
}
rc = sscanf ( pBuf, "%4d/%2d/%2d", &up->year, &up->month, &up->day ) ;
if ( rc != 3 || up->year < 2000 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Date error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
+ }
+#endif
up->lineerror = 1 ;
break ;
}
+
+ /*** Start of modification on 2004/10/31 */
+ /*
+ * Following codes are moved from the function jjy_poll_tristate_jjy01 in this source.
+ * The Tristate JJY-01 ( Firmware version 1.01 ) accepts "time" and "stim" commands without any delay.
+ * But the JJY-01 ( Firmware version 2.01 ) does not accept these commands continuously,
+ * so this driver issues the second command "stim" after the reply of the first command "date".
+ */
+
+ /*
+ * Send "stim<CR><LF>" or "time<CR><LF>" command
+ */
+
+
+ if ( up->version >= 100 ) {
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "%s (refclock_jjy.c) : send 'stim<CR><LF>'\n", sFunctionName ) ;
+ }
+#endif
+ if ( write ( pp->io.fd, "stim\r\n",6 ) != 6 ) {
+ refclock_report ( peer, CEVNT_FAULT ) ;
+ }
+ } else {
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "%s (refclock_jjy.c) : send 'time<CR><LF>'\n", sFunctionName ) ;
+ }
+#endif
+ if ( write ( pp->io.fd, "time\r\n",6 ) != 6 ) {
+ refclock_report ( peer, CEVNT_FAULT ) ;
+ }
+ }
+ /*** End of modification ***/
+
return 0 ;
case 2 : /* HH:MM:SS */
- if ( iLen < 8 ) {
+ if ( iLen != 8 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Reply length error ( up->linecount=%d iLen=%d )\n", sFunctionName, up->linecount, iLen ) ;
+ }
+#endif
up->lineerror = 1 ;
break ;
}
rc = sscanf ( pBuf, "%2d:%2d:%2d", &up->hour, &up->minute, &up->second ) ;
if ( rc != 3 || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Time error ( up->linecount=%d )\n", sFunctionName, up->linecount ) ;
+ }
+#endif
up->lineerror = 1 ;
break ;
}
@@ -524,7 +631,7 @@ jjy_receive_tristate_jjy01 ( struct recvbuf *rbufp )
/*
* The command "date" and "time" ( or "stim" ) were sent to the JJY receiver continuously.
* But the JJY receiver replies a date and time separately.
- * Just after midnight transtions, we ignore this time.
+ * Just after midnight transitions, we ignore this time.
*/
return 0 ;
}
@@ -547,6 +654,8 @@ static int
jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
{
+ static char *sFunctionName = "jjy_receive_cdex_jst2000" ;
+
struct jjyunit *up ;
struct refclockproc *pp ;
struct peer *peer;
@@ -574,7 +683,12 @@ jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
case 1 : /* JYYMMDD HHMMSSS */
- if ( iLen < 15 ) {
+ if ( iLen != 15 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
+ }
+#endif
up->lineerror = 1 ;
break ;
}
@@ -582,6 +696,12 @@ jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
&up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second, &up->msecond ) ;
if ( rc != 7 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
|| up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d.%1d ]\n", sFunctionName,
+ rc, up->year, up->month, up->day, up->hour, up->minute, up->second, up->msecond ) ;
+ }
+#endif
up->lineerror = 1 ;
break ;
}
@@ -601,6 +721,151 @@ jjy_receive_cdex_jst2000 ( struct recvbuf *rbufp )
}
/**************************************************************************************************/
+
+static int
+jjy_receive_echokeisokuki_lt2000 ( struct recvbuf *rbufp )
+{
+
+ static char *sFunctionName = "jjy_receive_echokeisokuki_lt2000" ;
+
+ struct jjyunit *up ;
+ struct refclockproc *pp ;
+ struct peer *peer;
+
+ char *pBuf ;
+ int iLen ;
+ int rc ;
+ int i, ibcc, ibcc1, ibcc2 ;
+
+ /*
+ * Initialize pointers and read the timecode and timestamp
+ */
+ peer = (struct peer *) rbufp->recv_srcclock ;
+ pp = peer->procptr ;
+ up = (struct jjyunit *) pp->unitptr ;
+
+ if ( up->linediscipline == LDISC_RAW ) {
+ pBuf = up->rawbuf ;
+ iLen = up->charcount ;
+ } else {
+ pBuf = pp->a_lastcode ;
+ iLen = pp->lencode ;
+ }
+
+ switch ( up->linecount ) {
+
+ case 1 : /* YYMMDDWHHMMSS<BCC1><BCC2> or YYMMDDWHHMMSS<ST1><ST2><ST3><ST4> */
+
+ if ( ( up->operationmode == 1 && iLen != 15 ) || ( up->operationmode == 2 && iLen != 17 ) ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Reply length error ( iLen=%d )\n", sFunctionName, iLen ) ;
+ }
+#endif
+ if ( up->operationmode == 1 ) {
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
+ }
+#endif
+ if ( write ( pp->io.fd, "#",1 ) != 1 ) {
+ refclock_report ( peer, CEVNT_FAULT ) ;
+ }
+ }
+ up->lineerror = 1 ;
+ break ;
+ }
+
+ if ( up->operationmode == 1 ) {
+
+ for ( i = ibcc = 0 ; i < 13 ; i ++ ) ibcc ^= pBuf[i] ;
+ ibcc1 = 0x30 | ( ( ibcc >> 4 ) & 0xF ) ;
+ ibcc2 = 0x30 | ( ( ibcc ) & 0xF ) ;
+ if ( pBuf[13] != ibcc1 || pBuf[14] != ibcc2 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : BCC error ( Recv=%02X,%02X / Calc=%02X,%02X)\n", sFunctionName, pBuf[13]&0xFF, pBuf[14]&0xFF, ibcc1, ibcc2 ) ;
+ }
+#endif
+ up->lineerror = 1 ;
+ break ;
+ }
+
+ }
+
+ rc = sscanf ( pBuf, "%2d%2d%2d%*1d%2d%2d%2d",
+ &up->year, &up->month, &up->day, &up->hour, &up->minute, &up->second ) ;
+ if ( rc != 6 || up->month < 1 || up->month > 12 || up->day < 1 || up->day > 31
+ || up->hour > 23 || up->minute > 59 || up->second > 60 ) {
+#ifdef DEBUG
+ if ( debug >= 2 ) {
+ printf ( "%s (refclock_jjy.c) : Time error (rc=%d) [ %02d %02d %02d * %02d %02d %02d ]\n", sFunctionName,
+ rc, up->year, up->month, up->day, up->hour, up->minute, up->second ) ;
+ }
+#endif
+ up->lineerror = 1 ;
+ break ;
+ }
+
+ up->year += 2000 ;
+
+ if ( up->operationmode == 2 ) {
+
+ /* A time stamp comes on every 0.5 seccond in the mode 2 of the LT-2000. */
+ up->msecond = 500 ;
+ pp->second -- ;
+ if ( pp->second < 0 ) {
+ pp->second = 59 ;
+ pp->minute -- ;
+ if ( pp->minute < 0 ) {
+ pp->minute = 59 ;
+ pp->hour -- ;
+ if ( pp->hour < 0 ) {
+ pp->hour = 23 ;
+ pp->day -- ;
+ if ( pp->day < 1 ) {
+ pp->year -- ;
+ pp->day = ymd2yd ( pp->year, 12, 31 ) ;
+ }
+ }
+ }
+ }
+
+ /* Switch from mode 2 to mode 1 in order to restraint of useless time stamp. */
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
+ }
+#endif
+ if ( write ( pp->io.fd, "#",1 ) != 1 ) {
+ refclock_report ( peer, CEVNT_FAULT ) ;
+ }
+
+ }
+
+ break ;
+
+ default : /* Unexpected reply */
+
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "%s (refclock_jjy.c) : send '#'\n", sFunctionName ) ;
+ }
+#endif
+ if ( write ( pp->io.fd, "#",1 ) != 1 ) {
+ refclock_report ( peer, CEVNT_FAULT ) ;
+ }
+
+ up->lineerror = 1 ;
+ break ;
+
+ }
+
+ return 1 ;
+
+}
+
+/**************************************************************************************************/
/* jjy_poll - called by the transmit procedure */
/**************************************************************************************************/
static void
@@ -642,6 +907,10 @@ jjy_poll ( int unit, struct peer *peer )
jjy_poll_cdex_jst2000 ( unit, peer ) ;
break ;
+ case UNITTYPE_ECHOKEISOKUKI_LT2000 :
+ jjy_poll_echokeisokuki_lt2000 ( unit, peer ) ;
+ break ;
+
default :
break ;
@@ -655,32 +924,48 @@ static void
jjy_poll_tristate_jjy01 ( int unit, struct peer *peer )
{
- struct jjyunit *up;
struct refclockproc *pp;
pp = peer->procptr;
- up = (struct jjyunit *) pp->unitptr ;
/*
* Send "date<CR><LF>" command
*/
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "jjy_poll_tristate_jjy01 (refclock_jjy.c) : send 'date<CR><LF>'\n" ) ;
+ }
+#endif
+
if ( write ( pp->io.fd, "date\r\n",6 ) != 6 ) {
refclock_report ( peer, CEVNT_FAULT ) ;
}
+}
+
+/**************************************************************************************************/
+
+static void
+jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
+{
+
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+
/*
- * Send "stim<CR><LF>" or "time<CR><LF>" command
+ * Send "<ENQ>1J<ETX>" command
*/
- if ( up->version >= 100 ) {
- if ( write ( pp->io.fd, "stim\r\n",6 ) != 6 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
- } else {
- if ( write ( pp->io.fd, "time\r\n",6 ) != 6 ) {
- refclock_report ( peer, CEVNT_FAULT ) ;
- }
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "jjy_poll_cdex_jst2000 (refclock_jjy.c) : send '<ENQ>1J<ETX>'\n" ) ;
+ }
+#endif
+
+ if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4 ) {
+ refclock_report ( peer, CEVNT_FAULT ) ;
}
}
@@ -688,18 +973,34 @@ jjy_poll_tristate_jjy01 ( int unit, struct peer *peer )
/**************************************************************************************************/
static void
-jjy_poll_cdex_jst2000 ( int unit, struct peer *peer )
+jjy_poll_echokeisokuki_lt2000 ( int unit, struct peer *peer )
{
+ struct jjyunit *up;
struct refclockproc *pp;
+ char sCmd[2] ;
+
pp = peer->procptr;
+ up = (struct jjyunit *) pp->unitptr ;
/*
- * Send "<ENQ>1J<ETX>" command
+ * Send "T" or "C" command
*/
- if ( write ( pp->io.fd, "\0051J\003", 4 ) != 4 ) {
+ switch ( up->operationmode ) {
+ case 1 : sCmd[0] = 'T' ; break ;
+ case 2 : sCmd[0] = 'C' ; break ;
+ }
+ sCmd[1] = 0 ;
+
+#ifdef DEBUG
+ if ( debug ) {
+ printf ( "jjy_poll_echokeisokuki_lt2000 (refclock_jjy.c) : send '%s'\n", sCmd ) ;
+ }
+#endif
+
+ if ( write ( pp->io.fd, sCmd, 1 ) != 1 ) {
refclock_report ( peer, CEVNT_FAULT ) ;
}
diff --git a/contrib/ntp/ntpd/refclock_jupiter.c b/contrib/ntp/ntpd/refclock_jupiter.c
index eff088b..c10d9fa 100644
--- a/contrib/ntp/ntpd/refclock_jupiter.c
+++ b/contrib/ntp/ntpd/refclock_jupiter.c
@@ -49,13 +49,7 @@
#include "jupiter.h"
#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
+# include "ppsapi_timepps.h"
#endif
#ifdef XNTP_BIG_ENDIAN
@@ -121,6 +115,7 @@ struct instance {
pps_info_t pps_info; /* last pps data */
pps_handle_t pps_handle; /* pps handle */
u_int assert; /* pps edge to use */
+ u_int hardpps; /* enable kernel mode */
struct timespec ts; /* last timestamp */
#endif
l_fp limit;
@@ -152,7 +147,7 @@ static void jupiter_poll P((int, struct peer *));
static void jupiter_control P((int, struct refclockstat *, struct
refclockstat *, struct peer *));
#ifdef HAVE_PPSAPI
-static int jupiter_ppsapi P((struct instance *, int, int));
+static int jupiter_ppsapi P((struct instance *));
static int jupiter_pps P((struct instance *));
#endif /* HAVE_PPSAPI */
static int jupiter_recv P((struct instance *));
@@ -229,6 +224,8 @@ jupiter_start(
memcpy((char *)&pp->refid, REFID, 4);
#ifdef HAVE_PPSAPI
+ instance->assert = 1;
+ instance->hardpps = 0;
/*
* Start the PPSAPI interface if it is there. Default to use
* the assert edge and do not enable the kernel hardpps.
@@ -238,7 +235,7 @@ jupiter_start(
msyslog(LOG_ERR,
"refclock_jupiter: time_pps_create failed: %m");
}
- else if (!jupiter_ppsapi(instance, 0, 0))
+ else if (!jupiter_ppsapi(instance))
goto clean_up;
#endif /* HAVE_PPSAPI */
@@ -265,7 +262,7 @@ jupiter_shutdown(int unit, struct peer *peer)
pp = peer->procptr;
instance = (struct instance *)pp->unitptr;
- if(!instance)
+ if (!instance)
return;
#ifdef HAVE_PPSAPI
@@ -336,9 +333,7 @@ jupiter_config(struct instance *instance)
*/
int
jupiter_ppsapi(
- struct instance *instance, /* unit structure pointer */
- int enb_clear, /* clear enable */
- int enb_hardpps /* hardpps enable */
+ struct instance *instance /* unit structure pointer */
)
{
int capability;
@@ -349,14 +344,14 @@ jupiter_ppsapi(
return (0);
}
memset(&instance->pps_params, 0, sizeof(pps_params_t));
- if (enb_clear)
+ if (!instance->assert)
instance->pps_params.mode = capability & PPS_CAPTURECLEAR;
else
instance->pps_params.mode = capability & PPS_CAPTUREASSERT;
if (!(instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
msyslog(LOG_ERR,
"refclock_jupiter: invalid capture edge %d",
- !enb_clear);
+ instance->assert);
return (0);
}
instance->pps_params.mode |= PPS_TSFMT_TSPEC;
@@ -365,9 +360,9 @@ jupiter_ppsapi(
"refclock_jupiter: time_pps_setparams failed: %m");
return (0);
}
- if (enb_hardpps) {
+ if (instance->hardpps) {
if (time_pps_kcbind(instance->pps_handle, PPS_KC_HARDPPS,
- instance->pps_params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR),
+ instance->pps_params.mode & ~PPS_TSFMT_TSPEC,
PPS_TSFMT_TSPEC) < 0) {
msyslog(LOG_ERR,
"refclock_jupiter: time_pps_kcbind failed: %m");
@@ -383,7 +378,7 @@ jupiter_ppsapi(
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);
+ instance->pps_params.mode, instance->hardpps);
}
#endif
@@ -503,7 +498,7 @@ jupiter_control(
#ifdef HAVE_PPSAPI
instance->assert = !(pp->sloppyclockflag & CLK_FLAG3);
- jupiter_ppsapi(instance, !instance->assert, 0);
+ jupiter_ppsapi(instance);
#endif /* HAVE_PPSAPI */
sloppyclockflag = instance->sloppyclockflag;
@@ -688,7 +683,7 @@ jupiter_receive(struct recvbuf *rbufp)
"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",
+ "jupiter_receive: %s chan ver %s, %s (%s)",
ip->chans, ip->vers, ip->date, ip->opts);
if (instance->wantid)
instance->wantid = 0;
@@ -907,12 +902,14 @@ jupiter_debug(peer, function, fmt, va_alist)
*/
vsnprintf(buffer, sizeof(buffer), fmt, ap);
record_clock_stats(&(peer->srcadr), buffer);
+#ifdef DEBUG
if (debug) {
fprintf(stdout, "%s: ", function);
fprintf(stdout, buffer);
fprintf(stdout, "\n");
fflush(stdout);
}
+#endif
va_end(ap);
}
@@ -953,8 +950,8 @@ static struct {
} reqmsg = {
{ putshort(JUPITER_SYNC), 0,
putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
- 0, (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
- JUPITER_FLAG_CONN | JUPITER_FLAG_LOG), 0 },
+ 0, JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
+ JUPITER_FLAG_CONN | JUPITER_FLAG_LOG, 0 },
{ 0, 0, 0, 0 }
};
@@ -979,7 +976,7 @@ jupiter_reqmsg(struct instance *instance, u_int id,
/* Cancel periodic message output */
static struct jheader canmsg = {
putshort(JUPITER_SYNC), 0, 0, 0,
- (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC),
+ JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC,
0
};
@@ -998,7 +995,7 @@ jupiter_canmsg(struct instance *instance, u_int id)
/* Request a single message output */
static struct jheader reqonemsg = {
putshort(JUPITER_SYNC), 0, 0, 0,
- (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY),
+ JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY,
0
};
@@ -1021,7 +1018,7 @@ static struct {
} platmsg = {
{ putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
- (u_char)putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK), 0 },
+ JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK, 0 },
{ 0, 0, 0 }
};
diff --git a/contrib/ntp/ntpd/refclock_leitch.c b/contrib/ntp/ntpd/refclock_leitch.c
index d7cd9bb..e1ba0c4 100644
--- a/contrib/ntp/ntpd/refclock_leitch.c
+++ b/contrib/ntp/ntpd/refclock_leitch.c
@@ -48,14 +48,20 @@
#define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver"
#define LEITCH232 "/dev/leitch%d" /* name of radio device */
#define SPEED232 B300 /* uart speed (300 baud) */
+#ifdef DEBUG
#define leitch_send(A,M) \
if (debug) fprintf(stderr,"write leitch %s\n",M); \
if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
- if (debug) \
- fprintf(stderr, "leitch_send: unit %d send failed\n", A->unit); \
- else \
- msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
-
+ if (debug) \
+ fprintf(stderr, "leitch_send: unit %d send failed\n", A->unit); \
+ else \
+ msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
+#else
+#define leitch_send(A,M) \
+if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
+ msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
+#endif
+
#define STATE_IDLE 0
#define STATE_DATE 1
#define STATE_TIME1 2
@@ -166,7 +172,7 @@ leitch_poll(
if (debug)
fprintf(stderr, "leitch_poll()\n");
#endif
- if (unit > MAXUNITS) {
+ if (unit >= MAXUNITS) {
/* XXXX syslog it */
return;
}
diff --git a/contrib/ntp/ntpd/refclock_local.c b/contrib/ntp/ntpd/refclock_local.c
index 3478f43..dc6f1ae 100644
--- a/contrib/ntp/ntpd/refclock_local.c
+++ b/contrib/ntp/ntpd/refclock_local.c
@@ -72,7 +72,7 @@
*
* 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.
+ * ID is 127.0.0.1 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
@@ -93,13 +93,7 @@
* Local interface definitions
*/
#define PRECISION (-7) /* about 10 ms precision */
-#if defined(VMS) && defined(VMS_LOCALUNIT)
-#define REFID "LCLv" /* reference ID */
-#else /* VMS VMS_LOCALUNIT */
-#define REFID "LCL\0" /* reference ID */
-#endif /* VMS VMS_LOCALUNIT */
#define DESCRIPTION "Undisciplined local clock" /* WRU */
-
#define STRATUM 5 /* default stratum */
#define DISPERSION .01 /* default dispersion (10 ms) */
@@ -168,7 +162,7 @@ local_start(
peer->stratum = STRATUM;
pp->stratum = STRATUM;
pp->clockdesc = DESCRIPTION;
- memcpy(&pp->refid, "INIT", 4);
+ memcpy(&pp->refid, "LOCL", 4);
poll_time = current_time;
return (1);
}
diff --git a/contrib/ntp/ntpd/refclock_msfees.c b/contrib/ntp/ntpd/refclock_msfees.c
index ebfb983..98034b5 100644
--- a/contrib/ntp/ntpd/refclock_msfees.c
+++ b/contrib/ntp/ntpd/refclock_msfees.c
@@ -40,12 +40,13 @@
#include "ntp_stdlib.h"
+int dbg = 0;
/*
fudgefactor = fudgetime1;
os_delay = fudgetime2;
offset_fudge = os_delay + fudgefactor + inherent_delay;
stratumtouse = fudgeval1 & 0xf
- debug = fudgeval2;
+ dbg = fudgeval2;
sloppyclockflag = flags & CLK_FLAG1;
1 log smoothing summary when processing sample
4 dump the buffer from the clock
@@ -675,7 +676,7 @@ ees_receive(
ees = (struct eesunit *)rbufp->recv_srcclock;
dpt = (u_char *)&rbufp->recv_space;
dpend = dpt + rbufp->recv_length;
- if ((debug & DB_LOG_AWAITMORE) && (rbufp->recv_length != LENEESCODE))
+ if ((dbg & DB_LOG_AWAITMORE) && (rbufp->recv_length != LENEESCODE))
printf("[%d] ", rbufp->recv_length);
/* Check out our state and process appropriately */
@@ -718,7 +719,7 @@ ees_receive(
/* Gave up because it was end of the buffer, rather than ff */
if (dpt == dpend) {
/* Incomplete. Wait for more. */
- if (debug & DB_LOG_AWAITMORE)
+ if (dbg & DB_LOG_AWAITMORE)
msyslog(LOG_INFO,
"I: ees clock %d: %p == %p: await more",
ees->unit, dpt, dpend);
@@ -897,7 +898,7 @@ ees_receive(
memset((char *) &ppsclockev, 0, sizeof ppsclockev);
rc = ioctl(ees->io.fd, request, (char *) &ppsclockev);
- if (debug & DB_PRINT_EV) fprintf(stderr,
+ if (dbg & DB_PRINT_EV) fprintf(stderr,
"[%x] CIOGETEV u%d %d (%x %d) gave %d (%d): %08lx %08lx %ld\n",
DB_PRINT_EV, ees->unit, ees->io.fd, request, is_pps(ees),
rc, errno, ptr[0], ptr[1], ptr[2]);
@@ -925,7 +926,7 @@ ees_receive(
diff = pps_arrvstamp;
conv = 0;
L_SUB(&diff, &ees->arrvtime);
- if (debug & DB_PRINT_CDT)
+ if (dbg & DB_PRINT_CDT)
printf("[%x] Have %lx.%08lx and %lx.%08lx -> %lx.%08lx @ %s",
DB_PRINT_CDT, (long)ees->arrvtime.l_ui, (long)ees->arrvtime.l_uf,
(long)pps_arrvstamp.l_ui, (long)pps_arrvstamp.l_uf,
@@ -962,7 +963,7 @@ ees_receive(
}
}
ees->last_pps_no = ppsclockev.serial;
- if (debug & DB_PRINT_CDTC)
+ if (dbg & DB_PRINT_CDTC)
printf(
"[%x] %08lx %08lx %d u%d (%d %d)\n",
DB_PRINT_CDTC, (long)pps_arrvstamp.l_ui,
@@ -985,7 +986,7 @@ ees_receive(
if (delta_f_abs < 0) delta_f_abs = -delta_f_abs;
/* Dump the deltas each minute */
- if (debug & DB_DUMP_DELTAS)
+ if (dbg & DB_DUMP_DELTAS)
{ if (/*0 <= ees->second && */
ees->second < ((sizeof deltas) / (sizeof deltas[0]))) deltas[ees->second] = delta_sfsec;
/* Dump on second 1, as second 0 sometimes missed */
@@ -1147,12 +1148,12 @@ ees_receive(
/* sec_of_ramp * ees->jump_fsecs may overflow 2**32 */
fsecs = sec_of_ramp * (ees->jump_fsecs / ees->last_step_secs);
- if (debug & DB_LOG_DELTAS) msyslog(LOG_ERR,
+ if (dbg & DB_LOG_DELTAS) msyslog(LOG_ERR,
"[%x] MSF%d: %3ld/%03d -> d=%11ld (%d|%ld)",
DB_LOG_DELTAS,
ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
- if (debug & DB_PRINT_DELTAS) printf(
+ if (dbg & DB_PRINT_DELTAS) printf(
"MSF%d: %3ld/%03d -> d=%11ld (%ld|%ld)\n",
ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
(long)pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
@@ -1160,7 +1161,7 @@ ees_receive(
/* Must sign extend the result */
inc.l_i = (fsecs < 0) ? -1 : 0;
inc.l_f = fsecs;
- if (debug & DB_INC_PPS)
+ if (dbg & DB_INC_PPS)
{ L_SUB(&pps_arrvstamp, &inc);
L_SUB(&ees->arrvtime, &inc);
}
@@ -1170,14 +1171,14 @@ ees_receive(
}
}
else {
- if (debug & DB_LOG_DELTAS) msyslog(LOG_ERR,
+ if (dbg & DB_LOG_DELTAS) msyslog(LOG_ERR,
"[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x",
DB_LOG_DELTAS,
ees->unit, ees->using_ramp,
sincelast,
(ees->last_step_secs)*2,
ees->last_step_secs);
- if (debug & DB_PRINT_DELTAS) printf(
+ if (dbg & DB_PRINT_DELTAS) printf(
"[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x\n",
DB_LOG_DELTAS,
ees->unit, ees->using_ramp,
@@ -1189,7 +1190,7 @@ ees_receive(
L_SUB(&ees->arrvtime, &offset_fudge[ees->unit]);
L_SUB(&pps_arrvstamp, &offset_fudge[ees->unit]);
- if (call_pps_sample && !(debug & DB_NO_PPS)) {
+ if (call_pps_sample && !(dbg & DB_NO_PPS)) {
/* Sigh -- it expects its args negated */
L_NEG(&pps_arrvstamp);
/*
@@ -1202,14 +1203,14 @@ ees_receive(
/* Subtract off the local clock time stamp */
L_SUB(&ees->codeoffsets[n_sample], &ees->arrvtime);
- if (debug & DB_LOG_SAMPLES) msyslog(LOG_ERR,
+ if (dbg & DB_LOG_SAMPLES) msyslog(LOG_ERR,
"MSF%d: [%x] %d (ees: %d %d) (pps: %d %d)%s",
ees->unit, DB_LOG_DELTAS, n_sample,
ees->codeoffsets[n_sample].l_f,
ees->codeoffsets[n_sample].l_f / 4295,
pps_arrvstamp.l_f,
pps_arrvstamp.l_f /4295,
- (debug & DB_NO_PPS) ? " [no PPS]" : "");
+ (dbg & DB_NO_PPS) ? " [no PPS]" : "");
if (ees->nsamples++ == NCODES-1) ees_process(ees);
@@ -1284,7 +1285,13 @@ ees_process(
if (ees->dump_vals) dump_buf(coffs, 0, samples, "Raw data is:");
/* Sort the offsets, trim off the extremes, then choose one. */
- qsort((char *) coffs, (size_t)samples, sizeof(l_fp), offcompare);
+ qsort(
+#ifdef QSORT_USES_VOID_P
+ (void *)
+#else
+ (char *)
+#endif
+ coffs, (size_t)samples, sizeof(l_fp), offcompare);
noff = samples;
i = 0;
@@ -1328,10 +1335,10 @@ ees_process(
L_SUB(&tmp, &coffs[i]);
#define FRACT_SEC(n) ((1 << 30) / (n/2))
dispersion = LFPTOFP(&tmp) / 2; /* ++++ */
- if (debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE)) msyslog(
- (debug & DB_SYSLOG_SMPLE) ? LOG_ERR : LOG_INFO,
+ if (dbg & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE)) msyslog(
+ (dbg & DB_SYSLOG_SMPLE) ? LOG_ERR : LOG_INFO,
"I: [%x] Offset=%06d (%d), disp=%f%s [%d], %d %d=%d %d:%d %d=%d %d",
- debug & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE),
+ dbg & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE),
offset.l_f / 4295, offset.l_f,
(dispersion * 1526) / 100,
(sloppyclockflag[ees->unit]) ? " by averaging" : "",
@@ -1371,24 +1378,24 @@ ees_process(
offset.l_ui += (new < 0) ? -1 : 1;
}
dispersion /= 4;
- if (debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE)) msyslog(
- (debug & DB_SYSLOG_SMTHE) ? LOG_ERR : LOG_INFO,
+ if (dbg & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE)) msyslog(
+ (dbg & DB_SYSLOG_SMTHE) ? LOG_ERR : LOG_INFO,
"I: [%x] Smooth data: %ld -> %ld, dispersion now %f",
- debug & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE),
+ dbg & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE),
((long) offset.l_uf) / 4295, new / 4295,
(dispersion * 1526) / 100);
offset.l_uf = (unsigned long) new;
}
- else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog(
- (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
+ else if (dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog(
+ (dbg & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
"[%x] No smooth as delta not %d < %ld < %d",
- debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
+ dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
- FRACT_SEC(100), diff, FRACT_SEC(100));
}
- else if (debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog(
- (debug & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
+ else if (dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog(
+ (dbg & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
"I: [%x] No smooth as flag=%x and old=%x=%d (%d:%d)",
- debug & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
+ dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
ees->usealldata, ees->offset.l_f, ees->offset.l_uf,
offset.l_f, ees->offset.l_f - offset.l_f);
diff --git a/contrib/ntp/ntpd/refclock_mx4200.c b/contrib/ntp/ntpd/refclock_mx4200.c
index bc694ad..68150b7 100644
--- a/contrib/ntp/ntpd/refclock_mx4200.c
+++ b/contrib/ntp/ntpd/refclock_mx4200.c
@@ -80,13 +80,9 @@ struct ppsclockev {
};
#endif /* ! HAVE_STRUCT_PPSCLOCKEV */
-#ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-#else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-#endif
+#ifdef HAVE_PPSAPI
+# include "ppsapi_timepps.h"
+#endif /* HAVE_PPSAPI */
/*
* This driver supports the Magnavox Model MX 4200 GPS Receiver
@@ -1524,15 +1520,15 @@ mx4200_pps(
if (time_pps_fetch(up->pps_h, PPS_TSFMT_TSPEC, &(up->pps_i),
&timeout) < 0) {
mx4200_debug(peer,
- "mx4200_pps: time_pps_fetch: serial=%d, %s\n",
- up->pps_i.assert_sequence, strerror(errno));
+ "mx4200_pps: time_pps_fetch: serial=%ul, %s\n",
+ (unsigned long)up->pps_i.assert_sequence, strerror(errno));
refclock_report(peer, CEVNT_FAULT);
return(1);
}
if (temp_serial == up->pps_i.assert_sequence) {
mx4200_debug(peer,
- "mx4200_pps: assert_sequence serial not incrementing: %d\n",
- up->pps_i.assert_sequence);
+ "mx4200_pps: assert_sequence serial not incrementing: %ul\n",
+ (unsigned long)up->pps_i.assert_sequence);
refclock_report(peer, CEVNT_FAULT);
return(1);
}
@@ -1544,8 +1540,8 @@ mx4200_pps(
if (up->pps_i.assert_sequence == up->lastserial) {
mx4200_debug(peer, "mx4200_pps: no new pps event\n");
} else {
- mx4200_debug(peer, "mx4200_pps: missed %d pps events\n",
- up->pps_i.assert_sequence - up->lastserial - 1);
+ mx4200_debug(peer, "mx4200_pps: missed %ul pps events\n",
+ up->pps_i.assert_sequence - up->lastserial - 1UL);
}
refclock_report(peer, CEVNT_FAULT);
}
@@ -1576,6 +1572,7 @@ mx4200_debug(peer, fmt, va_alist)
char *fmt;
#endif /* __STDC__ */
{
+#ifdef DEBUG
va_list ap;
struct refclockproc *pp;
struct mx4200unit *up;
@@ -1600,6 +1597,7 @@ mx4200_debug(peer, fmt, va_alist)
va_end(ap);
}
+#endif
}
/*
diff --git a/contrib/ntp/ntpd/refclock_neoclock4x.c b/contrib/ntp/ntpd/refclock_neoclock4x.c
index 082b1cf..374c81a 100644
--- a/contrib/ntp/ntpd/refclock_neoclock4x.c
+++ b/contrib/ntp/ntpd/refclock_neoclock4x.c
@@ -3,12 +3,12 @@
* Refclock_neoclock4x.c
* - NeoClock4X driver for DCF77 or FIA Timecode
*
- * Date: 2003-07-07 v1.13
+ * Date: 2006-01-11 v1.15
*
* see http://www.linum.com/redir/jump/id=neoclock4x&action=redir
* for details about the NeoClock4X device
*
- * Copyright (C) 2002-2003 by Linum Software GmbH <neoclock4x@linum.com>
+ * Copyright (C) 2002-2004 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
@@ -39,9 +39,11 @@
#if defined HAVE_SYS_MODEM_H
# include <sys/modem.h>
-# define TIOCMSET MCSETA
-# define TIOCMGET MCGETA
-# define TIOCM_RTS MRTS
+# ifndef __QNXNTO__
+# define TIOCMSET MCSETA
+# define TIOCMGET MCGETA
+# define TIOCM_RTS MRTS
+# endif
#endif
#ifdef HAVE_TERMIOS_H
@@ -59,6 +61,17 @@
#endif
/*
+ * NTP version 4.20 change the pp->msec field to pp->nsec.
+ * To allow to support older ntp versions with this sourcefile
+ * you can define NTP_PRE_420 to allow this driver to compile
+ * with ntp version back to 4.1.2.
+ *
+ */
+#if 0
+#define NTP_PRE_420
+#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
@@ -74,6 +87,7 @@
#define NEOCLOCK4X_FIRMWARE NEOCLOCK4X_FIRMWARE_VERSION_A
#endif
+/* at this time only firmware version A is known */
#define NEOCLOCK4X_FIRMWARE_VERSION_A 'A'
#define NEOCLOCK4X_TIMECODELEN 37
@@ -95,7 +109,9 @@
#define NEOCLOCK4X_OFFSET_ANTENNA2 33
#define NEOCLOCK4X_OFFSET_CRC 35
-#define NEOCLOCK4X_DRIVER_VERSION "1.12 (2003-01-10)"
+#define NEOCLOCK4X_DRIVER_VERSION "1.15 (2006-01-11)"
+
+#define NSEC_TO_MILLI 1000000
struct neoclock4x_unit {
l_fp laststamp; /* last receive timestamp */
@@ -133,9 +149,6 @@ 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 *));
@@ -172,13 +185,37 @@ neoclock4x_start(int unit,
/* LDISC_STD, LDISC_RAW
* Open serial port. Use CLK line discipline, if available.
*/
- fd = refclock_open(dev, B2400, LDISC_CLK);
+ fd = refclock_open(dev, B2400, LDISC_STD);
if(fd <= 0)
{
return (0);
}
#if defined(HAVE_TERMIOS)
+
+#if 1
+ 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_iflag = IGNBRK | IGNPAR | ICRNL;
+ termsettings.c_oflag = 0;
+ termsettings.c_cflag = CS8 | CSTOPB | CLOCAL | CREAD;
+ (void)cfsetispeed(&termsettings, (u_int)B2400);
+ (void)cfsetospeed(&termsettings, (u_int)B2400);
+
+ 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);
+ }
+
+#else
if(tcgetattr(fd, &termsettings) < 0)
{
msyslog(LOG_CRIT, "NeoClock4X(%d): (tcgetattr) can't query serial port settings: %m", unit);
@@ -198,6 +235,8 @@ neoclock4x_start(int unit,
(void) close(fd);
return (0);
}
+#endif
+
#elif defined(HAVE_SYSV_TTYS)
if(ioctl(fd, TCGETA, &termsettings) < 0)
{
@@ -307,7 +346,7 @@ neoclock4x_start(int unit,
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",
+ msyslog(LOG_EMERG, "NeoClock4X(%d): unknown firmware defined at compile time for NeoClock4X",
unit);
(void) close(fd);
pp->io.fd = -1;
@@ -524,7 +563,11 @@ neoclock4x_receive(struct recvbuf *rbufp)
neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_MINUTE], &pp->minute, 2);
neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_SECOND], &pp->second, 2);
neol_atoi_len(&pp->a_lastcode[NEOCLOCK4X_OFFSET_HSEC], &dsec, 2);
- pp->nsec = dsec * 10000; /* convert 1/100s from neoclock to nanoseconds */
+#if defined(NTP_PRE_420)
+ pp->msec = dsec * 10; /* convert 1/100s from neoclock to real miliseconds */
+#else
+ pp->nsec = dsec * 10 * NSEC_TO_MILLI; /* convert 1/100s from neoclock to nanoseconds */
+#endif
memcpy(up->radiosignal, &pp->a_lastcode[NEOCLOCK4X_OFFSET_RADIOSIGNAL], 3);
up->radiosignal[3] = 0;
@@ -583,7 +626,13 @@ neoclock4x_receive(struct recvbuf *rbufp)
msyslog(LOG_DEBUG, "NeoClock4X(%d): calculated UTC date/time: %04d-%02d-%02d %02d:%02d:%02d.%03ld",
up->unit,
pp->year, month, day,
- pp->hour, pp->minute, pp->second, pp->nsec/1000);
+ pp->hour, pp->minute, pp->second,
+#if defined(NTP_PRE_420)
+ pp->msec
+#else
+ pp->nsec/NSEC_TO_MILLI
+#endif
+ );
}
up->utc_year = pp->year;
@@ -592,7 +641,11 @@ neoclock4x_receive(struct recvbuf *rbufp)
up->utc_hour = pp->hour;
up->utc_minute = pp->minute;
up->utc_second = pp->second;
- up->utc_msec = pp->nsec/1000;
+#if defined(NTP_PRE_420)
+ up->utc_msec = pp->msec;
+#else
+ up->utc_msec = pp->nsec/NSEC_TO_MILLI;
+#endif
if(!refclock_process(pp))
{
@@ -678,11 +731,9 @@ neoclock4x_control(int unit,
if(NULL != out)
{
- static char outstatus[800]; /* status output buffer */
char *tt;
char tmpbuf[80];
- outstatus[0] = '\0';
out->kv_list = (struct ctl_var *)0;
out->type = REFCLK_NEOCLOCK4X;
@@ -741,9 +792,9 @@ neol_hexatoi_len(const char str[],
int i;
int n = 0;
- for(i=0; isxdigit(str[i]) && i < maxlen; i++)
+ for(i=0; isxdigit((int)str[i]) && i < maxlen; i++)
{
- hexdigit = isdigit(str[i]) ? toupper(str[i]) - '0' : toupper(str[i]) - 'A' + 10;
+ hexdigit = isdigit((int)str[i]) ? toupper(str[i]) - '0' : toupper(str[i]) - 'A' + 10;
n = 16 * n + hexdigit;
}
*result = n;
@@ -759,7 +810,7 @@ neol_atoi_len(const char str[],
int i;
int n = 0;
- for(i=0; isdigit(str[i]) && i < maxlen; i++)
+ for(i=0; isdigit((int)str[i]) && i < maxlen; i++)
{
digit = str[i] - '0';
n = 10 * n + digit;
@@ -849,24 +900,6 @@ neol_jdn_to_ymd(unsigned long jdn,
*dd = (int)d;
}
-#if 0
-/*
- * delay in milliseconds
- */
-static void
-neol_mdelay(int milliseconds)
-{
- struct timeval tv;
-
- if(milliseconds)
- {
- tv.tv_sec = 0;
- tv.tv_usec = milliseconds * 1000;
- select(1, NULL, NULL, NULL, &tv);
- }
-}
-#endif
-
#if !defined(NEOCLOCK4X_FIRMWARE)
static int
neol_query_firmware(int fd,
@@ -1065,4 +1098,16 @@ int refclock_neoclock4x_bs;
* - fix reporting of clock status
* changes. previously a bad clock
* status was never reset.
+ *
+ * 2004/04/07 cjh
+ * Revision 1.14
+ * - open serial port in a way
+ * AIX and some other OS can
+ * handle much better
+ *
+ * 2006/01/11 cjh
+ * Revision 1.15
+ * - remove some unsued #ifdefs
+ * - fix nsec calculation, closes #499
+ *
*/
diff --git a/contrib/ntp/ntpd/refclock_nmea.c b/contrib/ntp/ntpd/refclock_nmea.c
index 28d6263..5b124cb 100644
--- a/contrib/ntp/ntpd/refclock_nmea.c
+++ b/contrib/ntp/ntpd/refclock_nmea.c
@@ -14,23 +14,17 @@
#if defined(REFCLOCK) && defined(CLOCK_NMEA)
+#include <stdio.h>
+#include <ctype.h>
+
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
-#include <stdio.h>
-#include <ctype.h>
-
#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
+# include "ppsapi_timepps.h"
#endif /* HAVE_PPSAPI */
/*
@@ -153,8 +147,53 @@ nmea_start(
(void)sprintf(device, DEVICE, unit);
fd = refclock_open(device, SPEED232, LDISC_CLK);
- if (fd < 0)
- return (0);
+ if (fd <= 0) {
+#ifdef HAVE_READLINK
+ /* nmead support added by Jon Miner (cp_n18@yahoo.com)
+ *
+ * See http://home.hiwaay.net/~taylorc/gps/nmea-server/
+ * for information about nmead
+ *
+ * To use this, you need to create a link from /dev/gpsX to
+ * the server:port where nmead is running. Something like this:
+ *
+ * ln -s server:port /dev/gps1
+ */
+ char buffer[80];
+ char *nmea_host;
+ int nmea_port;
+ int len;
+ struct hostent *he;
+ struct protoent *p;
+ struct sockaddr_in so_addr;
+
+ if ((len = readlink(device,buffer,sizeof(buffer))) == -1)
+ return(0);
+ buffer[len] = 0;
+
+ if ((nmea_host = strtok(buffer,":")) == NULL)
+ return(0);
+
+ nmea_port = atoi(strtok(NULL,":"));
+
+ if ((he = gethostbyname(nmea_host)) == NULL)
+ return(0);
+ if ((p = getprotobyname("ip")) == NULL)
+ return(0);
+ so_addr.sin_family = AF_INET;
+ so_addr.sin_port = htons(nmea_port);
+ so_addr.sin_addr = *((struct in_addr *) he->h_addr);
+
+ if ((fd = socket(PF_INET,SOCK_STREAM,p->p_proto)) == -1)
+ return(0);
+ if (connect(fd,(struct sockaddr *)&so_addr,SOCKLEN(&so_addr)) == -1) {
+ close(fd);
+ return (0);
+ }
+#else
+ return (0);
+#endif
+ }
/*
* Allocate and initialize unit structure
diff --git a/contrib/ntp/ntpd/refclock_oncore.c b/contrib/ntp/ntpd/refclock_oncore.c
index 14db92f..e1d23a9 100644
--- a/contrib/ntp/ntpd/refclock_oncore.c
+++ b/contrib/ntp/ntpd/refclock_oncore.c
@@ -40,6 +40,35 @@
* MANUFACTUR DATE 417AMA199 MANUFACTUR DATE 0C27
* OPTIONS LIST AB
*
+ * (M12+T) (M12+T later version)
+ * COPYRIGHT 1991-2002 MOTOROLA INC. COPYRIGHT 1991-2003 MOTOROLA INC.
+ * SFTW P/N # 61-G10268A SFTW P/N # 61-G10268A
+ * SOFTWARE VER # 2 SOFTWARE VER # 2
+ * SOFTWARE REV # 0 SOFTWARE REV # 1
+ * SOFTWARE DATE AUG 14 2002 SOFTWARE DATE APR 16 2003
+ * MODEL # P283T12T11 MODEL # P273T12T12
+ * HWDR P/N # 2 HWDR P/N # 2
+ * SERIAL # P04DC2 SERIAL # P05Z7Z
+ * MANUFACTUR DATE 2J17 MANUFACTUR DATE 3G15
+ *
+ * --------------------------------------------------------------------------
+ * Reg Clemens (Feb 2006)
+ * Fix some gcc4 compiler complaints
+ * Fix possible segfault in oncore_init_shmem
+ * change all (possible) fprintf(stderr, to record_clock_stats
+ * Apply patch from Russell J. Yount <rjy@cmu.edu> Fixed (new) MT12+T UTC not correct
+ * immediately after new Almanac Read.
+ * Apply patch for new PPS implementation by Rodolfo Giometti <giometti@linux.it>
+ * now code can use old Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de> or
+ * the new one. Compiles depending on timepps.h seen.
+ * --------------------------------------------------------------------------
+ * Luis Batanero Guerrero <luisba@rao.es> (Dec 2005) Patch for leap seconds
+ * (the oncore driver was setting the wrong ntpd variable)
+ * --------------------------------------------------------------------------
+ * Reg.Clemens (Mar 2004)
+ * Support for interfaces other than PPSAPI removed, for Solaris, SunOS,
+ * SCO, you now need to use one of the timepps.h files in the root dir.
+ * this driver will 'grab' it for you if you dont have one in /usr/include
* --------------------------------------------------------------------------
* This code uses the two devices
* /dev/oncore.serial.n
@@ -84,7 +113,7 @@
#include <config.h>
#endif
-#if defined(REFCLOCK) && defined(CLOCK_ONCORE) && defined(HAVE_PPSAPI)
+#if defined(REFCLOCK) && defined(CLOCK_ONCORE)
#include "ntpd.h"
#include "ntp_io.h"
@@ -100,43 +129,18 @@
# include <sys/mman.h>
# ifndef MAP_FAILED
# define MAP_FAILED ((u_char *) -1)
-# endif /* not MAP_FAILED */
+# endif /* MAP_FAILED */
# endif /* HAVE_SYS_MMAN_H */
#endif /* ONCORE_SHMEM_STATUS */
#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
+# include "ppsapi_timepps.h"
#endif
#ifdef HAVE_SYS_SIO_H
# include <sys/sio.h>
#endif
-#ifdef HAVE_SYS_TERMIOS_H
-# include <sys/termios.h>
-#endif
-
-#ifdef HAVE_SYS_PPSCLOCK_H
-# include <sys/ppsclock.h>
-#endif
-
-#ifndef HAVE_STRUCT_PPSCLOCKEV
-struct ppsclockev {
-# ifdef HAVE_STRUCT_TIMESPEC
- struct timespec tv;
-# else
- struct timeval tv;
-# endif
- u_int serial;
-};
-#endif /* not HAVE_STRUCT_PPSCLOCKEV */
-
enum receive_state {
ONCORE_NO_IDEA,
ONCORE_CHECK_ID,
@@ -216,10 +220,8 @@ struct instance {
int ttyfd; /* TTY file descriptor */
int ppsfd; /* PPS file descriptor */
int shmemfd; /* Status shm descriptor */
-#ifdef HAVE_PPSAPI
pps_handle_t pps_h;
pps_params_t pps_p;
-#endif
enum receive_state o_state; /* Receive state */
enum posn_mode mode; /* 0D, 2D, 3D */
enum site_survey_state site_survey; /* Site Survey state */
@@ -253,8 +255,7 @@ 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, M12+T, -1 unknown, 0 no, +1 yes */
-
+ s_char traim; /* do we have traim? yes UT/VP, M12+T, no BASIC, GT, M12, -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 */
@@ -262,6 +263,8 @@ struct instance {
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 count5; /* cycles thru get_timestamp waiting for valid UTC correction */
+ u_char count5_set; /* only set count5 once */
u_char pollcnt;
u_char timeout; /* count to retry Cj after Fa self-test */
@@ -285,7 +288,7 @@ struct instance {
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_in; /* TRAIM from INPUT, will always use ON/OFF specified */
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 */
@@ -297,7 +300,6 @@ struct instance {
#define rcvptr instance->Rcvptr
static int oncore_start P((int, struct peer *));
-static void oncore_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
static void oncore_poll P((int, struct peer *));
static void oncore_shutdown P((int, struct peer *));
static void oncore_consume P((struct instance *));
@@ -344,7 +346,6 @@ 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));
@@ -352,7 +353,7 @@ struct refclock refclock_oncore = {
oncore_start, /* start up driver */
oncore_shutdown, /* shut down driver */
oncore_poll, /* transmit poll message */
- oncore_control, /* fudge (flag) control messages */
+ noentry, /* not used */
noentry, /* not used */
noentry, /* not used */
NOFLAGS /* not used */
@@ -405,7 +406,7 @@ static struct msg_desc {
{ "Ga", 20, oncore_msg_Ga, "" },
{ "Gb", 17, oncore_msg_Gb, "" },
{ "Gc", 8, 0, "" },
- { "Gd", 8, oncore_msg_Gd, "" },
+ { "Gd", 8, 0, "" },
{ "Ge", 8, 0, "" },
{ "Gj", 21, oncore_msg_Gj, "" },
{ "Ia", 10, oncore_msg_CaFaIa, "" },
@@ -446,8 +447,8 @@ static u_char oncore_cmd_Bd[] = { 'B', 'd', 1 }; /* 6/8/12? Almanac Stat
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_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', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6 TRAIM setup/status: msg off, 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 */
@@ -456,8 +457,8 @@ static u_char oncore_cmd_Ea0[] = { 'E', 'a', 0 }; /* 8 Position/Data/Stat
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_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', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT TRAIM setup/status: msg off, 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 */
@@ -489,9 +490,8 @@ static u_char oncore_cmd_Ia[] = { 'I', 'a' }; /* 12 Self Test */
static char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly",
"Aug", "Sep", "Oct", "Nov", "Dec" };
-#define DEVICE1 "/dev/oncore.serial.%d" /* name of serial device */
-#define DEVICE2 "/dev/oncore.pps.%d" /* name of pps device */
-#define INIT_FILE "/etc/ntp.oncore" /* optional init file */
+#define DEVICE1 "/dev/oncore.serial.%d" /* name of serial device */
+#define DEVICE2 "/dev/oncore.pps.%d" /* name of pps device */
#define SPEED B9600 /* Oncore Binary speed (9600 bps) */
@@ -528,37 +528,14 @@ oncore_start(
struct peer *peer
)
{
+#define STRING_LEN 32
register struct instance *instance;
struct refclockproc *pp;
- int fd1, fd2;
- char device1[30], device2[30];
+ int fd1, fd2, num;
+ char device1[STRING_LEN], device2[STRING_LEN], Msg[160];
const char *cp;
struct stat stat1, stat2;
- /* OPEN DEVICES */
- /* opening different devices for fd1 and fd2 presents no problems */
- /* opening the SAME device twice, seems to be OS dependent.
- (a) on Linux (no streams) no problem
- (b) on SunOS (and possibly Solaris, untested), (streams)
- never see the line discipline.
- Since things ALWAYS work if we only open the device once, we check
- to see if the two devices are in fact the same, then proceed to
- do one open or two.
- */
-
- (void)sprintf(device1, DEVICE1, unit);
- (void)sprintf(device2, DEVICE2, unit);
-
- if (stat(device1, &stat1)) {
- perror("ONCORE: stat fd1");
- exit(1);
- }
-
- if (stat(device2, &stat2)) {
- perror("ONCORE: stat fd2");
- exit(1);
- }
-
/* create instance structure for this unit */
if (!(instance = (struct instance *) malloc(sizeof *instance))) {
@@ -567,28 +544,6 @@ oncore_start(
}
memset((char *) instance, 0, sizeof *instance);
- if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino)) {
- /* same device here */
- if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW
-#if !defined(HAVE_PPSAPI) && !defined(TIOCDCDTIMESTAMP)
- | LDISC_PPS
-#endif
- ))) {
- perror("ONCORE: fd1");
- exit(1);
- }
- fd2 = fd1;
- } else { /* different devices here */
- if (!(fd1=refclock_open(device1, SPEED, LDISC_RAW))) {
- perror("ONCORE: fd1");
- exit(1);
- }
- if ((fd2=open(device2, O_RDWR)) < 0) {
- perror("ONCORE: fd2");
- exit(1);
- }
- }
-
/* initialize miscellaneous variables */
pp = peer->procptr;
@@ -599,16 +554,6 @@ oncore_start(
instance->assert = 1;
instance->once = 1;
- cp = "ONCORE DRIVER -- CONFIGURING";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->o_state = ONCORE_NO_IDEA;
- cp = "state = ONCORE_NO_IDEA";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- instance->ttyfd = fd1;
- instance->ppsfd = fd2;
-
instance->Bj_day = -1;
instance->traim = -1;
instance->traim_in = -1;
@@ -625,37 +570,86 @@ 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 or /etc/ntp/oncore.X */
+ cp = "ONCORE DRIVER -- CONFIGURING";
+ record_clock_stats(&(instance->peer->srcadr), cp);
- oncore_read_config(instance);
+ instance->o_state = ONCORE_NO_IDEA;
+ cp = "state = ONCORE_NO_IDEA";
+ record_clock_stats(&(instance->peer->srcadr), cp);
-#ifdef HAVE_PPSAPI
- if (time_pps_create(fd2, &instance->pps_h) < 0) {
- perror("time_pps_create");
- return(0);
+ /* Now open files.
+ * This is a bit complicated, a we dont want to open the same file twice
+ * (its a problem on some OS), and device2 may not exist for the new PPS
+ */
+
+ (void)sprintf(device1, DEVICE1, unit);
+ (void)sprintf(device2, DEVICE2, unit);
+
+ /* OPEN DEVICES */
+ /* opening different devices for fd1 and fd2 presents no problems */
+ /* opening the SAME device twice, seems to be OS dependent.
+ (a) on Linux (no streams) no problem
+ (b) on SunOS (and possibly Solaris, untested), (streams)
+ never see the line discipline.
+ Since things ALWAYS work if we only open the device once, we check
+ to see if the two devices are in fact the same, then proceed to
+ do one open or two.
+ */
+
+ if (stat(device1, &stat1)) {
+ sprintf(Msg, "Can't stat fd1 (%s)\n", device1);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ exit(1);
}
- if (instance->assert)
- cp = "Initializing timing to Assert.";
- else
- cp = "Initializing timing to Clear.";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ if (stat(device2, &stat2)) {
+ sprintf(Msg, "Can't stat fd2 (%s)\n", device2);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ exit(1);
+ }
- if (instance->hardpps) {
- cp = "HARDPPS Set.";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ if (!(fd1 = refclock_open(device1, SPEED, LDISC_RAW))) {
+ sprintf(Msg, "Can't open fd1 (%s)\n", device1);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ exit(1);
+ }
+
+ if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino)) /* same device here */
+ fd2 = fd1;
+ else { /* different devices here */
+ if ((fd2=open(device2, O_RDWR)) < 0) {
+ sprintf(Msg, "Can't open fd2 (%s)\n", device2);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ exit(1);
+ }
+ }
+ num = fd2;
+
+ /* open ppsapi soure */
+
+ if (time_pps_create(num, &instance->pps_h) < 0) {
+ record_clock_stats(&(instance->peer->srcadr), "PPSAPI not found in kernel");
+ return(0);
}
+ /* continue initialization */
+
+ instance->ttyfd = fd1;
+ instance->ppsfd = fd2;
+
+ /* go read any input data in /etc/ntp.oncoreX or /etc/ntp/oncore.X */
+
+ oncore_read_config(instance);
+
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");
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: io_addclock");
(void) close(fd1);
free(instance);
return (0);
@@ -690,44 +684,6 @@ oncore_start(
/*
- * 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
*/
@@ -745,10 +701,16 @@ oncore_shutdown(
io_closeclock(&pp->io);
+ time_pps_destroy (instance->pps_h);
+
close(instance->ttyfd);
- close(instance->ppsfd);
+
+ if ((instance->ppsfd != -1) && (instance->ppsfd != instance->ttyfd))
+ close(instance->ppsfd);
+
if (instance->shmemfd)
close(instance->shmemfd);
+
free(instance);
}
@@ -797,21 +759,21 @@ oncore_poll(
* Initialize PPSAPI
*/
-#ifdef HAVE_PPSAPI
static int
oncore_ppsapi(
struct instance *instance
)
{
- int mode;
+ int cap, mode, mode1;
+ char *cp, Msg[160];
- if (time_pps_getcap(instance->pps_h, &mode) < 0) {
- msyslog(LOG_ERR, "refclock_ioctl: time_pps_getcap failed: %m");
+ if (time_pps_getcap(instance->pps_h, &cap) < 0) {
+ msyslog(LOG_ERR, "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, "time_pps_getparams failed: %m");
return (0);
}
@@ -819,20 +781,36 @@ oncore_ppsapi(
* on before we get here, leave it alone!
*/
- if (instance->assert) { /* nb, default or ON */
- instance->pps_p.mode = PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
- instance->pps_p.assert_offset.tv_sec = 0;
- instance->pps_p.assert_offset.tv_nsec = 0;
+ if (instance->assert) {
+ cp = "Assert.";
+ mode = PPS_CAPTUREASSERT;
+ mode1 = PPS_OFFSETASSERT;
} else {
- instance->pps_p.mode = PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
- instance->pps_p.clear_offset.tv_sec = 0;
- instance->pps_p.clear_offset.tv_nsec = 0;
+ cp = "Clear.";
+ mode = PPS_CAPTURECLEAR;
+ mode1 = PPS_OFFSETCLEAR;
+ }
+ sprintf(Msg, "Initializing timeing to %s.", cp);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+
+ if (!(mode & cap)) {
+ sprintf(Msg, "Can't set timeing to %s, exiting...", cp);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ return(0);
}
- instance->pps_p.mode |= PPS_TSFMT_TSPEC;
- instance->pps_p.mode &= mode; /* only set what is legal */
+
+ if (!(mode1 & cap)) {
+ sprintf(Msg, "Can't set PPS_%sCLEAR, this will increase jitter.", cp);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ mode1 = 0;
+ }
+
+ /* only set what is legal */
+
+ instance->pps_p.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) {
- perror("time_pps_setparams");
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: time_pps_setparams fails");
exit(1);
}
@@ -841,23 +819,25 @@ oncore_ppsapi(
if (instance->hardpps) {
int i;
+ record_clock_stats(&(instance->peer->srcadr), "HARDPPS Set.");
+
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;
+ /* we know that 'i' is legal from above */
+
+ if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i,
+ PPS_TSFMT_TSPEC) < 0) {
+ msyslog(LOG_ERR, "time_pps_kcbind failed: %m");
+ record_clock_stats(&(instance->peer->srcadr), "HARDPPS failed, abort...");
+ return (0);
}
+ pps_enable = 1;
}
return(1);
}
-#endif
@@ -868,8 +848,8 @@ oncore_init_shmem(
)
{
int i, l, n, fd, shmem_old_size, n1;
- char *buf, Msg[160];
- u_char *cp, *cp1, *shmem_old;
+ char Msg[160];
+ u_char *cp, *cp1, *buf, *shmem_old;
struct msg_desc *mp;
struct stat sbuf;
size_t shmem_length;
@@ -881,26 +861,29 @@ oncore_init_shmem(
*/
shmem_old = 0;
+ shmem_old_size = 0;
if ((fd = open(instance->shmem_fname, O_RDONLY)) < 0)
- perror("LOAD:SHMEM");
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't open SHMEM file");
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;
+ if (shmem_old_size != 0) {
+ shmem_old = (u_char *) malloc((unsigned) sbuf.st_size);
+ if (shmem_old == NULL)
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't malloc buffer for shmem_old");
+ else
+ read(fd, shmem_old, shmem_old_size);
}
-
- read(fd, shmem_old, shmem_old_size);
close(fd);
}
/* OK, we now create the NEW SHMEM. */
if ((instance->shmemfd = open(instance->shmem_fname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
- perror(instance->shmem_fname);
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't open shmem");
+ if (shmem_old)
+ free(shmem_old);
+
return;
}
@@ -929,12 +912,14 @@ oncore_init_shmem(
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");
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: Can't malloc buffer for shmem");
close(instance->shmemfd);
+ if (shmem_old)
+ free(shmem_old);
+
return;
}
@@ -969,20 +954,21 @@ oncore_init_shmem(
}
/* 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.
+ * copying the data in shmem_old to buf.
+ * When we are done we write it out and free both buffers.
+ * If the structure sizes dont agree, I will not copy.
+ * This could be due to an addition/deletion or a problem with the disk file.
*/
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;
+ if (shmem_old_size == shmem_length) {
+ 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 (n == 0 || n1 != n || strncmp((char *) cp, (char *) cp1, 4))
+ break;
- memcpy(cp, cp1, (size_t) n);
+ memcpy(cp, cp1, (size_t) n);
+ }
}
free(shmem_old);
}
@@ -991,7 +977,7 @@ oncore_init_shmem(
free(buf);
if (i != shmem_length) {
- perror(instance->shmem_fname);
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: error writing shmem");
close(instance->shmemfd);
return;
}
@@ -1009,7 +995,8 @@ oncore_init_shmem(
return;
}
- sprintf(Msg, "SHMEM (size = %d) is CONFIGURED and available as %s", shmem_length, instance->shmem_fname);
+ sprintf(Msg, "SHMEM (size = %ld) is CONFIGURED and available as %s",
+ (u_long) shmem_length, instance->shmem_fname);
record_clock_stats(&(instance->peer->srcadr), Msg);
}
#endif /* ONCORE_SHMEM_STATUS */
@@ -1140,19 +1127,28 @@ oncore_read_config(
*/
FILE *fd;
- char *cp, *cc, *ca, line[100], units[2], device[20], Msg[160];
+ char *cp, *cc, *ca, line[100], units[2], device[20], Msg[160], **cpp;
+ char *dirs[] = { "/etc/ntp", "/etc", 0 };
int i, sign, lat_flg, long_flg, ht_flg, mode, mask;
double f1, f2, f3;
- sprintf(device, "%s%d", INIT_FILE, instance->unit); /* try "ntp.oncore0" first */
- if ((fd=fopen(device, "r")) == NULL) { /* it was in the original documentation */
- sprintf(device, "%s.%d", INIT_FILE, instance->unit); /* then try "ntp.oncore.0 */
- if ((fd=fopen(device, "r")) == NULL) {
- if ((fd=fopen(INIT_FILE, "r")) == NULL) { /* and finally "ntp.oncore" */
- instance->init_type = 4;
- return;
- }
- }
+ fd = NULL; /* just to shutup gcc complaint */
+ for (cpp=dirs; *cpp; cpp++) {
+ cp = *cpp;
+ sprintf(device, "%s/ntp.oncore.%d", cp, instance->unit); /* try "ntp.oncore.0 */
+ if ((fd=fopen(device, "r")))
+ break;
+ sprintf(device, "%s/ntp.oncore%d", cp, instance->unit); /* try "ntp.oncore0" */
+ if ((fd=fopen(device, "r")))
+ break;
+ sprintf(device, "%s/ntp.oncore", cp); /* and finally "ntp.oncore" */
+ if ((fd=fopen(device, "r")))
+ break;
+ }
+
+ if (!fd) { /* no inputfile, default to the works ... */
+ instance->init_type = 4;
+ return;
}
mode = mask = 0;
@@ -1306,7 +1302,7 @@ oncore_read_config(
instance->posn_set = 1;
if (!( lat_flg && long_flg && ht_flg )) {
- printf("ONCORE: incomplete data on %s\n", INIT_FILE);
+ printf("ONCORE: incomplete data on %s\n", device);
instance->posn_set = 0;
if (mode == 1 || mode == 3) {
sprintf(Msg, "Input Mode = %d, but no/incomplete position, mode set to %d", mode, mode+1);
@@ -1382,8 +1378,10 @@ oncore_consume(
for (i=1; i < rcvptr-1; i++)
if (rcvbuf[i] == '@' && rcvbuf[i+1] == '@')
break;
+#ifdef DEBUG
if (debug > 4)
printf("ONCORE[%d]: >>> skipping %d chars\n", instance->unit, i);
+#endif
if (i != rcvptr)
memcpy(rcvbuf, rcvbuf+i, (size_t)(rcvptr-i));
rcvptr -= i;
@@ -1396,8 +1394,10 @@ oncore_consume(
if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), (size_t) 2))
break;
if (m == l) {
+#ifdef DEBUG
if (debug > 4)
printf("ONCORE[%d]: >>> Unknown MSG, skipping 4 (%c%c)\n", instance->unit, rcvbuf[2], rcvbuf[3]);
+#endif
memcpy(rcvbuf, rcvbuf+4, (size_t) 4);
rcvptr -= 4;
continue;
@@ -1416,8 +1416,10 @@ oncore_consume(
/* are we at the end of message? should be <Cksum><CR><LF> */
if (rcvbuf[l-2] != '\r' || rcvbuf[l-1] != '\n') {
+#ifdef DEBUG
if (debug)
printf("ONCORE[%d]: NO <CR><LF> at end of message\n", instance->unit);
+#endif
} else { /* check the CheckSum */
if (oncore_checksum_ok(rcvbuf, l)) {
if (instance->shmem != NULL) {
@@ -1428,13 +1430,16 @@ oncore_consume(
oncore_msg_any(instance, rcvbuf, (size_t) (l-3), m);
if (oncore_messages[m].handler)
oncore_messages[m].handler(instance, rcvbuf, (size_t) (l-3));
- } else if (debug) {
+ }
+#ifdef DEBUG
+ else if (debug) {
printf("ONCORE[%d]: Checksum mismatch!\n", instance->unit);
printf("ONCORE[%d]: @@%c%c ", instance->unit, rcvbuf[2], rcvbuf[3]);
for (i=4; i<l; i++)
printf("%03o ", rcvbuf[i]);
printf("\n");
}
+#endif
}
if (l != rcvptr)
@@ -1453,7 +1458,7 @@ oncore_get_timestamp(
)
{
int Rsm;
- u_long i, j;
+ u_long j;
l_fp ts, ts_tmp;
double dmy;
#ifdef HAVE_STRUCT_TIMESPEC
@@ -1461,24 +1466,11 @@ oncore_get_timestamp(
#else
struct timeval *tsp = 0;
#endif
-#ifdef HAVE_PPSAPI
int current_mode;
+ u_long i;
pps_params_t current_params;
struct timespec timeout;
pps_info_t pps_i;
-#else /* ! HAVE_PPSAPI */
-#ifdef HAVE_CIOGETEV
- struct ppsclockev ev;
- int r = CIOGETEV;
-#endif
-#ifdef HAVE_TIOCGPPSEV
- struct ppsclockev ev;
- int r = TIOCGPPSEV;
-#endif
-#if TIOCDCDTIMESTAMP
- struct timeval tv;
-#endif
-#endif /* ! HAVE_PPS_API */
#if 1
/* If we are in SiteSurvey mode, then we are in 3D mode, and we fall thru.
@@ -1500,7 +1492,17 @@ oncore_get_timestamp(
if (instance->rsm.bad_almanac)
return;
-#ifdef HAVE_PPSAPI
+ /* Once the Almanac is valid, the M12+T does not produce valid UTC
+ * immediately.
+ * Wait for UTC offset decode valid, then wait one message more
+ * so we are not off by 13 seconds after reset.
+ */
+
+ if (instance->count5) {
+ instance->count5--;
+ return;
+ }
+
j = instance->ev_serial;
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
@@ -1513,18 +1515,20 @@ oncore_get_timestamp(
if (instance->assert) {
tsp = &pps_i.assert_timestamp;
+#ifdef DEBUG
if (debug > 2) {
i = (u_long) pps_i.assert_sequence;
-#ifdef HAVE_STRUCT_TIMESPEC
+# 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
+# else
printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%06ld\n",
instance->unit, i, j,
(long)tsp->tv_sec, (long)tsp->tv_usec);
-#endif
+# endif
}
+#endif
if (pps_i.assert_sequence == j) {
printf("ONCORE: oncore_get_timestamp, error serial pps\n");
@@ -1534,16 +1538,18 @@ oncore_get_timestamp(
} else {
tsp = &pps_i.clear_timestamp;
+#ifdef DEBUG
if (debug > 2) {
i = (u_long) pps_i.clear_sequence;
-#ifdef HAVE_STRUCT_TIMESPEC
+# 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
+# else
printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%06ld\n",
instance->unit, i, j, (long)tsp->tv_sec, (long)tsp->tv_usec);
-#endif
+# endif
}
+#endif
if (pps_i.clear_sequence == j) {
printf("ONCORE: oncore_get_timestamp, error serial pps\n");
@@ -1556,8 +1562,9 @@ oncore_get_timestamp(
dmy = tsp->tv_nsec;
dmy /= 1e9;
- ts.l_uf = dmy * 4294967296.0;
+ 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 */
@@ -1570,49 +1577,11 @@ oncore_get_timestamp(
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 */
+ /* they will be IGNORED if the PPSAPI cant do PPS_OFFSET/ASSERT/CLEAR */
+ /* we just try to add them in and dont test for that here */
/* saw_tooth not really necessary if using TIMEVAL */
/* since its only precise to us, but do it anyway. */
@@ -1620,7 +1589,6 @@ oncore_get_timestamp(
/* 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 */
@@ -1643,12 +1611,12 @@ oncore_get_timestamp(
*/
if (time_pps_getcap(instance->pps_h, &current_mode) < 0) {
- msyslog(LOG_ERR, "refclock_ioctl: time_pps_getcap failed: %m");
+ msyslog(LOG_ERR, "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");
+ msyslog(LOG_ERR, "time_pps_getparams failed: %m");
return;
}
@@ -1663,15 +1631,8 @@ oncore_get_timestamp(
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 */
+ record_clock_stats(&(instance->peer->srcadr), "ONCORE: Error doing time_pps_setparams");
- 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;
@@ -1693,47 +1654,74 @@ oncore_get_timestamp(
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",
+ char f1[5], f2[5], f3[5], f4[5];
+ if (instance->traim) {
+ sprintf(f1, "%d", instance->BEHn[21]);
+ sprintf(f2, "%d", instance->BEHn[22]);
+ sprintf(f3, "%2d", instance->BEHn[23]*256+instance->BEHn[24]);
+ sprintf(f4, "%3d", (s_char) instance->BEHn[25]);
+ } else {
+ strcpy(f1, "x");
+ strcpy(f2, "x");
+ strcpy(f3, "xx");
+ strcpy(f4, "xxx");
+ }
+ sprintf(instance->pp->a_lastcode, /* MAX length 128, currently at 121 */
+ "%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s 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 */
+ instance->BEHa[38], instance->BEHa[39], instance->traim, f1, f2,
+ /* nsat visible, nsat tracked, traim,traim,traim */
+ f3, f4,
+ /* 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) {
+ char f1[5], f2[5], f3[5], f4[5];
+ if (instance->traim) {
+ sprintf(f1, "%d", instance->BEHn[6]);
+ sprintf(f2, "%d", instance->BEHn[7]);
+ sprintf(f3, "%d", instance->BEHn[12]*256+instance->BEHn[13]);
+ sprintf(f4, "%3d", (s_char) instance->BEHn[14]);
+ } else {
+ strcpy(f1, "x");
+ strcpy(f2, "x");
+ strcpy(f3, "x");
+ strcpy(f4, "xxx");
+ }
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",
+ "%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s 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 */
+ instance->BEHa[55], instance->BEHa[56], instance->traim, f1, f2,
+ /* nsat visible, nsat tracked traim,traim,traim */
+ f3, f4,
+ /* 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]
);
}
+#ifdef DEBUG
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);
}
+#endif
- /* and some things I dont understnd (magic ntp things) */
+ /* and some things I dont understand (magic ntp things) */
if (!refclock_process(instance->pp)) {
refclock_report(instance->peer, CEVNT_BADTIME);
@@ -1745,9 +1733,7 @@ oncore_get_timestamp(
if (instance->polled) {
instance->polled = 0;
-/*
- instance->pp->dispersion = instance->pp->skew = 0;
-*/
+ /* instance->pp->dispersion = instance->pp->skew = 0; */
instance->pp->lastref = instance->pp->lastrec;
refclock_receive(instance->peer);
}
@@ -1777,14 +1763,15 @@ oncore_msg_any(
#endif
struct timeval tv;
+#ifdef DEBUG
if (debug > 3) {
-#ifdef HAVE_GETCLOCK
+# ifdef HAVE_GETCLOCK
(void) getclock(TIMEOFDAY, &ts);
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
-#else
+# else
GETTIMEOFDAY(&tv, 0);
-#endif
+# endif
printf("ONCORE[%d]: %ld.%06ld\n", instance->unit, (long) tv.tv_sec, (long) tv.tv_usec);
if (!*fmt) {
@@ -1807,6 +1794,7 @@ oncore_msg_any(
printf("\n");
}
}
+#endif
}
@@ -2010,22 +1998,22 @@ oncore_msg_BaEaHa(
if (instance->o_state != ONCORE_ALMANAC && instance->o_state != ONCORE_RUN)
return;
- /* PAUSE 5sec */
+ /* PAUSE 5sec - make sure results are stable, before using position */
if (instance->count) {
- if (instance->count++ < 5) /* make sure results are stable, using position */
+ if (instance->count++ < 5)
return;
instance->count = 0;
}
memcpy(instance->BEHa, buf, (size_t) (len+3)); /* Ba, Ea or Ha */
- /* check the antenna and almanac for changes (did it get unplugged, is it ready?) */
+ /* check the antenna (did it get unplugged) and almanac (is it ready) for changes. */
oncore_check_almanac(instance);
oncore_check_antenna(instance);
- /* Almanac mode, waiting for Almanac, we can't do anything till we have it */
+ /* If we are in Almanac mode, waiting for Almanac, we can't do anything till we have it */
/* When we have an almanac, we will start the Bn/En/@@Hn messages */
if (instance->o_state == ONCORE_ALMANAC)
@@ -2089,41 +2077,67 @@ oncore_msg_BaEaHa(
oncore_sendmsg(instance->ttyfd, oncore_cmd_Agx, sizeof(oncore_cmd_Agx));
}
- if (instance->count1) {
- if (instance->count1++ > 5 || instance->site_survey == ONCORE_SS_HW) {
- instance->count1 = 0;
- if (instance->site_survey == ONCORE_SS_TESTING) {
- /*
- * For instance->site_survey to still be ONCORE_SS_TESTING, then after a 5sec
- * wait after the @@At2/@@Gd3 command we have not changed the state to
- * ONCORE_SS_HW. If the Hardware is capable of doing a Site Survey, then
- * the variable would have been changed by now.
- * There are three possibilities:
- * 6/8chan
- * (a) We did not get a response to the @@At0 or @@At2 commands,
- * and it must be a GT/GT+/SL with no position hold mode.
- * We will have to do it ourselves.
- * (b) We saw the @@At0, @@At2 commands, but @@At2 failed,
- * must be a VP or older UT which doesn't have Site Survey mode.
- * We will have to do it ourselves.
- * 12chan
- * (c) We saw the @@Gd command, but @@Gd3 failed,
- * We will have to do it ourselves.
- */
-
- sprintf(Msg, "Initiating software 3D site survey (%d samples)",
- POS_HOLD_AVERAGE);
- record_clock_stats(&(instance->peer->srcadr), Msg);
- record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_SW");
- instance->site_survey = ONCORE_SS_SW;
+ /* Unfortunately, the Gd3 command returns '3' for the M12 v1.3 firmware where it is
+ * out-of-range and it should return 0-2. (v1.3 can't do a HW Site Survey)
+ * We must do the Gd3, and then wait a cycle or two for things to settle,
+ * then check Ha[130]&0x10 to see if a SS is in progress.
+ * We will set SW if HW has not been set after an appropriate delay.
+ */
- 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->site_survey == ONCORE_SS_TESTING) {
+ if (instance->chan == 12) {
+ if (instance->count1) {
+ if (instance->count1++ > 5 || instance->BEHa[130]&0x10) {
+ instance->count1 = 0;
+ if (instance->BEHa[130]&0x10) {
+ record_clock_stats(&(instance->peer->srcadr),
+ "Initiating hardware 3D site survey");
+
+ record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_HW");
+ instance->site_survey = ONCORE_SS_HW;
+ } else {
+ record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_SW");
+ instance->site_survey = ONCORE_SS_SW;
+ }
+ }
+ }
+ } else {
+ if (instance->count1) {
+ if (instance->count1++ > 5) {
+ instance->count1 = 0;
+ /*
+ * 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, and saw H[13]*0x10
+ * We will have to do it ourselves (done above)
+ */
+
+ sprintf(Msg, "Initiating software 3D site survey (%d samples)",
+ POS_HOLD_AVERAGE);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+
+ record_clock_stats(&(instance->peer->srcadr), "SSstate = ONCORE_SS_SW");
+ instance->site_survey = ONCORE_SS_SW;
+
+ instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
+ if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* disable */
+ else {
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* disable */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* disable */
+ }
}
}
}
@@ -2167,7 +2181,7 @@ oncore_msg_BaEaHa(
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;
+ default: smp = (u_char *) NULL; break;
}
switch (instance->mode) {
@@ -2177,7 +2191,7 @@ oncore_msg_BaEaHa(
default: i = 0; break;
}
- if (i) {
+ if (i && smp != NULL) {
i *= (len+6);
smp[i + 2]++;
memcpy(&smp[i+3], buf, (size_t) (len+3));
@@ -2185,7 +2199,7 @@ oncore_msg_BaEaHa(
}
/*
- * check if timer active
+ * check if traim timer active
* if it hasn't been cleared, then @@Bn/@@En/@@Hn did not respond
*/
@@ -2301,17 +2315,17 @@ oncore_msg_Bj(
switch(buf[4]) {
case 1:
- instance->peer->leap = LEAP_ADDSECOND;
- cp = "Set peer.leap to LEAP_ADDSECOND";
+ instance->pp->leap = LEAP_ADDSECOND;
+ cp = "Set pp.leap to LEAP_ADDSECOND";
break;
case 2:
- instance->peer->leap = LEAP_DELSECOND;
- cp = "Set peer.leap to LEAP_DELSECOND";
+ instance->pp->leap = LEAP_DELSECOND;
+ cp = "Set pp.leap to LEAP_DELSECOND";
break;
case 0:
default:
- instance->peer->leap = LEAP_NOWARNING;
- cp = "Set peer.leap to LEAP_NOWARNING";
+ instance->pp->leap = LEAP_NOWARNING;
+ cp = "Set pp.leap to LEAP_NOWARNING";
break;
}
record_clock_stats(&(instance->peer->srcadr), cp);
@@ -2343,6 +2357,9 @@ oncore_msg_BnEnHn(
memcpy(instance->BEHn, buf, (size_t) len); /* Bn or En or Hn */
+ if (!instance->traim) /* BnEnHn will be turned off in any case */
+ return;
+
/* If Time RAIM doesn't like it, don't trust it */
if (buf[2] == 'H') {
@@ -2350,14 +2367,14 @@ oncore_msg_BnEnHn(
return;
dt1 = instance->saw_tooth + instance->offset; /* dt this time step */
- instance->saw_tooth = (s_char) instance->BEHn[10]; /* update for next time Hn[10] */
+ instance->saw_tooth = (s_char) instance->BEHn[14]; /* update for next time Hn[14] */
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 */
+ instance->saw_tooth = (s_char) instance->BEHn[25]; /* update for next time Bn[25], En[25] */
dt2 = instance->saw_tooth + instance->offset; /* dt next time step */
}
@@ -2397,12 +2414,14 @@ oncore_msg_CaFaIa(
instance->timeout = 0;
+#ifdef DEBUG
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]);
}
+#endif
antenna = (buf[4] & 0xc0) >> 6;
buf[4] &= ~0xc0;
@@ -2608,13 +2627,13 @@ oncore_msg_Cj_id(
/* next, the Firmware Version and Revision numbers */
- instance->version = atoi(&instance->Cj[83]);
- instance->revision = atoi(&instance->Cj[111]);
+ instance->version = atoi((char *) &instance->Cj[83]);
+ instance->revision = atoi((char *) &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 #' */
+ for (cp= (char *) &instance->Cj[160]; *cp == ' '; cp++) /* start right after 'Model #' */
;
cp1 = cp;
cp2 = Model;
@@ -2701,7 +2720,8 @@ oncore_msg_Cj_init(
size_t len
)
{
- char *cp, Cmd[20], Msg[160];
+ char *cp, Msg[160];
+ u_char Cmd[20];
int mode;
@@ -2860,40 +2880,12 @@ oncore_msg_Gb(
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);
+ d, Month[mo-1], y, h, m, s, gmts, gmth, gmtm);
record_clock_stats(&(instance->peer->srcadr), Msg);
}
-/*
- * Try to use Oncore M12+Timing Auto Survey Feature
- * If its not there (M12), set flag to do it ourselves.
- */
-
-static void
-oncore_msg_Gd(
- struct instance *instance,
- u_char *buf,
- size_t len
- )
-{
- char *cp;
-
- if (instance->site_survey == ONCORE_SS_TESTING) {
- if (buf[4] == 3) {
- record_clock_stats(&(instance->peer->srcadr),
- "Initiating hardware 3D site survey");
-
- cp = "SSstate = ONCORE_SS_HW";
- record_clock_stats(&(instance->peer->srcadr), cp);
- instance->site_survey = ONCORE_SS_HW;
- }
- }
-}
-
-
-
/* Leap Second for M12, gives all info from satellite message */
/* also in UT v3.0 */
@@ -2924,25 +2916,25 @@ oncore_msg_Gj(
if (dt) {
sprintf(Msg, "ONCORE[%d]: Leap second (%d) scheduled for %d%s%d at %d:%d:%d",
instance->unit,
- dt, buf[9], Month[buf[8]], 256*buf[6]+buf[7],
+ dt, buf[9], Month[buf[8]-1], 256*buf[6]+buf[7],
buf[15], buf[16], buf[17]);
record_clock_stats(&(instance->peer->srcadr), Msg);
}
/* Only raise warning within a month of the leap second */
- instance->peer->leap = LEAP_NOWARNING;
- cp = "Set peer.leap to LEAP_NOWARNING";
+ instance->pp->leap = LEAP_NOWARNING;
+ cp = "Set pp.leap to LEAP_NOWARNING";
if (buf[6] == instance->BEHa[6] && buf[7] == instance->BEHa[7] && /* year */
buf[8] == instance->BEHa[4]) { /* month */
if (dt) {
if (dt < 0) {
- instance->peer->leap = LEAP_DELSECOND;
- cp = "Set peer.leap to LEAP_DELSECOND";
+ instance->pp->leap = LEAP_DELSECOND;
+ cp = "Set pp.leap to LEAP_DELSECOND";
} else {
- instance->peer->leap = LEAP_ADDSECOND;
- cp = "Set peer.leap to LEAP_ADDSECOND";
+ instance->pp->leap = LEAP_ADDSECOND;
+ cp = "Set pp.leap to LEAP_ADDSECOND";
}
}
}
@@ -3038,19 +3030,30 @@ oncore_check_almanac(
instance->rsm.bad_almanac = instance->BEHa[72]&0x1;
instance->rsm.bad_fix = instance->BEHa[72]&0x52;
} else if (instance->chan == 12) {
- int bits1, bits2;
+ int bits1, bits2, bits3;
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 */
+
+ bits3 = instance->BEHa[141]; /* UTC parameters */
+ if (!instance->count5_set && (bits3 & 0xC0)) {
+ instance->count5 = 2;
+ instance->count5_set = 1;
+ }
#if 0
- fprintf(stderr, "ONCORE[%d]: DEBUG BITS: (%x %x), (%x %x), %x %x %x %x %x\n",
+{
+ char Msg[160];
+
+ sprintf(Msg, "ONCORE[%d]: DEBUG BITS: (%x %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->BEHa[129], instance->BEHa[130], bits1, bits2, bits3, instance->mode == MODE_0D,
instance->mode == MODE_2D, instance->mode == MODE_3D,
instance->rsm.bad_almanac, instance->rsm.bad_fix);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+}
#endif
}
}
@@ -3212,7 +3215,7 @@ oncore_load_almanac(
#if 1
for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2)); cp+=(n+3)) {
- if (!strncmp(cp, "@@Cb", 4) &&
+ if (!strncmp((char *) cp, "@@Cb", 4) &&
oncore_checksum_ok(cp, 33) &&
(*(cp+4) == 4 || *(cp+4) == 5)) {
write(instance->ttyfd, cp, n);
@@ -3249,20 +3252,22 @@ oncore_load_almanac(
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)))) {
+ if ((instance->chan == 6 && (!strncmp((char *) cp, "@@Ba", 4) && oncore_checksum_ok(cp, 68))) ||
+ (instance->chan == 8 && (!strncmp((char *) cp, "@@Ea", 4) && oncore_checksum_ok(cp, 76))) ||
+ (instance->chan == 12 && (!strncmp((char *) 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);
+#if 0
{
char Msg[160];
-sprintf(Msg, "SHMEM posn = %d (%d, %d, %d)", cp-instance->shmem, ii, jj, kk);
+sprintf(Msg, "SHMEM posn = %ld (%d, %d, %d)", (long) (cp-instance->shmem), ii, jj, kk);
record_clock_stats(&(instance->peer->srcadr), Msg);
}
+#endif
if (ii != 0 || jj != 0 || kk != 0) { /* phk asked for this test */
instance->ss_lat = ii;
instance->ss_long = jj;
@@ -3287,7 +3292,7 @@ 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+4] = tm->tm_mon + 1;
Cmd[-2+5] = tm->tm_mday;
Cmd[-2+6] = (1900+tm->tm_year)/256;
Cmd[-2+7] = (1900+tm->tm_year)%256;
@@ -3304,7 +3309,7 @@ record_clock_stats(&(instance->peer->srcadr), Msg);
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+4] = tm->tm_mon + 1;
Cmd[-2+5] = tm->tm_mday;
Cmd[-2+6] = (1900+tm->tm_year)/256;
Cmd[-2+7] = (1900+tm->tm_year)%256;
@@ -3438,8 +3443,10 @@ oncore_sendmsg(
{
u_char cs = 0;
+#ifdef DEBUG
if (debug > 4)
printf("ONCORE: Send @@%c%c %d\n", ptr[0], ptr[1], (int) len);
+#endif
write(fd, "@@", (size_t) 2);
write(fd, ptr, len);
while (len--)
@@ -3456,7 +3463,7 @@ oncore_set_posn(
)
{
int mode;
- char Cmd[20];
+ u_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 */
@@ -3548,6 +3555,7 @@ oncore_set_traim(
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));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
}
}
@@ -3611,7 +3619,6 @@ oncore_ss(
if (instance->site_survey == ONCORE_SS_HW) {
-
/*
* Check to see if Hardware SiteSurvey has Finished.
*/
@@ -3680,8 +3687,10 @@ oncore_wait_almanac(
)
{
if (instance->rsm.bad_almanac) {
+#ifdef DEBUG
if (debug)
printf("ONCORE[%d]: waiting for almanac\n", instance->unit);
+#endif
/*
* If we get here (first time) then we don't have an almanac in memory.
diff --git a/contrib/ntp/ntpd/refclock_palisade.c b/contrib/ntp/ntpd/refclock_palisade.c
index 897221b..217ec10 100644
--- a/contrib/ntp/ntpd/refclock_palisade.c
+++ b/contrib/ntp/ntpd/refclock_palisade.c
@@ -494,7 +494,7 @@ if (debug > 1) {
return 0;
}
- pp->nsec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
+ pp->nsec = (long) (getdbl((u_char *) &mb(3)) * 1000000000);
if ((pp->day = day_of_year(&mb(14))) < 0)
break;
diff --git a/contrib/ntp/ntpd/refclock_palisade.h b/contrib/ntp/ntpd/refclock_palisade.h
index 7e1ed49..e63f3da 100644
--- a/contrib/ntp/ntpd/refclock_palisade.h
+++ b/contrib/ntp/ntpd/refclock_palisade.h
@@ -59,10 +59,12 @@
#if defined HAVE_SYS_MODEM_H
#include <sys/modem.h>
+#ifndef __QNXNTO__
#define TIOCMSET MCSETA
#define TIOCMGET MCGETA
#define TIOCM_RTS MRTS
#endif
+#endif
#ifdef HAVE_TERMIOS_H
# ifdef TERMIOS_NEEDS__SVID3
diff --git a/contrib/ntp/ntpd/refclock_parse.c b/contrib/ntp/ntpd/refclock_parse.c
index 52fadaa..0b0109c 100644
--- a/contrib/ntp/ntpd/refclock_parse.c
+++ b/contrib/ntp/ntpd/refclock_parse.c
@@ -1,32 +1,51 @@
/*
- * /src/NTP/ntp-4/ntpd/refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A
+ * /src/NTP/REPOSITORY/ntp4-dev/ntpd/refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
*
- * refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A
+ * refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp
*
- * generic reference clock driver for receivers
+ * generic reference clock driver for several DCF/GPS/MSF/... receivers
*
- * optionally make use of a STREAMS module for input processing where
- * available and configured. Currently the STREAMS module
- * is only available for Suns running SunOS 4.x and SunOS5.x
+ * PPS notes:
+ * On systems that support PPSAPI (RFC2783) PPSAPI is the
+ * preferred interface.
*
- * the STREAMS module is not required for operation and may be omitted
- * at the cost of reduced accuracy. As new kernel interfaces emerger this
- * restriction may be lifted in future.
+ * Optionally make use of a STREAMS module for input processing where
+ * available and configured. This STREAMS module reduces the time
+ * stamp latency for serial and PPS events.
+ * Currently the STREAMS module is only available for Suns running
+ * SunOS 4.x and SunOS5.x.
*
- * Copyright (c) 1995-1999 by Frank Kardel <kardel@acm.org>
+ * Copyright (c) 1995-2007 by Frank Kardel <kardel <AT> ntp.org>
* Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
*
- * This software may not be sold for profit without a written consent
- * from the author.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
*
- * 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.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
#endif
#if defined(REFCLOCK) && defined(CLOCK_PARSE)
@@ -42,12 +61,12 @@
* - Schmid clock (DCF)
* - Conrad DCF77 receiver module (DCF)
* - FAU DCF77 NTP receiver (TimeBrick) (DCF)
+ * - WHARTON 400A Series clock (DCF)
*
* - Meinberg GPS166/GPS167 (GPS)
* - Trimble (TSIP and TAIP protocol) (GPS)
*
* - RCC8000 MSF Receiver (MSF)
- * - WHARTON 400A Series clock (DCF)
* - VARITEXT clock (MSF)
*/
@@ -79,6 +98,7 @@
#include "ntp_refclock.h"
#include "ntp_unixtime.h" /* includes <sys/time.h> */
#include "ntp_control.h"
+#include "ntp_string.h"
#include <stdio.h>
#include <ctype.h>
@@ -86,6 +106,10 @@
# include <time.h>
#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
#if !defined(STREAM) && !defined(HAVE_SYSV_TTYS) && !defined(HAVE_BSD_TTYS) && !defined(HAVE_TERMIOS)
# include "Bletch: Define one of {STREAM,HAVE_SYSV_TTYS,HAVE_TERMIOS}"
#endif
@@ -115,14 +139,43 @@
# include <sys/ioctl.h>
#endif
+#ifdef HAVE_PPSAPI
+# include "ppsapi_timepps.h"
+#endif
+
#ifdef PPS
-#ifdef HAVE_SYS_PPSCLOCK_H
-#include <sys/ppsclock.h>
+# ifdef HAVE_SYS_PPSCLOCK_H
+# include <sys/ppsclock.h>
+# endif
+# ifdef HAVE_TIO_SERIAL_STUFF
+# include <linux/serial.h>
+# endif
+#endif
+
+#define BUFFER_SIZE(_BUF, _PTR) ((_BUF) + sizeof(_BUF) - (_PTR))
+#define BUFFER_SIZES(_BUF, _PTR, _SZ) ((_BUF) + (_SZ) - (_PTR))
+
+/*
+ * document type of PPS interfacing - copy of ifdef mechanism in local_input()
+ */
+#undef PPS_METHOD
+
+#ifdef HAVE_PPSAPI
+#define PPS_METHOD "PPS API"
+#else
+#ifdef TIOCDCDTIMESTAMP
+#define PPS_METHOD "TIOCDCDTIMESTAMP"
+#else /* TIOCDCDTIMESTAMP */
+#if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
+#ifdef HAVE_CIOGETEV
+#define PPS_METHOD "CIOGETEV"
#endif
-#ifdef HAVE_TIO_SERIAL_STUFF
-#include <linux/serial.h>
+#ifdef HAVE_TIOCGPPSEV
+#define PPS_METHOD "TIOCGPPSEV"
#endif
#endif
+#endif /* TIOCDCDTIMESTAMP */
+#endif /* HAVE_PPSAPI */
#include "ntp_io.h"
#include "ntp_stdlib.h"
@@ -133,28 +186,26 @@
#include "binio.h"
#include "ascii.h"
#include "ieee754io.h"
+#include "recvbuff.h"
-static char rcsid[]="refclock_parse.c,v 4.36 1999/11/28 17:18:20 kardel RELEASE_19991128_A";
+static char rcsid[] = "refclock_parse.c,v 4.80 2007/08/11 12:06:29 kardel Exp";
/**===========================================================================
** external interface to ntp mechanism
**/
-static void parse_init P((void));
static int parse_start P((int, struct peer *));
static void parse_shutdown P((int, struct peer *));
static void parse_poll P((int, struct peer *));
static void parse_control P((int, struct refclockstat *, struct refclockstat *, struct peer *));
-#define parse_buginfo noentry
-
struct refclock refclock_parse = {
parse_start,
parse_shutdown,
parse_poll,
parse_control,
- parse_init,
- parse_buginfo,
+ noentry,
+ noentry,
NOFLAGS
};
@@ -163,10 +214,14 @@ struct refclock refclock_parse = {
*/
#define MAXUNITS 4 /* maximum number of "PARSE" units permitted */
#define PARSEDEVICE "/dev/refclock-%d" /* device to open %d is unit number */
+#define PARSEPPSDEVICE "/dev/refclockpps-%d" /* optional pps device to open %d is unit number */
#undef ABS
#define ABS(_X_) (((_X_) < 0) ? -(_X_) : (_X_))
+#define PARSE_HARDPPS_DISABLE 0
+#define PARSE_HARDPPS_ENABLE 1
+
/**===========================================================================
** function vector for dynamically binding io handling mechanism
**/
@@ -344,9 +399,17 @@ struct parseunit
u_long pollneeddata; /* current_time(!=0) for receive sample expected in PPS mode */
u_short lastformat; /* last format used */
u_long lastsync; /* time (ntp) when clock was last seen fully synchronized */
- u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */
+ u_long maxunsync; /* max time in seconds a receiver is trusted after loosing synchronisation */
+ double ppsphaseadjust; /* phase adjustment of PPS time stamp */
+ u_long lastmissed; /* time (ntp) when poll didn't get data (powerup heuristic) */
u_long ppsserial; /* magic cookie for ppsclock serials (avoids stale ppsclock data) */
- parsetime_t time; /* last (parse module) data */
+ int ppsfd; /* fd to ise for PPS io */
+#ifdef HAVE_PPSAPI
+ pps_handle_t ppshandle; /* store PPSAPI handle */
+ pps_params_t ppsparams; /* current PPS parameters */
+ int hardppsstate; /* current hard pps state */
+#endif
+ parsetime_t timedata; /* last (parse module) data */
void *localdata; /* optional local, receiver-specific data */
unsigned long localstate; /* private local state */
struct errorinfo errors[ERR_CNT]; /* error state table for suppressing excessive error messages */
@@ -376,7 +439,7 @@ typedef struct poll_info
#define NO_INIT 0
#define NO_END 0
#define NO_EVENT 0
-#define NO_DATA 0
+#define NO_LCLDATA 0
#define NO_MESSAGE 0
#define NO_PPSDELAY 0
@@ -397,7 +460,7 @@ typedef struct poll_info
#define NOCLOCK_POLL NO_POLL
#define NOCLOCK_INIT NO_INIT
#define NOCLOCK_END NO_END
-#define NOCLOCK_DATA NO_DATA
+#define NOCLOCK_DATA NO_LCLDATA
#define NOCLOCK_FORMAT ""
#define NOCLOCK_TYPE CTL_SST_TS_UNSPEC
#define NOCLOCK_SAMPLES 0
@@ -410,7 +473,7 @@ typedef struct poll_info
* receiver specific constants
*/
#define MBG_SPEED (B9600)
-#define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL)
+#define MBG_CFLAG (CS7|PARENB|CREAD|CLOCAL|HUPCL|CSTOPB)
#define MBG_IFLAG (IGNBRK|IGNPAR|ISTRIP)
#define MBG_OFLAG 0
#define MBG_LFLAG 0
@@ -591,6 +654,11 @@ static poll_info_t wsdcf_pollinfo = { WS_POLLRATE, WS_POLLCMD, WS_CMDSIZE };
#define CONRAD_BASEDELAY 0.292 /* Conrad receiver @ 50 Baud on a Sun */
#define CONRAD_DESCRIPTION "RAW DCF77 CODE (Conrad DCF77 receiver module)"
+/* Gude Analog- und Digitalsystem GmbH 'Expert mouseCLOCK USB v2.0' */
+#define GUDE_EMC_USB_V20_SPEED (B4800)
+#define GUDE_EMC_USB_V20_BASEDELAY 0.425 /* USB serial<->USB converter FTDI232R */
+#define GUDE_EMC_USB_V20_DESCRIPTION "RAW DCF77 CODE (Expert mouseCLOCK USB v2.0)"
+
/*
* TimeBrick receiver
*/
@@ -645,6 +713,7 @@ static void trimbletsip_message P((struct parseunit *, parsetime_t *));
static void trimbletsip_event P((struct parseunit *, int));
#define TRIMBLETSIP_IDLE_TIME (300) /* 5 minutes silence at most */
+#define TRIMBLE_RESET_HOLDOFF TRIMBLETSIP_IDLE_TIME
#define TRIMBLETAIP_SPEED (B4800)
#define TRIMBLETAIP_CFLAG (CS8|CREAD|CLOCAL)
@@ -819,7 +888,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
DCFPZF535_ROOTDELAY,
DCFPZF535_BASEDELAY,
DCF_P_ID,
@@ -842,7 +911,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
DCFPZF535OCXO_ROOTDELAY,
DCFPZF535OCXO_BASEDELAY,
DCF_P_ID,
@@ -865,7 +934,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
DCFUA31_ROOTDELAY,
DCFUA31_BASEDELAY,
DCF_A_ID,
@@ -888,7 +957,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
DCF7000_ROOTDELAY,
DCF7000_BASEDELAY,
DCF_A_ID,
@@ -934,7 +1003,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
RAWDCF_ROOTDELAY,
CONRAD_BASEDELAY,
DCF_A_ID,
@@ -957,7 +1026,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
RAWDCF_ROOTDELAY,
TIMEBRICK_BASEDELAY,
DCF_A_ID,
@@ -1003,7 +1072,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
RAWDCF_ROOTDELAY,
IGELCLOCK_BASEDELAY,
DCF_A_ID,
@@ -1103,7 +1172,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
HOPF6021_ROOTDELAY,
HOPF6021_BASEDELAY,
DCF_ID,
@@ -1126,7 +1195,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
COMPUTIME_ROOTDELAY,
COMPUTIME_BASEDELAY,
COMPUTIME_ID,
@@ -1149,7 +1218,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
RAWDCF_ROOTDELAY,
RAWDCF_BASEDELAY,
DCF_A_ID,
@@ -1172,7 +1241,7 @@ static struct parse_clockinfo
NO_EVENT, /* special event handling (e.g. reset clock) */
NO_END, /* active poll end routine */
NO_MESSAGE, /* process a lower layer message */
- NO_DATA, /* local data area for "poll" mechanism */
+ NO_LCLDATA, /* local data area for "poll" mechanism */
0, /* rootdelay */
11.0 /* bits */ / 9600, /* current offset by which the RS232
time code is delayed from the actual time */
@@ -1197,7 +1266,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
RAWDCF_ROOTDELAY,
RAWDCF_BASEDELAY,
DCF_A_ID,
@@ -1220,7 +1289,7 @@ static struct parse_clockinfo
NO_EVENT,
NO_END,
NO_MESSAGE,
- NO_DATA,
+ NO_LCLDATA,
VARITEXT_ROOTDELAY,
VARITEXT_BASEDELAY,
VARITEXT_ID,
@@ -1235,7 +1304,53 @@ static struct parse_clockinfo
VARITEXT_LFLAG,
VARITEXT_SAMPLES,
VARITEXT_KEEP
- }
+ },
+ { /* mode 18 */
+ MBG_FLAGS,
+ NO_POLL,
+ NO_INIT,
+ NO_EVENT,
+ GPS16X_END,
+ GPS16X_MESSAGE,
+ GPS16X_DATA,
+ GPS16X_ROOTDELAY,
+ GPS16X_BASEDELAY,
+ GPS16X_ID,
+ GPS16X_DESCRIPTION,
+ GPS16X_FORMAT,
+ GPS_TYPE,
+ GPS16X_MAXUNSYNC,
+ GPS16X_SPEED,
+ GPS16X_CFLAG,
+ GPS16X_IFLAG,
+ GPS16X_OFLAG,
+ GPS16X_LFLAG,
+ GPS16X_SAMPLES,
+ GPS16X_KEEP
+ },
+ { /* mode 19 */
+ RAWDCF_FLAGS,
+ NO_POLL,
+ RAWDCF_INIT,
+ NO_EVENT,
+ NO_END,
+ NO_MESSAGE,
+ NO_LCLDATA,
+ RAWDCF_ROOTDELAY,
+ GUDE_EMC_USB_V20_BASEDELAY,
+ DCF_A_ID,
+ GUDE_EMC_USB_V20_DESCRIPTION,
+ RAWDCF_FORMAT,
+ DCF_TYPE,
+ RAWDCF_MAXUNSYNC,
+ GUDE_EMC_USB_V20_SPEED,
+ RAWDCF_CFLAG,
+ RAWDCF_IFLAG,
+ RAWDCF_OFLAG,
+ RAWDCF_LFLAG,
+ RAWDCF_SAMPLES,
+ RAWDCF_KEEP
+ },
};
static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
@@ -1252,8 +1367,6 @@ static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
#define PARSESTATISTICS (60*60) /* output state statistics every hour */
-static struct parseunit *parseunits[MAXUNITS];
-
static int notice = 0;
#define PARSE_STATETIME(parse, i) ((parse->generic->currentstatus == i) ? parse->statetime[i] + current_time - parse->lastchange : parse->statetime[i])
@@ -1551,8 +1664,8 @@ ppsclock_init(
* now push the parse streams module
* it will ensure exclusive access to the device
*/
- if (ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m1) == -1 &&
- ioctl(parse->generic->io.fd, I_PUSH, (caddr_t)m2) == -1)
+ if (ioctl(parse->ppsfd, I_PUSH, (caddr_t)m1) == -1 &&
+ ioctl(parse->ppsfd, I_PUSH, (caddr_t)m2) == -1)
{
if (errno != EINVAL)
{
@@ -1563,7 +1676,7 @@ ppsclock_init(
}
if (!local_init(parse))
{
- (void)ioctl(parse->generic->io.fd, I_POP, (caddr_t)0);
+ (void)ioctl(parse->ppsfd, I_POP, (caddr_t)0);
return 0;
}
@@ -1790,7 +1903,6 @@ stream_receive(
ERR(ERR_BADIO)
msyslog(LOG_ERR,"PARSE receiver #%d: stream_receive: bad size (got %d expected %d)",
CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
- parse->generic->baddata++;
parse_event(parse, CEVNT_BADREPLY);
return;
}
@@ -1807,12 +1919,12 @@ stream_receive(
CLK_UNIT(parse->peer),
(unsigned int)parsetime.parse_status,
(unsigned int)parsetime.parse_state,
- (long)parsetime.parse_time.tv.tv_sec,
- (long)parsetime.parse_time.tv.tv_usec,
- (long)parsetime.parse_stime.tv.tv_sec,
- (long)parsetime.parse_stime.tv.tv_usec,
- (long)parsetime.parse_ptime.tv.tv_sec,
- (long)parsetime.parse_ptime.tv.tv_usec);
+ (unsigned long)parsetime.parse_time.tv.tv_sec,
+ (unsigned long)parsetime.parse_time.tv.tv_usec,
+ (unsigned long)parsetime.parse_stime.tv.tv_sec,
+ (unsigned long)parsetime.parse_stime.tv.tv_usec,
+ (unsigned long)parsetime.parse_ptime.tv.tv_sec,
+ (unsigned long)parsetime.parse_ptime.tv.tv_usec);
}
#endif
@@ -1945,17 +2057,96 @@ local_input(
{
if (parse_ioread(&parse->parseio, (unsigned int)(*s++), &ts))
{
- struct recvbuf buf;
+ struct recvbuf *buf;
/*
* got something good to eat
*/
if (!PARSE_PPS(parse->parseio.parse_dtime.parse_state))
{
+#ifdef HAVE_PPSAPI
+ if (parse->flags & PARSE_PPSCLOCK)
+ {
+ struct timespec pps_timeout;
+ pps_info_t pps_info;
+
+ pps_timeout.tv_sec = 0;
+ pps_timeout.tv_nsec = 0;
+
+ if (time_pps_fetch(parse->ppshandle, PPS_TSFMT_TSPEC, &pps_info,
+ &pps_timeout) == 0)
+ {
+ if (pps_info.assert_sequence + pps_info.clear_sequence != parse->ppsserial)
+ {
+ double dtemp;
+
+ struct timespec pts;
+ /*
+ * add PPS time stamp if available via ppsclock module
+ * and not supplied already.
+ */
+ if (parse->flags & PARSE_CLEAR)
+ pts = pps_info.clear_timestamp;
+ else
+ pts = pps_info.assert_timestamp;
+
+ parse->parseio.parse_dtime.parse_ptime.fp.l_ui = pts.tv_sec + JAN_1970;
+
+ dtemp = pts.tv_nsec / 1e9;
+ if (dtemp < 0.) {
+ dtemp += 1;
+ parse->parseio.parse_dtime.parse_ptime.fp.l_ui--;
+ }
+ if (dtemp > 1.) {
+ dtemp -= 1;
+ parse->parseio.parse_dtime.parse_ptime.fp.l_ui++;
+ }
+ parse->parseio.parse_dtime.parse_ptime.fp.l_uf = dtemp * FRAC;
+
+ parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
+#ifdef DEBUG
+ if (debug > 3)
+ {
+ printf(
+ "parse: local_receive: fd %d PPSAPI seq %ld - PPS %s\n",
+ rbufp->fd,
+ (long)pps_info.assert_sequence + (long)pps_info.clear_sequence,
+ lfptoa(&parse->parseio.parse_dtime.parse_ptime.fp, 6));
+ }
+#endif
+ }
+#ifdef DEBUG
+ else
+ {
+ if (debug > 3)
+ {
+ printf(
+ "parse: local_receive: fd %d PPSAPI seq assert %ld, seq clear %ld - NO PPS event\n",
+ rbufp->fd,
+ (long)pps_info.assert_sequence, (long)pps_info.clear_sequence);
+ }
+ }
+#endif
+ parse->ppsserial = pps_info.assert_sequence + pps_info.clear_sequence;
+ }
+#ifdef DEBUG
+ else
+ {
+ if (debug > 3)
+ {
+ printf(
+ "parse: local_receive: fd %d PPSAPI time_pps_fetch errno = %d\n",
+ rbufp->fd,
+ errno);
+ }
+ }
+#endif
+ }
+#else
#ifdef TIOCDCDTIMESTAMP
struct timeval dcd_time;
- if (ioctl(rbufp->fd, TIOCDCDTIMESTAMP, &dcd_time) != -1)
+ if (ioctl(parse->ppsfd, TIOCDCDTIMESTAMP, &dcd_time) != -1)
{
l_fp tstmp;
@@ -1969,7 +2160,7 @@ local_input(
{
printf(
"parse: local_receive: fd %d DCDTIMESTAMP %s\n",
- rbufp->fd,
+ parse->ppsfd,
lfptoa(&tstmp, 6));
printf(" sigio %s\n",
lfptoa(&ts.fp, 6));
@@ -1982,54 +2173,58 @@ local_input(
#else /* TIOCDCDTIMESTAMP */
#if defined(HAVE_STRUCT_PPSCLOCKEV) && (defined(HAVE_CIOGETEV) || defined(HAVE_TIOCGPPSEV))
if (parse->flags & PARSE_PPSCLOCK)
- {
- l_fp tts;
- struct ppsclockev ev;
+ {
+ l_fp tts;
+ struct ppsclockev ev;
#ifdef HAVE_CIOGETEV
- if (ioctl(parse->generic->io.fd, CIOGETEV, (caddr_t)&ev) == 0)
+ if (ioctl(parse->ppsfd, CIOGETEV, (caddr_t)&ev) == 0)
#endif
#ifdef HAVE_TIOCGPPSEV
- if (ioctl(parse->generic->io.fd, TIOCGPPSEV, (caddr_t)&ev) == 0)
+ if (ioctl(parse->ppsfd, TIOCGPPSEV, (caddr_t)&ev) == 0)
#endif
{
- if (ev.serial != parse->ppsserial)
+ if (ev.serial != parse->ppsserial)
+ {
+ /*
+ * add PPS time stamp if available via ppsclock module
+ * and not supplied already.
+ */
+ if (!buftvtots((const char *)&ev.tv, &tts))
{
- /*
- * add PPS time stamp if available via ppsclock module
- * and not supplied already.
- */
- if (!buftvtots((const char *)&ev.tv, &tts))
- {
- ERR(ERR_BADDATA)
- msyslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
- }
- else
- {
- parse->parseio.parse_dtime.parse_ptime.fp = tts;
- parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
- }
+ ERR(ERR_BADDATA)
+ msyslog(LOG_ERR,"parse: local_receive: timestamp conversion error (buftvtots) (ppsclockev.tv)");
+ }
+ else
+ {
+ parse->parseio.parse_dtime.parse_ptime.fp = tts;
+ parse->parseio.parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
}
- parse->ppsserial = ev.serial;
+ }
+ parse->ppsserial = ev.serial;
}
- }
+ }
#endif
#endif /* TIOCDCDTIMESTAMP */
+#endif /* !HAVE_PPSAPI */
}
if (count)
{ /* simulate receive */
- memmove((caddr_t)buf.recv_buffer,
- (caddr_t)&parse->parseio.parse_dtime,
- sizeof(parsetime_t));
+ buf = get_free_recv_buffer();
+ if (buf != NULL) {
+ memmove((caddr_t)buf->recv_buffer,
+ (caddr_t)&parse->parseio.parse_dtime,
+ sizeof(parsetime_t));
+ buf->recv_length = sizeof(parsetime_t);
+ buf->recv_time = rbufp->recv_time;
+ buf->srcadr = rbufp->srcadr;
+ buf->dstadr = rbufp->dstadr;
+ buf->receiver = rbufp->receiver;
+ buf->fd = rbufp->fd;
+ buf->X_from_where = rbufp->X_from_where;
+ add_full_recv_buffer(buf);
+ }
parse_iodone(&parse->parseio);
- buf.recv_length = sizeof(parsetime_t);
- buf.recv_time = rbufp->recv_time;
- buf.srcadr = rbufp->srcadr;
- buf.dstadr = rbufp->dstadr;
- buf.fd = rbufp->fd;
- buf.next = 0;
- buf.X_from_where = rbufp->X_from_where;
- rbufp->receiver(&buf);
}
else
{
@@ -2064,7 +2259,6 @@ local_receive(
ERR(ERR_BADIO)
msyslog(LOG_ERR,"PARSE receiver #%d: local_receive: bad size (got %d expected %d)",
CLK_UNIT(parse->peer), rbufp->recv_length, (int)sizeof(parsetime_t));
- parse->generic->baddata++;
parse_event(parse, CEVNT_BADREPLY);
return;
}
@@ -2077,16 +2271,16 @@ local_receive(
#ifdef DEBUG
if (debug > 3)
{
- printf("PARSE receiver #%d: status %06x, state %08x, time %lx.%08lx, stime %lx.%08lx, ptime %lx.%08lx\n",
+ printf("PARSE receiver #%d: status %06x, state %08x, time(fp) %lx.%08lx, stime(fp) %lx.%08lx, ptime(fp) %lx.%08lx\n",
CLK_UNIT(parse->peer),
(unsigned int)parsetime.parse_status,
(unsigned int)parsetime.parse_state,
- (long)parsetime.parse_time.tv.tv_sec,
- (long)parsetime.parse_time.tv.tv_usec,
- (long)parsetime.parse_stime.tv.tv_sec,
- (long)parsetime.parse_stime.tv.tv_usec,
- (long)parsetime.parse_ptime.tv.tv_sec,
- (long)parsetime.parse_ptime.tv.tv_usec);
+ (unsigned long)parsetime.parse_time.fp.l_ui,
+ (unsigned long)parsetime.parse_time.fp.l_uf,
+ (unsigned long)parsetime.parse_stime.fp.l_ui,
+ (unsigned long)parsetime.parse_stime.fp.l_uf,
+ (unsigned long)parsetime.parse_ptime.fp.l_ui,
+ (unsigned long)parsetime.parse_ptime.fp.l_uf);
}
#endif
@@ -2124,7 +2318,8 @@ init_iobinding(
static char *
parsestate(
u_long lstate,
- char *buffer
+ char *buffer,
+ int size
)
{
static struct bits
@@ -2161,31 +2356,35 @@ parsestate(
{ 0 }
};
int i;
+ char *s, *t;
+
*buffer = '\0';
+ s = t = buffer;
i = 0;
while (flagstrings[i].bit)
{
if (flagstrings[i].bit & lstate)
{
- if (buffer[0])
- strcat(buffer, "; ");
- strcat(buffer, flagstrings[i].name);
+ if (s != t)
+ strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
+ strncat(t, flagstrings[i].name, BUFFER_SIZES(buffer, t, size));
+ t += strlen(t);
}
i++;
}
if (lstate & (PARSEB_S_LEAP|PARSEB_S_ANTENNA|PARSEB_S_PPS|PARSEB_S_POSITION))
{
- char *s, *t;
+ if (s != t)
+ strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
- if (buffer[0])
- strcat(buffer, "; ");
+ t += strlen(t);
- strcat(buffer, "(");
+ strncpy(t, "(", BUFFER_SIZES(buffer, t, size));
- t = s = buffer + strlen(buffer);
+ s = t = t + strlen(t);
i = 0;
while (sflagstrings[i].bit)
@@ -2194,16 +2393,16 @@ parsestate(
{
if (t != s)
{
- strcpy(t, "; ");
+ strncpy(t, "; ", BUFFER_SIZES(buffer, t, size));
t += 2;
}
- strcpy(t, sflagstrings[i].name);
+ strncpy(t, sflagstrings[i].name, BUFFER_SIZES(buffer, t, size));
t += strlen(t);
}
i++;
}
- strcpy(t, ")");
+ strncpy(t, ")", BUFFER_SIZES(buffer, t, size));
}
return buffer;
}
@@ -2214,7 +2413,8 @@ parsestate(
static char *
parsestatus(
u_long lstate,
- char *buffer
+ char *buffer,
+ int size
)
{
static struct bits
@@ -2242,8 +2442,8 @@ parsestatus(
if (flagstrings[i].bit & lstate)
{
if (buffer[0])
- strcat(buffer, "; ");
- strcat(buffer, flagstrings[i].name);
+ strncat(buffer, "; ", size);
+ strncat(buffer, flagstrings[i].name, size);
}
i++;
}
@@ -2287,7 +2487,7 @@ clockstatus(
i++;
}
- sprintf(buffer, "unknown #%ld", (u_long)lstate);
+ snprintf(buffer, sizeof(buffer), "unknown #%ld", (u_long)lstate);
return buffer;
}
@@ -2303,12 +2503,13 @@ l_mktime(
{
u_long tmp, m, s;
static char buffer[40];
+ char *t;
buffer[0] = '\0';
if ((tmp = delta / (60*60*24)) != 0)
{
- sprintf(buffer, "%ldd+", (u_long)tmp);
+ snprintf(buffer, BUFFER_SIZE(buffer, buffer), "%ldd+", (u_long)tmp);
delta -= tmp * 60*60*24;
}
@@ -2317,8 +2518,10 @@ l_mktime(
m = delta % 60;
delta /= 60;
- sprintf(buffer+strlen(buffer), "%02d:%02d:%02d",
- (int)delta, (int)m, (int)s);
+ t = buffer + strlen(buffer);
+
+ snprintf(t, BUFFER_SIZE(buffer, t), "%02d:%02d:%02d",
+ (int)delta, (int)m, (int)s);
return buffer;
}
@@ -2377,7 +2580,7 @@ parse_statistics(
*/
static void
cparse_statistics(
- register struct parseunit *parse
+ struct parseunit *parse
)
{
if (parse->laststatistic + PARSESTATISTICS < current_time)
@@ -2390,16 +2593,6 @@ cparse_statistics(
**/
/*--------------------------------------------------
- * parse_init - initialize internal parse driver data
- */
-static void
-parse_init(void)
-{
- memset((caddr_t)parseunits, 0, sizeof parseunits);
-}
-
-
-/*--------------------------------------------------
* parse_shutdown - shut down a PARSE clock
*/
static void
@@ -2408,15 +2601,32 @@ parse_shutdown(
struct peer *peer
)
{
- struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
+ struct parseunit *parse = (struct parseunit *)0;
+
+ if (peer && peer->procptr)
+ parse = (struct parseunit *)peer->procptr->unitptr;
- if (parse && !parse->peer)
+ if (!parse)
{
- msyslog(LOG_ERR,
- "PARSE receiver #%d: parse_shutdown: INTERNAL ERROR, unit not in use", unit);
+ /* nothing to clean up */
return;
}
+ if (!parse->peer)
+ {
+ msyslog(LOG_INFO, "PARSE receiver #%d: INTERNAL ERROR - unit already inactive - shutdown ignored", unit);
+ return;
+ }
+
+#ifdef HAVE_PPSAPI
+ if (parse->flags & PARSE_PPSCLOCK)
+ {
+ (void)time_pps_destroy(parse->ppshandle);
+ }
+#endif
+ if (parse->generic->io.fd != parse->ppsfd && parse->ppsfd != -1)
+ (void)close(parse->ppsfd); /* close separate PPS source */
+
/*
* print statistics a last time and
* stop statistics machine
@@ -2428,6 +2638,9 @@ parse_shutdown(
parse->parse_type->cl_end(parse);
}
+ /*
+ * cleanup before leaving this world
+ */
if (parse->binding)
PARSE_END(parse);
@@ -2443,9 +2656,138 @@ parse_shutdown(
CLK_UNIT(parse->peer), parse->parse_type->cl_description);
parse->peer = (struct peer *)0; /* unused now */
+ peer->procptr->unitptr = (caddr_t)0;
free(parse);
}
+#ifdef HAVE_PPSAPI
+/*----------------------------------------
+ * set up HARDPPS via PPSAPI
+ */
+static void
+parse_hardpps(
+ struct parseunit *parse,
+ int mode
+ )
+{
+ if (parse->hardppsstate == mode)
+ return;
+
+ if (CLK_PPS(parse->peer) && (parse->flags & PARSE_PPSKERNEL)) {
+ int i = 0;
+
+ if (mode == PARSE_HARDPPS_ENABLE)
+ {
+ if (parse->flags & PARSE_CLEAR)
+ i = PPS_CAPTURECLEAR;
+ else
+ i = PPS_CAPTUREASSERT;
+ }
+
+ if (time_pps_kcbind(parse->ppshandle, PPS_KC_HARDPPS, i,
+ PPS_TSFMT_TSPEC) < 0) {
+ msyslog(LOG_ERR, "PARSE receiver #%d: time_pps_kcbind failed: %m",
+ CLK_UNIT(parse->peer));
+ } else {
+ NLOG(NLOG_CLOCKINFO)
+ msyslog(LOG_INFO, "PARSE receiver #%d: kernel PPS synchronisation %sabled",
+ CLK_UNIT(parse->peer), (mode == PARSE_HARDPPS_ENABLE) ? "en" : "dis");
+ /*
+ * tell the rest, that we have a kernel PPS source, iff we ever enable HARDPPS
+ */
+ if (mode == PARSE_HARDPPS_ENABLE)
+ pps_enable = 1;
+ }
+ }
+
+ parse->hardppsstate = mode;
+}
+
+/*----------------------------------------
+ * set up PPS via PPSAPI
+ */
+static int
+parse_ppsapi(
+ struct parseunit *parse
+ )
+{
+ int cap, mode, mode1;
+ char *cp;
+
+ parse->flags &= ~PARSE_PPSCLOCK;
+
+ if (time_pps_getcap(parse->ppshandle, &cap) < 0) {
+ msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getcap failed: %m",
+ CLK_UNIT(parse->peer));
+
+ return 0;
+ }
+
+ if (time_pps_getparams(parse->ppshandle, &parse->ppsparams) < 0) {
+ msyslog(LOG_ERR, "PARSE receiver #%d: parse_ppsapi: time_pps_getparams failed: %m",
+ CLK_UNIT(parse->peer));
+ return 0;
+ }
+
+ /* nb. only turn things on, if someone else has turned something
+ * on before we get here, leave it alone!
+ */
+
+ if (parse->flags & PARSE_CLEAR) {
+ cp = "CLEAR";
+ mode = PPS_CAPTURECLEAR;
+ mode1 = PPS_OFFSETCLEAR;
+ } else {
+ cp = "ASSERT";
+ mode = PPS_CAPTUREASSERT;
+ mode1 = PPS_OFFSETASSERT;
+ }
+
+ msyslog(LOG_INFO, "PARSE receiver #%d: initializing PPS to %s",
+ CLK_UNIT(parse->peer), cp);
+
+ if (!(mode & cap)) {
+ msyslog(LOG_ERR, "PARSE receiver #%d: FAILED to initialize PPS to %s (PPS API capabilities=0x%x)",
+ CLK_UNIT(parse->peer), cp, cap);
+
+ return 0;
+ }
+
+ if (!(mode1 & cap)) {
+ msyslog(LOG_WARNING, "PARSE receiver #%d: Cannot set PPS_%sCLEAR, this will increase jitter (PPS API capabilities=0x%x)",
+ CLK_UNIT(parse->peer), cp, cap);
+ mode1 = 0;
+ } else {
+ if (mode1 == PPS_OFFSETCLEAR)
+ {
+ parse->ppsparams.clear_offset.tv_sec = -parse->ppsphaseadjust;
+ parse->ppsparams.clear_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
+ }
+
+ if (mode1 == PPS_OFFSETASSERT)
+ {
+ parse->ppsparams.assert_offset.tv_sec = -parse->ppsphaseadjust;
+ parse->ppsparams.assert_offset.tv_nsec = -1e9*(parse->ppsphaseadjust - (long)parse->ppsphaseadjust);
+ }
+ }
+
+ /* only set what is legal */
+
+ parse->ppsparams.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
+
+ if (time_pps_setparams(parse->ppshandle, &parse->ppsparams) < 0) {
+ msyslog(LOG_ERR, "PARSE receiver #%d: FAILED set PPS parameters: %m",
+ CLK_UNIT(parse->peer));
+ return 0;
+ }
+
+ parse->flags |= PARSE_PPSCLOCK;
+ return 1;
+}
+#else
+#define parse_hardpps(_PARSE_, _MODE_) /* empty */
+#endif
+
/*--------------------------------------------------
* parse_start - open the PARSE devices and initialize data for processing
*/
@@ -2465,9 +2807,20 @@ parse_start(
#endif
struct parseunit * parse;
char parsedev[sizeof(PARSEDEVICE)+20];
+ char parseppsdev[sizeof(PARSEPPSDEVICE)+20];
parsectl_t tmp_ctl;
u_int type;
+ /*
+ * get out Copyright information once
+ */
+ if (!notice)
+ {
+ NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
+ msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-2006, Frank Kardel");
+ notice = 1;
+ }
+
type = CLK_TYPE(peer);
unit = CLK_UNIT(peer);
@@ -2481,7 +2834,8 @@ parse_start(
/*
* Unit okay, attempt to open the device.
*/
- (void) sprintf(parsedev, PARSEDEVICE, unit);
+ (void) snprintf(parsedev, sizeof(parsedev), PARSEDEVICE, unit);
+ (void) snprintf(parseppsdev, sizeof(parsedev), PARSEPPSDEVICE, unit);
#ifndef O_NOCTTY
#define O_NOCTTY 0
@@ -2512,15 +2866,14 @@ parse_start(
parse->generic->timestarted = current_time;
parse->lastchange = current_time;
- parse->generic->currentstatus = CEVNT_TIMEOUT; /* expect the worst */
-
parse->flags = 0;
parse->pollneeddata = 0;
parse->laststatistic = current_time;
parse->lastformat = (unsigned short)~0; /* assume no format known */
- parse->time.parse_status = (unsigned short)~0; /* be sure to mark initial status change */
+ parse->timedata.parse_status = (unsigned short)~0; /* be sure to mark initial status change */
parse->lastmissed = 0; /* assume got everything */
parse->ppsserial = 0;
+ parse->ppsfd = -1;
parse->localdata = (void *)0;
parse->localstate = 0;
parse->kv = (struct ctl_var *)0;
@@ -2529,17 +2882,21 @@ parse_start(
parse->parse_type = &parse_clockinfo[type];
+ parse->maxunsync = parse->parse_type->cl_maxunsync;
+
parse->generic->fudgetime1 = parse->parse_type->cl_basedelay;
parse->generic->fudgetime2 = 0.0;
+ parse->ppsphaseadjust = parse->generic->fudgetime2;
- parse->generic->clockdesc = parse->parse_type->cl_description;
+ parse->generic->clockdesc = parse->parse_type->cl_description;
peer->rootdelay = parse->parse_type->cl_rootdelay;
peer->sstclktype = parse->parse_type->cl_type;
peer->precision = sys_precision;
peer->stratum = STRATUM_REFCLOCK;
+
if (peer->stratum <= 1)
memmove((char *)&parse->generic->refid, parse->parse_type->cl_id, 4);
else
@@ -2607,38 +2964,84 @@ parse_start(
tio.c_cflag |= parse_clockinfo[type].cl_speed;
#endif
+ /*
+ * set up pps device
+ * if the PARSEPPSDEVICE can be opened that will be used
+ * for PPS else PARSEDEVICE will be used
+ */
+ parse->ppsfd = open(parseppsdev, O_RDWR | O_NOCTTY
+#ifdef O_NONBLOCK
+ | O_NONBLOCK
+#endif
+ , 0777);
+
+ if (parse->ppsfd == -1)
+ {
+ parse->ppsfd = fd232;
+ }
+
+/*
+ * Linux PPS - the old way
+ */
#if defined(HAVE_TIO_SERIAL_STUFF) /* Linux hack: define PPS interface */
{
- struct serial_struct ss;
- if (ioctl(fd232, TIOCGSERIAL, &ss) < 0 ||
- (
+ struct serial_struct ss;
+ if (ioctl(parse->ppsfd, TIOCGSERIAL, &ss) < 0 ||
+ (
#ifdef ASYNC_LOW_LATENCY
- ss.flags |= ASYNC_LOW_LATENCY,
+ ss.flags |= ASYNC_LOW_LATENCY,
+#endif
+#ifndef HAVE_PPSAPI
+#ifdef ASYNC_PPS_CD_NEG
+ ss.flags |= ASYNC_PPS_CD_NEG,
#endif
+#endif
+ ioctl(parse->ppsfd, TIOCSSERIAL, &ss)) < 0) {
+ msyslog(LOG_NOTICE, "refclock_parse: TIOCSSERIAL fd %d, %m", parse->ppsfd);
+ msyslog(LOG_NOTICE,
+ "refclock_parse: optional PPS processing not available");
+ } else {
+ parse->flags |= PARSE_PPSCLOCK;
#ifdef ASYNC_PPS_CD_NEG
- ss.flags |= ASYNC_PPS_CD_NEG,
+ NLOG(NLOG_CLOCKINFO)
+ msyslog(LOG_INFO,
+ "refclock_parse: PPS detection on");
#endif
- ioctl(fd232, TIOCSSERIAL, &ss)) < 0) {
- msyslog(LOG_NOTICE, "refclock_parse: TIOCSSERIAL fd %d, %m", fd232);
- msyslog(LOG_NOTICE,
- "refclock_parse: optional PPS processing not available");
- } else {
- parse->flags |= PARSE_PPSCLOCK;
- msyslog(LOG_INFO,
- "refclock_parse: PPS detection on");
- }
+ }
}
#endif
+
+/*
+ * SUN the Solaris way
+ */
#ifdef HAVE_TIOCSPPS /* SUN PPS support */
if (CLK_PPS(parse->peer))
- {
- int i = 1;
+ {
+ int i = 1;
- if (ioctl(fd232, TIOCSPPS, (caddr_t)&i) == 0)
- {
- parse->flags |= PARSE_PPSCLOCK;
- }
- }
+ if (ioctl(parse->ppsfd, TIOCSPPS, (caddr_t)&i) == 0)
+ {
+ parse->flags |= PARSE_PPSCLOCK;
+ }
+ }
+#endif
+
+/*
+ * PPS via PPSAPI
+ */
+#if defined(HAVE_PPSAPI)
+ parse->hardppsstate = PARSE_HARDPPS_DISABLE;
+ if (CLK_PPS(parse->peer))
+ {
+ if (time_pps_create(parse->ppsfd, &parse->ppshandle) < 0)
+ {
+ msyslog(LOG_NOTICE, "PARSE receiver #%d: parse_start: could not set up PPS: %m", CLK_UNIT(parse->peer));
+ }
+ else
+ {
+ parse_ppsapi(parse);
+ }
+ }
#endif
if (TTY_SETATTR(fd232, &tio) == -1)
@@ -2650,22 +3053,12 @@ parse_start(
}
/*
- * Insert in async io device list.
+ * pick correct input machine
*/
parse->generic->io.srcclock = (caddr_t)parse;
parse->generic->io.datalen = 0;
- if (!io_addclock(&parse->generic->io))
- {
- msyslog(LOG_ERR,
- "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
- parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
- return 0;
- }
-
parse->binding = init_iobinding(parse);
- parse->generic->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
- parse->generic->io.io_input = parse->binding->bd_io_input; /* pick correct input routine */
if (parse->binding == (bind_t *)0)
{
@@ -2674,6 +3067,9 @@ parse_start(
return 0; /* well, ok - special initialisation broke */
}
+ parse->generic->io.clock_recv = parse->binding->bd_receive; /* pick correct receive routine */
+ parse->generic->io.io_input = parse->binding->bd_io_input; /* pick correct input routine */
+
/*
* as we always(?) get 8 bit chars we want to be
* sure, that the upper bits are zero for less
@@ -2708,7 +3104,7 @@ parse_start(
return 0; /* well, ok - special initialisation broke */
}
- strcpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format);
+ strncpy(tmp_ctl.parseformat.parse_buffer, parse->parse_type->cl_format, sizeof(tmp_ctl.parseformat.parse_buffer));
tmp_ctl.parseformat.parse_count = strlen(tmp_ctl.parseformat.parse_buffer);
if (!PARSE_SETFMT(parse, &tmp_ctl))
@@ -2724,11 +3120,8 @@ parse_start(
#ifdef HAVE_TERMIOS
(void) tcflush(parse->generic->io.fd, TCIOFLUSH);
#else
-#ifdef TCFLSH
+#if defined(TCFLSH) && defined(TCIOFLUSH)
{
-#ifndef TCIOFLUSH
-#define TCIOFLUSH 2
-#endif
int flshcmd = TCIOFLUSH;
(void) ioctl(parse->generic->io.fd, TCFLSH, (caddr_t)&flshcmd);
@@ -2749,13 +3142,14 @@ parse_start(
}
/*
- * get out Copyright information once
+ * Insert in async io device list.
*/
- if (!notice)
+ if (!io_addclock(&parse->generic->io))
{
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "NTP PARSE support: Copyright (c) 1989-1999, Frank Kardel");
- notice = 1;
+ msyslog(LOG_ERR,
+ "PARSE receiver #%d: parse_start: addclock %s fails (ABORT - clock type requires async io)", CLK_UNIT(parse->peer), parsedev);
+ parse_shutdown(CLK_UNIT(parse->peer), peer); /* let our cleaning staff do the work */
+ return 0;
}
/*
@@ -2764,33 +3158,99 @@ parse_start(
NLOG(NLOG_CLOCKINFO)
{
/* conditional if clause for conditional syslog */
- msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (device %s) added",
+ msyslog(LOG_INFO, "PARSE receiver #%d: reference clock \"%s\" (I/O device %s, PPS device %s) added",
CLK_UNIT(parse->peer),
- parse->parse_type->cl_description, parsedev);
+ parse->parse_type->cl_description, parsedev,
+ (parse->ppsfd != parse->generic->io.fd) ? parseppsdev : parsedev);
- msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, %sPPS support, trust time %s, precision %d",
+ msyslog(LOG_INFO, "PARSE receiver #%d: Stratum %d, trust time %s, precision %d",
CLK_UNIT(parse->peer),
- parse->peer->stratum, CLK_PPS(parse->peer) ? "" : "no ",
- l_mktime(parse->parse_type->cl_maxunsync), parse->peer->precision);
+ parse->peer->stratum,
+ l_mktime(parse->maxunsync), parse->peer->precision);
- msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phaseadjust %.6f s, %s IO handling",
+ msyslog(LOG_INFO, "PARSE receiver #%d: rootdelay %.6f s, phase adjustment %.6f s, PPS phase adjustment %.6f s, %s IO handling",
CLK_UNIT(parse->peer),
parse->parse_type->cl_rootdelay,
parse->generic->fudgetime1,
- parse->binding->bd_description);
+ parse->ppsphaseadjust,
+ parse->binding->bd_description);
- msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
+ msyslog(LOG_INFO, "PARSE receiver #%d: Format recognition: %s", CLK_UNIT(parse->peer),
parse->parse_type->cl_format);
-#ifdef PPS
- msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS ioctl support", CLK_UNIT(parse->peer),
- (parse->flags & PARSE_PPSCLOCK) ? "" : "NO ");
+ msyslog(LOG_INFO, "PARSE receiver #%d: %sPPS support%s", CLK_UNIT(parse->peer),
+ CLK_PPS(parse->peer) ? "" : "NO ",
+ CLK_PPS(parse->peer) ?
+#ifdef PPS_METHOD
+ " (implementation " PPS_METHOD ")"
+#else
+ ""
#endif
+ : ""
+ );
}
return 1;
}
/*--------------------------------------------------
+ * parse_ctl - process changes on flags/time values
+ */
+static void
+parse_ctl(
+ struct parseunit *parse,
+ struct refclockstat *in
+ )
+{
+ if (in)
+ {
+ if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
+ {
+ parse->flags = (parse->flags & ~(CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4)) |
+ (in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4));
+#if defined(HAVE_PPSAPI)
+ if (CLK_PPS(parse->peer))
+ {
+ parse_ppsapi(parse);
+ }
+#endif
+ }
+
+ if (in->haveflags & CLK_HAVETIME1)
+ {
+ parse->generic->fudgetime1 = in->fudgetime1;
+ msyslog(LOG_INFO, "PARSE receiver #%d: new phase adjustment %.6f s",
+ CLK_UNIT(parse->peer),
+ parse->generic->fudgetime1);
+ }
+
+ if (in->haveflags & CLK_HAVETIME2)
+ {
+ parse->generic->fudgetime2 = in->fudgetime2;
+ if (parse->flags & PARSE_TRUSTTIME)
+ {
+ parse->maxunsync = (u_long)ABS(in->fudgetime2);
+ msyslog(LOG_INFO, "PARSE receiver #%d: new trust time %s",
+ CLK_UNIT(parse->peer),
+ l_mktime(parse->maxunsync));
+ }
+ else
+ {
+ parse->ppsphaseadjust = in->fudgetime2;
+ msyslog(LOG_INFO, "PARSE receiver #%d: new PPS phase adjustment %.6f s",
+ CLK_UNIT(parse->peer),
+ parse->ppsphaseadjust);
+#if defined(HAVE_PPSAPI)
+ if (CLK_PPS(parse->peer))
+ {
+ parse_ppsapi(parse);
+ }
+#endif
+ }
+ }
+ }
+}
+
+/*--------------------------------------------------
* parse_poll - called by the transmit procedure
*/
static void
@@ -2821,12 +3281,11 @@ parse_poll(
* start worrying when exceeding a poll inteval
* bad news - didn't get a response last time
*/
- parse->generic->noreply++;
parse->lastmissed = current_time;
parse_event(parse, CEVNT_TIMEOUT);
ERR(ERR_NODATA)
- msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / cableling)", CLK_UNIT(parse->peer));
+ msyslog(LOG_WARNING, "PARSE receiver #%d: no data from device within poll interval (check receiver / wiring)", CLK_UNIT(parse->peer));
}
/*
@@ -2857,7 +3316,7 @@ parse_control(
struct peer *peer
)
{
- register struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
+ struct parseunit *parse = (struct parseunit *)peer->procptr->unitptr;
parsectl_t tmpctl;
static char outstatus[400]; /* status output buffer */
@@ -2878,32 +3337,36 @@ parse_control(
unit = CLK_UNIT(parse->peer);
- if (in)
- {
- if (in->haveflags & (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4))
- {
- parse->flags = in->flags & (CLK_FLAG1|CLK_FLAG2|CLK_FLAG3|CLK_FLAG4);
- }
- }
-
+ /*
+ * handle changes
+ */
+ parse_ctl(parse, in);
+
+ /*
+ * supply data
+ */
if (out)
{
u_long sum = 0;
- char *t, *tt, *start;
+ char *tt, *start;
int i;
outstatus[0] = '\0';
out->type = REFCLK_PARSE;
- out->haveflags |= CLK_HAVETIME2;
+
+ /*
+ * keep fudgetime2 in sync with TRUSTTIME/MAXUNSYNC flag1
+ */
+ parse->generic->fudgetime2 = (parse->flags & PARSE_TRUSTTIME) ? (double)parse->maxunsync : parse->ppsphaseadjust;
/*
* figure out skew between PPS and RS232 - just for informational
- * purposes - returned in time2 value
+ * purposes
*/
- if (PARSE_SYNC(parse->time.parse_state))
+ if (PARSE_SYNC(parse->timedata.parse_state))
{
- if (PARSE_PPS(parse->time.parse_state) && PARSE_TIMECODE(parse->time.parse_state))
+ if (PARSE_PPS(parse->timedata.parse_state) && PARSE_TIMECODE(parse->timedata.parse_state))
{
l_fp off;
@@ -2911,31 +3374,30 @@ parse_control(
* we have a PPS and RS232 signal - calculate the skew
* WARNING: assumes on TIMECODE == PULSE (timecode after pulse)
*/
- off = parse->time.parse_stime.fp;
- L_SUB(&off, &parse->time.parse_ptime.fp); /* true offset */
+ off = parse->timedata.parse_stime.fp;
+ L_SUB(&off, &parse->timedata.parse_ptime.fp); /* true offset */
tt = add_var(&out->kv_list, 80, RO);
- sprintf(tt, "refclock_ppsskew=%s", lfptoms(&off, 6));
+ snprintf(tt, 80, "refclock_ppsskew=%s", lfptoms(&off, 6));
}
}
- if (PARSE_PPS(parse->time.parse_state))
+ if (PARSE_PPS(parse->timedata.parse_state))
{
tt = add_var(&out->kv_list, 80, RO|DEF);
- sprintf(tt, "refclock_ppstime=\"%s\"", gmprettydate(&parse->time.parse_ptime.fp));
+ snprintf(tt, 80, "refclock_ppstime=\"%s\"", gmprettydate(&parse->timedata.parse_ptime.fp));
}
- tt = add_var(&out->kv_list, 128, RO|DEF);
- sprintf(tt, "refclock_time=\"");
+ start = tt = add_var(&out->kv_list, 128, RO|DEF);
+ snprintf(tt, 128, "refclock_time=\"");
tt += strlen(tt);
- if (parse->time.parse_time.fp.l_ui == 0)
+ if (parse->timedata.parse_time.fp.l_ui == 0)
{
- strcpy(tt, "<UNDEFINED>\"");
+ strncpy(tt, "<UNDEFINED>\"", BUFFER_SIZES(start, tt, 128));
}
else
{
- sprintf(tt, "%s\"", gmprettydate(&parse->time.parse_time.fp));
- t = tt + strlen(tt);
+ snprintf(tt, 128, "%s\"", gmprettydate(&parse->timedata.parse_time.fp));
}
if (!PARSE_GETTIMECODE(parse, &tmpctl))
@@ -2945,25 +3407,24 @@ parse_control(
}
else
{
- tt = add_var(&out->kv_list, 512, RO|DEF);
- sprintf(tt, "refclock_status=\"");
+ start = tt = add_var(&out->kv_list, 512, RO|DEF);
+ snprintf(tt, 512, "refclock_status=\"");
tt += strlen(tt);
/*
* copy PPS flags from last read transaction (informational only)
*/
- tmpctl.parsegettc.parse_state |= parse->time.parse_state &
+ tmpctl.parsegettc.parse_state |= parse->timedata.parse_state &
(PARSEB_PPS|PARSEB_S_PPS);
- (void) parsestate(tmpctl.parsegettc.parse_state, tt);
+ (void) parsestate(tmpctl.parsegettc.parse_state, tt, BUFFER_SIZES(start, tt, 512));
- strcat(tt, "\"");
+ strncat(tt, "\"", BUFFER_SIZES(start, tt, 512));
if (tmpctl.parsegettc.parse_count)
mkascii(outstatus+strlen(outstatus), (int)(sizeof(outstatus)- strlen(outstatus) - 1),
- tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1));
+ tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count));
- parse->generic->badformat += tmpctl.parsegettc.parse_badformat;
}
tmpctl.parseformat.parse_format = tmpctl.parsegettc.parse_format;
@@ -2976,10 +3437,10 @@ parse_control(
else
{
tt = add_var(&out->kv_list, 80, RO|DEF);
- sprintf(tt, "refclock_format=\"");
+ snprintf(tt, 80, "refclock_format=\"");
strncat(tt, tmpctl.parseformat.parse_buffer, tmpctl.parseformat.parse_count);
- strcat(tt,"\"");
+ strncat(tt,"\"", 80);
}
/*
@@ -2987,7 +3448,7 @@ parse_control(
*/
start = tt = add_var(&out->kv_list, LEN_STATES, RO|DEF);
- strcpy(tt, "refclock_states=\"");
+ strncpy(tt, "refclock_states=\"", LEN_STATES);
tt += strlen(tt);
for (i = 0; i <= CEVNT_MAX; i++)
@@ -3014,7 +3475,7 @@ parse_control(
char item[80];
int count;
- sprintf(item, "%s%s%s: %s (%d.%02d%%)",
+ snprintf(item, 80, "%s%s%s: %s (%d.%02d%%)",
sum ? "; " : "",
(parse->generic->currentstatus == i) ? "*" : "",
clockstatus((unsigned int)i),
@@ -3022,23 +3483,23 @@ parse_control(
(int)(percent / 100), (int)(percent % 100));
if ((count = strlen(item)) < (LEN_STATES - 40 - (tt - start)))
{
- strcpy(tt, item);
+ strncpy(tt, item, BUFFER_SIZES(start, tt, LEN_STATES));
tt += count;
}
sum += s_time;
}
}
- sprintf(tt, "; running time: %s\"", l_mktime(sum));
+ snprintf(tt, BUFFER_SIZES(start, tt, LEN_STATES), "; running time: %s\"", l_mktime(sum));
tt = add_var(&out->kv_list, 32, RO);
- sprintf(tt, "refclock_id=\"%s\"", parse->parse_type->cl_id);
+ snprintf(tt, 32, "refclock_id=\"%s\"", parse->parse_type->cl_id);
tt = add_var(&out->kv_list, 80, RO);
- sprintf(tt, "refclock_iomode=\"%s\"", parse->binding->bd_description);
+ snprintf(tt, 80, "refclock_iomode=\"%s\"", parse->binding->bd_description);
tt = add_var(&out->kv_list, 128, RO);
- sprintf(tt, "refclock_driver_version=\"%s\"", rcsid);
+ snprintf(tt, 128, "refclock_driver_version=\"%s\"", rcsid);
{
struct ctl_var *k;
@@ -3062,6 +3523,7 @@ parse_control(
/*--------------------------------------------------
* event handling - note that nominal events will also be posted
+ * keep track of state dwelling times
*/
static void
parse_event(
@@ -3074,41 +3536,17 @@ parse_event(
parse->statetime[parse->generic->currentstatus] += current_time - parse->lastchange;
parse->lastchange = current_time;
- parse->generic->currentstatus = (u_char)event;
-
if (parse->parse_type->cl_event)
parse->parse_type->cl_event(parse, event);
- if (event != CEVNT_NOMINAL)
- {
- parse->generic->lastevent = parse->generic->currentstatus;
- }
- else
+ if (event == CEVNT_NOMINAL)
{
NLOG(NLOG_CLOCKSTATUS)
msyslog(LOG_INFO, "PARSE receiver #%d: SYNCHRONIZED",
CLK_UNIT(parse->peer));
}
- if (event == CEVNT_FAULT)
- {
- NLOG(NLOG_CLOCKEVENT) /* conditional if clause for conditional syslog */
- ERR(ERR_BADEVENT)
- msyslog(LOG_ERR,
- "clock %s fault '%s' (0x%02x)", refnumtoa(&parse->peer->srcadr), ceventstr(event),
- (u_int)event);
- }
- else
- {
- NLOG(NLOG_CLOCKEVENT) /* conditional if clause for conditional syslog */
- if (event == CEVNT_NOMINAL || list_err(parse, ERR_BADEVENT))
- msyslog(LOG_INFO,
- "clock %s event '%s' (0x%02x)", refnumtoa(&parse->peer->srcadr), ceventstr(event),
- (u_int)event);
- }
-
- report_event(EVNT_PEERCLOCK, parse->peer);
- report_event(EVNT_CLOCKEXCPT, parse->peer);
+ refclock_report(parse->peer, event);
}
}
@@ -3130,13 +3568,13 @@ parse_process(
*/
if (((parsetime->parse_status & CVT_MASK) != CVT_OK) &&
((parsetime->parse_status & CVT_MASK) != CVT_NONE) &&
- (parse->time.parse_status != parsetime->parse_status))
+ (parse->timedata.parse_status != parsetime->parse_status))
{
char buffer[400];
NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
msyslog(LOG_WARNING, "PARSE receiver #%d: conversion status \"%s\"",
- CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer));
+ CLK_UNIT(parse->peer), parsestatus(parsetime->parse_status, buffer, sizeof(buffer)));
if ((parsetime->parse_status & CVT_MASK) == CVT_FAIL)
{
@@ -3155,9 +3593,8 @@ parse_process(
else
{
ERR(ERR_BADDATA)
- msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / cableling)",
+ msyslog(LOG_WARNING, "PARSE receiver #%d: FAILED TIMECODE: \"%s\" (check receiver configuration / wiring)",
CLK_UNIT(parse->peer), mkascii(buffer, sizeof buffer, tmpctl.parsegettc.parse_buffer, (unsigned)(tmpctl.parsegettc.parse_count - 1)));
- parse->generic->badformat += tmpctl.parsegettc.parse_badformat;
}
}
}
@@ -3176,10 +3613,17 @@ parse_process(
if ((parsetime->parse_status & CVT_ADDITIONAL) &&
parse->parse_type->cl_message)
parse->parse_type->cl_message(parse, parsetime);
+ /*
+ * save PPS information that comes piggyback
+ */
+ if (PARSE_PPS(parsetime->parse_state))
+ {
+ parse->timedata.parse_state |= PARSEB_PPS|PARSEB_S_PPS;
+ parse->timedata.parse_ptime = parsetime->parse_ptime;
+ }
break; /* well, still waiting - timeout is handled at higher levels */
case CVT_FAIL:
- parse->generic->badformat++;
if (parsetime->parse_status & CVT_BADFMT)
{
parse_event(parse, CEVNT_BADREPLY);
@@ -3229,16 +3673,17 @@ parse_process(
/*
* now, any changes ?
*/
- if (parse->time.parse_state != parsetime->parse_state)
+ if ((parse->timedata.parse_state ^ parsetime->parse_state) &
+ ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS))
{
char tmp1[200];
char tmp2[200];
/*
- * something happend
+ * something happend - except for PPS events
*/
- (void) parsestate(parsetime->parse_state, tmp1);
- (void) parsestate(parse->time.parse_state, tmp2);
+ (void) parsestate(parsetime->parse_state, tmp1, sizeof(tmp1));
+ (void) parsestate(parse->timedata.parse_state, tmp2, sizeof(tmp2));
NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
msyslog(LOG_INFO,"PARSE receiver #%d: STATE CHANGE: %s -> %s",
@@ -3246,9 +3691,18 @@ parse_process(
}
/*
+ * carry on PPS information if still usable
+ */
+ if (PARSE_PPS(parse->timedata.parse_state) && !PARSE_PPS(parsetime->parse_state))
+ {
+ parsetime->parse_state |= PARSEB_PPS|PARSEB_S_PPS;
+ parsetime->parse_ptime = parse->timedata.parse_ptime;
+ }
+
+ /*
* remember for future
*/
- parse->time = *parsetime;
+ parse->timedata = *parsetime;
/*
* check to see, whether the clock did a complete powerup or lost PZF signal
@@ -3351,6 +3805,17 @@ parse_process(
if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
{
l_fp offset;
+ double ppsphaseadjust = parse->ppsphaseadjust;
+
+#ifdef HAVE_PPSAPI
+ /*
+ * set fudge = 0.0 if already included in PPS time stamps
+ */
+ if (parse->ppsparams.mode & (PPS_OFFSETCLEAR|PPS_OFFSETASSERT))
+ {
+ ppsphaseadjust = 0.0;
+ }
+#endif
/*
* we have a PPS signal - much better than the RS232 stuff (we hope)
@@ -3368,7 +3833,7 @@ parse_process(
if (M_ISGEQ(off.l_i, off.l_f, -1, 0x80000000) &&
M_ISGEQ(0, 0x7fffffff, off.l_i, off.l_f))
{
- fudge = parse->generic->fudgetime2; /* pick PPS fudge factor */
+ fudge = ppsphaseadjust; /* pick PPS fudge factor */
/*
* RS232 offsets within [-0.5..0.5[ - take PPS offsets
@@ -3404,7 +3869,7 @@ parse_process(
}
else
{
- fudge = parse->generic->fudgetime2; /* pick PPS fudge factor */
+ fudge = ppsphaseadjust; /* pick PPS fudge factor */
/*
* Well, no time code to guide us - assume on second pulse
* and pray, that we are within [-0.5..0.5[
@@ -3473,35 +3938,22 @@ parse_process(
clear_err(parse, ERR_NODATA);
clear_err(parse, ERR_INTERNAL);
-#ifdef DEBUG
- if (debug > 2)
- {
- printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
- CLK_UNIT(parse->peer),
- prettydate(&reftime),
- prettydate(&rectime),
- fudge);
- }
-#endif
-
- refclock_process_offset(parse->generic, reftime, rectime, fudge);
- if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
- {
- (void) pps_sample(&parse->time.parse_ptime.fp);
- }
-
-
/*
* and now stick it into the clock machine
* samples are only valid iff lastsync is not too old and
* we have seen the clock in sync at least once
* after the last time we didn't see an expected data telegram
+ * at startup being not in sync is also bad just like
+ * POWERUP state
* see the clock states section above for more reasoning
*/
- if (((current_time - parse->lastsync) > parse->parse_type->cl_maxunsync) ||
- (parse->lastsync <= parse->lastmissed))
+ if (((current_time - parse->lastsync) > parse->maxunsync) ||
+ (parse->lastsync < parse->lastmissed) ||
+ ((parse->lastsync == 0) && !PARSE_SYNC(parsetime->parse_state)) ||
+ PARSE_POWERUP(parsetime->parse_state))
{
parse->generic->leap = LEAP_NOTINSYNC;
+ parse->lastsync = 0; /* wait for full sync again */
}
else
{
@@ -3524,15 +3976,49 @@ parse_process(
parse->generic->leap = LEAP_NOWARNING;
}
}
-
+
+ if (parse->generic->leap != LEAP_NOTINSYNC)
+ {
+ /*
+ * only good/trusted samples are interesting
+ */
+#ifdef DEBUG
+ if (debug > 2)
+ {
+ printf("PARSE receiver #%d: refclock_process_offset(reftime=%s, rectime=%s, Fudge=%f)\n",
+ CLK_UNIT(parse->peer),
+ prettydate(&reftime),
+ prettydate(&rectime),
+ fudge);
+ }
+#endif
+ parse->generic->lastref = reftime;
+
+ refclock_process_offset(parse->generic, reftime, rectime, fudge);
+
+ /*
+ * pass PPS information on to PPS clock
+ */
+ if (PARSE_PPS(parsetime->parse_state) && CLK_PPS(parse->peer))
+ {
+ (void) pps_sample(&parse->timedata.parse_ptime.fp);
+ parse_hardpps(parse, PARSE_HARDPPS_ENABLE);
+ }
+ } else {
+ parse_hardpps(parse, PARSE_HARDPPS_DISABLE);
+ }
+
/*
- * ready, unless the machine wants a sample
+ * ready, unless the machine wants a sample or
+ * we are in fast startup mode (peer->dist > MAXDISTANCE)
*/
- if (!parse->pollneeddata)
+ if (!parse->pollneeddata && parse->peer->disp <= MAXDISTANCE)
return;
parse->pollneeddata = 0;
+ parse->timedata.parse_state &= ~(unsigned)(PARSEB_PPS|PARSEB_S_PPS);
+
refclock_receive(parse->peer);
}
@@ -3547,12 +4033,14 @@ mk_utcinfo(
int wnlsf,
int dn,
int dtls,
- int dtlsf
+ int dtlsf,
+ int size
)
{
l_fp leapdate;
+ char *start = t;
- sprintf(t, "current correction %d sec", dtls);
+ snprintf(t, size, "current correction %d sec", dtls);
t += strlen(t);
if (wnlsf < 990)
@@ -3566,12 +4054,12 @@ mk_utcinfo(
if ((dtlsf != dtls) &&
((wnlsf - wnt) < 52))
{
- sprintf(t, ", next correction %d sec on %s, new GPS-UTC offset %d",
+ snprintf(t, BUFFER_SIZES(start, t, size), ", next correction %d sec on %s, new GPS-UTC offset %d",
dtlsf - dtls, gmprettydate(&leapdate), dtlsf);
}
else
{
- sprintf(t, ", last correction on %s",
+ snprintf(t, BUFFER_SIZES(start, t, size), ", last correction on %s",
gmprettydate(&leapdate));
}
}
@@ -3590,7 +4078,7 @@ gps16x_message(
parsetime_t *parsetime
)
{
- if (parse->time.parse_msglen && parsetime->parse_msg[0] == SOH)
+ if (parse->timedata.parse_msglen && parsetime->parse_msg[0] == SOH)
{
GPS_MSG_HDR header;
unsigned char *bufp = (unsigned char *)parsetime->parse_msg + 1;
@@ -3624,12 +4112,12 @@ gps16x_message(
SW_REV gps_sw_rev;
get_mbg_sw_rev(&bufp, &gps_sw_rev);
- sprintf(buffer, "meinberg_gps_version=\"%x.%02x%s%s\"",
+ snprintf(buffer, sizeof(buffer), "meinberg_gps_version=\"%x.%02x%s%s\"",
(gps_sw_rev.code >> 8) & 0xFF,
gps_sw_rev.code & 0xFF,
gps_sw_rev.name[0] ? " " : "",
gps_sw_rev.name);
- set_var(&parse->kv, buffer, 64, RO|DEF);
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
}
break;
@@ -3653,7 +4141,7 @@ gps16x_message(
char *p, *b;
status = get_lsb_short(&bufp);
- sprintf(buffer, "meinberg_gps_status=\"[0x%04x] ", status);
+ snprintf(buffer, sizeof(buffer), "meinberg_gps_status=\"[0x%04x] ", status);
if (status)
{
@@ -3668,7 +4156,7 @@ gps16x_message(
*p++ = ' ';
}
- strcat(p, (const char *)s->string);
+ strncat(p, (const char *)s->string, sizeof(buffer));
}
s++;
}
@@ -3678,10 +4166,10 @@ gps16x_message(
}
else
{
- strcat(buffer, "<OK>\"");
+ strncat(buffer, "<OK>\"", sizeof(buffer));
}
- set_var(&parse->kv, buffer, 64, RO|DEF);
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
}
break;
@@ -3691,7 +4179,7 @@ gps16x_message(
char buffer[256];
get_mbg_xyz(&bufp, xyz);
- sprintf(buffer, "gps_position(XYZ)=\"%s m, %s m, %s m\"",
+ snprintf(buffer, sizeof(buffer), "gps_position(XYZ)=\"%s m, %s m, %s m\"",
mfptoa(xyz[XP].l_ui, xyz[XP].l_uf, 1),
mfptoa(xyz[YP].l_ui, xyz[YP].l_uf, 1),
mfptoa(xyz[ZP].l_ui, xyz[ZP].l_uf, 1));
@@ -3707,7 +4195,7 @@ gps16x_message(
get_mbg_lla(&bufp, lla);
- sprintf(buffer, "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
+ snprintf(buffer, sizeof(buffer), "gps_position(LLA)=\"%s deg, %s deg, %s m\"",
mfptoa(lla[LAT].l_ui, lla[LAT].l_uf, 4),
mfptoa(lla[LON].l_ui, lla[LON].l_uf, 4),
mfptoa(lla[ALT].l_ui, lla[ALT].l_uf, 1));
@@ -3728,55 +4216,54 @@ gps16x_message(
case GPS_ANT_INFO:
{
ANT_INFO antinfo;
- u_char buffer[512];
- u_char *p;
+ char buffer[512];
+ char *p;
get_mbg_antinfo(&bufp, &antinfo);
- sprintf(buffer, "meinberg_antenna_status=\"");
+ snprintf(buffer, sizeof(buffer), "meinberg_antenna_status=\"");
p = buffer + strlen(buffer);
switch (antinfo.status)
{
case ANT_INVALID:
- strcat(p, "<OK>");
+ strncat(p, "<OK>", BUFFER_SIZE(buffer, p));
p += strlen(p);
break;
case ANT_DISCONN:
- strcat(p, "DISCONNECTED since ");
+ strncat(p, "DISCONNECTED since ", BUFFER_SIZE(buffer, p));
NLOG(NLOG_CLOCKSTATUS)
ERR(ERR_BADSTATUS)
msyslog(LOG_ERR,"PARSE receiver #%d: ANTENNA FAILURE: %s",
CLK_UNIT(parse->peer), p);
p += strlen(p);
- mbg_tm_str(&p, &antinfo.tm_disconn);
+ mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
*p = '\0';
break;
case ANT_RECONN:
- strcat(p, "RECONNECTED on ");
+ strncat(p, "RECONNECTED on ", BUFFER_SIZE(buffer, p));
p += strlen(p);
- mbg_tm_str(&p, &antinfo.tm_reconn);
- sprintf(p, ", reconnect clockoffset %c%ld.%07ld s, disconnect time ",
+ mbg_tm_str(&p, &antinfo.tm_reconn, BUFFER_SIZE(buffer, p));
+ snprintf(p, BUFFER_SIZE(buffer, p), ", reconnect clockoffset %c%ld.%07ld s, disconnect time ",
(antinfo.delta_t < 0) ? '-' : '+',
ABS(antinfo.delta_t) / 10000,
ABS(antinfo.delta_t) % 10000);
p += strlen(p);
- mbg_tm_str(&p, &antinfo.tm_disconn);
+ mbg_tm_str(&p, &antinfo.tm_disconn, BUFFER_SIZE(buffer, p));
*p = '\0';
break;
default:
- sprintf(p, "bad status 0x%04x", antinfo.status);
+ snprintf(p, BUFFER_SIZE(buffer, p), "bad status 0x%04x", antinfo.status);
p += strlen(p);
break;
}
- *p++ = '"';
- *p = '\0';
+ strncat(p, "\"", BUFFER_SIZE(buffer, p));
- set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
}
break;
@@ -3786,8 +4273,8 @@ gps16x_message(
case GPS_CFGH:
{
CFGH cfgh;
- u_char buffer[512];
- u_char *p;
+ char buffer[512];
+ char *p;
get_mbg_cfgh(&bufp, &cfgh);
if (cfgh.valid)
@@ -3795,77 +4282,74 @@ gps16x_message(
int i;
p = buffer;
- strcpy(buffer, "gps_tot_51=\"");
+ strncpy(buffer, "gps_tot_51=\"", BUFFER_SIZE(buffer, p));
p += strlen(p);
- mbg_tgps_str(&p, &cfgh.tot_51);
- *p++ = '"';
- *p = '\0';
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
+ mbg_tgps_str(&p, &cfgh.tot_51, BUFFER_SIZE(buffer, p));
+ strncpy(p, "\"", BUFFER_SIZE(buffer, p));
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
p = buffer;
- strcpy(buffer, "gps_tot_63=\"");
+ strncpy(buffer, "gps_tot_63=\"", BUFFER_SIZE(buffer, p));
p += strlen(p);
- mbg_tgps_str(&p, &cfgh.tot_63);
- *p++ = '"';
- *p = '\0';
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
+ mbg_tgps_str(&p, &cfgh.tot_63, BUFFER_SIZE(buffer, p));
+ strncpy(p, "\"", BUFFER_SIZE(buffer, p));
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
p = buffer;
- strcpy(buffer, "gps_t0a=\"");
+ strncpy(buffer, "gps_t0a=\"", BUFFER_SIZE(buffer, p));
p += strlen(p);
- mbg_tgps_str(&p, &cfgh.t0a);
- *p++ = '"';
- *p = '\0';
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
+ mbg_tgps_str(&p, &cfgh.t0a, BUFFER_SIZE(buffer, p));
+ strncpy(p, "\"", BUFFER_SIZE(buffer, p));
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
- for (i = MIN_SVNO; i <= MAX_SVNO; i++)
+ for (i = MIN_SVNO; i < MAX_SVNO; i++)
{
p = buffer;
- sprintf(p, "gps_cfg[%d]=\"[0x%x] ", i, cfgh.cfg[i]);
+ snprintf(p, BUFFER_SIZE(buffer, p), "gps_cfg[%d]=\"[0x%x] ", i, cfgh.cfg[i]);
p += strlen(p);
switch (cfgh.cfg[i] & 0x7)
{
case 0:
- strcpy(p, "BLOCK I");
+ strncpy(p, "BLOCK I", BUFFER_SIZE(buffer, p));
break;
case 1:
- strcpy(p, "BLOCK II");
+ strncpy(p, "BLOCK II", BUFFER_SIZE(buffer, p));
break;
default:
- sprintf(p, "bad CFG");
+ strncpy(p, "bad CFG", BUFFER_SIZE(buffer, p));
break;
}
- strcat(p, "\"");
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
+ strncat(p, "\"", BUFFER_SIZE(buffer, p));
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
p = buffer;
- sprintf(p, "gps_health[%d]=\"[0x%x] ", i, cfgh.health[i]);
+ snprintf(p, BUFFER_SIZE(buffer, p), "gps_health[%d]=\"[0x%x] ", i, cfgh.health[i]);
p += strlen(p);
switch ((cfgh.health[i] >> 5) & 0x7 )
{
case 0:
- strcpy(p, "OK;");
+ strncpy(p, "OK;", BUFFER_SIZE(buffer, p));
break;
case 1:
- strcpy(p, "PARITY;");
+ strncpy(p, "PARITY;", BUFFER_SIZE(buffer, p));
break;
case 2:
- strcpy(p, "TLM/HOW;");
+ strncpy(p, "TLM/HOW;", BUFFER_SIZE(buffer, p));
break;
case 3:
- strcpy(p, "Z-COUNT;");
+ strncpy(p, "Z-COUNT;", BUFFER_SIZE(buffer, p));
break;
case 4:
- strcpy(p, "SUBFRAME 1,2,3;");
+ strncpy(p, "SUBFRAME 1,2,3;", BUFFER_SIZE(buffer, p));
break;
case 5:
- strcpy(p, "SUBFRAME 4,5;");
+ strncpy(p, "SUBFRAME 4,5;", BUFFER_SIZE(buffer, p));
break;
case 6:
- strcpy(p, "UPLOAD BAD;");
+ strncpy(p, "UPLOAD BAD;", BUFFER_SIZE(buffer, p));
break;
case 7:
- strcpy(p, "DATA BAD;");
+ strncpy(p, "DATA BAD;", BUFFER_SIZE(buffer, p));
break;
}
@@ -3874,26 +4358,26 @@ gps16x_message(
switch (cfgh.health[i] & 0x1F)
{
case 0:
- strcpy(p, "SIGNAL OK");
+ strncpy(p, "SIGNAL OK", BUFFER_SIZE(buffer, p));
break;
case 0x1C:
- strcpy(p, "SV TEMP OUT");
+ strncpy(p, "SV TEMP OUT", BUFFER_SIZE(buffer, p));
break;
case 0x1D:
- strcpy(p, "SV WILL BE TEMP OUT");
+ strncpy(p, "SV WILL BE TEMP OUT", BUFFER_SIZE(buffer, p));
break;
case 0x1E:
break;
case 0x1F:
- strcpy(p, "MULTIPLE ERRS");
+ strncpy(p, "MULTIPLE ERRS", BUFFER_SIZE(buffer, p));
break;
default:
- strcpy(p, "TRANSMISSION PROBLEMS");
+ strncpy(p, "TRANSMISSION PROBLEMS", BUFFER_SIZE(buffer, p));
break;
}
- strcat(p, "\"");
- set_var(&parse->kv, buffer, sizeof(buffer), RO);
+ strncat(p, "\"", sizeof(buffer));
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO);
}
}
}
@@ -3917,16 +4401,16 @@ gps16x_message(
if (utc.valid)
{
- strcpy(p, "gps_utc_correction=\"");
+ strncpy(p, "gps_utc_correction=\"", sizeof(buffer));
p += strlen(p);
- mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf);
- strcat(p, "\"");
+ mk_utcinfo(p, utc.t0t.wn, utc.WNlsf, utc.DNt, utc.delta_tls, utc.delta_tlsf, BUFFER_SIZE(buffer, p));
+ strncat(p, "\"", BUFFER_SIZE(buffer, p));
}
else
{
- strcpy(p, "gps_utc_correction=\"<NO UTC DATA>\"");
+ strncpy(p, "gps_utc_correction=\"<NO UTC DATA>\"", BUFFER_SIZE(buffer, p));
}
- set_var(&parse->kv, buffer, sizeof(buffer), RO|DEF);
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
}
break;
@@ -3945,12 +4429,12 @@ gps16x_message(
char buffer1[128];
mkreadable(buffer1, sizeof(buffer1), gps_ascii_msg.s, strlen(gps_ascii_msg.s), (int)0);
- sprintf(buffer, "gps_message=\"%s\"", buffer1);
+ snprintf(buffer, sizeof(buffer), "gps_message=\"%s\"", buffer1);
}
else
- strcpy(buffer, "gps_message=<NONE>");
+ strncpy(buffer, "gps_message=<NONE>", sizeof(buffer));
- set_var(&parse->kv, buffer, 128, RO|DEF);
+ set_var(&parse->kv, buffer, strlen(buffer)+1, RO|DEF);
}
break;
@@ -4331,6 +4815,7 @@ trimbletaip_event(
typedef struct trimble
{
u_long last_msg; /* last message received */
+ u_long last_reset; /* last time a reset was issued */
u_char qtracking; /* query tracking status */
u_long ctrack; /* current tracking set */
u_long ltrack; /* last tracking set */
@@ -4366,6 +4851,12 @@ sendcmd(
buf->idx = 2;
}
+void sendcmd P((struct txbuf *buf, int c));
+void sendbyte P((struct txbuf *buf, int b));
+void sendetx P((struct txbuf *buf, struct parseunit *parse));
+void sendint P((struct txbuf *buf, int a));
+void sendflt P((struct txbuf *buf, double a));
+
void
sendbyte(
struct txbuf *buf,
@@ -4451,7 +4942,16 @@ trimbletsip_setup(
{
u_char buffer[256];
struct txbuf buf;
+ trimble_t *t = parse->localdata;
+ if (t && t->last_reset &&
+ ((t->last_reset + TRIMBLE_RESET_HOLDOFF) > current_time)) {
+ return 1; /* not yet */
+ }
+
+ if (t)
+ t->last_reset = current_time;
+
buf.txt = buffer;
sendcmd(&buf, CMD_CVERSION); /* request software versions */
@@ -4466,7 +4966,7 @@ trimbletsip_setup(
sendetx(&buf, parse);
sendcmd(&buf, CMD_CMODESEL); /* fix mode select */
- sendbyte(&buf, 0); /* automatic */
+ sendbyte(&buf, 1); /* time transfer mode */
sendetx(&buf, parse);
sendcmd(&buf, CMD_CMESSAGE); /* request system message */
@@ -4512,9 +5012,10 @@ trimble_check(
if (current_time > t->last_msg + TRIMBLETSIP_IDLE_TIME)
(void)trimbletsip_setup(parse, "message timeout");
}
+
poll_poll(parse->peer); /* emit query string and re-arm timer */
- if (t->qtracking)
+ if (t && t->qtracking)
{
u_long oldsats = t->ltrack & ~t->ctrack;
@@ -4525,14 +5026,15 @@ trimble_check(
{
int i;
- for (i = 0; oldsats; i++)
+ for (i = 0; oldsats; i++) {
if (oldsats & (1 << i))
{
sendcmd(&buf, CMD_CSTATTRACK);
sendbyte(&buf, i+1); /* old sat */
sendetx(&buf, parse);
}
- oldsats &= ~(1 << i);
+ oldsats &= ~(1 << i);
+ }
}
sendcmd(&buf, CMD_CSTATTRACK);
@@ -4777,11 +5279,11 @@ trimbletsip_message(
if (s)
{
- sprintf(t, "%s=\"", s->varname);
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "%s=\"", s->varname);
}
else
{
- printf("TRIMBLE unknown command 0x%02x\n", cmd);
+ DPRINTF(1, ("TRIMBLE UNKNOWN COMMAND 0x%02x\n", cmd));
return;
}
@@ -4792,40 +5294,40 @@ trimbletsip_message(
switch(cmd)
{
case CMD_RCURTIME:
- sprintf(t, "%f, %d, %f",
- getflt((unsigned char *)&mb(0)), getshort((unsigned char *)&mb(4)),
- getflt((unsigned char *)&mb(6)));
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "%f, %d, %f",
+ getflt((unsigned char *)&mb(0)), getshort((unsigned char *)&mb(4)),
+ getflt((unsigned char *)&mb(6)));
break;
case CMD_RBEST4:
- strcpy(t, "mode: ");
+ strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
t += strlen(t);
switch (mb(0) & 0xF)
{
default:
- sprintf(t, "0x%x", mb(0) & 0x7);
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
break;
case 1:
- strcat(t, "0D");
+ strncpy(t, "0D", BUFFER_SIZE(pbuffer, t));
break;
case 3:
- strcat(t, "2D");
+ strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
break;
case 4:
- strcat(t, "3D");
+ strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
break;
}
t += strlen(t);
if (mb(0) & 0x10)
- strcpy(t, "-MANUAL, ");
+ strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
else
- strcpy(t, "-AUTO, ");
+ strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
t += strlen(t);
- sprintf(t, "satellites %02d %02d %02d %02d, PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "satellites %02d %02d %02d %02d, PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f",
mb(1), mb(2), mb(3), mb(4),
getflt((unsigned char *)&mb(5)),
getflt((unsigned char *)&mb(9)),
@@ -4835,7 +5337,7 @@ trimbletsip_message(
break;
case CMD_RVERSION:
- sprintf(t, "%d.%d (%d/%d/%d)",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "%d.%d (%d/%d/%d)",
mb(0)&0xff, mb(1)&0xff, 1900+(mb(4)&0xff), mb(2)&0xff, mb(3)&0xff);
break;
@@ -4858,31 +5360,31 @@ trimbletsip_message(
switch (mb(0) & 0xFF)
{
default:
- sprintf(t, "illegal value 0x%02x", mb(0) & 0xFF);
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "illegal value 0x%02x", mb(0) & 0xFF);
break;
case 0x00:
- strcpy(t, "doing position fixes");
+ strncpy(t, "doing position fixes", BUFFER_SIZE(pbuffer, t));
break;
case 0x01:
- strcpy(t, "no GPS time yet");
+ strncpy(t, "no GPS time yet", BUFFER_SIZE(pbuffer, t));
break;
case 0x03:
- strcpy(t, "PDOP too high");
+ strncpy(t, "PDOP too high", BUFFER_SIZE(pbuffer, t));
break;
case 0x08:
- strcpy(t, "no usable satellites");
+ strncpy(t, "no usable satellites", BUFFER_SIZE(pbuffer, t));
break;
case 0x09:
- strcpy(t, "only ONE usable satellite");
+ strncpy(t, "only ONE usable satellite", BUFFER_SIZE(pbuffer, t));
break;
case 0x0A:
- strcpy(t, "only TWO usable satellites");
+ strncpy(t, "only TWO usable satellites", BUFFER_SIZE(pbuffer, t));
break;
case 0x0B:
- strcpy(t, "only THREE usable satellites");
+ strncpy(t, "only THREE usable satellites", BUFFER_SIZE(pbuffer, t));
break;
case 0x0C:
- strcpy(t, "the chosen satellite is unusable");
+ strncpy(t, "the chosen satellite is unusable", BUFFER_SIZE(pbuffer, t));
break;
}
@@ -4893,14 +5395,14 @@ trimbletsip_message(
for (i = 0; i < 8; i++)
if (bits & (0x1<<i))
{
- sprintf(t, ", %s", msgs[i]);
+ snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
t += strlen(t);
}
}
break;
case CMD_RMESSAGE:
- mkreadable(t, (int)(sizeof(pbuffer) - (t - pbuffer)), (char *)&mb(0), (unsigned)(size - 2 - (&mb(0) - buffer)), 0);
+ mkreadable(t, (int)BUFFER_SIZE(pbuffer, t), (char *)&mb(0), (unsigned)(size - 2 - (&mb(0) - buffer)), 0);
break;
case CMD_RMACHSTAT:
@@ -4919,7 +5421,7 @@ trimbletsip_message(
int i, bits;
- sprintf(t, "machine id 0x%02x", mb(0) & 0xFF);
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "machine id 0x%02x", mb(0) & 0xFF);
t += strlen(t);
bits = mb(1) & 0xFF;
@@ -4927,16 +5429,16 @@ trimbletsip_message(
for (i = 0; i < 8; i++)
if (bits & (0x1<<i))
{
- sprintf(t, ", %s", msgs[i]);
+ snprintf(t, BUFFER_SIZE(pbuffer, t), ", %s", msgs[i]);
t += strlen(t);
}
- sprintf(t, ", Superpackets %ssupported", (mb(2) & 0xFF) ? "" :"un" );
+ snprintf(t, BUFFER_SIZE(pbuffer, t), ", Superpackets %ssupported", (mb(2) & 0xFF) ? "" :"un" );
}
break;
case CMD_ROPERPARAM:
- sprintf(t, "%2x %.1f %.1f %.1f %.1f",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "%2x %.1f %.1f %.1f %.1f",
mb(0), getflt((unsigned char *)&mb(1)), getflt((unsigned char *)&mb(5)),
getflt((unsigned char *)&mb(9)), getflt((unsigned char *)&mb(13)));
break;
@@ -4952,23 +5454,23 @@ trimbletsip_message(
if ((int)t0t != 0)
{
- mk_utcinfo(t, wnt, wnlsf, dn, dtls, dtlsf);
+ mk_utcinfo(t, wnt, wnlsf, dn, dtls, dtlsf, BUFFER_SIZE(pbuffer, t));
}
else
{
- strcpy(t, "<NO UTC DATA>");
+ strncpy(t, "<NO UTC DATA>", BUFFER_SIZE(pbuffer, t));
}
}
break;
case CMD_RSAT1BIAS:
- sprintf(t, "%.1fm %.2fm/s at %.1fs",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "%.1fm %.2fm/s at %.1fs",
getflt(&mb(0)), getflt(&mb(4)), getflt(&mb(8)));
break;
case CMD_RIOOPTIONS:
{
- sprintf(t, "%02x %02x %02x %02x",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "%02x %02x %02x %02x",
mb(0), mb(1), mb(2), mb(3));
if (mb(0) != TRIM_POS_OPT ||
mb(2) != TRIM_TIME_OPT)
@@ -4986,7 +5488,7 @@ trimbletsip_message(
double f = getflt((unsigned char *)&mb(12));
if (f > 0.0)
- sprintf(t, "x= %.1fm, y= %.1fm, z= %.1fm, time_of_fix= %f sec",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm, time_of_fix= %f sec",
x, y, z,
f);
else
@@ -5001,7 +5503,7 @@ trimbletsip_message(
double f = getflt((unsigned char *)&mb(12));
if (f > 0.0)
- sprintf(t, "lat %f %c, long %f %c, alt %.2fm",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, long %f %c, alt %.2fm",
((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
getflt((unsigned char *)&mb(8)));
@@ -5015,7 +5517,7 @@ trimbletsip_message(
double x = getdbl((unsigned char *)&mb(0));
double y = getdbl((unsigned char *)&mb(8));
double z = getdbl((unsigned char *)&mb(16));
- sprintf(t, "x= %.1fm, y= %.1fm, z= %.1fm",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "x= %.1fm, y= %.1fm, z= %.1fm",
x, y, z);
}
break;
@@ -5024,7 +5526,7 @@ trimbletsip_message(
{
double lat = getdbl((unsigned char *)&mb(0));
double lng = getdbl((unsigned char *)&mb(8));
- sprintf(t, "lat %f %c, lon %f %c, alt %.2fm",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "lat %f %c, lon %f %c, alt %.2fm",
((lat < 0.0) ? (-lat) : (lat))*RTOD, (lat < 0.0 ? 'S' : 'N'),
((lng < 0.0) ? (-lng) : (lng))*RTOD, (lng < 0.0 ? 'W' : 'E'),
getdbl((unsigned char *)&mb(16)));
@@ -5035,32 +5537,32 @@ trimbletsip_message(
{
int i, sats;
- strcpy(t, "mode: ");
+ strncpy(t, "mode: ", BUFFER_SIZE(pbuffer, t));
t += strlen(t);
switch (mb(0) & 0x7)
{
default:
- sprintf(t, "0x%x", mb(0) & 0x7);
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "0x%x", mb(0) & 0x7);
break;
case 3:
- strcat(t, "2D");
+ strncpy(t, "2D", BUFFER_SIZE(pbuffer, t));
break;
case 4:
- strcat(t, "3D");
+ strncpy(t, "3D", BUFFER_SIZE(pbuffer, t));
break;
}
t += strlen(t);
if (mb(0) & 0x8)
- strcpy(t, "-MANUAL, ");
+ strncpy(t, "-MANUAL, ", BUFFER_SIZE(pbuffer, t));
else
- strcpy(t, "-AUTO, ");
+ strncpy(t, "-AUTO, ", BUFFER_SIZE(pbuffer, t));
t += strlen(t);
sats = (mb(0)>>4) & 0xF;
- sprintf(t, "PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f, %d satellite%s in view: ",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "PDOP %.2f, HDOP %.2f, VDOP %.2f, TDOP %.2f, %d satellite%s in view: ",
getflt((unsigned char *)&mb(1)),
getflt((unsigned char *)&mb(5)),
getflt((unsigned char *)&mb(9)),
@@ -5070,7 +5572,7 @@ trimbletsip_message(
for (i=0; i < sats; i++)
{
- sprintf(t, "%s%02d", i ? ", " : "", mb(17+i));
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "%s%02d", i ? ", " : "", mb(17+i));
t += strlen(t);
if (tr)
tr->ctrack |= (1 << (mb(17+i)-1));
@@ -5085,17 +5587,17 @@ trimbletsip_message(
case CMD_RSTATTRACK:
{
- sprintf(t-2, "[%02d]=\"", mb(0)); /* add index to var name */
+ snprintf(t-2, BUFFER_SIZE(pbuffer, t-2), "[%02d]=\"", mb(0)); /* add index to var name */
t += strlen(t);
if (getflt((unsigned char *)&mb(4)) < 0.0)
{
- strcpy(t, "<NO MEASUREMENTS>");
+ strncpy(t, "<NO MEASUREMENTS>", BUFFER_SIZE(pbuffer, t));
var_flag &= ~DEF;
}
else
{
- sprintf(t, "ch=%d, acq=%s, eph=%d, signal_level= %5.2f, elevation= %5.2f, azimuth= %6.2f",
+ snprintf(t, BUFFER_SIZE(pbuffer, t), "ch=%d, acq=%s, eph=%d, signal_level= %5.2f, elevation= %5.2f, azimuth= %6.2f",
(mb(1) & 0xFF)>>3,
mb(2) ? ((mb(2) == 1) ? "ACQ" : "SRCH") : "NEVER",
mb(3),
@@ -5106,29 +5608,31 @@ trimbletsip_message(
if (mb(20))
{
var_flag &= ~DEF;
- strcpy(t, ", OLD");
+ strncpy(t, ", OLD", BUFFER_SIZE(pbuffer, t));
}
t += strlen(t);
if (mb(22))
{
if (mb(22) == 1)
- strcpy(t, ", BAD PARITY");
+ strncpy(t, ", BAD PARITY", BUFFER_SIZE(pbuffer, t));
else
if (mb(22) == 2)
- strcpy(t, ", BAD EPH HEALTH");
+ strncpy(t, ", BAD EPH HEALTH", BUFFER_SIZE(pbuffer, t));
}
t += strlen(t);
if (mb(23))
- strcpy(t, ", collecting data");
+ strncpy(t, ", collecting data", BUFFER_SIZE(pbuffer, t));
}
}
break;
default:
- strcpy(t, "<UNDECODED>");
+ strncpy(t, "<UNDECODED>", BUFFER_SIZE(pbuffer, t));
break;
}
- strcat(t,"\"");
+ t += strlen(t);
+
+ strncpy(t,"\"", BUFFER_SIZE(pbuffer, t));
set_var(&parse->kv, pbuffer, sizeof(pbuffer), var_flag);
}
}
@@ -5240,6 +5744,161 @@ int refclock_parse_bs;
* History:
*
* refclock_parse.c,v
+ * Revision 4.80 2007/08/11 12:06:29 kardel
+ * update comments wrt/ to PPS
+ *
+ * Revision 4.79 2007/08/11 11:52:23 kardel
+ * - terminate io bindings before io_closeclock() will close our file descriptor
+ *
+ * Revision 4.78 2006/12/22 20:08:27 kardel
+ * Bug 746 (RFE): add configuration for Expert mouseCLOCK USB v2.0 as mode 19
+ *
+ * Revision 4.77 2006/08/05 07:44:49 kardel
+ * support optionally separate PPS devices via /dev/refclockpps-{0..3}
+ *
+ * Revision 4.76 2006/06/22 18:40:47 kardel
+ * clean up signedness (gcc 4)
+ *
+ * Revision 4.75 2006/06/22 16:58:10 kardel
+ * Bug #632: call parse_ppsapi() in parse_ctl() when updating
+ * the PPS offset. Fix sign of offset passed to kernel.
+ *
+ * Revision 4.74 2006/06/18 21:18:37 kardel
+ * NetBSD Coverity CID 3796: possible NULL deref
+ *
+ * Revision 4.73 2006/05/26 14:23:46 kardel
+ * cleanup of copyright info
+ *
+ * Revision 4.72 2006/05/26 14:19:43 kardel
+ * cleanup of ioctl cruft
+ *
+ * Revision 4.71 2006/05/26 14:15:57 kardel
+ * delay adding refclock to async refclock io after all initializations
+ *
+ * Revision 4.70 2006/05/25 18:20:50 kardel
+ * bug #619
+ * terminate parse io engine after de-registering
+ * from refclock io engine
+ *
+ * Revision 4.69 2006/05/25 17:28:02 kardel
+ * complete refclock io structure initialization *before* inserting it into the
+ * refclock input machine (avoids null pointer deref) (bug #619)
+ *
+ * Revision 4.68 2006/05/01 17:02:51 kardel
+ * copy receiver method also for newlwy created receive buffers
+ *
+ * Revision 4.67 2006/05/01 14:37:29 kardel
+ * If an input buffer parses into more than one message do insert the
+ * parsed message in a new input buffer instead of processing it
+ * directly. This avoids deed complicated processing in signal
+ * handling.
+ *
+ * Revision 4.66 2006/03/18 00:45:30 kardel
+ * coverity fixes found in NetBSD coverity scan
+ *
+ * Revision 4.65 2006/01/26 06:08:33 kardel
+ * output errno on PPS setup failure
+ *
+ * Revision 4.64 2005/11/09 20:44:47 kardel
+ * utilize full PPS timestamp resolution from PPS API
+ *
+ * Revision 4.63 2005/10/07 22:10:25 kardel
+ * bounded buffer implementation
+ *
+ * Revision 4.62.2.2 2005/09/25 10:20:16 kardel
+ * avoid unexpected buffer overflows due to sprintf("%f") on strange floats:
+ * replace almost all str* and *printf functions be their buffer bounded
+ * counterparts
+ *
+ * Revision 4.62.2.1 2005/08/27 16:19:27 kardel
+ * limit re-set rate of trimble clocks
+ *
+ * Revision 4.62 2005/08/06 17:40:00 kardel
+ * cleanup size handling wrt/ to buffer boundaries
+ *
+ * Revision 4.61 2005/07/27 21:16:19 kardel
+ * fix a long (> 11 years) misconfiguration wrt/ Meinberg cflag factory
+ * default setup. CSTOPB was missing for the 7E2 default data format of
+ * the DCF77 clocks.
+ *
+ * Revision 4.60 2005/07/17 21:14:44 kardel
+ * change contents of version string to include the RCS/CVS Id
+ *
+ * Revision 4.59 2005/07/06 06:56:38 kardel
+ * syntax error
+ *
+ * Revision 4.58 2005/07/04 13:10:40 kardel
+ * fix bug 455: tripping over NULL pointer on cleanup
+ * fix shadow storage logic for ppsphaseadjust and trustime wrt/ time2
+ * fix compiler warnings for some platforms wrt/ printf formatstrings and
+ * varying structure element sizes
+ * reorder assignment in binding to avoid tripping over NULL pointers
+ *
+ * Revision 4.57 2005/06/25 09:25:19 kardel
+ * sort out log output sequence
+ *
+ * Revision 4.56 2005/06/14 21:47:27 kardel
+ * collect samples only if samples are ok (sync or trusted flywheel)
+ * propagate pps phase adjustment value to kernel via PPSAPI to help HARDPPS
+ * en- and dis-able HARDPPS in correlation to receiver sync state
+ *
+ * Revision 4.55 2005/06/02 21:28:31 kardel
+ * clarify trust logic
+ *
+ * Revision 4.54 2005/06/02 17:06:49 kardel
+ * change status reporting to use fixed refclock_report()
+ *
+ * Revision 4.53 2005/06/02 16:33:31 kardel
+ * fix acceptance of clocks unsync clocks right at start
+ *
+ * Revision 4.52 2005/05/26 21:55:06 kardel
+ * cleanup status reporting
+ *
+ * Revision 4.51 2005/05/26 19:19:14 kardel
+ * implement fast refclock startup
+ *
+ * Revision 4.50 2005/04/16 20:51:35 kardel
+ * set pps_enable = 1 when binding a kernel PPS source
+ *
+ * Revision 4.49 2005/04/16 17:29:26 kardel
+ * add non polling clock type 18 for just listenning to Meinberg clocks
+ *
+ * Revision 4.48 2005/04/16 16:22:27 kardel
+ * bk sync 20050415 ntp-dev
+ *
+ * Revision 4.47 2004/11/29 10:42:48 kardel
+ * bk sync ntp-dev 20041129
+ *
+ * Revision 4.46 2004/11/29 10:26:29 kardel
+ * keep fudgetime2 in sync with trusttime/ppsphaseadjust depending in flag1
+ *
+ * Revision 4.45 2004/11/14 20:53:20 kardel
+ * clear PPS flags after using them
+ *
+ * Revision 4.44 2004/11/14 15:29:41 kardel
+ * support PPSAPI, upgrade Copyright to Berkeley style
+ *
+ * Revision 4.43 2001/05/26 22:53:16 kardel
+ * 20010526 reconcilation
+ *
+ * Revision 4.42 2000/05/14 15:31:51 kardel
+ * PPSAPI && RAWDCF modemline support
+ *
+ * Revision 4.41 2000/04/09 19:50:45 kardel
+ * fixed rawdcfdtr_init() -> rawdcf_init_1
+ *
+ * Revision 4.40 2000/04/09 15:27:55 kardel
+ * modem line fiddle in rawdcf_init_2
+ *
+ * Revision 4.39 2000/03/18 09:16:55 kardel
+ * PPSAPI integration
+ *
+ * Revision 4.38 2000/03/05 20:25:06 kardel
+ * support PPSAPI
+ *
+ * Revision 4.37 2000/03/05 20:11:14 kardel
+ * 4.0.99g reconcilation
+ *
* Revision 4.36 1999/11/28 17:18:20 kardel
* disabled burst mode
*
diff --git a/contrib/ntp/ntpd/refclock_pst.c b/contrib/ntp/ntpd/refclock_pst.c
index 2443b2c..776e28e 100644
--- a/contrib/ntp/ntpd/refclock_pst.c
+++ b/contrib/ntp/ntpd/refclock_pst.c
@@ -269,7 +269,8 @@ pst_receive(
*/
if (!refclock_process(pp))
refclock_report(peer, CEVNT_BADTIME);
-
+ else if (peer->disp > MAXDISTANCE)
+ refclock_receive(peer);
}
diff --git a/contrib/ntp/ntpd/refclock_ptbacts.c b/contrib/ntp/ntpd/refclock_ptbacts.c
deleted file mode 100644
index 09d7bf4..0000000
--- a/contrib/ntp/ntpd/refclock_ptbacts.c
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * crude hack to avoid hard links in distribution
- * and keep only one ACTS type source for different
- * ACTS refclocks
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_PTBACTS)
-# define KEEPPTBACTS
-# include "refclock_acts.c"
-#else /* not (REFCLOCK && CLOCK_PTBACTS) */
-int refclock_ptbacts_bs;
-#endif /* not (REFCLOCK && CLOCK_PTBACTS) */
diff --git a/contrib/ntp/ntpd/refclock_ripencc.c b/contrib/ntp/ntpd/refclock_ripencc.c
index 6337f63..d9fa204 100644
--- a/contrib/ntp/ntpd/refclock_ripencc.c
+++ b/contrib/ntp/ntpd/refclock_ripencc.c
@@ -44,13 +44,9 @@
#include "ntp_unixtime.h"
#include "ntp_io.h"
-#ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-#else /* HAVE_TIMEPPS_H */
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif /* HAVE_SYS_TIMEPPS_H */
-#endif /* HAVE_TIMEPPS_H */
+#ifdef HAVE_PPSAPI
+# include "ppsapi_timepps.h"
+#endif
/*
* Definitions
diff --git a/contrib/ntp/ntpd/refclock_shm.c b/contrib/ntp/ntpd/refclock_shm.c
index 4ab0ede..7be263d 100644
--- a/contrib/ntp/ntpd/refclock_shm.c
+++ b/contrib/ntp/ntpd/refclock_shm.c
@@ -244,6 +244,10 @@ shm_poll(
struct timeval tvt;
struct tm *t;
int ok=1;
+ tvr.tv_sec = 0;
+ tvr.tv_usec = 0;
+ tvt.tv_sec = 0;
+ tvt.tv_usec = 0;
switch (up->mode) {
case 0: {
tvr.tv_sec=up->receiveTimeStampSec;
@@ -266,11 +270,14 @@ shm_poll(
}
up->valid=0;
if (ok) {
+ time_t help; /* XXX NetBSD has incompatible tv_sec */
+
TVTOTS(&tvr,&pp->lastrec);
pp->lastrec.l_ui += JAN_1970;
/* pp->lasttime = current_time; */
pp->polls++;
- t=gmtime (&tvt.tv_sec);
+ help = tvt.tv_sec;
+ t = gmtime (&help);
pp->day=t->tm_yday+1;
pp->hour=t->tm_hour;
pp->minute=t->tm_min;
diff --git a/contrib/ntp/ntpd/refclock_ulink.c b/contrib/ntp/ntpd/refclock_ulink.c
index 1f5e78a..d7a62fe 100644
--- a/contrib/ntp/ntpd/refclock_ulink.c
+++ b/contrib/ntp/ntpd/refclock_ulink.c
@@ -1,6 +1,5 @@
/*
* refclock_ulink - clock driver for Ultralink WWVB receiver
- *
*/
/***********************************************************************
@@ -32,11 +31,9 @@
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
-#include "ntp_calendar.h"
#include "ntp_stdlib.h"
-/*
- * This driver supports ultralink Model 320,330,331,332 WWVB radios
+/* This driver supports ultralink Model 320,325,330,331,332 WWVB radios
*
* this driver was based on the refclock_wwvb.c driver
* in the ntp distribution.
@@ -62,6 +59,8 @@
* 01/02/21 s.l.smith fixed 33x quality flag
* added more debugging stuff
* updated 33x time code explanation
+ * 04/01/23 frank migge added support for 325 decoder
+ * (tested with ULM325.F)
*
* Questions, bugs, ideas send to:
* Joseph C. Lang
@@ -70,10 +69,13 @@
* Dave Strout
* dstrout@linuxfoundry.com
*
+ * Frank Migge
+ * frank.migge@oracle.com
+ *
*
* on the Ultralink model 33X decoder Dip switch 2 controls
* polled or continous timecode
- * set fudge flag1 if using polled (needed for model 320)
+ * set fudge flag1 if using polled (needed for model 320 and 325)
* dont set fudge flag1 if dip switch 2 is set on model 33x decoder
*/
@@ -87,9 +89,12 @@
#define REFID "WWVB" /* reference ID */
#define DESCRIPTION "Ultralink WWVB Receiver" /* WRU */
-#define LEN33X 32 /* timecode length Model 325 & 33X */
+#define LEN33X 32 /* timecode length Model 33X and 325 */
#define LEN320 24 /* timecode length Model 320 */
+#define SIGLCHAR33x 'S' /* signal strength identifier char 325 */
+#define SIGLCHAR325 'R' /* signal strength identifier char 33x */
+
/*
* unit control structure
*/
@@ -210,6 +215,7 @@ ulink_receive(
char syncchar; /* synchronization indicator */
char leapchar; /* leap indicator */
char modechar; /* model 320 mode flag */
+ char siglchar; /* model difference between 33x/325 */
char char_quality[2]; /* temp quality flag */
/*
@@ -247,77 +253,163 @@ ulink_receive(
* its contents. If the timecode has invalid length or is not in
* proper format, we declare bad format and exit.
*/
- syncchar = leapchar = modechar = ' ';
+ syncchar = leapchar = modechar = siglchar = ' ';
switch (pp->lencode ) {
case LEN33X:
+
/*
- * Model 33X decoder:
- * Timecode format from January 29, 2001 datasheet is:
- * <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5
- * S WWVB decoder sync indicator. S for in-sync(?)
- * or N for noisy signal.
- * 9+ RF signal level in S-units, 0-9 followed by
- * a space (0x20). The space turns to '+' if the
- * level is over 9.
- * D Data bit 0, 1, 2 (position mark), or
- * 3 (unknown).
- * space Space character (0x20)
- * 00 Hours since last good WWVB frame sync. Will
- * be 00-23 hrs, or '1d' to '7d'. Will be 'Lk'
- * if currently in sync.
- * space Space character (0x20)
- * YYYY Current year, 1990-2089
- * + Leap year indicator. '+' if a leap year,
- * a space (0x20) if not.
- * DDD Day of year, 001 - 366.
- * UTC Timezone (always 'UTC').
- * S Daylight savings indicator
- * S - standard time (STD) in effect
- * O - during STD to DST day 0000-2400
- * D - daylight savings time (DST) in effect
- * I - during DST to STD day 0000-2400
- * space Space character (0x20)
- * HH Hours 00-23
- * : This is the REAL in sync indicator (: = insync)
- * MM Minutes 00-59
- * : : = in sync ? = NOT in sync
- * SS Seconds 00-59
- * L Leap second flag. Changes from space (0x20)
- * to '+' or '-' during month preceding leap
- * second adjustment.
- * +5 UT1 correction (sign + digit ))
- */
-
- if (sscanf(pp->a_lastcode,
- "%*4c %2c %4d%*c%3d%*4c %2d%c%2d:%2d%c%*2c",
- char_quality, &pp->year, &pp->day,
- &pp->hour, &syncchar, &pp->minute, &pp->second,
- &leapchar) == 8) {
+ * First we check if the format is 33x or 325:
+ * <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5 (33x)
+ * <CR><LF>R5_1C00LYYYY+DDDUTCS HH:MM:SSL+5 (325)
+ * simply by comparing if the signal level is 'S' or 'R'
+ */
+
+ if (sscanf(pp->a_lastcode, "%c%*31c",
+ &siglchar) == 1) {
+
+ if(siglchar == SIGLCHAR325) {
+
+ /*
+ * decode for a Model 325 decoder.
+ * Timecode format from January 23, 2004 datasheet is:
+ *
+ * <CR><LF>R5_1C00LYYYY+DDDUTCS HH:MM:SSL+5
+ *
+ * R WWVB decodersignal readability R1 - R5
+ * 5 R1 is unreadable, R5 is best
+ * space a space (0x20)
+ * 1 Data bit 0, 1, M (pos mark), or ? (unknown).
+ * C Reception from either (C)olorado or (H)awaii
+ * 00 Hours since last good WWVB frame sync. Will
+ * be 00-99
+ * space Space char (0x20) or (0xa5) if locked to wwvb
+ * YYYY Current year, 2000-2099
+ * + Leap year indicator. '+' if a leap year,
+ * a space (0x20) if not.
+ * DDD Day of year, 000 - 365.
+ * UTC Timezone (always 'UTC').
+ * S Daylight savings indicator
+ * S - standard time (STD) in effect
+ * O - during STD to DST day 0000-2400
+ * D - daylight savings time (DST) in effect
+ * I - during DST to STD day 0000-2400
+ * space Space character (0x20)
+ * HH Hours 00-23
+ * : This is the REAL in sync indicator (: = insync)
+ * MM Minutes 00-59
+ * : : = in sync ? = NOT in sync
+ * SS Seconds 00-59
+ * L Leap second flag. Changes from space (0x20)
+ * to 'I' or 'D' during month preceding leap
+ * second adjustment. (I)nsert or (D)elete
+ * +5 UT1 correction (sign + digit ))
+ */
+
+ if (sscanf(pp->a_lastcode,
+ "%*2c %*2c%2c%*c%4d%*c%3d%*4c %2d%c%2d:%2d%c%*2c",
+ char_quality, &pp->year, &pp->day,
+ &pp->hour, &syncchar, &pp->minute, &pp->second,
+ &leapchar) == 8) {
+
+ if (char_quality[0] == '0') {
+ quality = 0;
+ } else if (char_quality[0] == '0') {
+ quality = (char_quality[1] & 0x0f);
+ } else {
+ quality = 99;
+ }
+
+ if (leapchar == 'I' ) leapchar = '+';
+ if (leapchar == 'D' ) leapchar = '-';
+
+ /*
+ #ifdef DEBUG
+ if (debug) {
+ printf("ulink: char_quality %c %c\n",
+ char_quality[0], char_quality[1]);
+ printf("ulink: quality %d\n", quality);
+ printf("ulink: syncchar %x\n", syncchar);
+ printf("ulink: leapchar %x\n", leapchar);
+ }
+ #endif
+ */
+
+ }
+
+ }
+ if(siglchar == SIGLCHAR33x) {
+
+ /*
+ * We got a Model 33X decoder.
+ * Timecode format from January 29, 2001 datasheet is:
+ * <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5
+ * S WWVB decoder sync indicator. S for in-sync(?)
+ * or N for noisy signal.
+ * 9+ RF signal level in S-units, 0-9 followed by
+ * a space (0x20). The space turns to '+' if the
+ * level is over 9.
+ * D Data bit 0, 1, 2 (position mark), or
+ * 3 (unknown).
+ * space Space character (0x20)
+ * 00 Hours since last good WWVB frame sync. Will
+ * be 00-23 hrs, or '1d' to '7d'. Will be 'Lk'
+ * if currently in sync.
+ * space Space character (0x20)
+ * YYYY Current year, 1990-2089
+ * + Leap year indicator. '+' if a leap year,
+ * a space (0x20) if not.
+ * DDD Day of year, 001 - 366.
+ * UTC Timezone (always 'UTC').
+ * S Daylight savings indicator
+ * S - standard time (STD) in effect
+ * O - during STD to DST day 0000-2400
+ * D - daylight savings time (DST) in effect
+ * I - during DST to STD day 0000-2400
+ * space Space character (0x20)
+ * HH Hours 00-23
+ * : This is the REAL in sync indicator (: = insync)
+ * MM Minutes 00-59
+ * : : = in sync ? = NOT in sync
+ * SS Seconds 00-59
+ * L Leap second flag. Changes from space (0x20)
+ * to '+' or '-' during month preceding leap
+ * second adjustment.
+ * +5 UT1 correction (sign + digit ))
+ */
+
+ if (sscanf(pp->a_lastcode,
+ "%*4c %2c %4d%*c%3d%*4c %2d%c%2d:%2d%c%*2c",
+ char_quality, &pp->year, &pp->day,
+ &pp->hour, &syncchar, &pp->minute, &pp->second,
+ &leapchar) == 8) {
- if (char_quality[0] == 'L') {
+ if (char_quality[0] == 'L') {
quality = 0;
- } else if (char_quality[0] == '0') {
+ } else if (char_quality[0] == '0') {
quality = (char_quality[1] & 0x0f);
- } else {
+ } else {
quality = 99;
- }
+ }
-/*
-#ifdef DEBUG
- if (debug) {
- printf("ulink: char_quality %c %c\n",
- char_quality[0], char_quality[1]);
- printf("ulink: quality %d\n", quality);
- printf("ulink: syncchar %x\n", syncchar);
- printf("ulink: leapchar %x\n", leapchar);
- }
-#endif
-*/
-
- break;
+ /*
+ #ifdef DEBUG
+ if (debug) {
+ printf("ulink: char_quality %c %c\n",
+ char_quality[0], char_quality[1]);
+ printf("ulink: quality %d\n", quality);
+ printf("ulink: syncchar %x\n", syncchar);
+ printf("ulink: leapchar %x\n", leapchar);
+ }
+ #endif
+ */
+
+ }
+ }
+ break;
}
-
+
case LEN320:
+
/*
* Model 320 Decoder
* The timecode format is:
@@ -345,6 +437,7 @@ ulink_receive(
* T = DST <-> STD transition indicators
*
*/
+
if (sscanf(pp->a_lastcode, "%c%1d%c%4d%3d%*c%2d:%2d:%2d.%2ld%c",
&syncchar, &quality, &modechar, &pp->year, &pp->day,
&pp->hour, &pp->minute, &pp->second,
@@ -362,7 +455,6 @@ ulink_receive(
return;
}
-
/*
* Decode quality indicator
* For the 325 & 33x series, the lower the number the "better"
@@ -455,10 +547,10 @@ ulink_receive(
}
-
/*
* ulink_poll - called by the transmit procedure
*/
+
static void
ulink_poll(
int unit,
diff --git a/contrib/ntp/ntpd/refclock_usno.c b/contrib/ntp/ntpd/refclock_usno.c
deleted file mode 100644
index 057eef9..0000000
--- a/contrib/ntp/ntpd/refclock_usno.c
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * refclock_usno - clock driver for the Naval Observatory dialup
- * Michael Shields <shields@tembel.org> 1995/02/25
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#if defined(REFCLOCK) && defined(CLOCK_USNO)
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-#include "ntp_control.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
-/*
- * This driver supports the Naval Observatory dialup at +1 202 653 0351.
- * It is a hacked-up version of the ACTS driver.
- *
- * This driver does not support the `phone' configuration because that
- * is needlessly global; it would clash with the ACTS driver.
- *
- * The Naval Observatory does not support the echo-delay measurement scheme.
- *
- * However, this driver *does* support UUCP port locking, allowing the
- * line to be shared with other processes when not actually dialing
- * for time.
- */
-
-/*
- * Interface definitions
- */
-
-#define DEVICE "/dev/cua%d" /* device name and unit */
-#define LOCKFILE "/var/lock/LCK..cua%d"
-/* #define LOCKFILE "/usr/spool/uucp/LCK..cua%d" */
-
-#define PHONE "atdt 202 653 0351"
-/* #define PHONE "atdt 1 202 653 0351" */
-
-#define SPEED232 B1200 /* uart speed (1200 cowardly baud) */
-#define PRECISION (-10) /* precision assumed (about 1 ms) */
-#define REFID "USNO" /* reference ID */
-#define DESCRIPTION "Naval Observatory dialup"
-
-#define MODE_AUTO 0 /* automatic mode */
-#define MODE_BACKUP 1 /* backup mode */
-#define MODE_MANUAL 2 /* manual mode */
-
-#define MSGCNT 10 /* we need this many time messages */
-#define SMAX 80 /* max token string length */
-#define LENCODE 20 /* length of valid timecode string */
-#define USNO_MINPOLL 10 /* log2 min poll interval (1024 s) */
-#define USNO_MAXPOLL 14 /* log2 max poll interval (16384 s) */
-#define MAXOUTAGE 3600 /* max before USNO kicks in (s) */
-
-/*
- * Modem control strings. These may have to be changed for some modems.
- *
- * AT command prefix
- * B1 initiate call negotiation using Bell 212A
- * &C1 enable carrier detect
- * &D2 hang up and return to command mode on DTR transition
- * E0 modem command echo disabled
- * l1 set modem speaker volume to low level
- * M1 speaker enabled untill carrier detect
- * Q0 return result codes
- * V1 return result codes as English words
- */
-#define MODEM_SETUP "ATB1&C1&D2E0L1M1Q0V1" /* modem setup */
-#define MODEM_HANGUP "ATH" /* modem disconnect */
-
-/*
- * Timeouts
- */
-#define IDLE 60 /* idle timeout (s) */
-#define WAIT 2 /* wait timeout (s) */
-#define ANSWER 30 /* answer timeout (s) */
-#define CONNECT 10 /* connect timeout (s) */
-#define TIMECODE (MSGCNT+16) /* timecode timeout (s) */
-
-/*
- * Unit control structure
- */
-struct usnounit {
- int pollcnt; /* poll message counter */
-
- int state; /* the first one was Delaware */
- int run; /* call program run switch */
- int msgcnt; /* count of time messages received */
- long redial; /* interval to next automatic call */
- int unit; /* unit number (= port) */
-};
-
-/*
- * Function prototypes
- */
-static int usno_start P((int, struct peer *));
-static void usno_shutdown P((int, struct peer *));
-static void usno_poll P((int, struct peer *));
-static void usno_disc P((struct peer *));
-#if 0
-static void usno_timeout P((struct peer *));
-static void usno_receive P((struct recvbuf *));
-static int usno_write P((struct peer *, const char *));
-#endif /* 0 */
-
-/*
- * Transfer vector
- */
-struct refclock refclock_usno = {
- usno_start, /* start up driver */
- usno_shutdown, /* shut down driver */
- usno_poll, /* transmit poll message */
- noentry, /* not used (usno_control) */
- noentry, /* not used (usno_init) */
- noentry, /* not used (usno_buginfo) */
- NOFLAGS /* not used */
-};
-
-
-/*
- * usno_start - open the devices and initialize data for processing
- */
-static int
-usno_start(
- int unit,
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
-
- /*
- * Initialize miscellaneous variables
- */
- pp = peer->procptr;
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- peer->minpoll = USNO_MINPOLL;
- peer->maxpoll = USNO_MAXPOLL;
- peer->sstclktype = CTL_SST_TS_TELEPHONE;
-
- /*
- * Allocate and initialize unit structure
- */
- if (!(up = (struct usnounit *)
- emalloc(sizeof(struct usnounit))))
- return (0);
- memset((char *)up, 0, sizeof(struct usnounit));
- up->unit = unit;
- pp->unitptr = (caddr_t)up;
-
- /*
- * Set up the driver timeout
- */
- peer->nextdate = current_time + WAIT;
- return (1);
-}
-
-
-/*
- * usno_shutdown - shut down the clock
- */
-static void
-usno_shutdown(
- int unit,
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
-
-#ifdef DEBUG
- if (debug)
- printf("usno: clock %s shutting down\n", ntoa(&peer->srcadr));
-#endif
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
- usno_disc(peer);
- free(up);
-}
-
-
-#if 0
-/*
- * usno_receive - receive data from the serial interface
- */
-static void
-usno_receive(
- struct recvbuf *rbufp
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
- struct peer *peer;
- char str[SMAX];
- u_long mjd; /* Modified Julian Day */
- static int day, hour, minute, second;
-
- /*
- * Initialize pointers and read the timecode and timestamp. If
- * the OK modem status code, leave it where folks can find it.
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
- &pp->lastrec);
- if (pp->lencode == 0) {
- if (strcmp(pp->a_lastcode, "OK") == 0)
- pp->lencode = 2;
- return;
- }
-#ifdef DEBUG
- if (debug)
- printf("usno: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif
-
- switch (up->state) {
-
- case 0:
-
- /*
- * State 0. We are not expecting anything. Probably
- * modem disconnect noise. Go back to sleep.
- */
- return;
-
- case 1:
-
- /*
- * State 1. We are about to dial. Just drop it.
- */
- return;
-
- case 2:
-
- /*
- * State 2. We are waiting for the call to be answered.
- * All we care about here is CONNECT as the first token
- * in the string. If the modem signals BUSY, ERROR, NO
- * ANSWER, NO CARRIER or NO DIALTONE, we immediately
- * hang up the phone. If CONNECT doesn't happen after
- * ANSWER seconds, hang up the phone. If everything is
- * okay, start the connect timeout and slide into state
- * 3.
- */
- (void)strncpy(str, strtok(pp->a_lastcode, " "), SMAX);
- if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") ==
- 0 || strcmp(str, "NO") == 0) {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO modem status %s",
- ntoa(&peer->srcadr), pp->a_lastcode);
- usno_disc(peer);
- } else if (strcmp(str, "CONNECT") == 0) {
- peer->nextdate = current_time + CONNECT;
- up->msgcnt = 0;
- up->state++;
- } else {
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_WARNING,
- "clock %s USNO unknown modem status %s",
- ntoa(&peer->srcadr), pp->a_lastcode);
- }
- return;
-
- case 3:
-
- /*
- * State 3. The call has been answered and we are
- * waiting for the first message. If this doesn't
- * happen within the timecode timeout, hang up the
- * phone. We probably got a wrong number or they are
- * down.
- */
- peer->nextdate = current_time + TIMECODE;
- up->state++;
- return;
-
- case 4:
-
- /*
- * State 4. We are reading a timecode. It's an actual
- * timecode, or it's the `*' OTM.
- *
- * jjjjj nnn hhmmss UTC
- */
- if (pp->lencode == LENCODE) {
- if (sscanf(pp->a_lastcode, "%5ld %3d %2d%2d%2d UTC",
- &mjd, &day, &hour, &minute, &second) != 5) {
-#ifdef DEBUG
- if (debug)
- printf("usno: bad timecode format\n");
-#endif
- refclock_report(peer, CEVNT_BADREPLY);
- } else
- up->msgcnt++;
- return;
- } else if (pp->lencode != 1 || !up->msgcnt)
- return;
- /* else, OTM; drop out of switch */
- }
-
- pp->leap = LEAP_NOWARNING;
- pp->day = day;
- pp->hour = hour;
- pp->minute = minute;
- pp->second = second;
-
- /*
- * Colossal hack here. We process each sample in a trimmed-mean
- * filter and determine the reference clock offset and
- * dispersion. The fudge time1 value is added to each sample as
- * received.
- */
- if (!refclock_process(pp)) {
-#ifdef DEBUG
- if (debug)
- printf("usno: time rejected\n");
-#endif
- refclock_report(peer, CEVNT_BADTIME);
- return;
- } else if (up->msgcnt < MSGCNT)
- return;
-
- /*
- * We have a filtered sample offset ready for peer processing.
- * We use lastrec as both the reference time and receive time in
- * order to avoid being cute, like setting the reference time
- * later than the receive time, which may cause a paranoid
- * protocol module to chuck out the data. Finaly, we unhook the
- * timeout, arm for the next call, fold the tent and go home.
- */
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- pp->sloppyclockflag &= ~CLK_FLAG1;
- up->pollcnt = 0;
- up->state = 0;
- usno_disc(peer);
-}
-#endif /* 0 */
-
-
-/*
- * usno_poll - called by the transmit routine
- */
-static void
-usno_poll(
- int unit,
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
-
- /*
- * If the driver is running, we set the enable flag (fudge
- * flag1), which causes the driver timeout routine to initiate a
- * call. If not, the enable flag can be set using
- * ntpdc. If this is the sustem peer, then follow the system
- * poll interval.
- */
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
- if (up->run) {
- pp->sloppyclockflag |= CLK_FLAG1;
- if (peer == sys_peer)
- peer->hpoll = sys_poll;
- else
- peer->hpoll = peer->minpoll;
- }
-}
-
-
-#if 0
-/*
- * usno_timeout - called by the timer interrupt
- */
-static void
-usno_timeout(
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
- int fd;
- char device[20];
- char lockfile[128], pidbuf[8];
- int dtr = TIOCM_DTR;
-
- /*
- * If a timeout occurs in other than state 0, the call has
- * failed. If in state 0, we just see if there is other work to
- * do.
- */
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
- if (up->state) {
- if (up->state != 1) {
- usno_disc(peer);
- return;
- }
- /*
- * Call, and start the answer timeout. We think it
- * strange if the OK status has not been received from
- * the modem, but plow ahead anyway.
- *
- * This code is *here* because we had to stick in a brief
- * delay to let the modem settle down after raising DTR,
- * and for the OK to be received. State machines are
- * contorted.
- */
- if (strcmp(pp->a_lastcode, "OK") != 0)
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s USNO no modem status",
- ntoa(&peer->srcadr));
- (void)usno_write(peer, PHONE);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE, "clock %s USNO calling %s\n",
- ntoa(&peer->srcadr), PHONE);
- up->state = 2;
- up->pollcnt++;
- pp->polls++;
- peer->nextdate = current_time + ANSWER;
- return;
- }
- switch (peer->ttl) {
-
- /*
- * In manual mode the calling program is activated
- * by the ntpdc program using the enable flag (fudge
- * flag1), either manually or by a cron job.
- */
- case MODE_MANUAL:
- up->run = 0;
- break;
-
- /*
- * In automatic mode the calling program runs
- * continuously at intervals determined by the sys_poll
- * variable.
- */
- case MODE_AUTO:
- if (!up->run)
- pp->sloppyclockflag |= CLK_FLAG1;
- up->run = 1;
- break;
-
- /*
- * In backup mode the calling program is disabled,
- * unless no system peer has been selected for MAXOUTAGE
- * (3600 s). Once enabled, it runs until some other NTP
- * peer shows up.
- */
- case MODE_BACKUP:
- if (!up->run && sys_peer == 0) {
- if (current_time - last_time > MAXOUTAGE) {
- up->run = 1;
- peer->hpoll = peer->minpoll;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO backup started ",
- ntoa(&peer->srcadr));
- }
- } else if (up->run && sys_peer->sstclktype != CTL_SST_TS_TELEPHONE) {
- peer->hpoll = peer->minpoll;
- up->run = 0;
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO backup stopped",
- ntoa(&peer->srcadr));
- }
- break;
-
- default:
- msyslog(LOG_ERR,
- "clock %s USNO invalid mode", ntoa(&peer->srcadr));
-
- }
-
- /*
- * The fudge flag1 is used as an enable/disable; if set either
- * by the code or via ntpdc, the calling program is
- * started; if reset, the phones stop ringing.
- */
- if (!(pp->sloppyclockflag & CLK_FLAG1)) {
- up->pollcnt = 0;
- peer->nextdate = current_time + IDLE;
- return;
- }
-
- /*
- * Lock the port.
- */
- (void)sprintf(lockfile, LOCKFILE, up->unit);
- fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL, 0644);
- if (fd < 0) {
- msyslog(LOG_ERR, "clock %s USNO port busy",
- ntoa(&peer->srcadr));
- return;
- }
- sprintf(pidbuf, "%d\n", (int) getpid());
- write(fd, pidbuf, strlen(pidbuf));
- close(fd);
-
- /*
- * Open serial port. Use ACTS line discipline, if available. It
- * pumps a timestamp into the data stream at every on-time
- * character '*' found. Note: the port must have modem control
- * or deep pockets for the phone bill. HP-UX 9.03 users should
- * have very deep pockets.
- */
- (void)sprintf(device, DEVICE, up->unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS))) {
- unlink(lockfile);
- return;
- }
- if (ioctl(fd, TIOCMBIC, (char *)&dtr) < 0)
- msyslog(LOG_WARNING, "usno_timeout: clock %s: couldn't clear DTR: %m",
- ntoa(&peer->srcadr));
-
- pp->io.clock_recv = usno_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
- (void) close(fd);
- unlink(lockfile);
- free(up);
- return;
- }
-
- /*
- * Initialize modem and kill DTR. We skedaddle if this comes
- * bum.
- */
- if (!usno_write(peer, MODEM_SETUP)) {
- msyslog(LOG_ERR, "clock %s USNO couldn't write",
- ntoa(&peer->srcadr));
- io_closeclock(&pp->io);
- unlink(lockfile);
- free(up);
- return;
- }
-
- /*
- * Initiate a call to the Observatory. If we wind up here in
- * other than state 0, a successful call could not be completed
- * within minpoll seconds.
- */
- if (up->pollcnt) {
- refclock_report(peer, CEVNT_TIMEOUT);
- NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
- msyslog(LOG_NOTICE,
- "clock %s USNO calling program terminated",
- ntoa(&peer->srcadr));
- pp->sloppyclockflag &= ~CLK_FLAG1;
- up->pollcnt = 0;
-#ifdef DEBUG
- if (debug)
- printf("usno: calling program terminated\n");
-#endif
- usno_disc(peer);
- return;
- }
-
- /*
- * Raise DTR, and let the modem settle. Then we'll dial.
- */
- if (ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr) < -1)
- msyslog(LOG_INFO, "usno_timeout: clock %s: couldn't set DTR: %m",
- ntoa(&peer->srcadr));
- up->state = 1;
- peer->nextdate = current_time + WAIT;
-}
-#endif /* 0 */
-
-
-/*
- * usno_disc - disconnect the call and wait for the ruckus to cool
- */
-static void
-usno_disc(
- struct peer *peer
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
- int dtr = TIOCM_DTR;
- char lockfile[128];
-
- /*
- * We should never get here other than in state 0, unless a call
- * has timed out. We drop DTR, which will reliably get the modem
- * off the air, even while the modem is hammering away full tilt.
- */
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
-
- if (ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr) < 0)
- msyslog(LOG_INFO, "usno_disc: clock %s: couldn't clear DTR: %m",
- ntoa(&peer->srcadr));
-
- if (up->state > 0) {
- up->state = 0;
- msyslog(LOG_NOTICE, "clock %s USNO call failed %d",
- ntoa(&peer->srcadr), up->state);
-#ifdef DEBUG
- if (debug)
- printf("usno: call failed %d\n", up->state);
-#endif
- }
-
- io_closeclock(&pp->io);
- sprintf(lockfile, LOCKFILE, up->unit);
- unlink(lockfile);
-
- peer->nextdate = current_time + WAIT;
-}
-
-
-#if 0
-/*
- * usno_write - write a message to the serial port
- */
-static int
-usno_write(
- struct peer *peer,
- const char *str
- )
-{
- register struct usnounit *up;
- struct refclockproc *pp;
- int len;
- int code;
- char cr = '\r';
-
- /*
- * Not much to do here, other than send the message, handle
- * debug and report faults.
- */
- pp = peer->procptr;
- up = (struct usnounit *)pp->unitptr;
- len = strlen(str);
-#ifdef DEBUG
- if (debug)
- printf("usno: state %d send %d %s\n", up->state, len,
- str);
-#endif
- code = write(pp->io.fd, str, (unsigned)len) == len;
- code |= write(pp->io.fd, &cr, 1) == 1;
- if (!code)
- refclock_report(peer, CEVNT_FAULT);
- return (code);
-}
-#endif /* 0 */
-
-#else
-int refclock_usno_bs;
-#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_wwv.c b/contrib/ntp/ntpd/refclock_wwv.c
index 11aae7f..b7e0d9a 100644
--- a/contrib/ntp/ntpd/refclock_wwv.c
+++ b/contrib/ntp/ntpd/refclock_wwv.c
@@ -33,11 +33,11 @@
* This driver synchronizes the computer time using data encoded in
* radio transmissions from NIST time/frequency stations WWV in Boulder,
* CO, and WWVH in Kauai, HI. Transmissions are made continuously on
- * 2.5, 5, 10, 15 and 20 MHz in AM mode. An ordinary shortwave receiver
- * can be tuned manually to one of these frequencies or, in the case of
- * ICOM receivers, the receiver can be tuned automatically using this
- * program as propagation conditions change throughout the day and
- * night.
+ * 2.5, 5, 10 and 15 MHz from WWV and WWVH, and 20 MHz from WWV. An
+ * ordinary AM shortwave receiver can be tuned manually to one of these
+ * frequencies or, in the case of ICOM receivers, the receiver can be
+ * tuned automatically using this program as propagation conditions
+ * change throughout the weasons, both day and night.
*
* The driver receives, demodulates and decodes the radio signals when
* connected to the audio codec of a workstation running Solaris, SunOS
@@ -50,7 +50,7 @@
* TI 320C25 digital signal processor described in: Mills, D.L. A
* precision radio clock for WWV transmissions. Electrical Engineering
* Report 97-8-1, University of Delaware, August 1997, 25 pp., available
- * from www.eecis.udel.edu/~mills/reports.htm. The algorithms described
+ * from www.eecis.udel.edu/~mills/reports.html. The algorithms described
* in this report have been modified somewhat to improve performance
* under weak signal conditions and to provide an automatic station
* identification feature.
@@ -59,9 +59,18 @@
* unless the mode keyword on the server configuration command specifies
* a nonzero ICOM ID select code. The C-IV trace is turned on if the
* debug level is greater than one.
+ *
+ * Fudge factors
+ *
+ * Fudge flag4 causes the dubugging output described above to be
+ * recorded in the clockstats file. 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.
*/
/*
- * Interface definitions
+ * General definitions. These ordinarily do not need to be changed.
*/
#define DEVICE_AUDIO "/dev/audio" /* audio device name */
#define AUDIO_BUFSIZ 320 /* audio buffer size (50 ms) */
@@ -71,52 +80,60 @@
#define MINUTE (SECOND * 60) /* minute epoch */
#define OFFSET 128 /* companded sample offset */
#define SIZE 256 /* decompanding table size */
-#define MAXSIG 6000. /* max signal level reference */
+#define MAXAMP 6000. /* max signal level reference */
#define MAXCLP 100 /* max clips above reference per s */
-#define MAXSNR 30. /* max SNR reference */
-#define DGAIN 20. /* data channel gain reference */
-#define SGAIN 10. /* sync channel gain reference */
-#define MAXFREQ 1. /* max frequency tolerance (125 PPM) */
-#define PI 3.1415926535 /* the real thing */
-#define DATSIZ (170 * MS) /* data matched filter size */
-#define SYNSIZ (800 * MS) /* minute sync matched filter size */
-#define MAXERR 30 /* max data bit errors in minute */
+#define MAXSNR 40. /* max SNR reference */
+#define MAXFREQ 1.5 /* max frequency tolerance (187 PPM) */
+#define DATCYC 170 /* data filter cycles */
+#define DATSIZ (DATCYC * MS) /* data filter size */
+#define SYNCYC 800 /* minute filter cycles */
+#define SYNSIZ (SYNCYC * MS) /* minute filter size */
+#define TCKCYC 5 /* tick filter cycles */
+#define TCKSIZ (TCKCYC * MS) /* tick filter size */
#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 */
+
+/*
+ * Tunable parameters. The DGAIN parameter can be changed to fit the
+ * audio response of the radio at 100 Hz. The WWV/WWVH data subcarrier
+ * is transmitted at about 20 percent percent modulation; the matched
+ * filter boosts it by a factor of 17 and the receiver response does
+ * what it does. The compromise value works for ICOM radios. If the
+ * radio is not tunable, the DCHAN parameter can be changed to fit the
+ * expected best propagation frequency: higher if further from the
+ * transmitter, lower if nearer. The compromise value works for the US
+ * right coast. The FREQ_OFFSET parameter can be used as a frequency
+ * vernier to correct codec requency if greater than MAXFREQ.
+ */
+#define DCHAN 3 /* default radio channel (15 Mhz) */
+#define DGAIN 5. /* subcarrier gain */
+#define FREQ_OFFSET 0. /* codec frequency correction (PPM) */
/*
* General purpose status bits (status)
*
- * SELV and/or SELH are set when WWV or WWVH has been heard and cleared
+ * SELV and/or SELH are set when WWV or WWVH have 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.
+ * sync pulse has been acquired. DSYNC is set when the units digit has
+ * has reached the threshold and INSYNC is set when all nine digits have
+ * reached the threshold. The MSYNC, DSYNC and INSYNC bits are cleared
+ * only by timeout, upon which the driver starts over from scratch.
*
- * DGATE is set if a data bit is invalid and BGATE is set if a BCD digit
- * bit is invalid. SFLAG is set when during seconds 59, 0 and 1 while
- * probing alternate frequencies. LEPDAY is set when SECWAR of the
- * timecode is set on 30 June or 31 December. LEPSEC is set during the
- * last minute of the day when LEPDAY is set. At the end of this minute
- * the driver inserts second 60 in the seconds state machine and the
- * minute sync slips a second. The SLOSS and SJITR bits are for monitor
- * only.
+ * DGATE is lit if the data bit amplitude or SNR is below thresholds and
+ * BGATE is lit if the pulse width amplitude or SNR is below thresolds.
+ * LEPSEC is set during the last minute of the leap day. At the end of
+ * this minute the driver inserts second 60 in the seconds state machine
+ * and the minute sync slips a second.
*/
#define MSYNC 0x0001 /* minute epoch sync */
#define SSYNC 0x0002 /* second epoch sync */
#define DSYNC 0x0004 /* minute units sync */
#define INSYNC 0x0008 /* clock synchronized */
#define FGATE 0x0010 /* frequency gate */
-#define DGATE 0x0020 /* data bit error */
-#define BGATE 0x0040 /* BCD digit bit error */
-#define SFLAG 0x1000 /* probe flag */
-#define LEPDAY 0x2000 /* leap second day */
-#define LEPSEC 0x4000 /* leap second minute */
+#define DGATE 0x0020 /* data pulse amplitude error */
+#define BGATE 0x0040 /* data pulse width error */
+#define LEPSEC 0x1000 /* leap minute */
/*
* Station scoreboard bits
@@ -124,9 +141,6 @@
* These are used to establish the signal quality for each of the five
* frequencies and two stations.
*/
-#define SYNCNG 0x0001 /* sync or SNR below threshold */
-#define DATANG 0x0002 /* data or SNR below threshold */
-#define ERRRNG 0x0004 /* data error */
#define SELV 0x0100 /* WWV station select */
#define SELH 0x0200 /* WWVH station select */
@@ -134,18 +148,12 @@
* Alarm status bits (alarm)
*
* These bits indicate various alarm conditions, which are decoded to
- * form the quality character included in the timecode. If not tracking
- * second sync, the SYNERR alarm is raised. The data error counter is
- * incremented for each invalid data bit. If too many data bit errors
- * are encountered in one minute, the MODERR alarm is raised. The DECERR
- * alarm is raised if a maximum likelihood digit fails to compare with
- * the current clock digit. If the probability of any miscellaneous bit
- * or any digit falls below the threshold, the SYMERR alarm is raised.
+ * form the quality character included in the timecode.
*/
-#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 */
+#define CMPERR 1 /* digit or misc bit compare error */
+#define LOWERR 2 /* low bit or digit amplitude or SNR */
+#define NINERR 4 /* less than nine digits in minute */
+#define SYNERR 8 /* not tracking second sync */
/*
* Watchcat timeouts (watch)
@@ -154,9 +162,9 @@
* driver starts from scratch. Suitably more refined procedures may be
* developed in future. All these are in minutes.
*/
-#define ACQSN 5 /* station acquisition timeout */
-#define DIGIT 30 /* minute unit digit timeout */
-#define HOLD 30 /* reachable timeout */
+#define ACQSN 6 /* station acquisition timeout */
+#define DATA 15 /* unit minutes timeout */
+#define SYNCH 40 /* station sync timeout */
#define PANIC (2 * 1440) /* panic timeout */
/*
@@ -165,25 +173,24 @@
* rates of the driver. The values defined here may be on the
* adventurous side in the interest of the highest sensitivity.
*/
-#define MTHR 13. /* acquisition signal gate (percent) */
-#define TTHR 50. /* tracking signal gate (percent) */
-#define ATHR 2000. /* acquisition amplitude threshold */
-#define ASNR 6. /* acquisition SNR threshold (dB) */
-#define AWND 20. /* acquisition jitter threshold (ms) */
-#define AMIN 3 /* min bit count */
-#define AMAX 6 /* max bit count */
-#define QTHR 2000 /* QSY sync threshold */
-#define QSNR 20. /* QSY sync SNR threshold (dB) */
-#define XTHR 1000. /* QSY data threshold */
-#define XSNR 10. /* QSY data SNR threshold (dB) */
-#define STHR 500 /* second sync amplitude threshold */
-#define SSNR 10. /* second sync SNR threshold */
+#define MTHR 13. /* minute sync gate (percent) */
+#define TTHR 50. /* minute sync threshold (percent) */
+#define AWND 20 /* minute sync jitter threshold (ms) */
+#define ATHR 2500. /* QRZ minute sync threshold */
+#define ASNR 20. /* QRZ minute sync SNR threshold (dB) */
+#define QTHR 2500. /* QSY minute sync threshold */
+#define QSNR 20. /* QSY minute sync SNR threshold (dB) */
+#define STHR 2500. /* second sync threshold */
+#define SSNR 15. /* second sync SNR threshold (dB) */
#define SCMP 10 /* second sync compare threshold */
-#define DTHR 1000 /* bit amplitude threshold */
+#define DTHR 1000. /* bit threshold */
#define DSNR 10. /* bit SNR threshold (dB) */
-#define BTHR 1000 /* digit amplitude threshold */
+#define AMIN 3 /* min bit count */
+#define AMAX 6 /* max bit count */
+#define BTHR 1000. /* digit threshold */
#define BSNR 3. /* digit likelihood threshold (dB) */
-#define BCMP 5 /* digit compare threshold */
+#define BCMP 3 /* digit compare threshold */
+#define MAXERR 40 /* maximum error alarm */
/*
* Tone frequency definitions. The increments are for 4.5-deg sine
@@ -195,10 +202,11 @@
#define IN1200 ((1200 * 80) / SECOND) /* 1200 Hz increment */
/*
- * Acquisition and tracking time constants. Usually powers of 2.
+ * Acquisition and tracking time constants
*/
-#define MINAVG 8 /* min time constant */
-#define MAXAVG 1024 /* max time constant */
+#define MINAVG 8 /* min averaging time */
+#define MAXAVG 1024 /* max averaging time */
+#define FCONST 3 /* frequency time constant */
#define TCONST 16 /* data bit/digit time constant */
/*
@@ -229,30 +237,29 @@
/*
* Table of sine values at 4.5-degree increments. This is used by the
- * synchronous matched filter demodulators. The integral of sine-squared
- * over one complete cycle is PI, so the table is normallized by 1 / PI.
+ * synchronous matched filter demodulators.
*/
double sintab[] = {
- 0.000000e+00, 2.497431e-02, 4.979464e-02, 7.430797e-02, /* 0-3 */
- 9.836316e-02, 1.218119e-01, 1.445097e-01, 1.663165e-01, /* 4-7 */
- 1.870979e-01, 2.067257e-01, 2.250791e-01, 2.420447e-01, /* 8-11 */
- 2.575181e-01, 2.714038e-01, 2.836162e-01, 2.940800e-01, /* 12-15 */
- 3.027307e-01, 3.095150e-01, 3.143910e-01, 3.173286e-01, /* 16-19 */
- 3.183099e-01, 3.173286e-01, 3.143910e-01, 3.095150e-01, /* 20-23 */
- 3.027307e-01, 2.940800e-01, 2.836162e-01, 2.714038e-01, /* 24-27 */
- 2.575181e-01, 2.420447e-01, 2.250791e-01, 2.067257e-01, /* 28-31 */
- 1.870979e-01, 1.663165e-01, 1.445097e-01, 1.218119e-01, /* 32-35 */
- 9.836316e-02, 7.430797e-02, 4.979464e-02, 2.497431e-02, /* 36-39 */
--0.000000e+00, -2.497431e-02, -4.979464e-02, -7.430797e-02, /* 40-43 */
--9.836316e-02, -1.218119e-01, -1.445097e-01, -1.663165e-01, /* 44-47 */
--1.870979e-01, -2.067257e-01, -2.250791e-01, -2.420447e-01, /* 48-51 */
--2.575181e-01, -2.714038e-01, -2.836162e-01, -2.940800e-01, /* 52-55 */
--3.027307e-01, -3.095150e-01, -3.143910e-01, -3.173286e-01, /* 56-59 */
--3.183099e-01, -3.173286e-01, -3.143910e-01, -3.095150e-01, /* 60-63 */
--3.027307e-01, -2.940800e-01, -2.836162e-01, -2.714038e-01, /* 64-67 */
--2.575181e-01, -2.420447e-01, -2.250791e-01, -2.067257e-01, /* 68-71 */
--1.870979e-01, -1.663165e-01, -1.445097e-01, -1.218119e-01, /* 72-75 */
--9.836316e-02, -7.430797e-02, -4.979464e-02, -2.497431e-02, /* 76-79 */
+ 0.000000e+00, 7.845910e-02, 1.564345e-01, 2.334454e-01, /* 0-3 */
+ 3.090170e-01, 3.826834e-01, 4.539905e-01, 5.224986e-01, /* 4-7 */
+ 5.877853e-01, 6.494480e-01, 7.071068e-01, 7.604060e-01, /* 8-11 */
+ 8.090170e-01, 8.526402e-01, 8.910065e-01, 9.238795e-01, /* 12-15 */
+ 9.510565e-01, 9.723699e-01, 9.876883e-01, 9.969173e-01, /* 16-19 */
+ 1.000000e+00, 9.969173e-01, 9.876883e-01, 9.723699e-01, /* 20-23 */
+ 9.510565e-01, 9.238795e-01, 8.910065e-01, 8.526402e-01, /* 24-27 */
+ 8.090170e-01, 7.604060e-01, 7.071068e-01, 6.494480e-01, /* 28-31 */
+ 5.877853e-01, 5.224986e-01, 4.539905e-01, 3.826834e-01, /* 32-35 */
+ 3.090170e-01, 2.334454e-01, 1.564345e-01, 7.845910e-02, /* 36-39 */
+-0.000000e+00, -7.845910e-02, -1.564345e-01, -2.334454e-01, /* 40-43 */
+-3.090170e-01, -3.826834e-01, -4.539905e-01, -5.224986e-01, /* 44-47 */
+-5.877853e-01, -6.494480e-01, -7.071068e-01, -7.604060e-01, /* 48-51 */
+-8.090170e-01, -8.526402e-01, -8.910065e-01, -9.238795e-01, /* 52-55 */
+-9.510565e-01, -9.723699e-01, -9.876883e-01, -9.969173e-01, /* 56-59 */
+-1.000000e+00, -9.969173e-01, -9.876883e-01, -9.723699e-01, /* 60-63 */
+-9.510565e-01, -9.238795e-01, -8.910065e-01, -8.526402e-01, /* 64-67 */
+-8.090170e-01, -7.604060e-01, -7.071068e-01, -6.494480e-01, /* 68-71 */
+-5.877853e-01, -5.224986e-01, -4.539905e-01, -3.826834e-01, /* 72-75 */
+-3.090170e-01, -2.334454e-01, -1.564345e-01, -7.845910e-02, /* 76-79 */
0.000000e+00}; /* 80 */
/*
@@ -271,18 +278,19 @@ struct progx {
*/
#define IDLE 0 /* no operation */
#define COEF 1 /* BCD bit */
-#define COEF2 2 /* BCD bit ignored */
-#define DECIM9 3 /* BCD digit 0-9 */
-#define DECIM6 4 /* BCD digit 0-6 */
-#define DECIM3 5 /* BCD digit 0-3 */
-#define DECIM2 6 /* BCD digit 0-2 */
-#define MSCBIT 7 /* miscellaneous bit */
-#define MSC20 8 /* miscellaneous bit */
-#define MSC21 9 /* QSY probe channel */
-#define MIN1 10 /* minute */
-#define MIN2 11 /* leap second */
-#define SYNC2 12 /* QSY data channel */
-#define SYNC3 13 /* QSY data channel */
+#define COEF1 2 /* BCD bit for minute unit */
+#define COEF2 3 /* BCD bit not used */
+#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 /* latch time */
+#define MIN2 12 /* leap second */
+#define SYNC2 13 /* latch minute sync pulse */
+#define SYNC3 14 /* latch data pulse */
/*
* Offsets in decoding matrix
@@ -293,8 +301,8 @@ struct progx {
#define YR 7 /* year digits (2) */
struct progx progx[] = {
- {SYNC2, 0}, /* 0 latch sync max */
- {SYNC3, 0}, /* 1 QSY data channel */
+ {SYNC2, 0}, /* 0 latch minute sync pulse */
+ {SYNC3, 0}, /* 1 latch data pulse */
{MSCBIT, DST2}, /* 2 dst2 */
{MSCBIT, SECWAR}, /* 3 lw */
{COEF, 0}, /* 4 1 year units */
@@ -303,10 +311,10 @@ struct progx progx[] = {
{COEF, 3}, /* 7 8 */
{DECIM9, YR}, /* 8 */
{IDLE, 0}, /* 9 p1 */
- {COEF, 0}, /* 10 1 minute units */
- {COEF, 1}, /* 11 2 */
- {COEF, 2}, /* 12 4 */
- {COEF, 3}, /* 13 8 */
+ {COEF1, 0}, /* 10 1 minute units */
+ {COEF1, 1}, /* 11 2 */
+ {COEF1, 2}, /* 12 4 */
+ {COEF1, 3}, /* 13 8 */
{DECIM9, MN}, /* 14 */
{COEF, 0}, /* 15 10 minute tens */
{COEF, 1}, /* 16 20 */
@@ -352,7 +360,7 @@ struct progx progx[] = {
{MSCBIT, DUT1}, /* 56 0.1 dut */
{MSCBIT, DUT2}, /* 57 0.2 */
{MSC21, DUT4}, /* 58 0.4 QSY probe channel */
- {MIN1, 0}, /* 59 p6 latch sync min */
+ {MIN1, 0}, /* 59 p6 latch time */
{MIN2, 0} /* 60 leap second */
};
@@ -447,7 +455,6 @@ struct decvec {
int radix; /* radix (3, 4, 6, 10) */
int digit; /* current clock digit */
int mldigit; /* maximum likelihood digit */
- int phase; /* maximum likelihood digit phase */
int count; /* match count */
double digprb; /* max digit probability */
double digsnr; /* likelihood function (dB) */
@@ -455,51 +462,50 @@ struct decvec {
};
/*
- * The station structure is used to acquire the minute pulse from WWV
- * and/or WWVH. These stations are distinguished by the frequency used
- * for the second and minute sync pulses, 1000 Hz for WWV and 1200 Hz
- * for WWVH. Other than frequency, the format is the same.
+ * The station structure (sp) is used to acquire the minute pulse from
+ * WWV and/or WWVH. These stations are distinguished by the frequency
+ * used for the second and minute sync pulses, 1000 Hz for WWV and 1200
+ * Hz for WWVH. Other than frequency, the format is the same.
*/
struct sync {
double epoch; /* accumulated epoch differences */
- double maxamp; /* sync max envelope (square) */
- double noiamp; /* sync noise envelope (square) */
+ double maxeng; /* sync max energy */
+ double noieng; /* sync noise energy */
long pos; /* max amplitude position */
long lastpos; /* last max position */
long mepoch; /* minute synch epoch */
- double amp; /* sync amplitude (I, Q squares) */
- double synamp; /* sync max envelope at 800 ms */
- double synmax; /* sync envelope at 0 s */
- double synmin; /* sync envelope at 59, 1 s */
+ double amp; /* sync signal */
+ double syneng; /* sync signal max */
+ double synmax; /* sync signal max latched at 0 s */
double synsnr; /* sync signal SNR */
+ double metric; /* signal quality metric */
+ int reach; /* reachability register */
int count; /* bit counter */
- char refid[5]; /* reference identifier */
int select; /* select bits */
- int reach; /* reachability register */
+ char refid[5]; /* reference identifier */
};
/*
- * The channel structure is used to mitigate between channels.
+ * The channel structure (cp) is used to mitigate between channels.
*/
struct chan {
int gain; /* audio gain */
- double sigamp; /* data max envelope (square) */
- double noiamp; /* data noise envelope (square) */
- double datsnr; /* data signal SNR */
struct sync wwv; /* wwv station */
struct sync wwvh; /* wwvh station */
};
/*
- * WWV unit control structure
+ * WWV unit control structure (up)
*/
struct wwvunit {
l_fp timestamp; /* audio sample timestamp */
l_fp tick; /* audio sample increment */
double phase, freq; /* logical clock phase and frequency */
double monitor; /* audio monitor point */
+#ifdef ICOM
int fd_icom; /* ICOM file descriptor */
+#endif /* ICOM */
int errflg; /* error flags */
int watch; /* watchcat */
@@ -511,18 +517,11 @@ struct wwvunit {
int gain; /* codec gain */
int mongain; /* codec monitor gain */
int clipcnt; /* sample clipped count */
-#ifdef IRIG_SUCKS
- l_fp wigwag; /* wiggle accumulator */
- int wp; /* wiggle filter pointer */
- l_fp wiggle[WIGGLE]; /* wiggle filter */
- l_fp wigbot[WIGGLE]; /* wiggle bottom fisher*/
-#endif /* IRIG_SUCKS */
/*
* Variables used to establish basic system timing
*/
int avgint; /* master time constant */
- int tepoch; /* sync epoch median */
int yepoch; /* sync epoch */
int repoch; /* buffered sync epoch */
double epomax; /* second sync amplitude */
@@ -554,10 +553,8 @@ struct wwvunit {
* Variables used to estimate signal levels and bit/digit
* probabilities
*/
- double sigsig; /* data max signal */
- double sigamp; /* data max envelope (square) */
- double noiamp; /* data noise envelope (square) */
- double datsnr; /* data SNR (dB) */
+ double datsig; /* data signal max */
+ double datsnr; /* data signal SNR (dB) */
/*
* Variables used to establish status and alarm conditions
@@ -566,7 +563,6 @@ struct wwvunit {
int alarm; /* alarm flashers */
int misc; /* miscellaneous timecode bits */
int errcnt; /* data bit error counter */
- int errbit; /* data bit errors in minute */
};
/*
@@ -584,19 +580,18 @@ static void wwv_epoch P((struct peer *));
static void wwv_rf P((struct peer *, double));
static void wwv_endpoc P((struct peer *, int));
static void wwv_rsec P((struct peer *, double));
-static void wwv_qrz P((struct peer *, struct sync *,
- double, int));
+static void wwv_qrz P((struct peer *, struct sync *, int));
static void wwv_corr4 P((struct peer *, struct decvec *,
double [], double [][4]));
static void wwv_gain P((struct peer *));
-static void wwv_tsec P((struct wwvunit *));
-static double wwv_data P((struct wwvunit *, double));
+static void wwv_tsec P((struct peer *));
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 int wwv_newchan P((struct peer *));
static void wwv_newgame P((struct peer *));
static double wwv_metric P((struct sync *));
+static void wwv_clock P((struct peer *));
#ifdef ICOM
static int wwv_qsy P((struct peer *, int));
#endif /* ICOM */
@@ -648,7 +643,7 @@ wwv_start(
#ifdef DEBUG
if (debug)
audio_show();
-#endif
+#endif /* DEBUG */
/*
* Allocate and initialize unit structure
@@ -681,8 +676,8 @@ wwv_start(
* contains all the 256 values in the interest of speed.
*/
up->comp[0] = up->comp[OFFSET] = 0.;
- up->comp[1] = 1; up->comp[OFFSET + 1] = -1.;
- up->comp[2] = 3; up->comp[OFFSET + 2] = -3.;
+ up->comp[1] = 1.; up->comp[OFFSET + 1] = -1.;
+ up->comp[2] = 3.; up->comp[OFFSET + 2] = -3.;
step = 2.;
for (i = 3; i < OFFSET; i++) {
up->comp[i] = up->comp[i - 1] + step;
@@ -705,20 +700,18 @@ wwv_start(
up->decvec[DA + 2].radix = 4;
up->decvec[YR].radix = 10; /* years */
up->decvec[YR + 1].radix = 10;
- wwv_newgame(peer);
- up->schan = up->achan = 3;
+#ifdef ICOM
/*
- * Initialize autotune if available. Start out at 15 MHz. Note
- * that the ICOM select code must be less than 128, so the high
- * order bit can be used to select the line speed.
+ * Initialize autotune if available. Note that the ICOM select
+ * code must be less than 128, so the high order bit can be used
+ * to select the line speed 0 (9600 bps) or 1 (1200 bps).
*/
-#ifdef ICOM
temp = 0;
#ifdef DEBUG
if (debug > 1)
temp = P_TRACE;
-#endif
+#endif /* DEBUG */
if (peer->ttl != 0) {
if (peer->ttl & 0x80)
up->fd_icom = icom_init("/dev/icom", B1200,
@@ -726,9 +719,15 @@ wwv_start(
else
up->fd_icom = icom_init("/dev/icom", B9600,
temp);
+ if (up->fd_icom < 0) {
+ NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
+ msyslog(LOG_NOTICE,
+ "icom: %m");
+ up->errflg = CEVNT_FAULT;
+ }
}
if (up->fd_icom > 0) {
- if ((temp = wwv_qsy(peer, up->schan)) != 0) {
+ if (wwv_qsy(peer, DCHAN) != 0) {
NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
msyslog(LOG_NOTICE,
"icom: radio not found");
@@ -742,6 +741,11 @@ wwv_start(
}
}
#endif /* ICOM */
+
+ /*
+ * Let the games begin.
+ */
+ wwv_newgame(peer);
return (1);
}
@@ -760,9 +764,14 @@ wwv_shutdown(
pp = peer->procptr;
up = (struct wwvunit *)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);
}
@@ -808,15 +817,15 @@ wwv_receive(
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.
+ * Clip noise spikes greater than MAXAMP (6000) and
+ * record the number of clips to be used later by the
+ * AGC.
*/
- if (sample > MAXSIG) {
- sample = MAXSIG;
+ if (sample > MAXAMP) {
+ sample = MAXAMP;
up->clipcnt++;
- } else if (sample < -MAXSIG) {
- sample = -MAXSIG;
+ } else if (sample < -MAXAMP) {
+ sample = -MAXAMP;
up->clipcnt++;
}
@@ -829,6 +838,7 @@ wwv_receive(
* 125 PPM.
*/
up->phase += up->freq / SECOND;
+ up->phase += FREQ_OFFSET / 1e6;
if (up->phase >= .5) {
up->phase -= 1.;
} else if (up->phase < -.5) {
@@ -861,8 +871,7 @@ wwv_receive(
* 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.
+ * well.
*/
static void
wwv_poll(
@@ -888,9 +897,9 @@ wwv_poll(
* wwv_rf - process signals and demodulate to baseband
*
* This routine grooms and filters decompanded raw audio samples. The
- * output signals include the 100-Hz baseband data signal in quadrature
- * form, plus the epoch index of the second sync signal and the second
- * index of the minute sync signal.
+ * output signal is the 100-Hz filtered baseband data signal in
+ * quadrature phase. The routine also determines the minute synch epoch,
+ * as well as certain signal maxima, minima and related values.
*
* There are two 1-s ramps used by this program. Both count the 8000
* logical clock samples spanning exactly one second. The epoch ramp
@@ -911,8 +920,8 @@ wwv_poll(
* 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).
+ * as required for the WWV second sync signal (5 cycles at 1000 Hz) and
+ * WWVH second sync signal (6 cycles at 1200 Hz).
*/
static void
wwv_rf(
@@ -922,7 +931,7 @@ wwv_rf(
{
struct refclockproc *pp;
struct wwvunit *up;
- struct sync *sp;
+ struct sync *sp, *rp;
static double lpf[5]; /* 150-Hz lpf delay line */
double data; /* lpf output */
@@ -936,24 +945,37 @@ wwv_rf(
static double qbuf[DATSIZ]; /* data Q channel delay line */
static int jptr; /* sync channel pointer */
+ static int kptr; /* tick channel pointer */
+
+ static int csinptr; /* wwv channel phase */
static double cibuf[SYNSIZ]; /* wwv I channel delay line */
static double cqbuf[SYNSIZ]; /* wwv Q channel delay line */
static double ciamp; /* wwv I channel amplitude */
static double cqamp; /* wwv Q channel amplitude */
- static int csinptr; /* wwv channel phase */
+
+ static double csibuf[TCKSIZ]; /* wwv I tick delay line */
+ static double csqbuf[TCKSIZ]; /* wwv Q tick delay line */
+ static double csiamp; /* wwv I tick amplitude */
+ static double csqamp; /* wwv Q tick amplitude */
+
+ static int hsinptr; /* wwvh channel phase */
static double hibuf[SYNSIZ]; /* wwvh I channel delay line */
static double hqbuf[SYNSIZ]; /* wwvh Q channel delay line */
static double hiamp; /* wwvh I channel amplitude */
static double hqamp; /* wwvh Q channel amplitude */
- static int hsinptr; /* wwvh channels phase */
- static double epobuf[SECOND]; /* epoch sync comb filter */
- static double epomax; /* epoch sync amplitude buffer */
- static int epopos; /* epoch sync position buffer */
+ static double hsibuf[TCKSIZ]; /* wwvh I tick delay line */
+ static double hsqbuf[TCKSIZ]; /* wwvh Q tick delay line */
+ static double hsiamp; /* wwvh I tick amplitude */
+ static double hsqamp; /* wwvh Q tick amplitude */
+
+ static double epobuf[SECOND]; /* second sync comb filter */
+ static double epomax, nxtmax; /* second sync amplitude buffer */
+ static int epopos; /* epoch second sync position buffer */
static int iniflg; /* initialization flag */
- int epoch; /* comb filter index */
int pdelay; /* propagation delay (samples) */
+ int epoch; /* comb filter index */
double dtemp;
int i;
@@ -969,8 +991,12 @@ wwv_rf(
memset((char *)qbuf, 0, sizeof(qbuf));
memset((char *)cibuf, 0, sizeof(cibuf));
memset((char *)cqbuf, 0, sizeof(cqbuf));
+ memset((char *)csibuf, 0, sizeof(csibuf));
+ memset((char *)csqbuf, 0, sizeof(csqbuf));
memset((char *)hibuf, 0, sizeof(hibuf));
memset((char *)hqbuf, 0, sizeof(hqbuf));
+ memset((char *)hsibuf, 0, sizeof(hsibuf));
+ memset((char *)hsqbuf, 0, sizeof(hsqbuf));
memset((char *)epobuf, 0, sizeof(epobuf));
}
@@ -981,6 +1007,10 @@ wwv_rf(
* 600-Hz tones and most of the noise and voice modulation
* components.
*
+ * The subcarrier is transmitted 10 dB down from the carrier.
+ * The DGAIN parameter can be adjusted for this and to
+ * compensate for the radio audio response at 100 Hz.
+ *
* Matlab IIR 4th-order IIR elliptic, 150 Hz lowpass, 0.2 dB
* passband ripple, -50 dB stopband ripple.
*/
@@ -988,7 +1018,7 @@ wwv_rf(
data += (lpf[3] = lpf[2]) * -3.481740e+00;
data += (lpf[2] = lpf[1]) * 5.452988e+00;
data += (lpf[1] = lpf[0]) * -3.807229e+00;
- lpf[0] = isig - data;
+ lpf[0] = isig * DGAIN - data;
data = lpf[0] * 3.281435e-03
+ lpf[1] * -1.149947e-02
+ lpf[2] * 1.654858e-02
@@ -996,20 +1026,24 @@ wwv_rf(
+ lpf[4] * 3.281435e-03;
/*
- * The I and Q quadrature data signals are produced by
+ * The 100-Hz data signal is demodulated using a pair of
+ * quadrature multipliers, matched filters and a phase lock
+ * loop. The I and Q quadrature data signals are produced by
* multiplying the filtered signal by 100-Hz sine and cosine
- * signals, respectively. The data signals are demodulated by
- * 170-ms synchronous matched filters to produce the amplitude
- * and phase signals used by the decoder.
+ * signals, respectively. The signals are processed by 170-ms
+ * synchronous matched filters to produce the amplitude and
+ * phase signals used by the demodulator. The signals are scaled
+ * to produce unit energy at the maximum value.
*/
i = up->datapt;
up->datapt = (up->datapt + IN100) % 80;
- dtemp = sintab[i] * data / DATSIZ * DGAIN;
+ dtemp = sintab[i] * data / (MS / 2. * DATCYC);
up->irig -= ibuf[iptr];
ibuf[iptr] = dtemp;
up->irig += dtemp;
+
i = (i + 20) % 80;
- dtemp = sintab[i] * data / DATSIZ * DGAIN;
+ dtemp = sintab[i] * data / (MS / 2. * DATCYC);
up->qrig -= qbuf[iptr];
qbuf[iptr] = dtemp;
up->qrig += dtemp;
@@ -1044,12 +1078,19 @@ wwv_rf(
+ bpf[8] * 8.203628e-03;
/*
- * The I and Q quadrature minute sync signals are produced by
- * multiplying the filtered signal by 1000-Hz (WWV) and 1200-Hz
- * (WWVH) sine and cosine signals, respectively. The resulting
- * signals are demodulated by 800-ms synchronous matched filters
- * to synchronize the second and minute and to detect which one
- * (or both) the WWV or WWVH signal is present.
+ * The 1000/1200 sync signals are demodulated using a pair of
+ * quadrature multipliers and matched filters. However,
+ * synchronous demodulation at these frequencies is impractical,
+ * so only the signal amplitude is used. The I and Q quadrature
+ * sync signals are produced by multiplying the filtered signal
+ * by 1000-Hz (WWV) and 1200-Hz (WWVH) sine and cosine signals,
+ * respectively. The WWV and WWVH signals are processed by 800-
+ * ms synchronous matched filters and combined to produce the
+ * minute sync signal and detect which one (or both) the WWV or
+ * WWVH signal is present. The WWV and WWVH signals are also
+ * processed by 5-ms synchronous matched filters and combined to
+ * produce the second sync signal. The signals are scaled to
+ * produce unit energy at the maximum value.
*
* Note the master timing ramps, which run continuously. The
* minute counter (mphase) counts the samples in the minute,
@@ -1058,37 +1099,64 @@ wwv_rf(
*/
up->mphase = (up->mphase + 1) % MINUTE;
epoch = up->mphase % SECOND;
+
+ /*
+ * WWV
+ */
i = csinptr;
csinptr = (csinptr + IN1000) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- ciamp = ciamp - cibuf[jptr] + dtemp;
+
+ dtemp = sintab[i] * syncx / (MS / 2.);
+ ciamp -= cibuf[jptr];
cibuf[jptr] = dtemp;
+ ciamp += dtemp;
+ csiamp -= csibuf[kptr];
+ csibuf[kptr] = dtemp;
+ csiamp += dtemp;
+
i = (i + 20) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- cqamp = cqamp - cqbuf[jptr] + dtemp;
+ dtemp = sintab[i] * syncx / (MS / 2.);
+ cqamp -= cqbuf[jptr];
cqbuf[jptr] = dtemp;
- sp = &up->mitig[up->schan].wwv;
- dtemp = ciamp * ciamp + cqamp * cqamp;
- sp->amp = dtemp;
+ cqamp += dtemp;
+ csqamp -= csqbuf[kptr];
+ csqbuf[kptr] = dtemp;
+ csqamp += dtemp;
+
+ sp = &up->mitig[up->achan].wwv;
+ sp->amp = sqrt(ciamp * ciamp + cqamp * cqamp) / SYNCYC;
if (!(up->status & MSYNC))
- wwv_qrz(peer, sp, dtemp, (int)(pp->fudgetime1 *
- SECOND));
+ wwv_qrz(peer, sp, (int)(pp->fudgetime1 * SECOND));
+
+ /*
+ * WWVH
+ */
i = hsinptr;
hsinptr = (hsinptr + IN1200) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- hiamp = hiamp - hibuf[jptr] + dtemp;
+
+ dtemp = sintab[i] * syncx / (MS / 2.);
+ hiamp -= hibuf[jptr];
hibuf[jptr] = dtemp;
+ hiamp += dtemp;
+ hsiamp -= hsibuf[kptr];
+ hsibuf[kptr] = dtemp;
+ hsiamp += dtemp;
+
i = (i + 20) % 80;
- dtemp = sintab[i] * syncx / SYNSIZ * SGAIN;
- hqamp = hqamp - hqbuf[jptr] + dtemp;
+ dtemp = sintab[i] * syncx / (MS / 2.);
+ hqamp -= hqbuf[jptr];
hqbuf[jptr] = dtemp;
- sp = &up->mitig[up->schan].wwvh;
- dtemp = hiamp * hiamp + hqamp * hqamp;
- sp->amp = dtemp;
+ hqamp += dtemp;
+ hsqamp -= hsqbuf[kptr];
+ hsqbuf[kptr] = dtemp;
+ hsqamp += dtemp;
+
+ rp = &up->mitig[up->achan].wwvh;
+ rp->amp = sqrt(hiamp * hiamp + hqamp * hqamp) / SYNCYC;
if (!(up->status & MSYNC))
- wwv_qrz(peer, sp, dtemp, (int)(pp->fudgetime2 *
- SECOND));
+ wwv_qrz(peer, rp, (int)(pp->fudgetime2 * SECOND));
jptr = (jptr + 1) % SYNSIZ;
+ kptr = (kptr + 1) % TCKSIZ;
/*
* The following section is called once per minute. It does
@@ -1100,22 +1168,16 @@ wwv_rf(
/*
* 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.
+ * ACQSN timeout (6 min), or if no signal is
+ * heard, the program cycles to the next
+ * frequency and tries again.
*/
- wwv_newchan(peer);
- if (!(up->status & (SELV | SELH)) || up->watch >
- ACQSN) {
- wwv_newgame(peer);
+ if (!wwv_newchan(peer))
+ up->watch = 0;
#ifdef ICOM
- if (up->fd_icom > 0) {
- up->schan = (up->schan + 1) %
- NCHAN;
- wwv_qsy(peer, up->schan);
- }
+ if (up->fd_icom > 0)
+ wwv_qsy(peer, up->dchan);
#endif /* ICOM */
- }
} else {
/*
@@ -1138,15 +1200,20 @@ wwv_rf(
* 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.
+ * must be set.
+ *
+ * Note the guard interval is 200 ms; if for some reason the
+ * clock drifts more than that, it might wind up in the wrong
+ * second. If the maximum frequency error is not more than about
+ * 1 PPM, the clock can go as much as two days while still in
+ * the same second.
*/
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;
+ } else if (up->sptr != NULL) {
+ sp = up->sptr;
+ if (sp->metric >= TTHR && epoch == sp->mepoch % SECOND) {
+ up->rsec = (60 - sp->mepoch / SECOND) % 60;
up->rphase = 0;
up->status |= MSYNC;
up->watch = 0;
@@ -1154,11 +1221,7 @@ wwv_rf(
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;
- }
+
}
}
@@ -1171,103 +1234,15 @@ wwv_rf(
*/
if (up->status & SELV) {
pdelay = (int)(pp->fudgetime1 * SECOND);
-
- /*
- * WWV FIR matched filter, five cycles of 1000-Hz
- * sinewave.
- */
- mf[40] = mf[39];
- mfsync = (mf[39] = mf[38]) * 4.224514e-02;
- mfsync += (mf[38] = mf[37]) * 5.974365e-02;
- mfsync += (mf[37] = mf[36]) * 4.224514e-02;
- mf[36] = mf[35];
- mfsync += (mf[35] = mf[34]) * -4.224514e-02;
- mfsync += (mf[34] = mf[33]) * -5.974365e-02;
- mfsync += (mf[33] = mf[32]) * -4.224514e-02;
- mf[32] = mf[31];
- mfsync += (mf[31] = mf[30]) * 4.224514e-02;
- mfsync += (mf[30] = mf[29]) * 5.974365e-02;
- mfsync += (mf[29] = mf[28]) * 4.224514e-02;
- mf[28] = mf[27];
- mfsync += (mf[27] = mf[26]) * -4.224514e-02;
- mfsync += (mf[26] = mf[25]) * -5.974365e-02;
- mfsync += (mf[25] = mf[24]) * -4.224514e-02;
- mf[24] = mf[23];
- mfsync += (mf[23] = mf[22]) * 4.224514e-02;
- mfsync += (mf[22] = mf[21]) * 5.974365e-02;
- mfsync += (mf[21] = mf[20]) * 4.224514e-02;
- mf[20] = mf[19];
- mfsync += (mf[19] = mf[18]) * -4.224514e-02;
- mfsync += (mf[18] = mf[17]) * -5.974365e-02;
- mfsync += (mf[17] = mf[16]) * -4.224514e-02;
- mf[16] = mf[15];
- mfsync += (mf[15] = mf[14]) * 4.224514e-02;
- mfsync += (mf[14] = mf[13]) * 5.974365e-02;
- mfsync += (mf[13] = mf[12]) * 4.224514e-02;
- mf[12] = mf[11];
- mfsync += (mf[11] = mf[10]) * -4.224514e-02;
- mfsync += (mf[10] = mf[9]) * -5.974365e-02;
- mfsync += (mf[9] = mf[8]) * -4.224514e-02;
- mf[8] = mf[7];
- mfsync += (mf[7] = mf[6]) * 4.224514e-02;
- mfsync += (mf[6] = mf[5]) * 5.974365e-02;
- mfsync += (mf[5] = mf[4]) * 4.224514e-02;
- mf[4] = mf[3];
- mfsync += (mf[3] = mf[2]) * -4.224514e-02;
- mfsync += (mf[2] = mf[1]) * -5.974365e-02;
- mfsync += (mf[1] = mf[0]) * -4.224514e-02;
- mf[0] = syncx;
+ mfsync = sqrt(csiamp * csiamp + csqamp * csqamp) /
+ TCKCYC;
} else if (up->status & SELH) {
pdelay = (int)(pp->fudgetime2 * SECOND);
-
- /*
- * WWVH FIR matched filter, six cycles of 1200-Hz
- * sinewave.
- */
- mf[40] = mf[39];
- mfsync = (mf[39] = mf[38]) * 4.833363e-02;
- mfsync += (mf[38] = mf[37]) * 5.681959e-02;
- mfsync += (mf[37] = mf[36]) * 1.846180e-02;
- mfsync += (mf[36] = mf[35]) * -3.511644e-02;
- mfsync += (mf[35] = mf[34]) * -5.974365e-02;
- mfsync += (mf[34] = mf[33]) * -3.511644e-02;
- mfsync += (mf[33] = mf[32]) * 1.846180e-02;
- mfsync += (mf[32] = mf[31]) * 5.681959e-02;
- mfsync += (mf[31] = mf[30]) * 4.833363e-02;
- mf[30] = mf[29];
- mfsync += (mf[29] = mf[28]) * -4.833363e-02;
- mfsync += (mf[28] = mf[27]) * -5.681959e-02;
- mfsync += (mf[27] = mf[26]) * -1.846180e-02;
- mfsync += (mf[26] = mf[25]) * 3.511644e-02;
- mfsync += (mf[25] = mf[24]) * 5.974365e-02;
- mfsync += (mf[24] = mf[23]) * 3.511644e-02;
- mfsync += (mf[23] = mf[22]) * -1.846180e-02;
- mfsync += (mf[22] = mf[21]) * -5.681959e-02;
- mfsync += (mf[21] = mf[20]) * -4.833363e-02;
- mf[20] = mf[19];
- mfsync += (mf[19] = mf[18]) * 4.833363e-02;
- mfsync += (mf[18] = mf[17]) * 5.681959e-02;
- mfsync += (mf[17] = mf[16]) * 1.846180e-02;
- mfsync += (mf[16] = mf[15]) * -3.511644e-02;
- mfsync += (mf[15] = mf[14]) * -5.974365e-02;
- mfsync += (mf[14] = mf[13]) * -3.511644e-02;
- mfsync += (mf[13] = mf[12]) * 1.846180e-02;
- mfsync += (mf[12] = mf[11]) * 5.681959e-02;
- mfsync += (mf[11] = mf[10]) * 4.833363e-02;
- mf[10] = mf[9];
- mfsync += (mf[9] = mf[8]) * -4.833363e-02;
- mfsync += (mf[8] = mf[7]) * -5.681959e-02;
- mfsync += (mf[7] = mf[6]) * -1.846180e-02;
- mfsync += (mf[6] = mf[5]) * 3.511644e-02;
- mfsync += (mf[5] = mf[4]) * 5.974365e-02;
- mfsync += (mf[4] = mf[3]) * 3.511644e-02;
- mfsync += (mf[3] = mf[2]) * -1.846180e-02;
- mfsync += (mf[2] = mf[1]) * -5.681959e-02;
- mfsync += (mf[1] = mf[0]) * -4.833363e-02;
- mf[0] = syncx;
+ mfsync = sqrt(hsiamp * hsiamp + hsqamp * hsqamp) /
+ TCKCYC;
} else {
- mfsync = 0;
pdelay = 0;
+ mfsync = 0;
}
/*
@@ -1276,29 +1251,27 @@ wwv_rf(
* 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.
+ * computed from the maximum sample and the envelope of the
+ * sample 6 ms before it, so if we slip more than a cycle the
+ * SNR should plummet. The signal is scaled to produce unit
+ * energy at the maximum value.
*/
dtemp = (epobuf[epoch] += (mfsync - epobuf[epoch]) /
up->avgint);
if (dtemp > epomax) {
+ int j;
+
epomax = dtemp;
epopos = epoch;
+ j = epoch - 6 * MS;
+ if (j < 0)
+ j += SECOND;
+ nxtmax = fabs(epobuf[j]);
}
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;
+ up->eposnr = wwv_snr(epomax, nxtmax);
+ epopos -= pdelay + TCKCYC * MS;
if (epopos < 0)
epopos += SECOND;
wwv_endpoc(peer, epopos);
@@ -1317,146 +1290,92 @@ 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
- * frequency in turn for the minute pulse from either station, which
- * involves searching through the entire minute of samples. After
- * finding a candidate, the process searches only the seconds before and
- * after the candidate for the signal and all other seconds for the
- * noise.
+ * frequency and station in turn for the minute pulse, which
+ * involves searching through the entire 480,000-sample minute. The
+ * process finds the maximum signal and RMS noise plus signal. Then, the
+ * actual noise is determined by subtracting the energy of the matched
+ * filter.
*
* Students of radar receiver technology will discover this algorithm
- * amounts to a range gate discriminator. The discriminator requires
- * that the peak minute pulse amplitude be at least 2000 and the SNR be
- * at least 6 dB. In addition after finding a candidate, The peak second
- * pulse amplitude must be at least 2000, the SNR at least 6 dB and the
+ * amounts to a range-gate discriminator. A valid pulse must have peak
+ * amplitude at least QTHR (2500) and SNR at least QSNR (20) 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.
+ * AWND (20 ms). Note that the discriminator peak occurs about 800 ms
+ * into the second, so the timing is retarded to the previous second
+ * epoch.
*/
static void
wwv_qrz(
struct peer *peer, /* peer structure pointer */
struct sync *sp, /* sync channel structure */
- double syncx, /* bandpass filtered sync signal */
int pdelay /* propagation delay (samples) */
)
{
struct refclockproc *pp;
struct wwvunit *up;
- char tbuf[80]; /* monitor buffer */
- double snr; /* on-pulse/off-pulse ratio (dB) */
- long epoch, fpoch;
- int isgood;
+ char tbuf[80]; /* monitor buffer */
+ long epoch;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
/*
- * Find the sample with peak energy, which defines the minute
- * epoch. If a sample has been found with good amplitude,
- * accumulate the noise squares for all except the second before
- * and after that position.
+ * Find the sample with peak amplitude, which defines the minute
+ * epoch. Accumulate all samples to determine the total noise
+ * energy.
*/
- 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;
+ epoch = up->mphase - pdelay - SYNSIZ;
if (epoch < 0)
epoch += MINUTE;
- if (syncx > sp->maxamp) {
- sp->maxamp = syncx;
+ if (sp->amp > sp->maxeng) {
+ sp->maxeng = sp->amp;
sp->pos = epoch;
}
- if (abs((epoch - sp->lastpos) % MINUTE) > SECOND)
- sp->noiamp += syncx;
+ sp->noieng += sp->amp;
/*
- * 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.
+ * At the end of the minute, determine the epoch of the minute
+ * sync pulse, as well as the difference between the current and
+ * previous epoches due to the intrinsic frequency error plus
+ * jitter. When calculating the SNR, subtract the pulse energy
+ * from the total noise energy and then normalize.
*/
if (up->mphase == 0) {
- sp->synmax = sqrt(sp->maxamp);
- sp->synmin = sqrt(sp->noiamp / (MINUTE - 2 * SECOND));
+ sp->synmax = sp->maxeng;
+ sp->synsnr = wwv_snr(sp->synmax, (sp->noieng -
+ sp->synmax) / MINUTE);
+ if (sp->count == 0)
+ sp->lastpos = sp->pos;
epoch = (sp->pos - sp->lastpos) % MINUTE;
-
- /*
- * If not yet in minute sync, we have to do a little
- * dance to find a valid minute sync pulse, emphasis
- * valid.
- */
- snr = wwv_snr(sp->synmax, sp->synmin);
- isgood = isgood && sp->synmax > ATHR && snr > ASNR;
- switch (sp->count) {
-
- /*
- * In state 0 the station was not heard during the
- * previous probe. Look for the biggest blip greater
- * than the amplitude threshold in the minute and assume
- * that the minute sync pulse. We're fishing here, since
- * the range gate has not yet been determined. If found,
- * bump to state 1.
- */
- case 0:
- if (sp->synmax >= ATHR)
+ sp->reach <<= 1;
+ if (sp->reach & (1 << AMAX))
+ sp->count--;
+ if (sp->synmax > ATHR && sp->synsnr > ASNR) {
+ if (abs(epoch) < AWND * MS) {
+ sp->reach |= 1;
sp->count++;
- break;
-
- /*
- * In state 1 a candidate blip has been found and the
- * next minute has been searched for another blip. If
- * none are found acceptable, drop back to state 0 and
- * hunt some more. Otherwise, a legitimate minute pulse
- * may have been found, so bump to state 2.
- */
- case 1:
- if (!isgood) {
- sp->count = 0;
- break;
+ sp->mepoch = sp->lastpos = sp->pos;
+ } else if (sp->count == 1) {
+ sp->lastpos = sp->pos;
}
- 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 (up->watch > ACQSN)
+ sp->metric = 0;
+ else
+ sp->metric = wwv_metric(sp);
if (pp->sloppyclockflag & CLK_FLAG4) {
sprintf(tbuf,
- "wwv8 %d %3d %s %d %5.0f %5.1f %5ld %5d %ld",
- up->port, up->gain, sp->refid, sp->count,
- sp->synmax, snr, sp->pos, up->tepoch,
- epoch);
+ "wwv8 %04x %3d %s %04x %.0f %.0f/%.1f %4ld %4ld",
+ up->status, up->gain, sp->refid,
+ sp->reach & 0xffff, sp->metric, sp->synmax,
+ sp->synsnr, sp->pos % SECOND, epoch);
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
if (debug)
printf("%s\n", tbuf);
-#endif
+#endif /* DEBUG */
}
- sp->lastpos = sp->pos;
- sp->maxamp = sp->noiamp = 0;
+ sp->maxeng = sp->noieng = 0;
}
}
@@ -1465,19 +1384,13 @@ wwv_qrz(
* wwv_endpoc - identify and acquire second sync pulse
*
* This routine is called at the end of the second sync interval. It
- * determines the second sync epoch position within the interval and
+ * determines the second sync epoch position within the second and
* disciplines the sample clock using a frequency-lock loop (FLL).
*
* Second sync is determined in the RF input routine as the maximum
* over all 8000 samples in the second comb filter. To assure accurate
* and reliable time and frequency discipline, this routine performs a
* great deal of heavy-handed heuristic data filtering and grooming.
- *
- * Note that, since the minute sync pulse is very wide (800 ms), precise
- * minute sync epoch acquisition requires at least a rough estimate of
- * the second sync pulse (5 ms). This becomes more important in choppy
- * conditions at the lower frequencies at night, since sferics and
- * cochannel crude can badly distort the minute pulse.
*/
static void
wwv_endpoc(
@@ -1488,11 +1401,15 @@ wwv_endpoc(
struct refclockproc *pp;
struct wwvunit *up;
static int epoch_mf[3]; /* epoch median filter */
+ static int tepoch; /* current second epoch */
static int xepoch; /* last second epoch */
- static int zepoch; /* last averaging interval epoch */
+ static int zepoch; /* last run epoch */
+ static int zcount; /* last run end time */
+ static int scount; /* seconds counter */
static int syncnt; /* run length counter */
static int maxrun; /* longest run length */
- static int mepoch; /* longest run epoch */
+ static int mepoch; /* longest run end epoch */
+ static int mcount; /* longest run end time */
static int avgcnt; /* averaging interval counter */
static int avginc; /* averaging ratchet */
static int iniflg; /* initialization flag */
@@ -1508,6 +1425,21 @@ wwv_endpoc(
}
/*
+ * If the signal amplitude or SNR fall below thresholds, dim the
+ * second sync lamp and wait for hotter ions. If no stations are
+ * heard, we are either in a probe cycle or the ions are really
+ * cold.
+ */
+ scount++;
+ if (up->epomax < STHR || up->eposnr < SSNR) {
+ up->status &= ~(SSYNC | FGATE);
+ avgcnt = syncnt = maxrun = 0;
+ return;
+ }
+ if (!(up->status & (SELV | SELH)))
+ return;
+
+ /*
* A three-stage median filter is used to help denoise the
* second sync pulse. The median sample becomes the candidate
* epoch.
@@ -1517,131 +1449,118 @@ wwv_endpoc(
epoch_mf[0] = epopos;
if (epoch_mf[0] > epoch_mf[1]) {
if (epoch_mf[1] > epoch_mf[2])
- up->tepoch = epoch_mf[1]; /* 0 1 2 */
+ tepoch = epoch_mf[1]; /* 0 1 2 */
else if (epoch_mf[2] > epoch_mf[0])
- up->tepoch = epoch_mf[0]; /* 2 0 1 */
+ tepoch = epoch_mf[0]; /* 2 0 1 */
else
- up->tepoch = epoch_mf[2]; /* 0 2 1 */
+ tepoch = epoch_mf[2]; /* 0 2 1 */
} else {
if (epoch_mf[1] < epoch_mf[2])
- up->tepoch = epoch_mf[1]; /* 2 1 0 */
+ tepoch = epoch_mf[1]; /* 2 1 0 */
else if (epoch_mf[2] < epoch_mf[0])
- up->tepoch = epoch_mf[0]; /* 1 0 2 */
+ tepoch = epoch_mf[0]; /* 1 0 2 */
else
- up->tepoch = epoch_mf[2]; /* 1 2 0 */
+ tepoch = epoch_mf[2]; /* 1 2 0 */
}
- /*
- * If the signal amplitude or SNR fall below thresholds or if no
- * stations are heard, dim the second sync lamp and start over.
- */
- if (!(up->status & (SELV | SELH)) || up->epomax < STHR ||
- up->eposnr < SSNR) {
- up->status &= ~(SSYNC | FGATE);
- avgcnt = syncnt = maxrun = 0;
- return;
- }
- avgcnt++;
/*
* If the epoch candidate is the same as the last one, increment
- * the compare counter. If not, save the length and epoch of the
- * current run for use later and reset the counter.
- */
- tmp2 = (up->tepoch - xepoch) % SECOND;
+ * the run counter. If not, save the length, epoch and end
+ * time of the current run for use later and reset the counter.
+ * The epoch is considered valid if the run is at least SCMP
+ * (10) s, the minute is synchronized and the interval since the
+ * last epoch is not greater than the averaging interval. Thus,
+ * after a long absence, the program will wait a full averaging
+ * interval while the comb filter charges up and noise
+ * dissapates..
+ */
+ tmp2 = (tepoch - xepoch) % SECOND;
if (tmp2 == 0) {
syncnt++;
- } else {
- if (maxrun > 0 && mepoch == xepoch) {
- maxrun += syncnt;
- } else if (syncnt > maxrun) {
- maxrun = syncnt;
- mepoch = xepoch;
+ if (syncnt > SCMP && up->status & MSYNC && (up->status &
+ FGATE || scount - zcount <= up->avgint)) {
+ up->status |= SSYNC;
+ up->yepoch = tepoch;
}
+ } else if (syncnt >= maxrun) {
+ maxrun = syncnt;
+ mcount = scount;
+ mepoch = xepoch;
syncnt = 0;
}
- if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & (SSYNC |
- MSYNC))) {
+ if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status & MSYNC))
+ {
sprintf(tbuf,
- "wwv1 %04x %5.0f %5.1f %5d %5d %4d %4d",
- up->status, up->epomax, up->eposnr, up->tepoch,
- tmp2, avgcnt, syncnt);
+ "wwv1 %04x %3d %4d %5.0f %5.1f %5d %4d %4d %4d",
+ up->status, up->gain, tepoch, up->epomax,
+ up->eposnr, tmp2, avgcnt, syncnt,
+ maxrun);
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
if (debug)
printf("%s\n", tbuf);
#endif /* DEBUG */
}
-
- /*
- * The sample clock frequency is disciplined using a first order
- * feedback loop with time constant consistent with the Allan
- * intercept of typical computer clocks.
- *
- * The frequency update is calculated from the epoch change in
- * 125-us units divided by the averaging interval in seconds.
- * The averaging interval affects other receiver functions,
- * including the the 1000/1200-Hz comb filter and codec clock
- * loop. It also affects the 100-Hz subcarrier loop and the bit
- * and digit comparison counter thresholds.
- */
+ avgcnt++;
if (avgcnt < up->avgint) {
- xepoch = up->tepoch;
+ xepoch = 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) {
+ * The sample clock frequency is disciplined using a first-order
+ * feedback loop with time constant consistent with the Allan
+ * intercept of typical computer clocks. During each averaging
+ * interval the candidate epoch at the end of the longest run is
+ * determined. If the longest run is zero, all epoches in the
+ * interval are different, so the candidate epoch is the current
+ * epoch. The frequency update is computed from the candidate
+ * epoch difference (125-us units) and time difference (seconds)
+ * between updates.
+ */
+ if (syncnt >= maxrun) {
maxrun = syncnt;
+ mcount = scount;
mepoch = xepoch;
}
- xepoch = up->tepoch;
- if (maxrun > SCMP) {
- up->status |= SSYNC;
- up->yepoch = mepoch;
- } else {
- up->status &= ~SSYNC;
+ xepoch = tepoch;
+ if (maxrun == 0) {
+ mepoch = tepoch;
+ mcount = scount;
}
/*
- * 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.
+ * The master clock runs at the codec sample frequency of 8000
+ * Hz, so the intrinsic time resolution is 125 us. The frequency
+ * resolution ranges from 18 PPM at the minimum averaging
+ * interval of 8 s to 0.12 PPM at the maximum interval of 1024
+ * s. An offset update is determined at the end of the longest
+ * run in each averaging interval. The frequency adjustment is
+ * computed from the difference between offset updates and the
+ * interval between them.
*
- * 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;
+ * The maximum frequency adjustment ranges from 187 PPM at the
+ * minimum interval to 1.5 PPM at the maximum. If the adjustment
+ * exceeds the maximum, the update is discarded and the
+ * hysteresis counter is decremented. Otherwise, the frequency
+ * is incremented by the adjustment, but clamped to the maximum
+ * 187.5 PPM. If the update is less than half the maximum, the
+ * hysteresis counter is incremented. If the counter increments
+ * to +3, the averaging interval is doubled and the counter set
+ * to zero; if it decrements to -3, the interval is halved and
+ * the counter set to zero.
+ */
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) {
+ up->freq += (dtemp / 2.) / ((mcount - zcount) *
+ FCONST);
+ 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 {
@@ -1664,17 +1583,23 @@ wwv_endpoc(
}
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);
+ "wwv2 %04x %5.0f %5.1f %5d %4d %4d %4d %4.0f %7.2f",
+ up->status, up->epomax, up->eposnr, mepoch,
+ up->avgint, maxrun, mcount - zcount, dtemp,
+ up->freq * 1e6 / SECOND);
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
if (debug)
printf("%s\n", tbuf);
#endif /* DEBUG */
}
+
+ /*
+ * This is a valid update; set up for the next interval.
+ */
up->status |= FGATE;
zepoch = mepoch;
+ zcount = mcount;
avgcnt = syncnt = maxrun = 0;
}
@@ -1682,21 +1607,21 @@ wwv_endpoc(
/*
* wwv_epoch - epoch scanner
*
- * This routine scans the receiver second epoch to determine the signal
- * amplitudes and pulse timings. Receiver synchronization is determined
- * by the minute sync pulse detected in the wwv_rf() routine and the
- * second sync pulse detected in the wwv_epoch() routine. A pulse width
- * discriminator extracts data signals from the 100-Hz subcarrier. The
- * transmitted signals are delayed by the propagation delay, receiver
- * delay and filter delay of this program. Delay corrections are
- * introduced separately for WWV and WWVH.
+ * This routine extracts data signals from the 100-Hz subcarrier. It
+ * 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. The transmitted
+ * signals are delayed by the propagation delay, receiver delay and
+ * filter delay of this program. Delay corrections are introduced
+ * separately for WWV and WWVH.
*
* Most communications radios use a highpass filter in the audio stages,
* which can do nasty things to the subcarrier phase relative to the
* sync pulses. Therefore, the data subcarrier reference phase is
* disciplined using the hardlimited quadrature-phase signal sampled at
* the same time as the in-phase signal. The phase tracking loop uses
- * phase adjustments of plus-minus one sample (125 us).
+ * phase adjustments of plus-minus one sample (125 us).
*/
static void
wwv_epoch(
@@ -1706,53 +1631,48 @@ wwv_epoch(
struct refclockproc *pp;
struct wwvunit *up;
struct chan *cp;
- static double dpulse; /* data pulse length */
- double dtemp;
+ static double sigmin, sigzer, sigone, engmax, engmin;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
/*
- * Sample the minute sync pulse envelopes at epoch 800 for both
- * the WWV and WWVH stations. This will be used later for
- * channel and station mitigation. Note that the seconds epoch
- * is set here well before the end of the second to make sure we
- * never seet the epoch backwards.
+ * Find the maximum minute sync pulse energy for both the
+ * WWV and WWVH stations. This will be used later for channel
+ * and station mitigation. Also set the seconds epoch at 800 ms
+ * well before the end of the second to make sure we never set
+ * the epoch backwards.
*/
- if (up->rphase == 800 * MS) {
+ cp = &up->mitig[up->achan];
+ if (cp->wwv.amp > cp->wwv.syneng)
+ cp->wwv.syneng = cp->wwv.amp;
+ if (cp->wwvh.amp > cp->wwvh.syneng)
+ cp->wwvh.syneng = cp->wwvh.amp;
+ if (up->rphase == 800 * MS)
up->repoch = up->yepoch;
- cp = &up->mitig[up->achan];
- cp->wwv.synamp = cp->wwv.amp;
- cp->wwvh.synamp = cp->wwvh.amp;
- }
/*
- * Sample the data subcarrier at epoch 15 ms, giving a guard
- * time of +-15 ms from the beginning of the second until the
- * pulse rises at 30 ms. The I-channel amplitude is used to
- * calculate the slice level. The envelope amplitude is used
- * during the probe seconds to determine the SNR. There is a
+ * Use the signal amplitude at epoch 15 ms as the noise floor.
+ * This gives a guard time of +-15 ms from the beginning of the
+ * second until the second pulse rises at 30 ms. 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;
+ if (up->rphase == 15 * MS)
+ sigmin = sigzer = sigone = up->irig;
/*
- * 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.
+ * Latch the data signal at 200 ms. Keep this around until the
+ * end of the second. Use the signal energy as the peak to
+ * compute the SNR. Use the Q sample to adjust the 100-Hz
+ * reference oscillator phase.
*/
- } else if (up->rphase == 215 * MS) {
- up->sigsig = up->irig;
- if (up->sigsig < 0)
- up->sigsig = 0;
+ if (up->rphase == 200 * MS) {
+ sigzer = up->irig;
+ engmax = sqrt(up->irig * up->irig + up->qrig *
+ up->qrig);
up->datpha = up->qrig / up->avgint;
if (up->datpha >= 0) {
up->datapt++;
@@ -1763,20 +1683,15 @@ wwv_epoch(
if (up->datapt < 0)
up->datapt += 80;
}
- up->sigamp = up->irig * up->irig + up->qrig * up->qrig;
+ }
+
/*
- * The slice level is set half way between the peak signal and
- * noise levels. Sample the negative zero crossing after epoch
- * 200 ms and record the epoch at that time. This defines the
- * length of the data pulse, which will later be converted into
- * scaled bit probabilities.
+ * Latch the data signal at 500 ms. Keep this around until the
+ * end of the second.
*/
- } else if (up->rphase > 200 * MS) {
- dtemp = (up->sigsig + sqrt(up->noiamp)) / 2;
- if (up->irig < dtemp && dpulse == 0)
- dpulse = up->rphase;
- }
+ else if (up->rphase == 500 * MS)
+ sigone = up->irig;
/*
* At the end of the second crank the clock state machine and
@@ -1785,17 +1700,43 @@ wwv_epoch(
* 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.
+ * Use the energy at the end of the second as the noise to
+ * compute the SNR for the data pulse. This gives a better
+ * measurement than the beginning of the second, especially when
+ * returning from the probe channel. This gives a guard time of
+ * 30 ms from the decay of the longest pulse to the rise of the
+ * next pulse.
*/
up->rphase++;
if (up->mphase % SECOND == up->repoch) {
- up->datsnr = wwv_snr(up->sigsig, sqrt(up->noiamp));
- wwv_rsec(peer, dpulse);
+ up->status &= ~(DGATE | BGATE);
+ engmin = sqrt(up->irig * up->irig + up->qrig *
+ up->qrig);
+ up->datsig = engmax;
+ up->datsnr = wwv_snr(engmax, engmin);
+
+ /*
+ * If the amplitude or SNR is below threshold, average a
+ * 0 in the the integrators; otherwise, average the
+ * bipolar signal. This is done to avoid noise polution.
+ */
+ if (engmax < DTHR || up->datsnr < DSNR) {
+ up->status |= DGATE;
+ wwv_rsec(peer, 0);
+ } else {
+ sigzer -= sigone;
+ sigone -= sigmin;
+ wwv_rsec(peer, sigone - sigzer);
+ }
+ if (up->status & (DGATE | BGATE))
+ up->errcnt++;
+ if (up->errcnt > MAXERR)
+ up->alarm |= LOWERR;
wwv_gain(peer);
- up->rphase = dpulse = 0;
+ cp = &up->mitig[up->achan];
+ cp->wwv.syneng = 0;
+ cp->wwvh.syneng = 0;
+ up->rphase = 0;
}
}
@@ -1817,7 +1758,7 @@ wwv_epoch(
static void
wwv_rsec(
struct peer *peer, /* peer structure pointer */
- double dpulse
+ double bit
)
{
static int iniflg; /* initialization flag */
@@ -1827,14 +1768,8 @@ 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 */
+ char tbuf[80]; /* monitor buffer */
+ int sw, arg, nsec;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
@@ -1852,11 +1787,16 @@ wwv_rsec(
* used, but it's easier to do them all. After that, crank the
* seconds state machine.
*/
- nsec = up->rsec + 1;
- bit = wwv_data(up, dpulse);
- bitvec[up->rsec] += (bit - bitvec[up->rsec]) / TCONST;
- sw = progx[up->rsec].sw;
- arg = progx[up->rsec].arg;
+ nsec = up->rsec;
+ up->rsec++;
+ bitvec[nsec] += (bit - bitvec[nsec]) / TCONST;
+ sw = progx[nsec].sw;
+ arg = progx[nsec].arg;
+
+ /*
+ * The minute state machine. Fly off to a particular section as
+ * directed by the transition matrix and second number.
+ */
switch (sw) {
/*
@@ -1869,123 +1809,132 @@ wwv_rsec(
* Probe channel stuff
*
* The WWV/H format contains data pulses in second 59 (position
- * identifier), second 1 (not used) and the minute sync pulse in
- * second 0. At the end of second 58, QSY to the probe channel,
- * which rotates over all WWV/H frequencies. At the end of
- * second 1 QSY back to the data channel.
+ * identifier) and second 1, but not in second 0. The minute
+ * sync pulse is contained in second 0. At the end of second 58
+ * QSY to the probe channel, which rotates in turn over all
+ * WWV/H frequencies. At the end of second 0 measure the minute
+ * sync pulse. At the end of second 1 measure the data pulse and
+ * QSY back to the data channel. Note that the actions commented
+ * here happen at the end of the second numbered as shown.
*
- * At the end of second 0 save the minute sync pulse peak value
- * previously latched at 800 ms.
+ * At the end of second 0 save the minute sync amplitude latched
+ * at 800 ms as the signal later used to calculate the SNR.
*/
case SYNC2: /* 0 */
cp = &up->mitig[up->achan];
- cp->wwv.synmax = sqrt(cp->wwv.synamp);
- cp->wwvh.synmax = sqrt(cp->wwvh.synamp);
+ cp->wwv.synmax = cp->wwv.syneng;
+ cp->wwvh.synmax = cp->wwvh.syneng;
break;
/*
- * At the end of second 1 determine the minute sync pulse
- * amplitude and SNR and set SYNCNG if these values are below
- * thresholds. Determine the data pulse amplitude and SNR and
- * set DATANG if these values are below thresholds. Set ERRRNG
- * if data pulses in second 59 and second 1 are decoded in
- * error. Shift a 1 into the reachability register if SYNCNG and
- * DATANG are both lit; otherwise shift a 0. Ignore ERRRNG for
- * the present. The number of 1 bits in the last six intervals
- * represents the channel metric used by the mitigation routine.
+ * At the end of second 1 use the minute sync amplitude latched
+ * at 800 ms as the noise to calculate the SNR. If the minute
+ * sync pulse and SNR are above thresholds and the data pulse
+ * amplitude and SNR are above thresolds, shift a 1 into the
+ * station reachability register; otherwise, shift a 0. The
+ * number of 1 bits in the last six intervals is a component of
+ * the channel metric computed by the wwv_metric() routine.
* Finally, QSY back to the data channel.
*/
case SYNC3: /* 1 */
cp = &up->mitig[up->achan];
- cp->sigamp = sqrt(up->sigamp);
- cp->noiamp = sqrt(up->noiamp);
- cp->datsnr = wwv_snr(cp->sigamp, cp->noiamp);
/*
* WWV station
*/
sp = &cp->wwv;
- sp->synmin = sqrt((sp->synmin + sp->synamp) / 2.);
- sp->synsnr = wwv_snr(sp->synmax, sp->synmin);
- sp->select &= ~(SYNCNG | DATANG | ERRRNG);
- if (sp->synmax < QTHR || sp->synsnr < QSNR)
- sp->select |= SYNCNG;
- if (cp->sigamp < XTHR || cp->datsnr < XSNR)
- sp->select |= DATANG;
- if (up->errcnt > 2)
- sp->select |= ERRRNG;
+ sp->synsnr = wwv_snr(sp->synmax, sp->amp);
sp->reach <<= 1;
if (sp->reach & (1 << AMAX))
sp->count--;
- if (!(sp->select & (SYNCNG | DATANG))) {
+ if (sp->synmax >= QTHR && sp->synsnr >= QSNR &&
+ !(up->status & (DGATE | BGATE))) {
sp->reach |= 1;
sp->count++;
}
+ sp->metric = wwv_metric(sp);
/*
* WWVH station
*/
rp = &cp->wwvh;
- rp->synmin = sqrt((rp->synmin + rp->synamp) / 2.);
- rp->synsnr = wwv_snr(rp->synmax, rp->synmin);
- rp->select &= ~(SYNCNG | DATANG | ERRRNG);
- if (rp->synmax < QTHR || rp->synsnr < QSNR)
- rp->select |= SYNCNG;
- if (cp->sigamp < XTHR || cp->datsnr < XSNR)
- rp->select |= DATANG;
- if (up->errcnt > 2)
- rp->select |= ERRRNG;
+ rp->synsnr = wwv_snr(rp->synmax, rp->amp);
rp->reach <<= 1;
if (rp->reach & (1 << AMAX))
rp->count--;
- if (!(rp->select & (SYNCNG | DATANG | ERRRNG))) {
+ if (rp->synmax >= QTHR && rp->synsnr >= QSNR &&
+ !(up->status & (DGATE | BGATE))) {
rp->reach |= 1;
rp->count++;
}
-
- /*
- * Set up for next minute.
- */
+ rp->metric = wwv_metric(rp);
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,
+ "wwv5 %04x %3d %4d %.0f/%.1f %.0f/%.1f %s %04x %.0f %.0f/%.1f %s %04x %.0f %.0f/%.1f",
+ up->status, up->gain, up->yepoch,
+ up->epomax, up->eposnr, up->datsig,
+ up->datsnr,
sp->refid, sp->reach & 0xffff,
- wwv_metric(sp), sp->synmax, sp->synsnr,
+ sp->metric, sp->synmax, sp->synsnr,
rp->refid, rp->reach & 0xffff,
- wwv_metric(rp), rp->synmax, rp->synsnr);
+ rp->metric, rp->synmax, rp->synsnr);
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
if (debug)
printf("%s\n", tbuf);
#endif /* DEBUG */
}
+ up->errcnt = up->digcnt = up->alarm = 0;
+
+ /*
+ * We now begin the minute scan. If not yet synchronized
+ * to a station, restart if the units digit has not been
+ * found within the DATA timeout (15 m) or if not
+ * synchronized within the SYNCH timeout (40 m). After
+ * synchronizing to a station, restart if no stations
+ * are found within the PANIC timeout (2 days).
+ */
+ if (up->status & INSYNC) {
+ if (up->watch > PANIC) {
+ wwv_newgame(peer);
+ return;
+ }
+ } else {
+ if (!(up->status & DSYNC)) {
+ if (up->watch > DATA) {
+ wwv_newgame(peer);
+ return;
+ }
+ }
+ if (up->watch > SYNCH) {
+ wwv_newgame(peer);
+ return;
+ }
+ }
+ wwv_newchan(peer);
#ifdef ICOM
if (up->fd_icom > 0)
wwv_qsy(peer, up->dchan);
#endif /* ICOM */
- up->status &= ~SFLAG;
- up->errcnt = 0;
- up->alarm = 0;
- wwv_newchan(peer);
break;
/*
* Save the bit probability in the BCD data vector at the index
- * given by the argument. Note that all bits of the vector have
- * to be above the data gate threshold for the digit to be
- * considered valid. Bits not used in the digit are forced to
- * zero and not checked for errors.
- */
- case COEF: /* 4-7, 10-13, 15-17, 20-23,
- 25-26, 30-33, 35-38, 40-41,
- 51-54 */
- if (up->status & DGATE)
- up->status |= BGATE;
+ * given by the argument. Bits not used in the digit are forced
+ * to zero.
+ */
+ case COEF1: /* 4-7 */
bcddld[arg] = bit;
break;
+ case COEF: /* 10-13, 15-17, 20-23, 25-26,
+ 30-33, 35-38, 40-41, 51-54 */
+ if (up->status & DSYNC)
+ bcddld[arg] = bit;
+ else
+ bcddld[arg] = 0;
+ break;
+
case COEF2: /* 18, 27-28, 42-43 */
bcddld[arg] = 0;
break;
@@ -2015,174 +1964,129 @@ 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. The design is intended to preserve the bits
- * over periods of signal loss.
+ * raise the BGATE bit. The design is intended to avoid
+ * integrating noise under low SNR conditions.
*/
case MSC20: /* 55 */
wwv_corr4(peer, &up->decvec[YR + 1], bcddld, bcd9);
/* fall through */
case MSCBIT: /* 2-3, 50, 56-57 */
- if (bitvec[up->rsec] > BTHR)
+ if (bitvec[nsec] > BTHR) {
+ if (!(up->misc & arg))
+ up->alarm |= CMPERR;
up->misc |= arg;
- else if (bitvec[up->rsec] < -BTHR)
+ } else if (bitvec[nsec] < -BTHR) {
+ if (up->misc & arg)
+ up->alarm |= CMPERR;
up->misc &= ~arg;
- else
- up->alarm |= SYMERR;
+ } else {
+ up->status |= BGATE;
+ }
break;
/*
- * Save the data channel gain, then QSY to the probe channel.
+ * Save the data channel gain, then QSY to the probe channel and
+ * dim the seconds comb filters. The newchan() routine will
+ * light them back up.
*/
case MSC21: /* 58 */
- if (bitvec[up->rsec] > BTHR)
+ if (bitvec[nsec] > BTHR) {
+ if (!(up->misc & arg))
+ up->alarm |= CMPERR;
up->misc |= arg;
- else if (bitvec[up->rsec] < -BTHR)
+ } else if (bitvec[nsec] < -BTHR) {
+ if (up->misc & arg)
+ up->alarm |= CMPERR;
up->misc &= ~arg;
- else
- up->alarm |= SYMERR;
- up->mitig[up->dchan].gain = up->gain;
+ } else {
+ up->status |= BGATE;
+ }
+ up->status &= ~(SELV | SELH);
#ifdef ICOM
if (up->fd_icom > 0) {
up->schan = (up->schan + 1) % NCHAN;
wwv_qsy(peer, up->schan);
+ } else {
+ up->mitig[up->achan].gain = up->gain;
}
+#else
+ up->mitig[up->achan].gain = up->gain;
#endif /* ICOM */
- up->status |= SFLAG | SELV | SELH;
- up->errbit = up->errcnt;
- up->errcnt = 0;
break;
/*
* The endgames
*
* During second 59 the receiver and codec AGC are settling
- * down, so the data pulse is unusable. At the end of this
- * second, latch the minute sync pulse noise floor. Then do the
- * minute processing and update the system clock. If a leap
- * second sail on to the next second (60); otherwise, set up for
- * the next minute.
+ * down, so the data pulse is unusable as quality metric. If
+ * LEPSEC is set on the last minute of 30 June or 31 December,
+ * the transmitter and receiver insert an extra second (60) in
+ * the timescale and the minute sync repeats the second. Once
+ * leaps occurred at intervals of about 18 months, but the last
+ * leap before the most recent leap in 1995 was in 1998.
*/
case MIN1: /* 59 */
- cp = &up->mitig[up->achan];
- cp->wwv.synmin = cp->wwv.synamp;
- cp->wwvh.synmin = cp->wwvh.synamp;
+ if (up->status & LEPSEC)
+ break;
- /*
- * Dance the leap if necessary and the kernel has the
- * right stuff. Then, wind up the clock and initialize
- * for the following minute. If the leap dance, note the
- * kernel is armed one second before the actual leap is
- * scheduled.
- */
- if (up->status & SSYNC && up->digcnt >= 9)
- up->status |= INSYNC;
- if (up->status & LEPDAY) {
- pp->leap = LEAP_ADDSECOND;
- } else {
- pp->leap = LEAP_NOWARNING;
- wwv_tsec(up);
- nsec = up->digcnt = 0;
- }
- pp->lencode = timecode(up, pp->a_lastcode);
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
-#ifdef DEBUG
- if (debug)
- printf("wwv: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
-#endif /* DEBUG */
- if (up->status & INSYNC && up->watch < HOLD)
- refclock_receive(peer);
- break;
+ /* fall through */
- /*
- * 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;
+ up->status &= ~LEPSEC;
+ wwv_tsec(peer);
+ up->rsec = 0;
+ wwv_clock(peer);
break;
}
-
- /*
- * If digit sync has not been acquired before timeout or if no
- * station has been heard, game over and restart from scratch.
- */
- if (!(up->status & DSYNC) && (!(up->status & (SELV | SELH)) ||
- up->watch > DIGIT)) {
- wwv_newgame(peer);
- return;
- }
-
- /*
- * If no timestamps have been struck before timeout, game over
- * and restart from scratch.
- */
- if (up->watch > PANIC) {
- wwv_newgame(peer);
- return;
+ if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
+ DSYNC)) {
+ sprintf(tbuf,
+ "wwv3 %2d %04x %3d %4d %5.0f %5.1f %5.0f %5.1f %5.0f",
+ nsec, up->status, up->gain, up->yepoch, up->epomax,
+ up->eposnr, up->datsig, up->datsnr, bit);
+ record_clock_stats(&peer->srcadr, tbuf);
+#ifdef DEBUG
+ if (debug)
+ printf("%s\n", tbuf);
+#endif /* DEBUG */
}
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 */
+/*
+ * The radio clock is set if the alarm bits are all zero. After that,
+ * the time is considered valid if the second sync bit is lit. It should
+ * not be a surprise, especially if the radio is not tunable, that
+ * sometimes no stations are above the noise and the integrators
+ * discharge below the thresholds. We assume that, after a day of signal
+ * loss, the minute sync epoch will be in the same second. This requires
+ * the codec frequency be accurate within 6 PPM. Practical experience
+ * shows the frequency typically within 0.1 PPM, so after a day of
+ * signal loss, the time should be within 8.6 ms..
+ */
+static void
+wwv_clock(
+ struct peer *peer /* peer unit pointer */
+ )
+{
+ struct refclockproc *pp;
+ struct wwvunit *up;
+ l_fp offset; /* offset in NTP seconds */
- /*
- * 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.
- */
+ pp = peer->procptr;
+ up = (struct wwvunit *)pp->unitptr;
+ if (!(up->status & SSYNC))
+ up->alarm |= SYNERR;
+ if (up->digcnt < 9)
+ up->alarm |= NINERR;
+ if (!(up->alarm))
+ up->status |= INSYNC;
if (up->status & INSYNC && up->status & SSYNC) {
+ if (up->misc & SECWAR)
+ pp->leap = LEAP_ADDSECOND;
+ else
+ pp->leap = LEAP_NOWARNING;
pp->second = up->rsec;
pp->minute = up->decvec[MN].digit + up->decvec[MN +
1].digit * 10;
@@ -2201,95 +2105,19 @@ wwv_rsec(
} else {
up->watch = 0;
pp->disp = 0;
+ pp->lastref = up->timestamp;
refclock_process_offset(pp, offset,
up->timestamp, PDELAY);
+ refclock_receive(peer);
}
}
- if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
- DSYNC)) {
- sprintf(tbuf,
- "wwv3 %2d %04x %5.0f %5.1f %5.0f %5.1f %5.0f",
- up->rsec, up->status, up->epomax, up->eposnr,
- up->sigsig, up->datsnr, bit);
- record_clock_stats(&peer->srcadr, tbuf);
+ pp->lencode = timecode(up, pp->a_lastcode);
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
#ifdef DEBUG
- if (debug)
- printf("%s\n", tbuf);
+ if (debug)
+ printf("wwv: timecode %d %s\n", pp->lencode,
+ pp->a_lastcode);
#endif /* DEBUG */
- }
-}
-
-
-/*
- * wwv_data - calculate bit probability
- *
- * This routine is called at the end of the receiver second to calculate
- * the probabilities that the previous second contained a zero (P0), one
- * (P1) or position indicator (P2) pulse. If not in sync or if the data
- * bit is bad, a bit error is declared and the probabilities are forced
- * to zero. Otherwise, the data gate is enabled and the probabilities
- * are calculated. Note that the data matched filter contributes half
- * the pulse width, or 85 ms.
- *
- * It's important to observe that there are three conditions to
- * determine: average to +1 (hit), average to -1 (miss) or average to
- * zero (erasure). The erasure condition results from insufficient
- * signal (noise) and has no bias toward either a hit or miss.
- */
-static double
-wwv_data(
- struct wwvunit *up, /* driver unit pointer */
- double pulse /* pulse length (sample units) */
- )
-{
- double p0, p1, p2; /* probabilities */
- double dpulse; /* pulse length in ms */
-
- p0 = p1 = p2 = 0;
- dpulse = pulse - DATSIZ / 2;
-
- /*
- * If no station is being tracked, if either the data amplitude
- * or SNR are below threshold or if the pulse length is less
- * than 170 ms, declare an erasure.
- */
- if (!(up->status & (SELV | SELH)) || up->sigsig < DTHR ||
- up->datsnr < DSNR || dpulse < DATSIZ) {
- up->status |= DGATE;
- up->errcnt++;
- if (up->errcnt > MAXERR)
- up->alarm |= MODERR;
- return (0);
- }
-
- /*
- * The probability of P0 is one below 200 ms falling to zero at
- * 500 ms. The probability of P1 is zero below 200 ms rising to
- * one at 500 ms and falling to zero at 800 ms. The probability
- * of P2 is zero below 500 ms, rising to one above 800 ms.
- */
- up->status &= ~DGATE;
- if (dpulse < (200 * MS)) {
- p0 = 1;
- } else if (dpulse < 500 * MS) {
- dpulse -= 200 * MS;
- p1 = dpulse / (300 * MS);
- p0 = 1 - p1;
- } else if (dpulse < 800 * MS) {
- dpulse -= 500 * MS;
- p2 = dpulse / (300 * MS);
- p1 = 1 - p2;
- } else {
- p2 = 1;
- }
-
- /*
- * The ouput is a metric that ranges from -1 (P0), to +1 (P1)
- * scaled for convenience. An output of zero represents an
- * erasure, either because of a data error or pulse length
- * greater than 500 ms. At the moment, we don't use P2.
- */
- return ((p1 - p0) * MAXSIG);
}
@@ -2307,35 +2135,34 @@ static void
wwv_corr4(
struct peer *peer, /* peer unit pointer */
struct decvec *vp, /* decoding table pointer */
- double data[], /* received data vector */
- double tab[][4] /* correlation vector array */
+ double data[], /* received data vector */
+ double tab[][4] /* correlation vector array */
)
{
struct refclockproc *pp;
struct wwvunit *up;
-
- double topmax, nxtmax; /* metrics */
- double acc; /* accumulator */
- char tbuf[80]; /* monitor buffer */
- int mldigit; /* max likelihood digit */
- int diff; /* decoding difference */
- int i, j;
+ double topmax, nxtmax; /* metrics */
+ double acc; /* accumulator */
+ char tbuf[80]; /* monitor buffer */
+ int mldigit; /* max likelihood digit */
+ int i, j;
pp = peer->procptr;
up = (struct wwvunit *)pp->unitptr;
/*
* Correlate digit vector with each BCD coefficient vector. If
- * any BCD digit bit is bad, consider all bits a miss.
- */
+ * any BCD digit bit is bad, consider all bits a miss. Until the
+ * minute units digit has been resolved, don't to anything else.
+ * Note the SNR is calculated as the ratio of the largest
+ * likelihood value to the next largest likelihood value.
+ */
mldigit = 0;
- topmax = nxtmax = -MAXSIG;
+ topmax = nxtmax = -MAXAMP;
for (i = 0; tab[i][0] != 0; i++) {
acc = 0;
- for (j = 0; j < 4; j++) {
- if (!(up->status & BGATE))
- acc += data[j] * tab[i][j];
- }
+ for (j = 0; j < 4; j++)
+ acc += data[j] * tab[i][j];
acc = (vp->like[i] += (acc - vp->like[i]) / TCONST);
if (acc > topmax) {
nxtmax = topmax;
@@ -2345,69 +2172,57 @@ wwv_corr4(
nxtmax = acc;
}
}
- vp->mldigit = mldigit;
vp->digprb = topmax;
vp->digsnr = wwv_snr(topmax, nxtmax);
/*
- * The maximum likelihood digit is compared with the current
- * clock digit. The difference represents the decoding phase
- * error. If the clock is not yet synchronized, the phase error
- * is corrected even of the digit probability and likelihood are
- * below thresholds. This avoids lengthy averaging times should
- * a carry mistake occur. However, the digit is not declared
- * synchronized until these values are above thresholds and the
- * last five decoded values are identical. If the clock is
- * synchronized, the phase error is not corrected unless the
- * last five digits are all above thresholds and identical. This
- * avoids mistakes when the signal is coming out of the noise
- * and the SNR is very marginal.
- */
- diff = mldigit - vp->digit;
- if (diff < 0)
- diff += vp->radix;
- if (diff != vp->phase) {
- vp->count = 0;
- vp->phase = diff;
- }
- if (vp->digsnr < BSNR) {
- vp->count = 0;
- up->alarm |= SYMERR;
- } else if (vp->digprb < BTHR) {
+ * The current maximum likelihood digit is compared to the last
+ * maximum likelihood digit. If different, the compare counter
+ * and maximum likelihood digit are reset. When the compare
+ * counter reaches the BCMP threshold (3), the digit is assumed
+ * correct. When the compare counter of all nine digits have
+ * reached threshold, the clock is assumed correct.
+ *
+ * Note that the clock display digit is set before the compare
+ * counter has reached threshold; however, the clock display is
+ * not considered correct until all nine clock digits have
+ * reached threshold. This is intended as eye candy, but avoids
+ * mistakes when the signal is low and the SNR is very marginal.
+ * once correctly set, the maximum likelihood digit is ignored
+ * on the assumption the clock will always be correct unless for
+ * some reason it drifts to a different second.
+ */
+ vp->mldigit = mldigit;
+ if (vp->digprb < BTHR || vp->digsnr < BSNR) {
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 |= BGATE;
+ } else {
up->status |= DSYNC;
- if (!(up->status & INSYNC)) {
- vp->phase = 0;
- vp->digit = mldigit;
+ if (vp->digit != mldigit) {
+ vp->count = 0;
+ up->alarm |= CMPERR;
+ if (!(up->status & INSYNC))
+ vp->digit = mldigit;
+ } else {
+ if (vp->count < BCMP)
+ vp->count++;
+ else
+ up->digcnt++;
}
- } else {
- vp->phase = 0;
- vp->digit = mldigit;
- up->digcnt++;
}
- if (vp->digit != mldigit)
- up->alarm |= DECERR;
if ((pp->sloppyclockflag & CLK_FLAG4) && !(up->status &
INSYNC)) {
sprintf(tbuf,
- "wwv4 %2d %04x %5.0f %2d %d %d %d %d %5.0f %5.1f",
- up->rsec, up->status, up->epomax, vp->radix,
- vp->digit, vp->mldigit, vp->phase, vp->count,
- vp->digprb, vp->digsnr);
+ "wwv4 %2d %04x %3d %4d %5.0f %2d %d %d %d %5.0f %5.1f",
+ up->rsec - 1, up->status, up->gain, up->yepoch,
+ up->epomax, vp->radix, vp->digit, vp->mldigit,
+ vp->count, vp->digprb, vp->digsnr);
record_clock_stats(&peer->srcadr, tbuf);
#ifdef DEBUG
if (debug)
printf("%s\n", tbuf);
#endif /* DEBUG */
}
- up->status &= ~BGATE;
}
@@ -2420,16 +2235,24 @@ wwv_corr4(
*/
static void
wwv_tsec(
- struct wwvunit *up /* driver structure pointer */
+ struct peer *peer /* driver structure pointer */
)
{
+ struct refclockproc *pp;
+ struct wwvunit *up;
int minute, day, isleap;
int temp;
+ pp = peer->procptr;
+ up = (struct wwvunit *)pp->unitptr;
+
/*
- * Advance minute unit of the day.
+ * Advance minute unit of the day. Don't propagate carries until
+ * the unit minute digit has been found.
*/
temp = carry(&up->decvec[MN]); /* minute units */
+ if (!(up->status & DSYNC))
+ return;
/*
* Propagate carries through the day.
@@ -2444,25 +2267,24 @@ wwv_tsec(
/*
* 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 if the last minute on leap day, but only if the clock
+ * is syncrhronized. This code fails in 2400 AD.
*/
minute = up->decvec[MN].digit + up->decvec[MN + 1].digit *
10 + up->decvec[HR].digit * 60 + up->decvec[HR +
1].digit * 600;
day = up->decvec[DA].digit + up->decvec[DA + 1].digit * 10 +
up->decvec[DA + 2].digit * 100;
- isleap = (up->decvec[YR].digit & 0x3) == 0;
- if (up->misc & SECWAR && (day == (isleap ? 182 : 183) || day ==
- (isleap ? 365 : 366)) && up->status & INSYNC && up->status &
- SSYNC)
- up->status |= LEPDAY;
- else
- up->status &= ~LEPDAY;
- if (up->status & LEPDAY && minute == 1439)
- up->status |= LEPSEC;
- else
- up->status &= ~LEPSEC;
+
+ /*
+ * Set the leap bit on the last minute of the leap day.
+ */
+ isleap = up->decvec[YR].digit & 0x3;
+ if (up->misc & SECWAR && up->status & INSYNC) {
+ if ((day == (isleap ? 182 : 183) || day == (isleap ?
+ 365 : 366)) && minute == 1439)
+ up->status |= LEPSEC;
+ }
/*
* Roll the day if this the first minute and propagate carries
@@ -2470,6 +2292,7 @@ wwv_tsec(
*/
if (minute != 1440)
return;
+
minute = 0;
while (carry(&up->decvec[HR]) != 0); /* advance to minute 0 */
while (carry(&up->decvec[HR + 1]) != 0);
@@ -2486,12 +2309,13 @@ wwv_tsec(
*/
if (day != (isleap ? 365 : 366))
return;
+
day = 1;
while (carry(&up->decvec[DA]) != 1); /* advance to day 1 */
while (carry(&up->decvec[DA + 1]) != 0);
while (carry(&up->decvec[DA + 2]) != 0);
temp = carry(&up->decvec[YR]); /* carry years */
- if (temp)
+ if (temp == 0)
carry(&up->decvec[YR + 1]);
}
@@ -2512,11 +2336,10 @@ carry(
int temp;
int j;
- dp->digit++; /* advance clock digit */
- if (dp->digit == dp->radix) { /* modulo radix */
+ dp->digit++;
+ if (dp->digit == dp->radix)
dp->digit = 0;
- }
- temp = dp->like[dp->radix - 1]; /* rotate likelihood vector */
+ temp = dp->like[dp->radix - 1];
for (j = dp->radix - 1; j > 0; j--)
dp->like[j] = dp->like[j - 1];
dp->like[0] = temp;
@@ -2544,14 +2367,14 @@ wwv_snr(
* other hand, in the likelihood function the "noise" is the
* next maximum down from the peak and this could be negative.
* However, in this case the SNR is truly stupendous, so we
- * simply cap at MAXSNR dB.
+ * simply cap at MAXSNR dB (40).
*/
if (signal <= 0) {
rval = 0;
} else if (noise <= 0) {
rval = MAXSNR;
} else {
- rval = 20 * log10(signal / noise);
+ rval = 20. * log10(signal / noise);
if (rval > MAXSNR)
rval = MAXSNR;
}
@@ -2564,7 +2387,7 @@ wwv_snr(
*
* 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
+ * if not tunable only the DCHAN channel appears 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
@@ -2583,13 +2406,12 @@ wwv_snr(
* 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.
+ * from polluting the integrators. In order to consider a station valid,
+ * the metric must be at least MTHR (13); otherwise, the station select
+ * bits are cleared so the second sync is disabled and the data bit
+ * integrators averaged to a miss.
*/
-static void
+static int
wwv_newchan(
struct peer *peer /* peer structure pointer */
)
@@ -2605,44 +2427,66 @@ wwv_newchan(
/*
* 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.
+ * maximum metric. If no station is found above thresholds, tune
+ * to WWV on 15 MHz, set the reference ID to NONE and wait for
+ * hotter ions.
*/
- j = 0;
sp = NULL;
+ j = 0;
rank = 0;
for (i = 0; i < NCHAN; i++) {
rp = &up->mitig[i].wwvh;
- dtemp = wwv_metric(rp);
+ dtemp = rp->metric;
if (dtemp >= rank) {
rank = dtemp;
sp = rp;
j = i;
}
rp = &up->mitig[i].wwv;
- dtemp = wwv_metric(rp);
+ dtemp = rp->metric;
if (dtemp >= rank) {
rank = dtemp;
sp = rp;
j = i;
}
}
+
+ /*
+ * If the strongest signal is less than the MTHR threshold (13),
+ * we are beneath the waves, so squelch the second sync. If the
+ * strongest signal is greater than the threshold, tune to that
+ * frequency and transmitter QTH.
+ */
+ if (rank < MTHR) {
+ up->dchan = (up->dchan + 1) % NCHAN;
+ up->status &= ~(SELV | SELH);
+ return (FALSE);
+ }
up->dchan = j;
+ up->status |= SELV | SELH;
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);
+ memcpy(&pp->refid, sp->refid, 4);
+ peer->refid = pp->refid;
+ return (TRUE);
}
/*
- * www_newgame - reset and start over
+ * wwv_newgame - reset and start over
+ *
+ * There are four conditions resulting in a new game:
+ *
+ * 1 During initial acquisition (MSYNC dark) going 6 minutes (ACQSN)
+ * without reliably finding the minute pulse (MSYNC lit).
+ *
+ * 2 After finding the minute pulse (MSYNC lit), going 15 minutes
+ * (DATA) without finding the unit seconds digit.
+ *
+ * 3 After finding good data (DATA lit), going more than 40 minutes
+ * (SYNCH) without finding station sync (INSYNC lit).
+ *
+ * 4 After finding station sync (INSYNC lit), going more than 2 days
+ * (PANIC) without finding any station.
*/
static void
wwv_newgame(
@@ -2665,12 +2509,12 @@ wwv_newgame(
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.
+ * station/frequency identifier and reference identifier. Start
+ * probing at the next channel after the data channel.
*/
memset(up->mitig, 0, sizeof(up->mitig));
for (i = 0; i < NCHAN; i++) {
@@ -2681,15 +2525,21 @@ wwv_newgame(
cp->wwvh.select = SELH;
sprintf(cp->wwvh.refid, "WH%.0f", floor(qsy[i]));
}
+ up->dchan = (DCHAN + NCHAN - 1) % NCHAN;;
wwv_newchan(peer);
+ up->achan = up->schan = up->dchan;
+#ifdef ICOM
+ if (up->fd_icom > 0)
+ wwv_qsy(peer, up->dchan);
+#endif /* ICOM */
}
/*
* 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.
+ * station reachability register. The least significant bits represent
+ * the minute sync pulse amplitude. The combined value is scaled 0-100.
*/
double
wwv_metric(
@@ -2698,12 +2548,12 @@ wwv_metric(
{
double dtemp;
- dtemp = sp->count * MAXSIG;
- if (sp->synmax < MAXSIG)
+ dtemp = sp->count * MAXAMP;
+ if (sp->synmax < MAXAMP)
dtemp += sp->synmax;
else
- dtemp += MAXSIG - 1;
- dtemp /= (AMAX + 1) * MAXSIG;
+ dtemp += MAXAMP - 1;
+ dtemp /= (AMAX + 1) * MAXAMP;
return (dtemp * 100.);
}
@@ -2803,8 +2653,8 @@ timecode(
*/
sp = up->sptr;
sprintf(cptr, " %d %d %s %.0f %d %.1f %d", up->watch,
- up->mitig[up->dchan].gain, sp->refid, wwv_metric(sp),
- up->errbit, up->freq / SECOND * 1e6, up->avgint);
+ up->mitig[up->dchan].gain, sp->refid, sp->metric,
+ up->errcnt, up->freq / SECOND * 1e6, up->avgint);
strcat(ptr, cptr);
return (strlen(ptr));
}
@@ -2813,12 +2663,12 @@ timecode(
/*
* wwv_gain - adjust codec gain
*
- * This routine is called at the end of each second. It counts the
- * number of signal clips above the MAXSIG threshold during the previous
- * second. If there are no clips, the gain is bumped up; if too many
- * clips, it is bumped down. The decoder is relatively insensitive to
- * amplitude, so this crudity works just fine. The input port is set and
- * the error flag is cleared, mostly to be ornery.
+ * This routine is called at the end of each second. During the second
+ * the number of signal clips above the MAXAMP threshold (6000). If
+ * there are no clips, the gain is bumped up; if there are more than
+ * MAXCLP clips (100), it is bumped down. The decoder is relatively
+ * insensitive to amplitude, so this crudity works just peachy. The
+ * input port is set and the error flag is cleared, mostly to be ornery.
*/
static void
wwv_gain(
diff --git a/contrib/ntp/ntpd/refclock_wwvb.c b/contrib/ntp/ntpd/refclock_wwvb.c
index c5ef9f9..7bddd3a 100644
--- a/contrib/ntp/ntpd/refclock_wwvb.c
+++ b/contrib/ntp/ntpd/refclock_wwvb.c
@@ -1,5 +1,5 @@
/*
- * refclock_wwvb - clock driver for Spectracom WWVB receivers
+ * refclock_wwvb - clock driver for Spectracom WWVB and GPS receivers
*/
#ifdef HAVE_CONFIG_H
@@ -43,7 +43,7 @@
*
* Format 0 (22 ASCII printing characters):
*
- * <cr><lf>i ddd hh:mm:ss TZ=zz<cr><lf>
+ * <cr><lf>i ddd hh:mm:ss TZ=zz<cr><lf>
*
* on-time = first <cr>
* hh:mm:ss = hours, minutes, seconds
@@ -80,19 +80,20 @@
* synchronized to the indicated time as returned.
*
* This driver does not need to be told which format is in use - it
- * figures out which one from the length of the message.The driver makes
- * no attempt to correct for the intrinsic jitter of the radio itself,
- * which is a known problem with the older radios.
+ * figures out which one from the length of the message. The driver
+ * makes no attempt to correct for the intrinsic jitter of the radio
+ * itself, which is a known problem with the older radios.
*
* Fudge Factors
*
* This driver can retrieve a table of quality data maintained
* internally by the Netclock/2 clock. If flag4 of the fudge
* configuration command is set to 1, the driver will retrieve this
- * table and write it to the clockstats file on when the first timecode
+ * table and write it to the clockstats file when the first timecode
* message of a new day is received.
+ *
+ * PPS calibration fudge time 1: format 0 .003134, format 2 .004034
*/
-
/*
* Interface definitions
*/
@@ -100,7 +101,7 @@
#define SPEED232 B9600 /* uart speed (9600 baud) */
#define PRECISION (-13) /* precision assumed (about 100 us) */
#define REFID "WWVB" /* reference ID */
-#define DESCRIPTION "Spectracom WWVB/GPS Receivers" /* WRU */
+#define DESCRIPTION "Spectracom WWVB/GPS Receiver" /* WRU */
#define LENWWVB0 22 /* format 0 timecode length */
#define LENWWVB1 22 /* format 1 timecode length */
@@ -112,7 +113,6 @@
* WWVB unit control structure
*/
struct wwvbunit {
- u_char tcswitch; /* timecode switch */
l_fp laststamp; /* last receive timestamp */
u_char lasthour; /* last hour (for monitor) */
u_char linect; /* count ignored lines (for monitor */
@@ -125,6 +125,7 @@ static int wwvb_start P((int, struct peer *));
static void wwvb_shutdown P((int, struct peer *));
static void wwvb_receive P((struct recvbuf *));
static void wwvb_poll P((int, struct peer *));
+static void wwvb_timer P((int, struct peer *));
/*
* Transfer vector
@@ -136,7 +137,7 @@ struct refclock refclock_wwvb = {
noentry, /* not used (old wwvb_control) */
noentry, /* initialize driver (not used) */
noentry, /* not used (old wwvb_buginfo) */
- NOFLAGS /* not used */
+ wwvb_timer /* called once per second */
};
@@ -157,7 +158,7 @@ wwvb_start(
/*
* Open serial port. Use CLK line discipline, if available.
*/
- (void)sprintf(device, DEVICE, unit);
+ sprintf(device, DEVICE, unit);
if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
return (0);
@@ -166,7 +167,7 @@ wwvb_start(
*/
if (!(up = (struct wwvbunit *)
emalloc(sizeof(struct wwvbunit)))) {
- (void) close(fd);
+ close(fd);
return (0);
}
memset((char *)up, 0, sizeof(struct wwvbunit));
@@ -177,7 +178,7 @@ wwvb_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void) close(fd);
+ close(fd);
free(up);
return (0);
}
@@ -188,7 +189,6 @@ wwvb_start(
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
- peer->burst = MAXSTAGE;
return (1);
}
@@ -249,21 +249,15 @@ wwvb_receive(
* +-50 us relative to the pps; however, on an unmodified 8170
* the start bit can be delayed up to 10 ms. In format 2 the
* reading precision is only to the millisecond. Thus, unless
- * you have a pps gadget and don't have to have the year, format
+ * you have a PPS gadget and don't have to have the year, format
* 0 provides the lowest jitter.
*/
if (temp == 0) {
- if (up->tcswitch == 0) {
- up->tcswitch = 1;
- up->laststamp = trtmp;
- } else
- up->tcswitch = 0;
+ up->laststamp = trtmp;
return;
}
pp->lencode = temp;
pp->lastrec = up->laststamp;
- up->laststamp = trtmp;
- up->tcswitch = 1;
/*
* We get down to business, check the timecode format and decode
@@ -378,14 +372,16 @@ wwvb_receive(
*/
if (!refclock_process(pp))
refclock_report(peer, CEVNT_BADTIME);
+ if (peer->disp > MAXDISTANCE)
+ refclock_receive(peer);
}
/*
- * wwvb_poll - called by the transmit procedure
+ * wwvb_timer - called once per second by the transmit procedure
*/
static void
-wwvb_poll(
+wwvb_timer(
int unit,
struct peer *peer
)
@@ -399,8 +395,7 @@ wwvb_poll(
* 'T' by returning a timecode in the format(s) specified above.
* Note there is no checking on state, since this may not be the
* only customer reading the clock. Only one customer need poll
- * the clock; all others just listen in. If the clock becomes
- * unreachable, declare a timeout and keep going.
+ * the clock; all others just listen in.
*/
pp = peer->procptr;
up = (struct wwvbunit *)pp->unitptr;
@@ -410,8 +405,42 @@ wwvb_poll(
pollchar = 'T';
if (write(pp->io.fd, &pollchar, 1) != 1)
refclock_report(peer, CEVNT_FAULT);
- if (peer->burst > 0)
- return;
+}
+
+
+/*
+ * wwvb_poll - called by the transmit procedure
+ */
+static void
+wwvb_poll(
+ int unit,
+ struct peer *peer
+ )
+{
+ register struct wwvbunit *up;
+ struct refclockproc *pp;
+
+ /*
+ * Sweep up the samples received since the last poll. If none
+ * are received, declare a timeout and keep going.
+ */
+ pp = peer->procptr;
+ up = (struct wwvbunit *)pp->unitptr;
+ pp->polls++;
+
+ /*
+ * If the monitor flag is set (flag4), we dump the internal
+ * quality table at the first timecode beginning the day.
+ */
+ if (pp->sloppyclockflag & CLK_FLAG4 && pp->hour <
+ (int)up->lasthour)
+ up->linect = MONLIN;
+ up->lasthour = pp->hour;
+
+ /*
+ * Process median filter samples. If none received, declare a
+ * timeout and keep going.
+ */
if (pp->coderecv == pp->codeproc) {
refclock_report(peer, CEVNT_TIMEOUT);
return;
@@ -423,17 +452,6 @@ wwvb_poll(
printf("wwvb: timecode %d %s\n", pp->lencode,
pp->a_lastcode);
#endif
- peer->burst = MAXSTAGE;
- pp->polls++;
-
- /*
- * If the monitor flag is set (flag4), we dump the internal
- * quality table at the first timecode beginning the day.
- */
- if (pp->sloppyclockflag & CLK_FLAG4 && pp->hour <
- (int)up->lasthour)
- up->linect = MONLIN;
- up->lasthour = pp->hour;
}
#else
OpenPOWER on IntegriCloud