summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/ntpd')
-rw-r--r--contrib/ntp/ntpd/Makefile.am16
-rw-r--r--contrib/ntp/ntpd/Makefile.in558
-rw-r--r--contrib/ntp/ntpd/check_y2k.c14
-rw-r--r--contrib/ntp/ntpd/cmd_args.c313
-rw-r--r--contrib/ntp/ntpd/ntp_config.c937
-rw-r--r--contrib/ntp/ntpd/ntp_control.c1477
-rw-r--r--contrib/ntp/ntpd/ntp_crypto.c2060
-rw-r--r--contrib/ntp/ntpd/ntp_intres.c246
-rw-r--r--contrib/ntp/ntpd/ntp_io.c298
-rw-r--r--contrib/ntp/ntpd/ntp_loopfilter.c651
-rw-r--r--contrib/ntp/ntpd/ntp_monitor.c17
-rw-r--r--contrib/ntp/ntpd/ntp_peer.c566
-rw-r--r--contrib/ntp/ntpd/ntp_proto.c2559
-rw-r--r--contrib/ntp/ntpd/ntp_refclock.c384
-rw-r--r--contrib/ntp/ntpd/ntp_request.c272
-rw-r--r--contrib/ntp/ntpd/ntp_resolver.c987
-rw-r--r--contrib/ntp/ntpd/ntp_timer.c45
-rw-r--r--contrib/ntp/ntpd/ntp_util.c57
-rw-r--r--contrib/ntp/ntpd/ntpd.c226
-rw-r--r--contrib/ntp/ntpd/refclock_acts.c34
-rw-r--r--contrib/ntp/ntpd/refclock_arbiter.c7
-rw-r--r--contrib/ntp/ntpd/refclock_arc.c10
-rw-r--r--contrib/ntp/ntpd/refclock_as2201.c7
-rw-r--r--contrib/ntp/ntpd/refclock_atom.c608
-rw-r--r--contrib/ntp/ntpd/refclock_bancomm.c77
-rw-r--r--contrib/ntp/ntpd/refclock_chronolog.c8
-rw-r--r--contrib/ntp/ntpd/refclock_chu.c215
-rw-r--r--contrib/ntp/ntpd/refclock_conf.c21
-rw-r--r--contrib/ntp/ntpd/refclock_datum.c32
-rw-r--r--contrib/ntp/ntpd/refclock_dumbclock.c8
-rw-r--r--contrib/ntp/ntpd/refclock_fg.c2
-rw-r--r--contrib/ntp/ntpd/refclock_gpsvme.c13
-rw-r--r--contrib/ntp/ntpd/refclock_heath.c288
-rw-r--r--contrib/ntp/ntpd/refclock_hopfpci.c274
-rw-r--r--contrib/ntp/ntpd/refclock_hopfser.c372
-rw-r--r--contrib/ntp/ntpd/refclock_hpgps.c10
-rw-r--r--contrib/ntp/ntpd/refclock_irig.c15
-rw-r--r--contrib/ntp/ntpd/refclock_jupiter.c9
-rw-r--r--contrib/ntp/ntpd/refclock_leitch.c10
-rw-r--r--contrib/ntp/ntpd/refclock_local.c16
-rw-r--r--contrib/ntp/ntpd/refclock_msfees.c9
-rw-r--r--contrib/ntp/ntpd/refclock_mx4200.c404
-rw-r--r--contrib/ntp/ntpd/refclock_nmea.c427
-rw-r--r--contrib/ntp/ntpd/refclock_oncore.c2039
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.c2
-rw-r--r--contrib/ntp/ntpd/refclock_palisade.h6
-rw-r--r--contrib/ntp/ntpd/refclock_parse.c44
-rw-r--r--contrib/ntp/ntpd/refclock_pcf.c28
-rw-r--r--contrib/ntp/ntpd/refclock_pst.c7
-rw-r--r--contrib/ntp/ntpd/refclock_shm.c44
-rw-r--r--contrib/ntp/ntpd/refclock_tpro.c7
-rw-r--r--contrib/ntp/ntpd/refclock_trak.c11
-rw-r--r--contrib/ntp/ntpd/refclock_true.c69
-rw-r--r--contrib/ntp/ntpd/refclock_ulink.c395
-rw-r--r--contrib/ntp/ntpd/refclock_usno.c15
-rw-r--r--contrib/ntp/ntpd/refclock_wwv.c44
-rw-r--r--contrib/ntp/ntpd/refclock_wwvb.c18
57 files changed, 11811 insertions, 5477 deletions
diff --git a/contrib/ntp/ntpd/Makefile.am b/contrib/ntp/ntpd/Makefile.am
index 2fd16c4..718d996 100644
--- a/contrib/ntp/ntpd/Makefile.am
+++ b/contrib/ntp/ntpd/Makefile.am
@@ -1,9 +1,14 @@
#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
AUTOMAKE_OPTIONS = ../util/ansi2knr
bin_PROGRAMS = ntpd
-INCLUDES = -I$(top_srcdir)/include
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/librsaref
# LDADD might need RESLIB and ADJLIB
LDADD = version.o @LIBPARSE@ ../libntp/libntp.a @LIBRSAREF@
+# ntpd may need:
+# log10 refclock_wwv.o
+# sqrt ntp_control.o
+# floor refclock_wwv.o
+# which are (usually) provided by -lm.
ntpd_LDADD = $(LDADD) -lm
DISTCLEANFILES = .version version.c
#EXTRA_DIST = ntpd.mak
@@ -13,15 +18,18 @@ check_PROGRAMS = @MAKE_CHECK_Y2K@
EXTRA_PROGRAMS = check_y2k
check-local: @MAKE_CHECK_Y2K@
- [ -z "@MAKE_CHECK_Y2K@" ] || ./@MAKE_CHECK_Y2K@
+ test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
-ntpd_SOURCES = jupiter.h map_vme.c ntp_config.c ntp_control.c ntp_filegen.c \
+ntpd_SOURCES = cmd_args.c jupiter.h map_vme.c ntp_config.c ntp_control.c \
+ ntp_crypto.c ntp_filegen.c \
ntp_intres.c ntp_io.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \
- ntp_proto.c ntp_refclock.c ntp_request.c ntp_restrict.c ntp_timer.c \
+ ntp_proto.c ntp_refclock.c ntp_request.c ntp_resolver.c \
+ ntp_restrict.c ntp_timer.c \
ntp_util.c ntpd.c refclock_acts.c refclock_arbiter.c refclock_arc.c \
refclock_as2201.c refclock_atom.c refclock_bancomm.c \
refclock_chronolog.c refclock_chu.c refclock_conf.c refclock_datum.c \
refclock_dumbclock.c refclock_fg.c refclock_gpsvme.c refclock_heath.c \
+ refclock_hopfser.c refclock_hopfpci.c \
refclock_hpgps.c refclock_irig.c refclock_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 \
diff --git a/contrib/ntp/ntpd/Makefile.in b/contrib/ntp/ntpd/Makefile.in
index d12a343..0e3ad1c 100644
--- a/contrib/ntp/ntpd/Makefile.in
+++ b/contrib/ntp/ntpd/Makefile.in
@@ -1,6 +1,7 @@
-# Makefile.in generated automatically by automake 1.4a from Makefile.am
+# Makefile.in generated automatically by automake 1.4e from Makefile.am.
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# 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.
@@ -31,8 +32,6 @@ mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
-DESTDIR =
-
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
@@ -48,7 +47,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_FLAG =
+INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
@@ -57,24 +56,30 @@ POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
+
build_alias = @build_alias@
build_triplet = @build@
host_alias = @host_alias@
host_triplet = @host@
target_alias = @target_alias@
target_triplet = @target@
+
+@SET_MAKE@
AMDEP = @AMDEP@
AMTAR = @AMTAR@
+AUTOKEY = @AUTOKEY@
AWK = @AWK@
CC = @CC@
CFLAGS = @CFLAGS@
CHUTEST = @CHUTEST@
CLKTEST = @CLKTEST@
CPP = @CPP@
-CXX = @CXX@
-CXXCPP = @CXXCPP@
DCFD = @DCFD@
DEPDIR = @DEPDIR@
+EF_LIBS = @EF_LIBS@
+EF_PROGS = @EF_PROGS@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTALL_STRIP_PROGRAM_ENV = @INSTALL_STRIP_PROGRAM_ENV@
LDFLAGS = @LDFLAGS@
LIBPARSE = @LIBPARSE@
LIBRSAREF = @LIBRSAREF@
@@ -86,16 +91,27 @@ MAKE_LIBPARSE = @MAKE_LIBPARSE@
MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
MAKE_LIBRSAREF = @MAKE_LIBRSAREF@
MAKE_NTPTIME = @MAKE_NTPTIME@
+MAKE_NTP_GENKEYS = @MAKE_NTP_GENKEYS@
MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
MAKE_TICKADJ = @MAKE_TICKADJ@
+MAKE_TIMETRIM = @MAKE_TIMETRIM@
+OPENSSL = @OPENSSL@
+OPENSSL_INC = @OPENSSL_INC@
+OPENSSL_LIB = @OPENSSL_LIB@
PACKAGE = @PACKAGE@
+PATH_PERL = @PATH_PERL@
PATH_SH = @PATH_SH@
PROPDELAY = @PROPDELAY@
RANLIB = @RANLIB@
+RSADIR = @RSADIR@
+RSAOBJS = @RSAOBJS@
RSAREF = @RSAREF@
+RSASRCS = @RSASRCS@
+STRIP = @STRIP@
TESTDCF = @TESTDCF@
U = @U@
VERSION = @VERSION@
+_am_include = @_am_include@
install_sh = @install_sh@
#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
@@ -103,9 +119,14 @@ install_sh = @install_sh@
AUTOMAKE_OPTIONS = ../util/ansi2knr
bin_PROGRAMS = ntpd
-INCLUDES = -I$(top_srcdir)/include
+INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/librsaref
# LDADD might need RESLIB and ADJLIB
LDADD = version.o @LIBPARSE@ ../libntp/libntp.a @LIBRSAREF@
+# ntpd may need:
+# log10 refclock_wwv.o
+# sqrt ntp_control.o
+# floor refclock_wwv.o
+# which are (usually) provided by -lm.
ntpd_LDADD = $(LDADD) -lm
DISTCLEANFILES = .version version.c
#EXTRA_DIST = ntpd.mak
@@ -114,13 +135,16 @@ ETAGS_ARGS = Makefile.am
check_PROGRAMS = @MAKE_CHECK_Y2K@
EXTRA_PROGRAMS = check_y2k
-ntpd_SOURCES = jupiter.h map_vme.c ntp_config.c ntp_control.c ntp_filegen.c \
+ntpd_SOURCES = cmd_args.c jupiter.h map_vme.c ntp_config.c ntp_control.c \
+ ntp_crypto.c ntp_filegen.c \
ntp_intres.c ntp_io.c ntp_loopfilter.c ntp_monitor.c ntp_peer.c \
- ntp_proto.c ntp_refclock.c ntp_request.c ntp_restrict.c ntp_timer.c \
+ ntp_proto.c ntp_refclock.c ntp_request.c ntp_resolver.c \
+ ntp_restrict.c ntp_timer.c \
ntp_util.c ntpd.c refclock_acts.c refclock_arbiter.c refclock_arc.c \
refclock_as2201.c refclock_atom.c refclock_bancomm.c \
refclock_chronolog.c refclock_chu.c refclock_conf.c refclock_datum.c \
refclock_dumbclock.c refclock_fg.c refclock_gpsvme.c refclock_heath.c \
+ refclock_hopfser.c refclock_hopfpci.c \
refclock_hpgps.c refclock_irig.c refclock_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 \
@@ -128,154 +152,148 @@ ntpd_SOURCES = jupiter.h map_vme.c ntp_config.c ntp_control.c ntp_filegen.c \
refclock_shm.c refclock_tpro.c refclock_trak.c refclock_true.c \
refclock_ulink.c refclock_usno.c refclock_wwv.c refclock_wwvb.c
+EXEEXT =
+OBJEXT = o
subdir = ntpd
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = ../config.h
-CONFIG_CLEAN_FILES =
-PROGRAMS = $(bin_PROGRAMS)
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+EXTRA_PROGRAMS = check_y2k$(EXEEXT)
+bin_PROGRAMS = ntpd$(EXEEXT)
+check_PROGRAMS = @MAKE_CHECK_Y2K@
+PROGRAMS = $(bin_PROGRAMS)
-DEFS = @DEFS@ -I. -I$(srcdir) -I..
+DEFS = @DEFS@ -I. -I$(srcdir) -I$(top_builddir)
CPPFLAGS = @CPPFLAGS@
LIBS = @LIBS@
ANSI2KNR = ../util/ansi2knr
check_y2k_SOURCES = check_y2k.c
-check_y2k_OBJECTS = check_y2k$U.o
+check_y2k_OBJECTS = check_y2k$U.$(OBJEXT)
check_y2k_LDADD = $(LDADD)
-check_y2k_DEPENDENCIES = version.o ../libntp/libntp.a
+check_y2k_DEPENDENCIES = version.o ../libntp/libntp.a
check_y2k_LDFLAGS =
-am_ntpd_OBJECTS = map_vme$U.o ntp_config$U.o ntp_control$U.o \
-ntp_filegen$U.o ntp_intres$U.o ntp_io$U.o ntp_loopfilter$U.o \
-ntp_monitor$U.o ntp_peer$U.o ntp_proto$U.o ntp_refclock$U.o \
-ntp_request$U.o ntp_restrict$U.o ntp_timer$U.o ntp_util$U.o ntpd$U.o \
-refclock_acts$U.o refclock_arbiter$U.o refclock_arc$U.o \
-refclock_as2201$U.o refclock_atom$U.o refclock_bancomm$U.o \
-refclock_chronolog$U.o refclock_chu$U.o refclock_conf$U.o \
-refclock_datum$U.o refclock_dumbclock$U.o refclock_fg$U.o \
-refclock_gpsvme$U.o refclock_heath$U.o refclock_hpgps$U.o \
-refclock_irig$U.o refclock_jupiter$U.o refclock_leitch$U.o \
-refclock_local$U.o refclock_msfees$U.o refclock_mx4200$U.o \
-refclock_nmea$U.o refclock_oncore$U.o refclock_palisade$U.o \
-refclock_parse$U.o refclock_pcf$U.o refclock_pst$U.o \
-refclock_ptbacts$U.o refclock_shm$U.o refclock_tpro$U.o \
-refclock_trak$U.o refclock_true$U.o refclock_ulink$U.o \
-refclock_usno$U.o refclock_wwv$U.o refclock_wwvb$U.o
-ntpd_OBJECTS = $(am_ntpd_OBJECTS)
-ntpd_DEPENDENCIES = version.o ../libntp/libntp.a
+am_ntpd_OBJECTS = cmd_args$U.$(OBJEXT) map_vme$U.$(OBJEXT) \
+ntp_config$U.$(OBJEXT) ntp_control$U.$(OBJEXT) ntp_crypto$U.$(OBJEXT) \
+ntp_filegen$U.$(OBJEXT) ntp_intres$U.$(OBJEXT) ntp_io$U.$(OBJEXT) \
+ntp_loopfilter$U.$(OBJEXT) ntp_monitor$U.$(OBJEXT) ntp_peer$U.$(OBJEXT) \
+ntp_proto$U.$(OBJEXT) ntp_refclock$U.$(OBJEXT) ntp_request$U.$(OBJEXT) \
+ntp_resolver$U.$(OBJEXT) ntp_restrict$U.$(OBJEXT) ntp_timer$U.$(OBJEXT) \
+ntp_util$U.$(OBJEXT) ntpd$U.$(OBJEXT) refclock_acts$U.$(OBJEXT) \
+refclock_arbiter$U.$(OBJEXT) refclock_arc$U.$(OBJEXT) \
+refclock_as2201$U.$(OBJEXT) refclock_atom$U.$(OBJEXT) \
+refclock_bancomm$U.$(OBJEXT) refclock_chronolog$U.$(OBJEXT) \
+refclock_chu$U.$(OBJEXT) refclock_conf$U.$(OBJEXT) \
+refclock_datum$U.$(OBJEXT) refclock_dumbclock$U.$(OBJEXT) \
+refclock_fg$U.$(OBJEXT) refclock_gpsvme$U.$(OBJEXT) \
+refclock_heath$U.$(OBJEXT) refclock_hopfser$U.$(OBJEXT) \
+refclock_hopfpci$U.$(OBJEXT) refclock_hpgps$U.$(OBJEXT) \
+refclock_irig$U.$(OBJEXT) refclock_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_ulink$U.$(OBJEXT) \
+refclock_usno$U.$(OBJEXT) refclock_wwv$U.$(OBJEXT) \
+refclock_wwvb$U.$(OBJEXT)
+ntpd_OBJECTS = $(am_ntpd_OBJECTS)
+ntpd_DEPENDENCIES = version.o ../libntp/libntp.a
ntpd_LDFLAGS =
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-DIST_SOURCES = check_y2k.c $(ntpd_SOURCES)
-DIST_COMMON = Makefile.am Makefile.in
-
-
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-
-GZIP_ENV = --best
+DIST_SOURCES = check_y2k.c $(ntpd_SOURCES)
depcomp = $(SHELL) $(top_srcdir)/depcomp
-DEP_FILES = @AMDEP@ $(DEPDIR)/check_y2k$U.Po $(DEPDIR)/map_vme$U.Po \
-$(DEPDIR)/ntp_config$U.Po $(DEPDIR)/ntp_control$U.Po \
-$(DEPDIR)/ntp_filegen$U.Po $(DEPDIR)/ntp_intres$U.Po \
-$(DEPDIR)/ntp_io$U.Po $(DEPDIR)/ntp_loopfilter$U.Po \
-$(DEPDIR)/ntp_monitor$U.Po $(DEPDIR)/ntp_peer$U.Po \
-$(DEPDIR)/ntp_proto$U.Po $(DEPDIR)/ntp_refclock$U.Po \
-$(DEPDIR)/ntp_request$U.Po $(DEPDIR)/ntp_restrict$U.Po \
-$(DEPDIR)/ntp_timer$U.Po $(DEPDIR)/ntp_util$U.Po $(DEPDIR)/ntpd$U.Po \
-$(DEPDIR)/refclock_acts$U.Po $(DEPDIR)/refclock_arbiter$U.Po \
-$(DEPDIR)/refclock_arc$U.Po $(DEPDIR)/refclock_as2201$U.Po \
-$(DEPDIR)/refclock_atom$U.Po $(DEPDIR)/refclock_bancomm$U.Po \
-$(DEPDIR)/refclock_chronolog$U.Po $(DEPDIR)/refclock_chu$U.Po \
-$(DEPDIR)/refclock_conf$U.Po $(DEPDIR)/refclock_datum$U.Po \
-$(DEPDIR)/refclock_dumbclock$U.Po $(DEPDIR)/refclock_fg$U.Po \
-$(DEPDIR)/refclock_gpsvme$U.Po $(DEPDIR)/refclock_heath$U.Po \
-$(DEPDIR)/refclock_hpgps$U.Po $(DEPDIR)/refclock_irig$U.Po \
-$(DEPDIR)/refclock_jupiter$U.Po $(DEPDIR)/refclock_leitch$U.Po \
-$(DEPDIR)/refclock_local$U.Po $(DEPDIR)/refclock_msfees$U.Po \
-$(DEPDIR)/refclock_mx4200$U.Po $(DEPDIR)/refclock_nmea$U.Po \
-$(DEPDIR)/refclock_oncore$U.Po $(DEPDIR)/refclock_palisade$U.Po \
-$(DEPDIR)/refclock_parse$U.Po $(DEPDIR)/refclock_pcf$U.Po \
-$(DEPDIR)/refclock_pst$U.Po $(DEPDIR)/refclock_ptbacts$U.Po \
-$(DEPDIR)/refclock_shm$U.Po $(DEPDIR)/refclock_tpro$U.Po \
-$(DEPDIR)/refclock_trak$U.Po $(DEPDIR)/refclock_true$U.Po \
-$(DEPDIR)/refclock_ulink$U.Po $(DEPDIR)/refclock_usno$U.Po \
-$(DEPDIR)/refclock_wwv$U.Po $(DEPDIR)/refclock_wwvb$U.Po
-SOURCES = check_y2k.c $(ntpd_SOURCES)
-OBJECTS = check_y2k$U.o $(am_ntpd_OBJECTS)
-
-all: all-redirect
-.SUFFIXES:
-.SUFFIXES: .c .h .o
-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
- cd $(top_srcdir) && $(AUTOMAKE) --gnu ntpd/Makefile
-
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
- cd $(top_builddir) \
- && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
+@AMDEP@DEP_FILES = $(DEPDIR)/check_y2k$U.Po $(DEPDIR)/cmd_args$U.Po \
+@AMDEP@ $(DEPDIR)/map_vme$U.Po $(DEPDIR)/ntp_config$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_control$U.Po $(DEPDIR)/ntp_crypto$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_filegen$U.Po $(DEPDIR)/ntp_intres$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_io$U.Po $(DEPDIR)/ntp_loopfilter$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_monitor$U.Po $(DEPDIR)/ntp_peer$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_proto$U.Po $(DEPDIR)/ntp_refclock$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_request$U.Po $(DEPDIR)/ntp_resolver$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_restrict$U.Po $(DEPDIR)/ntp_timer$U.Po \
+@AMDEP@ $(DEPDIR)/ntp_util$U.Po $(DEPDIR)/ntpd$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_acts$U.Po $(DEPDIR)/refclock_arbiter$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_arc$U.Po $(DEPDIR)/refclock_as2201$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_atom$U.Po $(DEPDIR)/refclock_bancomm$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_chronolog$U.Po $(DEPDIR)/refclock_chu$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_conf$U.Po $(DEPDIR)/refclock_datum$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_dumbclock$U.Po $(DEPDIR)/refclock_fg$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_gpsvme$U.Po $(DEPDIR)/refclock_heath$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_hopfpci$U.Po $(DEPDIR)/refclock_hopfser$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_hpgps$U.Po $(DEPDIR)/refclock_irig$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_jupiter$U.Po $(DEPDIR)/refclock_leitch$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_local$U.Po $(DEPDIR)/refclock_msfees$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_mx4200$U.Po $(DEPDIR)/refclock_nmea$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_oncore$U.Po $(DEPDIR)/refclock_palisade$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_parse$U.Po $(DEPDIR)/refclock_pcf$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_pst$U.Po $(DEPDIR)/refclock_ptbacts$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_shm$U.Po $(DEPDIR)/refclock_tpro$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_trak$U.Po $(DEPDIR)/refclock_true$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_ulink$U.Po $(DEPDIR)/refclock_usno$U.Po \
+@AMDEP@ $(DEPDIR)/refclock_wwv$U.Po $(DEPDIR)/refclock_wwvb$U.Po
+DIST_COMMON = Makefile.am Makefile.in
-mostlyclean-binPROGRAMS:
+SOURCES = check_y2k.c $(ntpd_SOURCES)
+OBJECTS = check_y2k$U.$(OBJEXT) $(am_ntpd_OBJECTS)
-clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+all: all-am
-distclean-binPROGRAMS:
+.SUFFIXES:
+.SUFFIXES: .c .h .o .obj
-maintainer-clean-binPROGRAMS:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu ntpd/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && \
+ CONFIG_HEADERS= CONFIG_LINKS= \
+ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
if test -f $$p; then \
- f="`echo $$p|sed -e 's/$(EXEEXT)$$//' -e '$(transform)' -e 's/$$/$(EXEEXT)/'`"; \
- echo " $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/$$f"; \
- $(INSTALL_PROGRAM) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(bindir)/$$f; \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$f; \
else :; fi; \
done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; for p in $$list; do \
- f="`echo $$p|sed -e 's/$(EXEEXT)$$//' -e '$(transform)' -e 's/$$/$(EXEEXT)/'`"; \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
rm -f $(DESTDIR)$(bindir)/$$f; \
done
-mostlyclean-checkPROGRAMS:
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
clean-checkPROGRAMS:
-test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
-distclean-checkPROGRAMS:
-
-maintainer-clean-checkPROGRAMS:
-
mostlyclean-compile:
- -rm -f *.o core *.core
-
-clean-compile:
+ -rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
-
-maintainer-clean-compile:
-../util/ansi2knr: ../util/ansi2knr.o
+../util/ansi2knr: ../util/ansi2knr.$(OBJEXT)
cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr
-../util/ansi2knr.o:
- cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr.o
+../util/ansi2knr.$(OBJEXT):
+ cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr.$(OBJEXT)
mostlyclean-kr:
-rm -f *_.c
-clean-kr:
-
-distclean-kr:
-
-maintainer-clean-kr:
-
check_y2k: $(check_y2k_OBJECTS) $(check_y2k_DEPENDENCIES)
@rm -f check_y2k
$(LINK) $(check_y2k_LDFLAGS) $(check_y2k_OBJECTS) $(check_y2k_LDADD) $(LIBS)
@@ -285,12 +303,16 @@ ntpd: $(ntpd_OBJECTS) $(ntpd_DEPENDENCIES)
$(LINK) $(ntpd_LDFLAGS) $(ntpd_OBJECTS) $(ntpd_LDADD) $(LIBS)
check_y2k_.c: check_y2k.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/check_y2k.c; then echo $(srcdir)/check_y2k.c; else echo check_y2k.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > check_y2k_.c
+cmd_args_.c: cmd_args.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/cmd_args.c; then echo $(srcdir)/cmd_args.c; else echo cmd_args.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > cmd_args_.c
map_vme_.c: map_vme.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/map_vme.c; then echo $(srcdir)/map_vme.c; else echo map_vme.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > map_vme_.c
ntp_config_.c: ntp_config.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_config.c; then echo $(srcdir)/ntp_config.c; else echo ntp_config.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_config_.c
ntp_control_.c: ntp_control.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_control.c; then echo $(srcdir)/ntp_control.c; else echo ntp_control.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_control_.c
+ntp_crypto_.c: ntp_crypto.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_crypto.c; then echo $(srcdir)/ntp_crypto.c; else echo ntp_crypto.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_crypto_.c
ntp_filegen_.c: ntp_filegen.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_filegen.c; then echo $(srcdir)/ntp_filegen.c; else echo ntp_filegen.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_filegen_.c
ntp_intres_.c: ntp_intres.c $(ANSI2KNR)
@@ -309,6 +331,8 @@ ntp_refclock_.c: ntp_refclock.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_refclock.c; then echo $(srcdir)/ntp_refclock.c; else echo ntp_refclock.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_refclock_.c
ntp_request_.c: ntp_request.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_request.c; then echo $(srcdir)/ntp_request.c; else echo ntp_request.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_request_.c
+ntp_resolver_.c: ntp_resolver.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_resolver.c; then echo $(srcdir)/ntp_resolver.c; else echo ntp_resolver.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_resolver_.c
ntp_restrict_.c: ntp_restrict.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/ntp_restrict.c; then echo $(srcdir)/ntp_restrict.c; else echo ntp_restrict.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > ntp_restrict_.c
ntp_timer_.c: ntp_timer.c $(ANSI2KNR)
@@ -345,6 +369,10 @@ refclock_gpsvme_.c: refclock_gpsvme.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_gpsvme.c; then echo $(srcdir)/refclock_gpsvme.c; else echo refclock_gpsvme.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_gpsvme_.c
refclock_heath_.c: refclock_heath.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_heath.c; then echo $(srcdir)/refclock_heath.c; else echo refclock_heath.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_heath_.c
+refclock_hopfpci_.c: refclock_hopfpci.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hopfpci.c; then echo $(srcdir)/refclock_hopfpci.c; else echo refclock_hopfpci.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_hopfpci_.c
+refclock_hopfser_.c: refclock_hopfser.c $(ANSI2KNR)
+ $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hopfser.c; then echo $(srcdir)/refclock_hopfser.c; else echo refclock_hopfser.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_hopfser_.c
refclock_hpgps_.c: refclock_hpgps.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_hpgps.c; then echo $(srcdir)/refclock_hpgps.c; else echo refclock_hpgps.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_hpgps_.c
refclock_irig_.c: refclock_irig.c $(ANSI2KNR)
@@ -389,20 +417,32 @@ refclock_wwv_.c: refclock_wwv.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwv.c; then echo $(srcdir)/refclock_wwv.c; else echo refclock_wwv.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_wwv_.c
refclock_wwvb_.c: refclock_wwvb.c $(ANSI2KNR)
$(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/refclock_wwvb.c; then echo $(srcdir)/refclock_wwvb.c; else echo refclock_wwvb.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > refclock_wwvb_.c
-check_y2k_.o map_vme_.o ntp_config_.o ntp_control_.o ntp_filegen_.o \
-ntp_intres_.o ntp_io_.o ntp_loopfilter_.o ntp_monitor_.o ntp_peer_.o \
-ntp_proto_.o ntp_refclock_.o ntp_request_.o ntp_restrict_.o \
-ntp_timer_.o ntp_util_.o ntpd_.o refclock_acts_.o refclock_arbiter_.o \
-refclock_arc_.o refclock_as2201_.o refclock_atom_.o refclock_bancomm_.o \
-refclock_chronolog_.o refclock_chu_.o refclock_conf_.o \
-refclock_datum_.o refclock_dumbclock_.o refclock_fg_.o \
-refclock_gpsvme_.o refclock_heath_.o refclock_hpgps_.o refclock_irig_.o \
-refclock_jupiter_.o refclock_leitch_.o refclock_local_.o \
-refclock_msfees_.o refclock_mx4200_.o refclock_nmea_.o \
-refclock_oncore_.o refclock_palisade_.o refclock_parse_.o \
-refclock_pcf_.o refclock_pst_.o refclock_ptbacts_.o refclock_shm_.o \
-refclock_tpro_.o refclock_trak_.o refclock_true_.o refclock_ulink_.o \
-refclock_usno_.o refclock_wwv_.o refclock_wwvb_.o : $(ANSI2KNR)
+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_resolver_.$(OBJEXT) ntp_restrict_.$(OBJEXT) ntp_timer_.$(OBJEXT) \
+ntp_util_.$(OBJEXT) ntpd_.$(OBJEXT) refclock_acts_.$(OBJEXT) \
+refclock_arbiter_.$(OBJEXT) refclock_arc_.$(OBJEXT) \
+refclock_as2201_.$(OBJEXT) refclock_atom_.$(OBJEXT) \
+refclock_bancomm_.$(OBJEXT) refclock_chronolog_.$(OBJEXT) \
+refclock_chu_.$(OBJEXT) refclock_conf_.$(OBJEXT) \
+refclock_datum_.$(OBJEXT) refclock_dumbclock_.$(OBJEXT) \
+refclock_fg_.$(OBJEXT) refclock_gpsvme_.$(OBJEXT) \
+refclock_heath_.$(OBJEXT) refclock_hopfpci_.$(OBJEXT) \
+refclock_hopfser_.$(OBJEXT) refclock_hpgps_.$(OBJEXT) \
+refclock_irig_.$(OBJEXT) refclock_jupiter_.$(OBJEXT) \
+refclock_leitch_.$(OBJEXT) refclock_local_.$(OBJEXT) \
+refclock_msfees_.$(OBJEXT) refclock_mx4200_.$(OBJEXT) \
+refclock_nmea_.$(OBJEXT) refclock_oncore_.$(OBJEXT) \
+refclock_palisade_.$(OBJEXT) refclock_parse_.$(OBJEXT) \
+refclock_pcf_.$(OBJEXT) refclock_pst_.$(OBJEXT) \
+refclock_ptbacts_.$(OBJEXT) refclock_shm_.$(OBJEXT) \
+refclock_tpro_.$(OBJEXT) refclock_trak_.$(OBJEXT) \
+refclock_true_.$(OBJEXT) refclock_ulink_.$(OBJEXT) \
+refclock_usno_.$(OBJEXT) refclock_wwv_.$(OBJEXT) \
+refclock_wwvb_.$(OBJEXT) : $(ANSI2KNR)
tags: TAGS
@@ -413,9 +453,9 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
- mkid -f$$here/ID $$unique $(LISP)
+ mkid -fID $$unique $(LISP)
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
@@ -428,128 +468,130 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| etags $(ETAGS_ARGS) $$tags $$unique $(LISP)
-mostlyclean-tags:
-
-clean-tags:
+GTAGS:
+ here=`CDPATH=: && cd $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $$here
distclean-tags:
-rm -f TAGS ID
-maintainer-clean-tags:
-
-distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
-
-distdir: $(DISTFILES)
- @for file in $(DISTFILES); do \
- d=$(srcdir); \
- if test -d $$d/$$file; then \
- cp -pR $$d/$$file $(distdir); \
- else \
- test -f $(distdir)/$$file \
- || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
- || cp -p $$d/$$file $(distdir)/$$file || :; \
- fi; \
- done
-
-@AMDEP@include $(DEPDIR)/check_y2k$U.Po
-@AMDEP@include $(DEPDIR)/map_vme$U.Po
-@AMDEP@include $(DEPDIR)/ntp_config$U.Po
-@AMDEP@include $(DEPDIR)/ntp_control$U.Po
-@AMDEP@include $(DEPDIR)/ntp_filegen$U.Po
-@AMDEP@include $(DEPDIR)/ntp_intres$U.Po
-@AMDEP@include $(DEPDIR)/ntp_io$U.Po
-@AMDEP@include $(DEPDIR)/ntp_loopfilter$U.Po
-@AMDEP@include $(DEPDIR)/ntp_monitor$U.Po
-@AMDEP@include $(DEPDIR)/ntp_peer$U.Po
-@AMDEP@include $(DEPDIR)/ntp_proto$U.Po
-@AMDEP@include $(DEPDIR)/ntp_refclock$U.Po
-@AMDEP@include $(DEPDIR)/ntp_request$U.Po
-@AMDEP@include $(DEPDIR)/ntp_restrict$U.Po
-@AMDEP@include $(DEPDIR)/ntp_timer$U.Po
-@AMDEP@include $(DEPDIR)/ntp_util$U.Po
-@AMDEP@include $(DEPDIR)/ntpd$U.Po
-@AMDEP@include $(DEPDIR)/refclock_acts$U.Po
-@AMDEP@include $(DEPDIR)/refclock_arbiter$U.Po
-@AMDEP@include $(DEPDIR)/refclock_arc$U.Po
-@AMDEP@include $(DEPDIR)/refclock_as2201$U.Po
-@AMDEP@include $(DEPDIR)/refclock_atom$U.Po
-@AMDEP@include $(DEPDIR)/refclock_bancomm$U.Po
-@AMDEP@include $(DEPDIR)/refclock_chronolog$U.Po
-@AMDEP@include $(DEPDIR)/refclock_chu$U.Po
-@AMDEP@include $(DEPDIR)/refclock_conf$U.Po
-@AMDEP@include $(DEPDIR)/refclock_datum$U.Po
-@AMDEP@include $(DEPDIR)/refclock_dumbclock$U.Po
-@AMDEP@include $(DEPDIR)/refclock_fg$U.Po
-@AMDEP@include $(DEPDIR)/refclock_gpsvme$U.Po
-@AMDEP@include $(DEPDIR)/refclock_heath$U.Po
-@AMDEP@include $(DEPDIR)/refclock_hpgps$U.Po
-@AMDEP@include $(DEPDIR)/refclock_irig$U.Po
-@AMDEP@include $(DEPDIR)/refclock_jupiter$U.Po
-@AMDEP@include $(DEPDIR)/refclock_leitch$U.Po
-@AMDEP@include $(DEPDIR)/refclock_local$U.Po
-@AMDEP@include $(DEPDIR)/refclock_msfees$U.Po
-@AMDEP@include $(DEPDIR)/refclock_mx4200$U.Po
-@AMDEP@include $(DEPDIR)/refclock_nmea$U.Po
-@AMDEP@include $(DEPDIR)/refclock_oncore$U.Po
-@AMDEP@include $(DEPDIR)/refclock_palisade$U.Po
-@AMDEP@include $(DEPDIR)/refclock_parse$U.Po
-@AMDEP@include $(DEPDIR)/refclock_pcf$U.Po
-@AMDEP@include $(DEPDIR)/refclock_pst$U.Po
-@AMDEP@include $(DEPDIR)/refclock_ptbacts$U.Po
-@AMDEP@include $(DEPDIR)/refclock_shm$U.Po
-@AMDEP@include $(DEPDIR)/refclock_tpro$U.Po
-@AMDEP@include $(DEPDIR)/refclock_trak$U.Po
-@AMDEP@include $(DEPDIR)/refclock_true$U.Po
-@AMDEP@include $(DEPDIR)/refclock_ulink$U.Po
-@AMDEP@include $(DEPDIR)/refclock_usno$U.Po
-@AMDEP@include $(DEPDIR)/refclock_wwv$U.Po
-@AMDEP@include $(DEPDIR)/refclock_wwvb$U.Po
-
-mostlyclean-depend:
-
-clean-depend:
+@AMDEP@@_am_include@ $(DEPDIR)/check_y2k$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/cmd_args$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/map_vme$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_config$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_control$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_crypto$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_filegen$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_intres$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_io$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_loopfilter$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_monitor$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_peer$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_proto$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_refclock$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_request$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_resolver$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_restrict$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_timer$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntp_util$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/ntpd$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_acts$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_arbiter$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_arc$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_as2201$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_atom$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_bancomm$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_chronolog$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_chu$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_conf$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_datum$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_dumbclock$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_fg$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_gpsvme$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_heath$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_hopfpci$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_hopfser$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_hpgps$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_irig$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_jupiter$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_leitch$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_local$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_msfees$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_mx4200$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_nmea$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_oncore$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_palisade$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_parse$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_pcf$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_pst$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_ptbacts$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_shm$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_tpro$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_trak$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_true$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_ulink$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_usno$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_wwv$U.Po
+@AMDEP@@_am_include@ $(DEPDIR)/refclock_wwvb$U.Po
distclean-depend:
-rm -rf $(DEPDIR)
-maintainer-clean-depend:
-
@AMDEP@CCDEPMODE = @CCDEPMODE@
.c.o:
@AMDEP@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- $(COMPILE) -c -o $@ $<
+ $(COMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
-info-am:
-info: info-am
-dvi-am:
-dvi: dvi-am
+.c.obj:
+@AMDEP@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(COMPILE) -c -o $@ `cygpath -w $<`
+
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pR $$d/$$file $(distdir) \
+ || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-local
check: check-am
-installcheck-am:
-installcheck: installcheck-am
-install-exec-am: install-binPROGRAMS
-install-exec: install-exec-am
+all-am: Makefile $(PROGRAMS)
-install-data-am:
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+
+install: install-am
+install-exec: install-exec-am
install-data: install-data-am
+uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-install: install-am
-uninstall-am: uninstall-binPROGRAMS
-uninstall: uninstall-am
-all-am: Makefile $(PROGRAMS)
-all-redirect: all-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
-installdirs:
- $(mkinstalldirs) $(DESTDIR)$(bindir)
+installcheck: installcheck-am
+
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_PROGRAM_ENV='$(INSTALL_STRIP_PROGRAM_ENV)' install
mostlyclean-generic:
@@ -561,51 +603,61 @@ distclean-generic:
-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."
-rm -f Makefile.in
-mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-checkPROGRAMS \
- mostlyclean-compile mostlyclean-kr mostlyclean-tags \
- mostlyclean-depend mostlyclean-generic
+clean: clean-am
-mostlyclean: mostlyclean-am
+clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
+ mostlyclean-am
-clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-compile clean-kr \
- clean-tags clean-depend clean-generic mostlyclean-am
+distclean: distclean-am
-clean: clean-am
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-tags
-distclean-am: distclean-binPROGRAMS distclean-checkPROGRAMS \
- distclean-compile distclean-kr distclean-tags \
- distclean-depend distclean-generic clean-am
+dvi:
-distclean: distclean-am
+dvi-am:
-maintainer-clean-am: maintainer-clean-binPROGRAMS \
- maintainer-clean-checkPROGRAMS maintainer-clean-compile \
- maintainer-clean-kr maintainer-clean-tags \
- maintainer-clean-depend maintainer-clean-generic \
- distclean-am
- @echo "This command is intended for maintainers to use;"
- @echo "it deletes files that may require special tools to rebuild."
+info:
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info:
+
+install-man:
+
+installcheck-am:
maintainer-clean: maintainer-clean-am
-.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
-maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
-mostlyclean-checkPROGRAMS distclean-checkPROGRAMS clean-checkPROGRAMS \
-maintainer-clean-checkPROGRAMS mostlyclean-compile distclean-compile \
-clean-compile maintainer-clean-compile mostlyclean-kr distclean-kr \
-clean-kr maintainer-clean-kr tags mostlyclean-tags distclean-tags \
-clean-tags maintainer-clean-tags distdir mostlyclean-depend \
-distclean-depend clean-depend maintainer-clean-depend info-am info \
-dvi-am dvi check-local check check-am installcheck-am installcheck \
-install-exec-am install-exec install-data-am install-data install-am \
-install uninstall-am uninstall all-redirect all-am all install-strip \
-installdirs mostlyclean-generic distclean-generic clean-generic \
-maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic mostlyclean-kr
+
+uninstall-am: uninstall-binPROGRAMS
+
+.PHONY: all all-am check check-am check-local clean clean-binPROGRAMS \
+ clean-checkPROGRAMS clean-generic distclean distclean-compile \
+ distclean-depend distclean-generic distclean-tags distdir dvi \
+ dvi-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-exec install-exec-am \
+ install-info install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-kr tags uninstall uninstall-am \
+ uninstall-binPROGRAMS
check-local: @MAKE_CHECK_Y2K@
- [ -z "@MAKE_CHECK_Y2K@" ] || ./@MAKE_CHECK_Y2K@
+ test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
$(PROGRAMS): $(LDADD)
diff --git a/contrib/ntp/ntpd/check_y2k.c b/contrib/ntp/ntpd/check_y2k.c
index 3cc05fc..f0f4480 100644
--- a/contrib/ntp/ntpd/check_y2k.c
+++ b/contrib/ntp/ntpd/check_y2k.c
@@ -31,7 +31,8 @@
# include <config.h>
#endif
-#include <sys/types.h>
+#include "ntpd.h"
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -48,7 +49,6 @@
# ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
# endif /* HAVE_SYS_IOCTL_H */
-# include <sys/time.h>
# if !defined(VMS) /*wjm*/
# include <sys/resource.h>
# endif /* VMS */
@@ -94,8 +94,6 @@
# include <apollo/base.h>
#endif /* SYS_DOMAINOS */
-#include "ntpd.h"
-
/* } end definitions lifted from ntpd.c */
#include "ntp_calendar.h"
@@ -103,10 +101,11 @@
#define GoodLeap(Year) (((Year)%4 || (!((Year)%100) && (Year)%400)) ? 0 : 13 )
-int debug = 0; /* debugging requests for parse stuff */
+volatile int debug = 0; /* debugging requests for parse stuff */
char const *progname = "check_y2k";
-long Days ( int Year ) /* return number of days since year "0" */
+long
+Days ( int Year ) /* return number of days since year "0" */
{
long Return;
/* this is a known to be good algorithm */
@@ -137,7 +136,8 @@ static struct tm LocalTime;
#define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \
Warnings++; else Fatals++
-int main( void )
+int
+main( void )
{
int Fatals;
int Warnings;
diff --git a/contrib/ntp/ntpd/cmd_args.c b/contrib/ntp/ntpd/cmd_args.c
new file mode 100644
index 0000000..9f61b4a
--- /dev/null
+++ b/contrib/ntp/ntpd/cmd_args.c
@@ -0,0 +1,313 @@
+/*
+ * cmd_args.c = command-line argument processing
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ntpd.h"
+#include "ntp_stdlib.h"
+#include "ntp_cmdargs.h"
+
+/*
+ * Definitions of things either imported from or exported to outside
+ */
+extern char const *progname;
+int listen_to_virtual_ips = 0;
+
+static const char *ntp_options = "aAbc:dD:f:gk:l:LmnN:p:P:qr:s:t:v:V:x";
+
+#ifdef HAVE_NETINFO
+extern int check_netinfo;
+#endif
+
+
+/*
+ * getstartup - search through the options looking for a debugging flag
+ */
+void
+getstartup(
+ int argc,
+ char *argv[]
+ )
+{
+ int errflg;
+ extern int priority_done;
+ int c;
+
+#ifdef DEBUG
+ debug = 0; /* no debugging by default */
+#endif
+
+ /*
+ * This is a big hack. We don't really want to read command line
+ * configuration until everything else is initialized, since
+ * the ability to configure the system may depend on storage
+ * and the like having been initialized. Except that we also
+ * don't want to initialize anything until after detaching from
+ * the terminal, but we won't know to do that until we've
+ * parsed the command line. Do that now, crudely, and do it
+ * again later. Our ntp_getopt() is explicitly reusable, by the
+ * way. Your own mileage may vary.
+ *
+ * This hack is even called twice (to allow complete logging to file)
+ */
+ errflg = 0;
+ progname = argv[0];
+
+ /*
+ * Decode argument list
+ */
+ while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF)
+ switch (c) {
+#ifdef DEBUG
+ case 'd':
+ ++debug;
+ break;
+ case 'D':
+ debug = (int)atol(ntp_optarg);
+ printf("Debug1: %s -> %x = %d\n", ntp_optarg, debug, debug);
+ break;
+#else
+ case 'd':
+ case 'D':
+ msyslog(LOG_ERR, "ntpd not compiled with -DDEBUG option - no DEBUG support");
+ fprintf(stderr, "ntpd not compiled with -DDEBUG option - no DEBUG support");
+ ++errflg;
+ break;
+#endif
+ case 'L':
+ listen_to_virtual_ips = 1;
+ break;
+ case 'l':
+ {
+ FILE *new_file;
+
+ new_file = fopen(ntp_optarg, "a");
+ if (new_file != NULL) {
+ NLOG(NLOG_SYSINFO)
+ msyslog(LOG_NOTICE, "logging to file %s", ntp_optarg);
+ if (syslog_file != NULL &&
+ fileno(syslog_file) != fileno(new_file))
+ (void)fclose(syslog_file);
+
+ syslog_file = new_file;
+ syslogit = 0;
+ }
+ else
+ msyslog(LOG_ERR,
+ "Cannot open log file %s",
+ ntp_optarg);
+ }
+ break;
+
+ case 'n':
+ case 'q':
+ ++nofork;
+ break;
+
+ case 'N':
+ priority_done = strcmp(ntp_optarg, "high");
+ break;
+
+ case '?':
+ ++errflg;
+ break;
+
+ default:
+ break;
+ }
+
+ if (errflg || ntp_optind != argc) {
+ (void) fprintf(stderr, "usage: %s [ -abdgmnqx ] [ -c config_file ] [ -e e_delay ]\n", progname);
+ (void) fprintf(stderr, "\t\t[ -f freq_file ] [ -k key_file ] [ -l log_file ]\n");
+ (void) fprintf(stderr, "\t\t[ -p pid_file ] [ -r broad_delay ] [ -s statdir ]\n");
+ (void) fprintf(stderr, "\t\t[ -t trust_key ] [ -v sys_var ] [ -V default_sysvar ]\n");
+#if defined(HAVE_SCHED_SETSCHEDULER)
+ (void) fprintf(stderr, "\t\t[ -P fixed_process_priority ]\n");
+#endif
+ exit(2);
+ }
+ ntp_optind = 0; /* reset ntp_optind to restart ntp_getopt */
+
+#ifdef DEBUG
+ if (debug) {
+#ifdef HAVE_SETVBUF
+ static char buf[BUFSIZ];
+ setvbuf(stdout, buf, _IOLBF, BUFSIZ);
+#else
+ setlinebuf(stdout);
+#endif
+ }
+#endif
+}
+
+/*
+ * getCmdOpts - get command line options
+ */
+void
+getCmdOpts(
+ int argc,
+ char *argv[]
+ )
+{
+ extern char *config_file;
+ int errflg;
+ int c;
+
+ /*
+ * Initialize, initialize
+ */
+ errflg = 0;
+#ifdef DEBUG
+ debug = 0;
+#endif /* DEBUG */
+
+ progname = argv[0];
+
+ /*
+ * Decode argument list
+ */
+ while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF) {
+ switch (c) {
+ case 'a':
+ proto_config(PROTO_AUTHENTICATE, 1, 0.);
+ break;
+
+ case 'A':
+ proto_config(PROTO_AUTHENTICATE, 0, 0.);
+ break;
+
+ case 'b':
+ proto_config(PROTO_BROADCLIENT, 1, 0.);
+ break;
+
+ case 'c':
+ config_file = ntp_optarg;
+#ifdef HAVE_NETINFO
+ check_netinfo = 0;
+#endif
+ break;
+
+ case 'd':
+#ifdef DEBUG
+ debug++;
+#else
+ errflg++;
+#endif /* DEBUG */
+ break;
+
+ case 'D':
+#ifdef DEBUG
+ debug = (int)atol(ntp_optarg);
+ printf("Debug2: %s -> %x = %d\n", ntp_optarg, debug, debug);
+#else
+ errflg++;
+#endif /* DEBUG */
+ break;
+
+ case 'f':
+ stats_config(STATS_FREQ_FILE, ntp_optarg);
+ break;
+
+ case 'g':
+ allow_panic = TRUE;
+ break;
+
+ case 'k':
+ getauthkeys(ntp_optarg);
+ break;
+
+ case 'L': /* already done at pre-scan */
+ case 'l': /* already done at pre-scan */
+ break;
+
+ case 'm':
+ proto_config(PROTO_MULTICAST_ADD, htonl(INADDR_NTP), 0.);
+ sys_bclient = 1;
+ break;
+
+ case 'n': /* already done at pre-scan */
+ break;
+
+ case 'N': /* already done at pre-scan */
+ break;
+
+ case 'p':
+ stats_config(STATS_PID_FILE, ntp_optarg);
+ break;
+
+ case 'P':
+#if defined(HAVE_SCHED_SETSCHEDULER)
+ config_priority = (int)atol(ntp_optarg);
+ config_priority_override = 1;
+#else
+ errflg++;
+#endif
+ break;
+
+ case 'q':
+ mode_ntpdate = TRUE;
+ break;
+
+ case 'r':
+ do {
+ double tmp;
+
+ if (sscanf(ntp_optarg, "%lf", &tmp) != 1) {
+ msyslog(LOG_ERR,
+ "command line broadcast delay value %s undecodable",
+ ntp_optarg);
+ } else {
+ proto_config(PROTO_BROADDELAY, 0, tmp);
+ }
+ } while (0);
+ 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,
+ RW | ((c == 'V') ? DEF : 0));
+ break;
+
+ case 'x':
+ allow_step = FALSE;
+ break;
+
+ 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
+ exit(2);
+ }
+ return;
+}
diff --git a/contrib/ntp/ntpd/ntp_config.c b/contrib/ntp/ntpd/ntp_config.c
index e21f5b0..208b257 100644
--- a/contrib/ntp/ntpd/ntp_config.c
+++ b/contrib/ntp/ntpd/ntp_config.c
@@ -1,28 +1,12 @@
/*
* ntp_config.c - read and apply configuration information
*/
-
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <signal.h>
-#ifndef SIGCHLD
-#define SIGCHLD SIGCLD
-#endif
-#if !defined(VMS)
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-#endif /* VMS */
-#include <sys/time.h>
-
#ifdef HAVE_NETINFO
-#include <netinfo/ni.h>
+# include <netinfo/ni.h>
#endif
#include "ntpd.h"
@@ -31,12 +15,33 @@
#include "ntp_refclock.h"
#include "ntp_filegen.h"
#include "ntp_stdlib.h"
+#include "ntp_config.h"
+#include "ntp_cmdargs.h"
+
+#ifdef PUBKEY
+# include "ntp_crypto.h"
+#endif /* PUBKEY */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/param.h>
+#include <signal.h>
+#ifndef SIGCHLD
+# define SIGCHLD SIGCLD
+#endif
+#if !defined(VMS)
+# ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+# endif
+#endif /* VMS */
#ifdef SYS_WINNT
-#include <io.h>
+# include <io.h>
extern HANDLE ResolverThreadHandle;
#endif /* SYS_WINNT */
+extern int priority_done;
+
/*
* These routines are used to read the configuration file at
* startup time. An entry in the file must fit on a single line.
@@ -46,18 +51,6 @@ extern HANDLE ResolverThreadHandle;
*/
/*
- * Configuration file name
- */
-#ifndef CONFIG_FILE
-# ifndef SYS_WINNT
-# define CONFIG_FILE "/etc/ntp.conf"
-# else /* SYS_WINNT */
-# define CONFIG_FILE "%windir%\\system32\\drivers\\etc\\ntp.conf"
-# define ALT_CONFIG_FILE "%windir%\\ntp.conf"
-# endif /* SYS_WINNT */
-#endif /* not CONFIG_FILE */
-
-/*
* We understand the following configuration entries and defaults.
*
* peer [ addr ] [ version 3 ] [ key 0 ] [ minpoll 6 ] [ maxpoll 10 ]
@@ -71,6 +64,8 @@ extern HANDLE ResolverThreadHandle;
* restrict [ addr ] [ mask 255.255.255.0 ] ignore|noserve|notrust|noquery
* driftfile file_name
* keys file_name
+ * publickey file_name
+ * privatekey file_name
* statsdir /var/NTP/
* filegen peerstats [ file peerstats ] [ type day ] [ link ]
* clientlimit [ n ]
@@ -88,94 +83,10 @@ extern HANDLE ResolverThreadHandle;
* disable auth|bclient|pll|kernel|monitor|stats
* phone ...
* pps device [assert|clear] [hardpps]
+ * priority high|normal
*/
/*
- * Types of entries we understand.
- */
-#define CONFIG_UNKNOWN 0
-
-#define CONFIG_PEER 1
-#define CONFIG_SERVER 2
-#define CONFIG_AUTOMAX 3
-#define CONFIG_DRIFTFILE 4
-#define CONFIG_BROADCAST 5
-#define CONFIG_BROADCASTCLIENT 6
-#define CONFIG_AUTHENTICATE 7
-#define CONFIG_KEYS 8
-#define CONFIG_REVOKE 9
-#define CONFIG_PPS 10
-#define CONFIG_RESTRICT 11
-#define CONFIG_BDELAY 12
-#define CONFIG_TRUSTEDKEY 13
-#define CONFIG_REQUESTKEY 14
-#define CONFIG_CONTROLKEY 15
-#define CONFIG_TRAP 16
-#define CONFIG_FUDGE 17
-#define CONFIG_18 18 /* unused */
-#define CONFIG_STATSDIR 19
-#define CONFIG_FILEGEN 20
-#define CONFIG_STATISTICS 21
-#define CONFIG_PIDFILE 22
-#define CONFIG_SETVAR 23
-#define CONFIG_CLIENTLIMIT 24
-#define CONFIG_CLIENTPERIOD 25
-#define CONFIG_MULTICASTCLIENT 26
-#define CONFIG_ENABLE 27
-#define CONFIG_DISABLE 28
-#define CONFIG_PHONE 29
-#define CONFIG_LOGFILE 30
-#define CONFIG_LOGCONFIG 31
-#define CONFIG_MANYCASTCLIENT 32
-#define CONFIG_MANYCASTSERVER 33
-
-#define CONF_MOD_VERSION 1
-#define CONF_MOD_KEY 2
-#define CONF_MOD_MINPOLL 3
-#define CONF_MOD_MAXPOLL 4
-#define CONF_MOD_PREFER 5
-#define CONF_MOD_BURST 6
-#define CONF_MOD_SKEY 7
-#define CONF_MOD_TTL 8
-#define CONF_MOD_MODE 9
-#define CONF_MOD_NOSELECT 10
-
-#define CONF_RES_MASK 1
-#define CONF_RES_IGNORE 2
-#define CONF_RES_NOSERVE 3
-#define CONF_RES_NOTRUST 4
-#define CONF_RES_NOQUERY 5
-#define CONF_RES_NOMODIFY 6
-#define CONF_RES_NOPEER 7
-#define CONF_RES_NOTRAP 8
-#define CONF_RES_LPTRAP 9
-#define CONF_RES_NTPPORT 10
-#define CONF_RES_LIMITED 11
-
-#define CONF_TRAP_PORT 1
-#define CONF_TRAP_INTERFACE 2
-
-#define CONF_FDG_TIME1 1
-#define CONF_FDG_TIME2 2
-#define CONF_FDG_STRATUM 3
-#define CONF_FDG_REFID 4
-#define CONF_FDG_FLAG1 5
-#define CONF_FDG_FLAG2 6
-#define CONF_FDG_FLAG3 7
-#define CONF_FDG_FLAG4 8
-
-#define CONF_FGEN_FILE 1
-#define CONF_FGEN_TYPE 2
-#define CONF_FGEN_FLAG_LINK 3
-#define CONF_FGEN_FLAG_NOLINK 4
-#define CONF_FGEN_FLAG_ENABLE 5
-#define CONF_FGEN_FLAG_DISABLE 6
-
-#define CONF_PPS_ASSERT 1
-#define CONF_PPS_CLEAR 2
-#define CONF_PPS_HARDPPS 3
-
-/*
* Translation table - keywords to function index
*/
struct keyword {
@@ -187,38 +98,46 @@ struct keyword {
* Command keywords
*/
static struct keyword keywords[] = {
- { "peer", CONFIG_PEER },
- { "server", CONFIG_SERVER },
- { "driftfile", CONFIG_DRIFTFILE },
- { "broadcast", CONFIG_BROADCAST },
- { "broadcastclient", CONFIG_BROADCASTCLIENT },
- { "multicastclient", CONFIG_MULTICASTCLIENT },
- { "manycastclient", CONFIG_MANYCASTCLIENT },
- { "manycastserver", CONFIG_MANYCASTSERVER },
{ "authenticate", CONFIG_AUTHENTICATE },
- { "keys", CONFIG_KEYS },
- { "revoke", CONFIG_REVOKE },
- { "pps", CONFIG_PPS },
{ "automax", CONFIG_AUTOMAX },
- { "restrict", CONFIG_RESTRICT },
+ { "broadcast", CONFIG_BROADCAST },
+ { "broadcastclient", CONFIG_BROADCASTCLIENT },
{ "broadcastdelay", CONFIG_BDELAY },
- { "trustedkey", CONFIG_TRUSTEDKEY },
- { "requestkey", CONFIG_REQUESTKEY },
- { "controlkey", CONFIG_CONTROLKEY },
- { "trap", CONFIG_TRAP },
- { "fudge", CONFIG_FUDGE },
- { "statsdir", CONFIG_STATSDIR },
- { "filegen", CONFIG_FILEGEN },
- { "statistics", CONFIG_STATISTICS },
- { "pidfile", CONFIG_PIDFILE },
- { "setvar", CONFIG_SETVAR },
{ "clientlimit", CONFIG_CLIENTLIMIT },
{ "clientperiod", CONFIG_CLIENTPERIOD },
- { "enable", CONFIG_ENABLE },
+#ifdef PUBKEY
+ { "crypto", CONFIG_CRYPTO },
+#endif /* PUBKEY */
+ { "controlkey", CONFIG_CONTROLKEY },
{ "disable", CONFIG_DISABLE },
- { "phone", CONFIG_PHONE },
- { "logfile", CONFIG_LOGFILE },
+ { "driftfile", CONFIG_DRIFTFILE },
+ { "enable", CONFIG_ENABLE },
+ { "filegen", CONFIG_FILEGEN },
+ { "fudge", CONFIG_FUDGE },
+ { "includefile", CONFIG_INCLUDEFILE },
+ { "keys", CONFIG_KEYS },
+#ifdef PUBKEY
+ { "keysdir", CONFIG_KEYSDIR },
+#endif /* PUBKEY */
{ "logconfig", CONFIG_LOGCONFIG },
+ { "logfile", CONFIG_LOGFILE },
+ { "manycastclient", CONFIG_MANYCASTCLIENT },
+ { "manycastserver", CONFIG_MANYCASTSERVER },
+ { "multicastclient", CONFIG_MULTICASTCLIENT },
+ { "peer", CONFIG_PEER },
+ { "phone", CONFIG_PHONE },
+ { "pidfile", CONFIG_PIDFILE },
+ { "pps", CONFIG_PPS },
+ { "requestkey", CONFIG_REQUESTKEY },
+ { "restrict", CONFIG_RESTRICT },
+ { "revoke", CONFIG_REVOKE },
+ { "server", CONFIG_SERVER },
+ { "setvar", CONFIG_SETVAR },
+ { "statistics", CONFIG_STATISTICS },
+ { "statsdir", CONFIG_STATSDIR },
+ { "tinker", CONFIG_TINKER },
+ { "trap", CONFIG_TRAP },
+ { "trustedkey", CONFIG_TRUSTEDKEY },
{ "", CONFIG_UNKNOWN }
};
@@ -226,16 +145,20 @@ static struct keyword keywords[] = {
* "peer", "server", "broadcast" modifier keywords
*/
static struct keyword mod_keywords[] = {
- { "version", CONF_MOD_VERSION },
+ { "autokey", CONF_MOD_SKEY },
+ { "burst", CONF_MOD_BURST },
+ { "iburst", CONF_MOD_IBURST },
{ "key", CONF_MOD_KEY },
- { "minpoll", CONF_MOD_MINPOLL },
{ "maxpoll", CONF_MOD_MAXPOLL },
- { "prefer", CONF_MOD_PREFER },
+ { "minpoll", CONF_MOD_MINPOLL },
+ { "mode", CONF_MOD_MODE }, /* refclocks */
{ "noselect", CONF_MOD_NOSELECT },
- { "burst", CONF_MOD_BURST },
- { "autokey", CONF_MOD_SKEY },
- { "mode", CONF_MOD_MODE }, /* reference clocks */
+ { "prefer", CONF_MOD_PREFER },
+#ifdef PUBKEY
+ { "publickey", CONF_MOD_PUBLICKEY },
+#endif /* PUBKEY */
{ "ttl", CONF_MOD_TTL }, /* NTP peers */
+ { "version", CONF_MOD_VERSION },
{ "", CONFIG_UNKNOWN }
};
@@ -243,17 +166,19 @@ static struct keyword mod_keywords[] = {
* "restrict" modifier keywords
*/
static struct keyword res_keywords[] = {
- { "mask", CONF_RES_MASK },
{ "ignore", CONF_RES_IGNORE },
- { "noserve", CONF_RES_NOSERVE },
- { "notrust", CONF_RES_NOTRUST },
- { "noquery", CONF_RES_NOQUERY },
+ { "limited", CONF_RES_LIMITED },
+ { "kod", CONF_RES_DEMOBILIZE },
+ { "lowpriotrap", CONF_RES_LPTRAP },
+ { "mask", CONF_RES_MASK },
{ "nomodify", CONF_RES_NOMODIFY },
{ "nopeer", CONF_RES_NOPEER },
+ { "noquery", CONF_RES_NOQUERY },
+ { "noserve", CONF_RES_NOSERVE },
{ "notrap", CONF_RES_NOTRAP },
- { "lowpriotrap", CONF_RES_LPTRAP },
+ { "notrust", CONF_RES_NOTRUST },
{ "ntpport", CONF_RES_NTPPORT },
- { "limited", CONF_RES_LIMITED },
+ { "version", CONF_RES_VERSION },
{ "", CONFIG_UNKNOWN }
};
@@ -266,19 +191,18 @@ static struct keyword trap_keywords[] = {
{ "", CONFIG_UNKNOWN }
};
-
/*
* "fudge" modifier keywords
*/
static struct keyword fudge_keywords[] = {
- { "time1", CONF_FDG_TIME1 },
- { "time2", CONF_FDG_TIME2 },
- { "stratum", CONF_FDG_STRATUM },
- { "refid", CONF_FDG_REFID },
{ "flag1", CONF_FDG_FLAG1 },
{ "flag2", CONF_FDG_FLAG2 },
{ "flag3", CONF_FDG_FLAG3 },
{ "flag4", CONF_FDG_FLAG4 },
+ { "refid", CONF_FDG_REFID },
+ { "stratum", CONF_FDG_STRATUM },
+ { "time1", CONF_FDG_TIME1 },
+ { "time2", CONF_FDG_TIME2 },
{ "", CONFIG_UNKNOWN }
};
@@ -287,12 +211,12 @@ static struct keyword fudge_keywords[] = {
* "filegen" modifier keywords
*/
static struct keyword filegen_keywords[] = {
+ { "disable", CONF_FGEN_FLAG_DISABLE },
+ { "enable", CONF_FGEN_FLAG_ENABLE },
{ "file", CONF_FGEN_FILE },
- { "type", CONF_FGEN_TYPE },
{ "link", CONF_FGEN_FLAG_LINK },
{ "nolink", CONF_FGEN_FLAG_NOLINK },
- { "enable", CONF_FGEN_FLAG_ENABLE },
- { "disable", CONF_FGEN_FLAG_DISABLE },
+ { "type", CONF_FGEN_TYPE },
{ "", CONFIG_UNKNOWN }
};
@@ -300,13 +224,13 @@ static struct keyword filegen_keywords[] = {
* "type" modifier keywords
*/
static struct keyword fgen_types[] = {
+ { "age", FILEGEN_AGE },
+ { "day", FILEGEN_DAY },
+ { "month", FILEGEN_MONTH },
{ "none", FILEGEN_NONE },
{ "pid", FILEGEN_PID },
- { "day", FILEGEN_DAY },
{ "week", FILEGEN_WEEK },
- { "month", FILEGEN_MONTH },
{ "year", FILEGEN_YEAR },
- { "age", FILEGEN_AGE },
{ "", CONFIG_UNKNOWN}
};
@@ -316,15 +240,17 @@ static struct keyword fgen_types[] = {
static struct keyword flags_keywords[] = {
{ "auth", PROTO_AUTHENTICATE },
{ "bclient", PROTO_BROADCLIENT },
- { "ntp", PROTO_NTP },
{ "kernel", PROTO_KERNEL },
{ "monitor", PROTO_MONITOR },
+ { "ntp", PROTO_NTP },
{ "stats", PROTO_FILEGEN },
+ { "pps", PROTO_PPS },
+ { "calibrate", PROTO_CAL },
{ "", CONFIG_UNKNOWN }
};
/*
- * pps modifier keywords
+ * "pps" modifier keywords
*/
static struct keyword pps_keywords[] = {
{ "assert", CONF_PPS_ASSERT },
@@ -334,6 +260,34 @@ static struct keyword pps_keywords[] = {
};
/*
+ * "tinker" modifier keywords
+ */
+static struct keyword tinker_keywords[] = {
+ { "step", CONF_CLOCK_MAX },
+ { "panic", CONF_CLOCK_PANIC },
+ { "dispersion", CONF_CLOCK_PHI },
+ { "stepout", CONF_CLOCK_MINSTEP },
+ { "minpoll", CONF_CLOCK_MINPOLL },
+ { "allan", CONF_CLOCK_ALLAN },
+ { "huffpuff", CONF_CLOCK_HUFFPUFF },
+ { "", CONFIG_UNKNOWN }
+};
+
+#ifdef PUBKEY
+/*
+ * "crypto" modifier keywords
+ */
+static struct keyword crypto_keywords[] = {
+ { "dh", CONF_CRYPTO_DH },
+ { "flags", CONF_CRYPTO_FLAGS },
+ { "leap", CONF_CRYPTO_LEAP },
+ { "privatekey", CONF_CRYPTO_PRIVATEKEY },
+ { "publickey", CONF_CRYPTO_PUBLICKEY },
+ { "", CONFIG_UNKNOWN }
+};
+#endif /* PUBKEY */
+
+/*
* "logconfig" building blocks
*/
struct masks {
@@ -342,10 +296,10 @@ struct masks {
};
static struct masks logcfg_class[] = {
- { "sys", NLOG_OSYS },
- { "peer", NLOG_OPEER },
{ "clock", NLOG_OCLOCK },
+ { "peer", NLOG_OPEER },
{ "sync", NLOG_OSYNC },
+ { "sys", NLOG_OSYS },
{ (char *)0, 0 }
};
@@ -373,8 +327,7 @@ static struct masks logcfg_item[] = {
#define MAXLINE 1024 /* maximum length of line */
#define MAXPHONE 5 /* maximum number of phone strings */
#define MAXPPS 20 /* maximum length of PPS device string */
-#define MAXFILENAME 128 /* maximum length of a file name (alloca()?) */
-
+#define MAXINCLUDELEVEL 5 /* maximum include file levels */
/*
* Miscellaneous macros
@@ -384,6 +337,8 @@ static struct masks logcfg_item[] = {
#define ISSPACE(c) ((c) == ' ' || (c) == '\t')
#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
+#define KEY_TYPE_MD5 4
+
/*
* File descriptor used by the resolver save routines, and temporary file
* name.
@@ -402,15 +357,24 @@ static char res_file[MAX_PATH];
char const *progname;
char sys_phone[MAXPHONE][MAXDIAL]; /* ACTS phone numbers */
char pps_device[MAXPPS + 1]; /* PPS device name */
-int pps_assert = 1;
+int pps_assert;
int pps_hardpps;
-int listen_to_virtual_ips = 0;
#if defined(HAVE_SCHED_SETSCHEDULER)
int config_priority_override = 0;
int config_priority;
#endif
-static const char *ntp_options = "aAbc:dD:f:gk:l:Lmnp:P:r:s:t:v:V:x";
+const char *config_file;
+#ifdef HAVE_NETINFO
+ struct netinfo_config_state *config_netinfo = NULL;
+ int check_netinfo = 1;
+#endif /* HAVE_NETINFO */
+#ifdef SYS_WINNT
+ char *alt_config_file;
+ LPTSTR temp;
+ char config_file_storage[MAX_PATH];
+ char alt_config_file_storage[MAX_PATH];
+#endif /* SYS_WINNT */
#ifdef HAVE_NETINFO
/*
@@ -439,7 +403,8 @@ static int gettokens_netinfo P((struct netinfo_config_state *, char **, int *));
static int gettokens P((FILE *, char *, char **, int *));
static int matchkey P((char *, struct keyword *));
static int getnetnum P((const char *, struct sockaddr_in *, int));
-static void save_resolve P((char *, int, int, int, int, int, int, u_long));
+static void save_resolve P((char *, int, int, int, int, u_int, int,
+ keyid_t, u_char *));
static void do_resolve_internal P((void));
static void abort_resolve P((void));
#if !defined(VMS)
@@ -510,119 +475,6 @@ get_logmask(
return 0;
}
-/*
- * getstartup - search through the options looking for a debugging flag
- */
-void
-getstartup(
- int argc,
- char *argv[]
- )
-{
- int errflg;
- int c;
-
-#ifdef DEBUG
- debug = 0; /* no debugging by default */
-#endif
-
- /*
- * This is a big hack. We don't really want to read command line
- * configuration until everything else is initialized, since
- * the ability to configure the system may depend on storage
- * and the like having been initialized. Except that we also
- * don't want to initialize anything until after detaching from
- * the terminal, but we won't know to do that until we've
- * parsed the command line. Do that now, crudely, and do it
- * again later. Our ntp_getopt() is explicitly reusable, by the
- * way. Your own mileage may vary.
- *
- * This hack is even called twice (to allow complete logging to file)
- */
- errflg = 0;
- progname = argv[0];
-
- /*
- * Decode argument list
- */
- while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF)
- switch (c) {
-#ifdef DEBUG
- case 'd':
- ++debug;
- break;
- case 'D':
- debug = (int)atol(ntp_optarg);
- printf("Debug1: %s -> %x = %d\n", ntp_optarg, debug, debug);
- break;
-#else
- case 'd':
- case 'D':
- msyslog(LOG_ERR, "ntpd not compiled with -DDEBUG option - no DEBUG support");
- fprintf(stderr, "ntpd not compiled with -DDEBUG option - no DEBUG support");
- ++errflg;
- break;
-#endif
- case 'L':
- listen_to_virtual_ips = 1;
- break;
- case 'l':
- {
- FILE *new_file;
-
- new_file = fopen(ntp_optarg, "a");
- if (new_file != NULL) {
- NLOG(NLOG_SYSINFO)
- msyslog(LOG_NOTICE, "logging to file %s", ntp_optarg);
- if (syslog_file != NULL &&
- fileno(syslog_file) != fileno(new_file))
- (void)fclose(syslog_file);
-
- syslog_file = new_file;
- syslogit = 0;
- }
- else
- msyslog(LOG_ERR,
- "Cannot open log file %s",
- ntp_optarg);
- }
- break;
-
- case 'n':
- ++nofork;
- break;
-
- case '?':
- ++errflg;
- break;
-
- default:
- 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
- exit(2);
- }
- ntp_optind = 0; /* reset ntp_optind to restart ntp_getopt */
-
-#ifdef DEBUG
- if (debug) {
-#ifdef HAVE_SETVBUF
- static char buf[BUFSIZ];
- setvbuf(stdout, buf, _IOLBF, BUFSIZ);
-#else
- setlinebuf(stdout);
-#endif
- }
-#endif
-}
/*
* getconfig - get command line options and read the configuration file
@@ -640,29 +492,23 @@ getconfig(
int minpoll;
int maxpoll;
int ttl;
- u_long peerkey;
- u_long lpeerkey;
- int peerflags;
+ long stratum;
+ unsigned long ul;
+ keyid_t peerkey;
+ u_char *peerkeystr;
+ u_long fudgeflag;
+ u_int peerflags;
int hmode;
struct sockaddr_in peeraddr;
struct sockaddr_in maskaddr;
- FILE *fp;
+ FILE *fp[MAXINCLUDELEVEL+1];
+ FILE *includefile;
+ int includelevel = 0;
char line[MAXLINE];
char *(tokens[MAXTOKENS]);
int ntokens;
int tok = CONFIG_UNKNOWN;
struct interface *localaddr;
- const char *config_file;
-#ifdef HAVE_NETINFO
- struct netinfo_config_state *config_netinfo = NULL;
- int check_netinfo = 1;
-#endif /* HAVE_NETINFO */
-#ifdef SYS_WINNT
- char *alt_config_file;
- LPTSTR temp;
- char config_file_storage[MAX_PATH];
- char alt_config_file_storage[MAX_PATH];
-#endif /* SYS_WINNT */
struct refclockstat clock_stat;
FILEGEN *filegen;
@@ -670,9 +516,7 @@ getconfig(
* Initialize, initialize
*/
errflg = 0;
-#ifdef DEBUG
- debug = 0;
-#endif /* DEBUG */
+ /* HMS: don't initialize debug to 0 here! */
#ifndef SYS_WINNT
config_file = CONFIG_FILE;
#else
@@ -713,146 +557,10 @@ getconfig(
*/
loop_config(LOOP_DRIFTINIT, 0.);
- /*
- * Decode argument list
- */
- while ((c = ntp_getopt(argc, argv, ntp_options)) != EOF) {
- switch (c) {
- case 'a':
- proto_config(PROTO_AUTHENTICATE, 1, 0.);
- break;
-
- case 'A':
- proto_config(PROTO_AUTHENTICATE, 0, 0.);
- break;
-
- case 'b':
- proto_config(PROTO_BROADCLIENT, 1, 0.);
- break;
-
- case 'c':
- config_file = ntp_optarg;
-#ifdef HAVE_NETINFO
- check_netinfo = 0;
-#endif
- break;
-
- case 'd':
-#ifdef DEBUG
- debug++;
-#else
- errflg++;
-#endif /* DEBUG */
- break;
-
- case 'D':
-#ifdef DEBUG
- debug = (int)atol(ntp_optarg);
- printf("Debug2: %s -> %x = %d\n", ntp_optarg, debug, debug);
-#else
- errflg++;
-#endif /* DEBUG */
- break;
-
- case 'f':
- stats_config(STATS_FREQ_FILE, ntp_optarg);
- break;
-
- case 'g':
- correct_any = TRUE;
- break;
-
- case 'k':
- getauthkeys(ntp_optarg);
- break;
-
- case 'L': /* already done at pre-scan */
- case 'l': /* already done at pre-scan */
- break;
-
- case 'm':
- proto_config(PROTO_MULTICAST_ADD, htonl(INADDR_NTP), 0.);
- sys_bclient = 1;
- break;
-
- case 'n': /* already done at pre-scan */
- break;
-
- case 'p':
- stats_config(STATS_PID_FILE, ntp_optarg);
- break;
-
- case 'P':
-#if defined(HAVE_SCHED_SETSCHEDULER)
- config_priority = (int)atol(ntp_optarg);
- config_priority_override = 1;
-#else
- errflg++;
-#endif
- break;
-
- case '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);
- }
- } while (0);
- 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,
- RW | ((c == 'V') ? DEF : 0));
- break;
-
- case 'x':
- allow_set_backward = FALSE;
- break;
-
- 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
- exit(2);
- }
+ getCmdOpts(argc, argv);
if (
- (fp = fopen(FindConfig(config_file), "r")) == NULL
+ (fp[0] = fopen(FindConfig(config_file), "r")) == NULL
#ifdef HAVE_NETINFO
/* If there is no config_file, try NetInfo. */
&& check_netinfo && !(config_netinfo = get_netinfo_config())
@@ -863,7 +571,7 @@ getconfig(
#ifdef SYS_WINNT
/* Under WinNT try alternate_config_file name, first NTP.CONF, then NTP.INI */
- if ((fp = fopen(FindConfig(alt_config_file), "r")) == NULL) {
+ if ((fp[0] = fopen(FindConfig(alt_config_file), "r")) == NULL) {
/*
* Broadcast clients can sometimes run without
@@ -880,14 +588,21 @@ getconfig(
}
for (;;) {
- if (fp)
- tok = gettokens(fp, line, tokens, &ntokens);
+ if (fp[includelevel])
+ tok = gettokens(fp[includelevel], line, tokens, &ntokens);
#ifdef HAVE_NETINFO
else
tok = gettokens_netinfo(config_netinfo, tokens, &ntokens);
#endif /* HAVE_NETINFO */
- if (tok == CONFIG_UNKNOWN) break;
+ if (tok == CONFIG_UNKNOWN) {
+ if (includelevel > 0) {
+ fclose(fp[includelevel--]);
+ continue;
+ } else {
+ break;
+ }
+ }
switch(tok) {
case CONFIG_PEER:
@@ -954,6 +669,7 @@ getconfig(
minpoll = NTP_MINDPOLL;
maxpoll = NTP_MAXDPOLL;
peerkey = 0;
+ peerkeystr = "*";
peerflags = 0;
ttl = 0;
for (i = 2; i < ntokens; i++)
@@ -994,8 +710,12 @@ getconfig(
break;
}
minpoll = atoi(tokens[++i]);
- if (minpoll < NTP_MINPOLL)
+ if (minpoll < NTP_MINPOLL) {
+ msyslog(LOG_INFO,
+ "minpoll: provided value (%d) is below minimum (%d)",
+ minpoll, NTP_MINPOLL);
minpoll = NTP_MINPOLL;
+ }
break;
case CONF_MOD_MAXPOLL:
@@ -1007,8 +727,12 @@ getconfig(
break;
}
maxpoll = atoi(tokens[++i]);
- if (maxpoll > NTP_MAXPOLL)
+ if (maxpoll > NTP_MAXPOLL) {
+ msyslog(LOG_INFO,
+ "maxpoll: provided value (%d) is above maximum (%d)",
+ maxpoll, NTP_MAXPOLL);
maxpoll = NTP_MAXPOLL;
+ }
break;
case CONF_MOD_PREFER:
@@ -1023,10 +747,30 @@ getconfig(
peerflags |= FLAG_BURST;
break;
+ case CONF_MOD_IBURST:
+ peerflags |= FLAG_IBURST;
+ break;
+#ifdef AUTOKEY
case CONF_MOD_SKEY:
- peerflags |= FLAG_SKEY | FLAG_AUTHENABLE;
+ peerflags |= FLAG_SKEY |
+ FLAG_AUTHENABLE;
break;
+#ifdef PUBKEY
+ case CONF_MOD_PUBLICKEY:
+ if (i >= ntokens - 1) {
+ msyslog(LOG_ERR,
+ "Public key file name required");
+ errflg = 1;
+ break;
+ }
+ peerflags |= FLAG_SKEY |
+ FLAG_AUTHENABLE;
+ peerkeystr = tokens[++i];
+ break;
+#endif /* PUBKEY */
+#endif /* AUTOKEY */
+
case CONF_MOD_TTL:
if (i >= ntokens-1) {
msyslog(LOG_ERR,
@@ -1056,19 +800,18 @@ getconfig(
errflg = 1;
}
if (errflg == 0) {
- if (peer_config(&peeraddr,
- (struct interface *)0, hmode,
- peerversion, minpoll, maxpoll,
- peerflags, ttl, peerkey)
- == 0) {
+ if (peer_config(&peeraddr, any_interface, hmode,
+ peerversion, minpoll, maxpoll, peerflags,
+ ttl, peerkey, peerkeystr) == 0) {
msyslog(LOG_ERR,
"configuration of %s failed",
ntoa(&peeraddr));
- }
+ }
+
} else if (errflg == -1) {
save_resolve(tokens[1], hmode, peerversion,
- minpoll, maxpoll, peerflags, ttl,
- peerkey);
+ minpoll, maxpoll, peerflags, ttl,
+ peerkey, peerkeystr);
}
break;
@@ -1086,9 +829,29 @@ getconfig(
stats_config(STATS_PID_FILE, (char *)0);
break;
+ case CONFIG_INCLUDEFILE:
+ if (ntokens < 2) {
+ msyslog(LOG_ERR, "includefile needs one argument");
+ break;
+ }
+ if (includelevel >= MAXINCLUDELEVEL) {
+ fprintf(stderr, "getconfig: Maximum include file level exceeded.\n");
+ msyslog(LOG_INFO, "getconfig: Maximum include file level exceeded.");
+ break;
+ }
+ includefile = fopen(FindConfig(tokens[1]), "r");
+ if (includefile == NULL) {
+ fprintf(stderr, "getconfig: Couldn't open <%s>\n", FindConfig(tokens[1]));
+ msyslog(LOG_INFO, "getconfig: Couldn't open <%s>", FindConfig(tokens[1]));
+ break;
+ }
+ fp[++includelevel] = includefile;
+ break;
+
case CONFIG_LOGFILE:
if (ntokens >= 2) {
FILE *new_file;
+
new_file = fopen(tokens[1], "a");
if (new_file != NULL) {
NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
@@ -1159,20 +922,10 @@ getconfig(
} else
proto_config(PROTO_MULTICAST_ADD,
htonl(INADDR_NTP), 0.);
- if (tok == CONFIG_MULTICASTCLIENT) {
+ if (tok == CONFIG_MULTICASTCLIENT)
sys_bclient = 1;
-#ifdef DEBUG
- if (debug)
- printf("sys_bclient\n");
-#endif /* DEBUG */
- }
- else if (tok == CONFIG_MANYCASTSERVER) {
+ else if (tok == CONFIG_MANYCASTSERVER)
sys_manycastserver = 1;
-#ifdef DEBUG
- if (debug)
- printf("sys_manycastserver\n");
-#endif /* DEBUG */
- }
break;
case CONFIG_AUTHENTICATE:
@@ -1199,17 +952,121 @@ getconfig(
}
break;
- case CONFIG_REVOKE:
- if (ntokens >= 2) {
- sys_revoke = 1 << max(atoi(tokens[1]), 10);
+ case CONFIG_TINKER:
+ for (i = 1; i < ntokens; i++) {
+ int temp;
+ double ftemp;
+
+ temp = matchkey(tokens[i++],
+ tinker_keywords);
+ if (i > ntokens - 1) {
+ msyslog(LOG_ERR,
+ "tinker: missing argument");
+ errflg++;
+ break;
+ }
+ sscanf(tokens[i], "%lf", &ftemp);
+ switch(temp) {
+ case CONF_CLOCK_MAX:
+ loop_config(LOOP_MAX, ftemp);
+ break;
+
+ case CONF_CLOCK_PANIC:
+ loop_config(LOOP_PANIC, ftemp);
+ break;
+
+ case CONF_CLOCK_PHI:
+ loop_config(LOOP_PHI, ftemp);
+ break;
+
+ case CONF_CLOCK_MINSTEP:
+ loop_config(LOOP_MINSTEP, ftemp);
+ break;
+
+ case CONF_CLOCK_MINPOLL:
+ loop_config(LOOP_MINPOLL, ftemp);
+ break;
+
+ case CONF_CLOCK_ALLAN:
+ loop_config(LOOP_ALLAN, ftemp);
+ break;
+
+ case CONF_CLOCK_HUFFPUFF:
+ loop_config(LOOP_HUFFPUFF, ftemp);
+ break;
+ }
}
break;
+#ifdef AUTOKEY
+ case CONFIG_REVOKE:
+ if (ntokens >= 2)
+ sys_revoke = 1 << max(atoi(tokens[1]), 10);
+ break;
+
case CONFIG_AUTOMAX:
- if (ntokens >= 2) {
- sys_automax = 1 << max(atoi(tokens[1]), 10);
+ if (ntokens >= 2)
+ sys_automax = 1 << max(atoi(tokens[1]), 10);
+ break;
+
+#ifdef PUBKEY
+ case CONFIG_KEYSDIR:
+ if (ntokens < 2) {
+ msyslog(LOG_ERR,
+ "Keys directory name required");
+ break;
+ }
+ crypto_config(CRYPTO_CONF_KEYS, tokens[1]);
+ break;
+
+ case CONFIG_CRYPTO:
+ if (ntokens == 1) {
+ crypto_config(CRYPTO_CONF_FLAGS , "0");
+ break;
+ }
+ for (i = 1; i < ntokens; i++) {
+ int temp;
+
+ temp = matchkey(tokens[i++], crypto_keywords);
+ if (i > ntokens - 1) {
+ msyslog(LOG_ERR,
+ "crypto: missing argument");
+ errflg++;
+ break;
+ }
+ switch(temp) {
+ case CONF_CRYPTO_FLAGS:
+ crypto_config(CRYPTO_CONF_FLAGS, tokens[i]);
+ break;
+
+ case CONF_CRYPTO_LEAP:
+ crypto_config(CRYPTO_CONF_LEAP, tokens[i]);
+ break;
+
+ case CONF_CRYPTO_DH:
+ crypto_config(CRYPTO_CONF_DH, tokens[i]);
+ break;
+
+ case CONF_CRYPTO_PRIVATEKEY:
+ crypto_config(CRYPTO_CONF_PRIV, tokens[i]);
+ break;
+
+ case CONF_CRYPTO_PUBLICKEY:
+ crypto_config(CRYPTO_CONF_PUBL, tokens[i]);
+ break;
+
+ case CONF_CRYPTO_CERT:
+ crypto_config(CRYPTO_CONF_CERT, tokens[i]);
+ break;
+
+ default:
+ msyslog(LOG_ERR, "crypto: unknown keyword");
+ break;
+ }
}
break;
+#endif /* PUBKEY */
+#endif /* AUTOKEY */
case CONFIG_RESTRICT:
if (ntokens < 2) {
@@ -1278,6 +1135,14 @@ getconfig(
peerkey |= RESM_NTPONLY;
break;
+ case CONF_RES_VERSION:
+ peerversion |= RES_VERSION;
+ break;
+
+ case CONF_RES_DEMOBILIZE:
+ peerversion |= RES_DEMOBILIZE;
+ break;
+
case CONF_RES_LIMITED:
peerversion |= RES_LIMITED;
break;
@@ -1310,7 +1175,7 @@ getconfig(
case CONFIG_TRUSTEDKEY:
for (i = 1; i < ntokens; i++) {
- u_long tkey;
+ keyid_t tkey;
tkey = atol(tokens[i]);
if (tkey == 0) {
@@ -1325,13 +1190,11 @@ getconfig(
case CONFIG_REQUESTKEY:
if (ntokens >= 2) {
- u_long rkey;
-
- if (!atouint(tokens[1], &rkey)) {
+ if (!atouint(tokens[1], &ul)) {
msyslog(LOG_ERR,
"%s is undecodable as request key",
tokens[1]);
- } else if (rkey == 0) {
+ } else if (ul == 0) {
msyslog(LOG_ERR,
"%s makes a poor request keyid",
tokens[1]);
@@ -1339,16 +1202,16 @@ getconfig(
#ifdef DEBUG
if (debug > 3)
printf(
- "set info_auth_key to %lu\n", rkey);
+ "set info_auth_key to %08lx\n", ul);
#endif
- info_auth_keyid = rkey;
+ info_auth_keyid = (keyid_t)ul;
}
}
break;
case CONFIG_CONTROLKEY:
if (ntokens >= 2) {
- u_long ckey;
+ keyid_t ckey;
ckey = atol(tokens[1]);
if (ckey == 0) {
@@ -1455,6 +1318,7 @@ getconfig(
}
memset((void *)&clock_stat, 0, sizeof clock_stat);
+ fudgeflag = 0;
errflg = 0;
for (i = 2; i < ntokens-1; i++) {
switch (c = matchkey(tokens[i],
@@ -1485,9 +1349,7 @@ getconfig(
case CONF_FDG_STRATUM:
- /* HMS: the (long *)_ may be trouble */
- if (!atoint(tokens[++i],
- (long *)&clock_stat.fudgeval1))
+ if (!atoint(tokens[++i], &stratum))
{
msyslog(LOG_ERR,
"fudge %s stratum value in error",
@@ -1495,6 +1357,7 @@ getconfig(
errflg = i;
break;
}
+ clock_stat.fudgeval1 = stratum;
clock_stat.haveflags |= CLK_HAVEVAL1;
break;
@@ -1510,16 +1373,14 @@ getconfig(
case CONF_FDG_FLAG2:
case CONF_FDG_FLAG3:
case CONF_FDG_FLAG4:
- if (!atouint(tokens[++i], &lpeerkey)
- || lpeerkey > 1) {
+ if (!atouint(tokens[++i], &fudgeflag)
+ || fudgeflag > 1) {
msyslog(LOG_ERR,
"fudge %s flag value in error",
ntoa(&peeraddr));
- peerkey = lpeerkey;
errflg = i;
break;
}
- peerkey = lpeerkey;
switch(c) {
case CONF_FDG_FLAG1:
c = CLK_FLAG1;
@@ -1538,7 +1399,7 @@ getconfig(
clock_stat.haveflags|=CLK_HAVEFLAG4;
break;
}
- if (peerkey == 0)
+ if (fudgeflag == 0)
clock_stat.flags &= ~c;
else
clock_stat.flags |= c;
@@ -1558,15 +1419,14 @@ getconfig(
*/
if (!errflg) {
refclock_control(&peeraddr, &clock_stat,
- (struct refclockstat *)0);
+ (struct refclockstat *)0);
}
#endif
break;
case CONFIG_STATSDIR:
- if (ntokens >= 2) {
+ if (ntokens >= 2)
stats_config(STATS_STATSDIR,tokens[1]);
- }
break;
case CONFIG_STATISTICS:
@@ -1659,10 +1519,9 @@ getconfig(
break;
}
}
- if (!errflg) {
+ if (!errflg)
filegen_config(filegen, tokens[peerversion],
- (u_char)peerkey, (u_char)peerflags);
- }
+ (u_char)peerkey, (u_char)peerflags);
break;
case CONFIG_SETVAR:
@@ -1776,10 +1635,10 @@ getconfig(
flag = matchkey(tokens[i], pps_keywords);
switch(flag) {
case CONF_PPS_ASSERT:
- pps_assert = 1;
+ pps_assert = 0;
break;
case CONF_PPS_CLEAR:
- pps_assert = 0;
+ pps_assert = 1;
break;
case CONF_PPS_HARDPPS:
pps_hardpps = 1;
@@ -1797,11 +1656,44 @@ getconfig(
break;
}
}
- if (fp) (void)fclose(fp);
+ if (fp[0])
+ (void)fclose(fp[0]);
+
#ifdef HAVE_NETINFO
- if (config_netinfo) free_netinfo_config(config_netinfo);
+ if (config_netinfo)
+ free_netinfo_config(config_netinfo);
#endif /* HAVE_NETINFO */
+#if !defined(VMS) && !defined(SYS_VXWORKS)
+ /* find a keyid */
+ if (info_auth_keyid == 0)
+ req_keyid = 65535;
+ else
+ req_keyid = info_auth_keyid;
+
+ /* if doesn't exist, make up one at random */
+ if (!authhavekey(req_keyid)) {
+ char rankey[9];
+ int j;
+
+ for (i = 0; i < 8; i++)
+ for (j = 1; j < 100; ++j) {
+ rankey[i] = RANDOM & 0xff;
+ if (rankey[i] != 0) break;
+ }
+ rankey[8] = 0;
+ authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
+ authtrust(req_keyid, 1);
+ if (!authhavekey(req_keyid)) {
+ msyslog(LOG_ERR, "getconfig: Couldn't generate a valid random key!");
+ /* HMS: Should this be fatal? */
+ }
+ }
+
+ /* save keyid so we will accept config requests with it */
+ info_auth_keyid = req_keyid;
+#endif /* !defined(VMS) && !defined(SYS_VXWORKS) */
+
if (res_fp != NULL) {
/*
* Need name resolution
@@ -2165,9 +2057,10 @@ save_resolve(
int version,
int minpoll,
int maxpoll,
- int flags,
+ u_int flags,
int ttl,
- u_long keyid
+ keyid_t keyid,
+ u_char *keystr
)
{
#ifndef SYS_VXWORKS
@@ -2191,7 +2084,7 @@ save_resolve(
res_fp = NULL;
if ((fd = mkstemp(res_file)) != -1)
- res_fp = fdopen(fd, "w");
+ res_fp = fdopen(fd, "r+");
}
#else
(void) mktemp(res_file);
@@ -2208,8 +2101,14 @@ save_resolve(
}
#endif
- (void) fprintf(res_fp, "%s %d %d %d %d %d %d %lu\n", name, mode,
- version, minpoll, maxpoll, flags, ttl, keyid);
+ (void)fprintf(res_fp, "%s %d %d %d %d %d %d %d %s\n", name,
+ mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
+#ifdef DEBUG
+ if (debug > 1)
+ printf("config: %s %d %d %d %d %x %d %08x %s\n", name, mode,
+ version, minpoll, maxpoll, flags, ttl, keyid, keystr);
+#endif
+
#else /* SYS_VXWORKS */
/* save resolve info to a struct */
#endif /* SYS_VXWORKS */
@@ -2242,8 +2141,6 @@ abort_resolve(void)
}
-#define KEY_TYPE_MD5 4
-
/*
* do_resolve_internal - start up the resolver function (not program)
*/
@@ -2262,7 +2159,7 @@ do_resolve_internal(void)
if (res_fp == NULL) {
/* belch */
msyslog(LOG_ERR,
- "internal error in do_resolve_internal: res_fp == NULL");
+ "do_resolve_internal: Fatal: res_fp == NULL");
exit(1);
}
@@ -2271,24 +2168,6 @@ do_resolve_internal(void)
res_fp = NULL;
#if !defined(VMS) && !defined (SYS_VXWORKS)
- /* find a keyid */
- if (info_auth_keyid == 0)
- req_keyid = 65535;
- else
- req_keyid = info_auth_keyid;
-
- /* if doesn't exist, make up one at random */
- if (!authhavekey(req_keyid)) {
- char rankey[8];
-
- for (i = 0; i < 8; i++)
- rankey[i] = RANDOM & 0xff;
- authusekey(req_keyid, KEY_TYPE_MD5, (u_char *)rankey);
- authtrust(req_keyid, 1);
- }
-
- /* save keyid so we will accept config requests with it */
- info_auth_keyid = req_keyid;
req_file = res_file; /* set up pointer to res file */
#ifndef SYS_WINNT
(void) signal_no_reset(SIGCHLD, catchchild);
@@ -2317,10 +2196,10 @@ do_resolve_internal(void)
* async io information causes it to process requests from
* all file decriptor causing a race between the NTP daemon
* and the resolver. which then eats data when it wins 8-(.
- * It is absolutly necessary to kill ane io associations
- * shared with the NTP daemon. I currently don't want
+ * It is absolutly necessary to kill any IO associations
+ * shared with the NTP daemon.
*
- * we also block SIGIO (currently no portes means to
+ * We also block SIGIO (currently no ports means to
* disable the signal handle for IO).
*
* Thanks to wgstuken@informatik.uni-erlangen.de to notice
diff --git a/contrib/ntp/ntpd/ntp_control.c b/contrib/ntp/ntpd/ntp_control.c
index e2fb039..570e2f9 100644
--- a/contrib/ntp/ntpd/ntp_control.c
+++ b/contrib/ntp/ntpd/ntp_control.c
@@ -5,18 +5,23 @@
#include <config.h>
#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_control.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifdef PUBKEY
+#include "ntp_crypto.h"
+#endif /* PUBKEY */
+
/*
* Structure to hold request procedure information
*/
@@ -26,9 +31,9 @@
#define NO_REQUEST (-1)
struct ctl_proc {
- short control_code; /* defined request code */
- u_short flags; /* flags word */
- void (*handler) P((struct recvbuf *, int)); /* routine to handle request */
+ short control_code; /* defined request code */
+ u_short flags; /* flags word */
+ void (*handler) P((struct recvbuf *, int)); /* handle request */
};
/*
@@ -44,9 +49,10 @@ static void ctl_error P((int));
static u_short ctlclkstatus P((struct refclockstat *));
static void ctl_flushpkt P((int));
static void ctl_putdata P((const char *, unsigned int, int));
-static void ctl_putstr P((const char *, const char *, unsigned int));
+static void ctl_putstr P((const char *, const char *,
+ unsigned int));
static void ctl_putdbl P((const char *, double));
-static void ctl_putuint P((const char *, u_long));
+static void ctl_putuint P((const char *, u_long));
static void ctl_puthex P((const char *, u_long));
static void ctl_putint P((const char *, long));
static void ctl_putts P((const char *, l_fp *));
@@ -54,21 +60,22 @@ static void ctl_putadr P((const char *, u_int32));
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 *));
+static void ctl_putpeer P((int, struct peer *));
#ifdef REFCLOCK
static void ctl_putclock P((int, struct refclockstat *, int));
#endif /* REFCLOCK */
static struct ctl_var *ctl_getitem P((struct ctl_var *, char **));
-static u_long count_var P((struct ctl_var *));
+static u_long count_var P((struct ctl_var *));
static void control_unspec P((struct recvbuf *, int));
-static void read_status P((struct recvbuf *, int));
+static void read_status P((struct recvbuf *, int));
static void read_variables P((struct recvbuf *, int));
static void write_variables P((struct recvbuf *, int));
-static void read_clock_status P((struct recvbuf *, int));
-static void write_clock_status P((struct recvbuf *, int));
+static void read_clock_status P((struct recvbuf *, int));
+static void write_clock_status P((struct recvbuf *, int));
static void set_trap P((struct recvbuf *, int));
static void unset_trap P((struct recvbuf *, int));
-static struct ctl_trap *ctlfindtrap P((struct sockaddr_in *, struct interface *));
+static struct ctl_trap *ctlfindtrap P((struct sockaddr_in *,
+ struct interface *));
static struct ctl_proc control_codes[] = {
{ CTL_OP_UNSPEC, NOAUTH, control_unspec },
@@ -83,10 +90,10 @@ static struct ctl_proc control_codes[] = {
};
/*
- * System variable values. The array can be indexed by
- * the variable index to find the textual name.
+ * System variable values. The array can be indexed by the variable
+ * index to find the textual name.
*/
-static struct ctl_var sys_var[] = {
+static struct ctl_var sys_var[] = {
{ 0, PADDING, "" }, /* 0 */
{ CS_LEAP, RW, "leap" }, /* 1 */
{ CS_STRATUM, RO, "stratum" }, /* 2 */
@@ -98,23 +105,36 @@ static struct ctl_var sys_var[] = {
{ CS_POLL, RO, "poll" }, /* 8 */
{ CS_PEERID, RO, "peer" }, /* 9 */
{ CS_STATE, RO, "state" }, /* 10 */
- { CS_OFFSET, RO, "phase" }, /* 11 */
+ { CS_OFFSET, RO, "offset" }, /* 11 */
{ CS_DRIFT, RO, "frequency" }, /* 12 */
- { CS_COMPLIANCE, RO, "jitter" }, /* 13 */
+ { CS_JITTER, RO, "jitter" }, /* 13 */
{ CS_CLOCK, RO, "clock" }, /* 14 */
{ CS_PROCESSOR, RO, "processor" }, /* 15 */
{ CS_SYSTEM, RO, "system" }, /* 16 */
- { CS_STABIL, RO, "stability" }, /* 17 */
- { CS_VARLIST, RO, "sys_var_list" }, /* 18 */
- { 0, EOV, "" }
+ { CS_VERSION, RO, "version" }, /* 17 */
+ { CS_STABIL, RO, "stability" }, /* 18 */
+ { CS_VARLIST, RO, "sys_var_list" }, /* 19 */
+#ifdef PUBKEY
+ { CS_FLAGS, RO, "flags" }, /* 20 */
+ { CS_HOST, RO, "hostname" }, /* 21 */
+ { CS_PUBLIC, RO, "publickey" }, /* 22 */
+ { CS_CERTIF, RO, "certificate" }, /* 23 */
+ { CS_DHPARAMS, RO, "params" }, /* 24 */
+ { CS_REVTIME, RO, "refresh" }, /* 25 */
+ { CS_LEAPTAB, RO, "leapseconds" }, /* 26 */
+ { CS_TAI, RO, "tai"}, /* 27 */
+#endif /* PUBKEY */
+ { 0, EOV, "" } /* 28 */
};
-static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
+static struct ctl_var *ext_sys_var = (struct ctl_var *)0;
/*
- * System variables we print by default (in fuzzball order, more-or-less)
+ * System variables we print by default (in fuzzball order,
+ * more-or-less)
*/
static u_char def_sys_var[] = {
+ CS_VERSION,
CS_PROCESSOR,
CS_SYSTEM,
CS_LEAP,
@@ -130,8 +150,16 @@ static u_char def_sys_var[] = {
CS_STATE,
CS_OFFSET,
CS_DRIFT,
- CS_COMPLIANCE,
+ CS_JITTER,
CS_STABIL,
+#ifdef PUBKEY
+ CS_FLAGS,
+ CS_HOST,
+ CS_CERTIF,
+ CS_DHPARAMS,
+ CS_REVTIME,
+ CS_LEAPTAB,
+#endif /* PUBKEY */
0
};
@@ -139,82 +167,103 @@ static u_char def_sys_var[] = {
/*
* Peer variable list
*/
-static struct ctl_var peer_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CP_CONFIG, RO, "config" }, /* 1 */
- { CP_AUTHENABLE, RO, "authenable" }, /* 2 */
- { CP_AUTHENTIC, RO, "authentic" }, /* 3 */
- { CP_SRCADR, RO, "srcadr" }, /* 4 */
- { CP_SRCPORT, RO, "srcport" }, /* 5 */
- { CP_DSTADR, RO, "dstadr" }, /* 6 */
- { CP_DSTPORT, RO, "dstport" }, /* 7 */
- { CP_LEAP, RO, "leap" }, /* 8 */
- { CP_HMODE, RO, "hmode" }, /* 9 */
- { CP_STRATUM, RO, "stratum" }, /* 10 */
- { CP_PPOLL, RO, "ppoll" }, /* 11 */
- { CP_HPOLL, RO, "hpoll" }, /* 12 */
- { CP_PRECISION, RO, "precision" }, /* 13 */
- { CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
+static struct ctl_var peer_var[] = {
+ { 0, PADDING, "" }, /* 0 */
+ { CP_CONFIG, RO, "config" }, /* 1 */
+ { CP_AUTHENABLE, RO, "authenable" }, /* 2 */
+ { CP_AUTHENTIC, RO, "authentic" }, /* 3 */
+ { CP_SRCADR, RO, "srcadr" }, /* 4 */
+ { CP_SRCPORT, RO, "srcport" }, /* 5 */
+ { CP_DSTADR, RO, "dstadr" }, /* 6 */
+ { CP_DSTPORT, RO, "dstport" }, /* 7 */
+ { CP_LEAP, RO, "leap" }, /* 8 */
+ { CP_HMODE, RO, "hmode" }, /* 9 */
+ { CP_STRATUM, RO, "stratum" }, /* 10 */
+ { CP_PPOLL, RO, "ppoll" }, /* 11 */
+ { CP_HPOLL, RO, "hpoll" }, /* 12 */
+ { CP_PRECISION, RO, "precision" }, /* 13 */
+ { CP_ROOTDELAY, RO, "rootdelay" }, /* 14 */
{ CP_ROOTDISPERSION, RO, "rootdispersion" }, /* 15 */
- { CP_REFID, RO, "refid" }, /* 16 */
- { CP_REFTIME, RO, "reftime" }, /* 17 */
- { CP_ORG, RO, "org" }, /* 18 */
- { CP_REC, RO, "rec" }, /* 19 */
- { CP_XMT, RO, "xmt" }, /* 20 */
- { CP_REACH, RO, "reach" }, /* 21 */
- { CP_VALID, RO, "valid" }, /* 22 */
- { CP_TIMER, RO, "timer" }, /* 23 */
- { CP_DELAY, RO, "delay" }, /* 24 */
- { CP_OFFSET, RO, "offset" }, /* 25 */
- { CP_JITTER, RO, "jitter" }, /* 26 */
- { CP_DISPERSION,RO, "dispersion" }, /* 27 */
- { CP_KEYID, RO, "keyid" }, /* 28 */
- { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */
- { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */
- { CP_PMODE, RO, "pmode" }, /* 31 */
- { CP_RECEIVED, RO, "received"}, /* 32 */
- { CP_SENT, RO, "sent" }, /* 33 */
- { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
- { CP_FLASH, RO, "flash" }, /* 35 */
- { CP_DISP, PADDING,"" }, /* 36 */
- { CP_VARLIST, RO, "peer_var_list" }, /* 37 */
- { 0, EOV, "" }
+ { CP_REFID, RO, "refid" }, /* 16 */
+ { CP_REFTIME, RO, "reftime" }, /* 17 */
+ { CP_ORG, RO, "org" }, /* 18 */
+ { CP_REC, RO, "rec" }, /* 19 */
+ { CP_XMT, RO, "xmt" }, /* 20 */
+ { CP_REACH, RO, "reach" }, /* 21 */
+ { CP_VALID, RO, "unreach" }, /* 22 */
+ { CP_TIMER, RO, "timer" }, /* 23 */
+ { CP_DELAY, RO, "delay" }, /* 24 */
+ { CP_OFFSET, RO, "offset" }, /* 25 */
+ { CP_JITTER, RO, "jitter" }, /* 26 */
+ { CP_DISPERSION, RO, "dispersion" }, /* 27 */
+ { CP_KEYID, RO, "keyid" }, /* 28 */
+ { CP_FILTDELAY, RO, "filtdelay=" }, /* 29 */
+ { CP_FILTOFFSET, RO, "filtoffset=" }, /* 30 */
+ { CP_PMODE, RO, "pmode" }, /* 31 */
+ { CP_RECEIVED, RO, "received"}, /* 32 */
+ { CP_SENT, RO, "sent" }, /* 33 */
+ { CP_FILTERROR, RO, "filtdisp=" }, /* 34 */
+ { CP_FLASH, RO, "flash" }, /* 35 */
+ { CP_TTL, RO, "ttl" }, /* 36 */
+ { CP_TTLMAX, RO, "ttlmax" }, /* 37 */
+ { CP_VARLIST, RO, "peer_var_list" }, /* 38 */
+#ifdef PUBKEY
+ { CP_FLAGS, RO, "flags" }, /* 38 */
+ { CP_HOST, RO, "hostname" }, /* 39 */
+ { CP_PUBLIC, RO, "publickey" }, /* 40 */
+ { CP_CERTIF, RO, "certificate" }, /* 41 */
+ { CP_SESKEY, RO, "pcookie" }, /* 42 */
+ { CP_SASKEY, RO, "hcookie" }, /* 43 */
+ { CP_INITSEQ, RO, "initsequence" }, /* 44 */
+ { CP_INITKEY, RO, "initkey" }, /* 45 */
+ { CP_INITTSP, RO, "timestamp" }, /* 46 */
+#endif /* PUBKEY */
+ { 0, EOV, "" } /* 47 */
};
/*
* Peer variables we print by default
*/
-static u_char def_peer_var[] = {
+static u_char def_peer_var[] = {
CP_SRCADR,
CP_SRCPORT,
CP_DSTADR,
CP_DSTPORT,
- CP_KEYID,
+ CP_LEAP,
CP_STRATUM,
CP_PRECISION,
CP_ROOTDELAY,
CP_ROOTDISPERSION,
CP_REFID,
- CP_REFTIME,
- CP_DELAY,
- CP_OFFSET,
- CP_JITTER,
- CP_DISPERSION,
CP_REACH,
CP_VALID,
CP_HMODE,
CP_PMODE,
CP_HPOLL,
CP_PPOLL,
- CP_LEAP,
CP_FLASH,
+ CP_KEYID,
+ CP_TTL,
+ CP_TTLMAX,
+ CP_OFFSET,
+ CP_DELAY,
+ CP_DISPERSION,
+ CP_JITTER,
+ CP_REFTIME,
CP_ORG,
CP_REC,
CP_XMT,
CP_FILTDELAY,
CP_FILTOFFSET,
CP_FILTERROR,
+#ifdef PUBKEY
+ CP_FLAGS,
+ CP_HOST,
+ CP_CERTIF,
+ CP_SESKEY,
+ CP_INITSEQ,
+#endif /* PUBKEY */
0
};
@@ -223,31 +272,31 @@ static u_char def_peer_var[] = {
/*
* Clock variable list
*/
-static struct ctl_var clock_var[] = {
- { 0, PADDING, "" }, /* 0 */
- { CC_TYPE, RO, "type" }, /* 1 */
- { CC_TIMECODE, RO, "timecode" }, /* 2 */
- { CC_POLL, RO, "poll" }, /* 3 */
- { CC_NOREPLY, RO, "noreply" }, /* 4 */
- { CC_BADFORMAT, RO, "badformat" }, /* 5 */
- { CC_BADDATA, RO, "baddata" }, /* 6 */
- { CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */
- { CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */
- { CC_FUDGEVAL1, RO, "stratum" }, /* 9 */
- { CC_FUDGEVAL2, RO, "refid" }, /* 10 */
- { CC_FLAGS, RO, "flags" }, /* 11 */
- { CC_DEVICE, RO, "device" }, /* 12 */
- { CC_VARLIST, RO, "clock_var_list" },/* 13 */
- { 0, EOV, "" }
+static struct ctl_var clock_var[] = {
+ { 0, PADDING, "" }, /* 0 */
+ { CC_TYPE, RO, "type" }, /* 1 */
+ { CC_TIMECODE, RO, "timecode" }, /* 2 */
+ { CC_POLL, RO, "poll" }, /* 3 */
+ { CC_NOREPLY, RO, "noreply" }, /* 4 */
+ { CC_BADFORMAT, RO, "badformat" }, /* 5 */
+ { CC_BADDATA, RO, "baddata" }, /* 6 */
+ { CC_FUDGETIME1, RO, "fudgetime1" }, /* 7 */
+ { CC_FUDGETIME2, RO, "fudgetime2" }, /* 8 */
+ { CC_FUDGEVAL1, RO, "stratum" }, /* 9 */
+ { CC_FUDGEVAL2, RO, "refid" }, /* 10 */
+ { CC_FLAGS, RO, "flags" }, /* 11 */
+ { CC_DEVICE, RO, "device" }, /* 12 */
+ { CC_VARLIST, RO, "clock_var_list" }, /* 13 */
+ { 0, EOV, "" } /* 14 */
};
/*
* Clock variables printed by default
*/
-static u_char def_clock_var[] = {
+static u_char def_clock_var[] = {
CC_DEVICE,
- CC_TYPE, /* won't be output if device= known */
+ CC_TYPE, /* won't be output if device = known */
CC_TIMECODE,
CC_POLL,
CC_NOREPLY,
@@ -264,14 +313,14 @@ static u_char def_clock_var[] = {
/*
- * System and processor definitions. These will change for the gizmo board.
+ * System and processor definitions.
*/
#ifndef HAVE_UNAME
# ifndef STR_SYSTEM
-# define STR_SYSTEM "UNIX"
+# define STR_SYSTEM "UNIX"
# endif
# ifndef STR_PROCESSOR
-# define STR_PROCESSOR "unknown"
+# define STR_PROCESSOR "unknown"
# endif
static char str_system[] = STR_SYSTEM;
@@ -282,10 +331,10 @@ static struct utsname utsnamebuf;
#endif /* HAVE_UNAME */
/*
- * Trap structures. We only allow a few of these, and send
- * a copy of each async message to each live one. Traps time
- * out after an hour, it is up to the trap receipient to
- * keep resetting it to avoid being timed out.
+ * Trap structures. We only allow a few of these, and send a copy of
+ * each async message to each live one. Traps time out after an hour, it
+ * is up to the trap receipient to keep resetting it to avoid being
+ * timed out.
*/
/* ntp_request.c */
struct ctl_trap ctl_trap[CTL_MAXTRAPS];
@@ -301,9 +350,9 @@ int num_ctl_traps;
/*
* List relating reference clock types to control message time sources.
- * Index by the reference clock type.
- * This list will only be used iff the reference clock driver doesn't
- * set peer->sstclktype to something different than CTL_SST_TS_UNSPEC.
+ * Index by the reference clock type. This list will only be used iff
+ * the reference clock driver doesn't set peer->sstclktype to something
+ * different than CTL_SST_TS_UNSPEC.
*/
static u_char clocktypes[] = {
CTL_SST_TS_NTP, /* REFCLK_NONE (0) */
@@ -342,15 +391,17 @@ static u_char clocktypes[] = {
CTL_SST_TS_LF, /* REFCLK_DUMBCLOCK (32) */
CTL_SST_TS_LF, /* REFCLK_ULINK (33) */
CTL_SST_TS_LF, /* REFCLK_PCF (35) */
- CTL_SST_TS_LF, /* REFCLK_WWW (36) */
+ CTL_SST_TS_LF, /* REFCLK_WWV (36) */
CTL_SST_TS_LF, /* REFCLK_FG (37) */
+ CTL_SST_TS_UHF, /* REFCLK_HOPF_SERIAL (38) */
+ CTL_SST_TS_UHF, /* REFCLK_HOPF_PCI (39) */
};
/*
* Keyid used for authenticating write requests.
*/
-u_long ctl_auth_keyid;
+keyid_t ctl_auth_keyid;
/*
* We keep track of the last error reported by the system internally
@@ -366,7 +417,7 @@ u_long ctltimereset; /* time stats reset */
u_long numctlreq; /* number of requests we've received */
u_long numctlbadpkts; /* number of bad control packets */
u_long numctlresponses; /* number of resp packets sent with data */
-u_long numctlfrags; /* number of fragments sent */
+u_long numctlfrags; /* number of fragments sent */
u_long numctlerrors; /* number of error responses sent */
u_long numctltooshort; /* number of too short input packets */
u_long numctlinputresp; /* number of responses on input */
@@ -375,11 +426,11 @@ u_long numctlinputerr; /* number of input pkts with err bit set */
u_long numctlbadoffset; /* number of input pkts with nonzero offset */
u_long numctlbadversion; /* number of input pkts with unknown version */
u_long numctldatatooshort; /* data too short for count */
-u_long numctlbadop; /* bad op code found in packet */
+u_long numctlbadop; /* bad op code found in packet */
u_long numasyncmsgs; /* number of async messages we've sent */
/*
- * Response packet used by these routines. Also some state information
+ * Response packet used by these routines. Also some state information
* so that we can handle packet formatting within a common set of
* subroutines. Note we try to enter data in place whenever possible,
* but the need to set the more bit correctly means we occasionally
@@ -388,7 +439,7 @@ u_long numasyncmsgs; /* number of async messages we've sent */
static struct ntp_control rpkt;
static u_char res_version;
static u_char res_opcode;
-static u_short res_associd;
+static associd_t res_associd;
static int res_offset;
static u_char * datapt;
static u_char * dataend;
@@ -399,7 +450,7 @@ static struct interface *lcl_inter;
static u_char res_authenticate;
static u_char res_authokay;
-static u_long res_keyid;
+static keyid_t res_keyid;
#define MAXDATALINELEN (72)
@@ -448,10 +499,11 @@ ctl_error(
printf("sending control error %d\n", errcode);
#endif
/*
- * fill in the fields. We assume rpkt.sequence and rpkt.associd
+ * Fill in the fields. We assume rpkt.sequence and rpkt.associd
* have already been filled in.
*/
- rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode & CTL_OP_MASK));
+ rpkt.r_m_e_op = (u_char) (CTL_RESPONSE|CTL_ERROR|(res_opcode &
+ CTL_OP_MASK));
rpkt.status = htons((u_short) ((errcode<<8) & 0xff00));
rpkt.count = 0;
@@ -461,15 +513,15 @@ ctl_error(
if (res_authenticate && sys_authenticate) {
int maclen;
- *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN)
- = htonl(res_keyid);
+ *(u_int32 *)((u_char *)&rpkt + CTL_HEADER_LEN) =
+ htonl(res_keyid);
maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
- CTL_HEADER_LEN);
+ CTL_HEADER_LEN);
sendpkt(rmt_addr, lcl_inter, -2, (struct pkt *)&rpkt,
- CTL_HEADER_LEN + maclen);
+ CTL_HEADER_LEN + maclen);
} else {
sendpkt(rmt_addr, lcl_inter, -3, (struct pkt *)&rpkt,
- CTL_HEADER_LEN);
+ CTL_HEADER_LEN);
}
numctlerrors++;
}
@@ -492,7 +544,7 @@ process_control(
int maclen;
#ifdef DEBUG
- if (debug > 1)
+ if (debug > 2)
printf("in process_control()\n");
#endif
@@ -509,8 +561,8 @@ process_control(
* it is a response or a fragment, ignore this.
*/
if (rbufp->recv_length < CTL_HEADER_LEN
- || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
- || pkt->offset != 0) {
+ || pkt->r_m_e_op & (CTL_RESPONSE|CTL_MORE|CTL_ERROR)
+ || pkt->offset != 0) {
#ifdef DEBUG
if (debug)
printf("invalid format in control packet\n");
@@ -539,9 +591,11 @@ process_control(
}
/*
- * Pull enough data from the packet to make intelligent responses
+ * Pull enough data from the packet to make intelligent
+ * responses
*/
- rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version, MODE_CONTROL);
+ rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, res_version,
+ MODE_CONTROL);
res_opcode = pkt->r_m_e_op;
rpkt.sequence = pkt->sequence;
rpkt.associd = pkt->associd;
@@ -559,8 +613,8 @@ process_control(
dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
/*
- * We're set up now. Make sure we've got at least
- * enough incoming data space to match the count.
+ * We're set up now. Make sure we've got at least enough
+ * incoming data space to match the count.
*/
req_data = rbufp->recv_length - CTL_HEADER_LEN;
if (req_data < req_count || rbufp->recv_length & 0x3) {
@@ -571,40 +625,43 @@ process_control(
properlen = req_count + CTL_HEADER_LEN;
#ifdef DEBUG
- if (debug >= 2 && (rbufp->recv_length & 0x3) != 0)
- printf("Packet length %d unrounded\n", rbufp->recv_length);
+ if (debug > 2 && (rbufp->recv_length & 0x3) != 0)
+ printf("Packet length %d unrounded\n",
+ rbufp->recv_length);
#endif
/* round up proper len to a 8 octet boundary */
properlen = (properlen + 7) & ~7;
maclen = rbufp->recv_length - properlen;
if ((rbufp->recv_length & (sizeof(u_long) - 1)) == 0 &&
- maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
- sys_authenticate) {
+ maclen >= MIN_MAC_LEN && maclen <= MAX_MAC_LEN &&
+ sys_authenticate) {
res_authenticate = 1;
- res_keyid = ntohl(*(u_int32 *)((u_char *)pkt + properlen));
+ res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
+ properlen));
#ifdef DEBUG
- if (debug >= 3)
+ if (debug > 2)
printf(
- "recv_len %d, properlen %d, wants auth with keyid %ld, MAC length=%d\n",
- rbufp->recv_length, properlen, res_keyid, maclen);
+ "recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
+ rbufp->recv_length, properlen, res_keyid, maclen);
#endif
if (!authistrusted(res_keyid)) {
#ifdef DEBUG
- if (debug >= 2)
- printf("invalid keyid %lu\n", res_keyid);
+ if (debug > 2)
+ printf("invalid keyid %08x\n",
+ res_keyid);
#endif
} else if (authdecrypt(res_keyid, (u_int32 *)pkt,
- rbufp->recv_length - maclen, maclen)) {
+ rbufp->recv_length - maclen, maclen)) {
#ifdef DEBUG
- if (debug >= 3)
+ if (debug > 2)
printf("authenticated okay\n");
#endif
res_authokay = 1;
} else {
#ifdef DEBUG
- if (debug >= 3)
+ if (debug > 2)
printf("authentication failed\n");
#endif
res_keyid = 0;
@@ -623,12 +680,12 @@ process_control(
for (cc = control_codes; cc->control_code != NO_REQUEST; cc++) {
if (cc->control_code == res_opcode) {
#ifdef DEBUG
- if (debug >= 2)
+ if (debug > 2)
printf("opcode %d, found command handler\n",
- res_opcode);
+ res_opcode);
#endif
- if (cc->flags == AUTH && (!res_authokay
- || res_keyid != ctl_auth_keyid)) {
+ if (cc->flags == AUTH && (!res_authokay ||
+ res_keyid != ctl_auth_keyid)) {
ctl_error(CERR_PERMISSION);
return;
}
@@ -666,7 +723,7 @@ ctlpeerstatus(
if (peer->reach != 0)
status |= CTL_PST_REACH;
return (u_short)CTL_PEER_STATUS(status, peer->num_events,
- peer->last_event);
+ peer->last_event);
}
@@ -678,12 +735,11 @@ ctlclkstatus(
struct refclockstat *this_clock
)
{
- return ((u_short)(this_clock->currentstatus) << 8)
- | (u_short)(this_clock->lastevent);
+ return ((u_short)(this_clock->currentstatus) << 8) |
+ (u_short)(this_clock->lastevent);
}
-
/*
* ctlsysstatus - return the system status word
*/
@@ -700,17 +756,17 @@ ctlsysstatus(void)
this_clock |= CTL_SST_TS_PPS;
} else {
if (sys_peer->refclktype < sizeof(clocktypes))
- this_clock = clocktypes[sys_peer->refclktype];
+ this_clock =
+ clocktypes[sys_peer->refclktype];
if (pps_control)
this_clock |= CTL_SST_TS_PPS;
}
}
return (u_short)CTL_SYS_STATUS(sys_leap, this_clock,
- ctl_sys_num_events, ctl_sys_last_event);
+ ctl_sys_num_events, ctl_sys_last_event);
}
-
/*
* ctl_flushpkt - write out the current packet and prepare
* another if necessary.
@@ -744,7 +800,8 @@ ctl_flushpkt(
/*
* Fill in the packet with the current info
*/
- rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode & CTL_OP_MASK));
+ rpkt.r_m_e_op = (u_char)(CTL_RESPONSE|more|(res_opcode &
+ CTL_OP_MASK));
rpkt.count = htons((u_short) dlen);
rpkt.offset = htons( (u_short) res_offset);
if (res_async) {
@@ -752,12 +809,14 @@ ctl_flushpkt(
for (i = 0; i < CTL_MAXTRAPS; i++) {
if (ctl_trap[i].tr_flags & TRAP_INUSE) {
- rpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
- ctl_trap[i].tr_version, MODE_CONTROL);
- rpkt.sequence = htons(ctl_trap[i].tr_sequence);
+ rpkt.li_vn_mode =
+ PKT_LI_VN_MODE(sys_leap,
+ ctl_trap[i].tr_version,
+ MODE_CONTROL);
+ rpkt.sequence =
+ htons(ctl_trap[i].tr_sequence);
sendpkt(&ctl_trap[i].tr_addr,
- ctl_trap[i].tr_localaddr,
- -4,
+ ctl_trap[i].tr_localaddr, -4,
(struct pkt *)&rpkt, sendlen);
if (!more)
ctl_trap[i].tr_sequence++;
@@ -768,25 +827,25 @@ ctl_flushpkt(
if (res_authenticate && sys_authenticate) {
int maclen;
int totlen = sendlen;
- u_long keyid = htonl(res_keyid);
+ keyid_t keyid = htonl(res_keyid);
/*
- * If we are going to authenticate, then there is
- * an additional requirement that the MAC begin on
- * a 64 bit boundary.
+ * If we are going to authenticate, then there
+ * is an additional requirement that the MAC
+ * begin on a 64 bit boundary.
*/
while (totlen & 7) {
*datapt++ = '\0';
totlen++;
}
memcpy(datapt, &keyid, sizeof keyid);
- maclen = authencrypt(res_keyid, (u_int32 *)&rpkt,
- totlen);
- sendpkt(rmt_addr, lcl_inter, -5, (struct pkt *)&rpkt,
- totlen + maclen);
+ maclen = authencrypt(res_keyid,
+ (u_int32 *)&rpkt, totlen);
+ sendpkt(rmt_addr, lcl_inter, -5,
+ (struct pkt *)&rpkt, totlen + maclen);
} else {
- sendpkt(rmt_addr, lcl_inter, -6, (struct pkt *)&rpkt,
- sendlen);
+ sendpkt(rmt_addr, lcl_inter, -6,
+ (struct pkt *)&rpkt, sendlen);
}
if (more)
numctlfrags++;
@@ -803,8 +862,8 @@ ctl_flushpkt(
/*
- * ctl_putdata - write data into the packet, fragmenting and
- * starting another if this one is full.
+ * ctl_putdata - write data into the packet, fragmenting and starting
+ * another if this one is full.
*/
static void
ctl_putdata(
@@ -822,7 +881,8 @@ ctl_putdata(
if (datapt != rpkt.data) {
*datapt++ = ',';
datalinelen++;
- if ((dlen + datalinelen + 1) >= MAXDATALINELEN) {
+ if ((dlen + datalinelen + 1) >= MAXDATALINELEN)
+ {
*datapt++ = '\r';
*datapt++ = '\n';
datalinelen = 0;
@@ -842,7 +902,6 @@ ctl_putdata(
*/
ctl_flushpkt(CTL_MORE);
}
-
memmove((char *)datapt, dp, (unsigned)dlen);
datapt += dlen;
datalinelen += dlen;
@@ -867,7 +926,6 @@ ctl_putstr(
cq = tag;
while (*cq != '\0')
*cp++ = *cq++;
-
if (len > 0) {
*cp++ = '=';
*cp++ = '"';
@@ -877,7 +935,6 @@ ctl_putstr(
cp += len;
*cp++ = '"';
}
-
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -928,7 +985,6 @@ ctl_putuint(
(void) sprintf(cp, "%lu", uval);
while (*cp != '\0')
cp++;
-
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -955,7 +1011,6 @@ ctl_puthex(
(void) sprintf(cp, "0x%lx", uval);
while (*cp != '\0')
cp++;
-
ctl_putdata(buffer,(unsigned)( cp - buffer ), 0);
}
@@ -982,7 +1037,6 @@ ctl_putint(
(void) sprintf(cp, "%ld", ival);
while (*cp != '\0')
cp++;
-
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1010,7 +1064,6 @@ ctl_putts(
ts->l_uf & 0xffffffffL);
while (*cp != '\0')
cp++;
-
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1037,7 +1090,6 @@ ctl_putadr(
cq = numtoa(addr);
while (*cq != '\0')
*cp++ = *cq++;
-
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1064,7 +1116,6 @@ ctl_putid(
cq = id;
while (*cq != '\0' && (cq - id) < 4)
*cp++ = *cq++;
-
ctl_putdata(buffer, (unsigned)( cp - buffer ), 0);
}
@@ -1111,145 +1162,213 @@ ctl_putsys(
{
l_fp tmp;
#ifdef HAVE_UNAME
- char str[50];
+ char str[256];
#endif
switch (varid) {
- case CS_LEAP:
+
+ case CS_LEAP:
ctl_putuint(sys_var[CS_LEAP].text, sys_leap);
break;
- case CS_STRATUM:
+
+ case CS_STRATUM:
ctl_putuint(sys_var[CS_STRATUM].text, sys_stratum);
break;
- case CS_PRECISION:
+
+ case CS_PRECISION:
ctl_putint(sys_var[CS_PRECISION].text, sys_precision);
break;
- case CS_ROOTDELAY:
- ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay * 1e3);
+
+ case CS_ROOTDELAY:
+ ctl_putdbl(sys_var[CS_ROOTDELAY].text, sys_rootdelay *
+ 1e3);
break;
- case CS_ROOTDISPERSION:
+
+ case CS_ROOTDISPERSION:
ctl_putdbl(sys_var[CS_ROOTDISPERSION].text,
sys_rootdispersion * 1e3);
break;
- case CS_REFID:
+
+ case CS_REFID:
if (sys_stratum > 1)
ctl_putadr(sys_var[CS_REFID].text, sys_refid);
else
- ctl_putid(sys_var[CS_REFID].text, (char *)&sys_refid);
+ ctl_putid(sys_var[CS_REFID].text,
+ (char *)&sys_refid);
break;
- case CS_REFTIME:
+
+ case CS_REFTIME:
ctl_putts(sys_var[CS_REFTIME].text, &sys_reftime);
break;
- case CS_POLL:
+
+ case CS_POLL:
ctl_putuint(sys_var[CS_POLL].text, sys_poll);
break;
- case CS_PEERID:
+
+ case CS_PEERID:
if (sys_peer == NULL)
ctl_putuint(sys_var[CS_PEERID].text, 0);
else
ctl_putuint(sys_var[CS_PEERID].text,
sys_peer->associd);
break;
- case CS_STATE:
+
+ case CS_STATE:
ctl_putuint(sys_var[CS_STATE].text, (unsigned)state);
break;
- case CS_OFFSET:
+
+ case CS_OFFSET:
ctl_putdbl(sys_var[CS_OFFSET].text, last_offset * 1e3);
break;
- case CS_DRIFT:
+
+ case CS_DRIFT:
ctl_putdbl(sys_var[CS_DRIFT].text, drift_comp * 1e6);
break;
- case CS_COMPLIANCE:
- ctl_putdbl(sys_var[CS_COMPLIANCE].text, sys_error * 1e3);
+
+ case CS_JITTER:
+ ctl_putdbl(sys_var[CS_JITTER].text, sys_jitter * 1e3);
break;
- case CS_CLOCK:
+
+ case CS_CLOCK:
get_systime(&tmp);
ctl_putts(sys_var[CS_CLOCK].text, &tmp);
break;
- case CS_PROCESSOR:
+
+ case CS_PROCESSOR:
#ifndef HAVE_UNAME
ctl_putstr(sys_var[CS_PROCESSOR].text, str_processor,
- sizeof(str_processor) - 1);
+ sizeof(str_processor) - 1);
#else
- ctl_putstr(sys_var[CS_PROCESSOR].text, utsnamebuf.machine,
- strlen(utsnamebuf.machine));
+ ctl_putstr(sys_var[CS_PROCESSOR].text,
+ utsnamebuf.machine, strlen(utsnamebuf.machine));
#endif /* HAVE_UNAME */
break;
- case CS_SYSTEM:
+
+ case CS_SYSTEM:
#ifndef HAVE_UNAME
ctl_putstr(sys_var[CS_SYSTEM].text, str_system,
- sizeof(str_system) - 1);
+ sizeof(str_system) - 1);
#else
(void)strcpy(str, utsnamebuf.sysname);
(void)strcat(str, utsnamebuf.release);
ctl_putstr(sys_var[CS_SYSTEM].text, str, strlen(str));
#endif /* HAVE_UNAME */
break;
- case CS_STABIL:
- ctl_putdbl(sys_var[CS_STABIL].text, clock_stability * 1e6);
- break;
- case CS_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) - strlen(sys_var[CS_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name 8-( - Killer */
-
- strcpy(s, sys_var[CS_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
-
- for (k = sys_var; !(k->flags &EOV); k++)
- {
- if (k->flags & PADDING)
+
+ case CS_VERSION:
+ ctl_putstr(sys_var[CS_VERSION].text, Version,
+ strlen(Version));
+ break;
+
+ case CS_STABIL:
+ ctl_putdbl(sys_var[CS_STABIL].text, clock_stability *
+ 1e6);
+ break;
+
+ case CS_VARLIST:
+ {
+ char buf[CTL_MAX_DATA_LEN];
+ register char *s, *t, *be;
+ register const char *ss;
+ register int i;
+ register struct ctl_var *k;
+
+ s = buf;
+ be = buf + sizeof(buf) -
+ strlen(sys_var[CS_VARLIST].text) - 4;
+ if (s > be)
+ break; /* really long var name */
+
+ strcpy(s, sys_var[CS_VARLIST].text);
+ strcat(s, "=\"");
+ s += strlen(s);
+ t = s;
+ for (k = sys_var; !(k->flags &EOV); k++) {
+ if (k->flags & PADDING)
continue;
+ i = strlen(k->text);
+ if (s+i+1 >= be)
+ break;
- i = strlen(k->text);
- if (s+i+1 >= be)
- break;
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
+ if (s != t)
+ *s++ = ',';
+ strcpy(s, k->text);
+ s += i;
+ }
- for (k = ext_sys_var; k && !(k->flags &EOV); k++)
- {
- if (k->flags & PADDING)
+ for (k = ext_sys_var; k && !(k->flags &EOV);
+ k++) {
+ if (k->flags & PADDING)
continue;
- ss = k->text;
- if (!ss)
+ ss = k->text;
+ if (!ss)
continue;
- while (*ss && *ss != '=')
+ while (*ss && *ss != '=')
ss++;
-
- i = ss - k->text;
- if (s+i+1 >= be)
+ i = ss - k->text;
+ if (s + i + 1 >= be)
break;
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text, (unsigned)i);
- s += i;
- }
- if (s+2 >= be)
+ if (s != t)
+ *s++ = ',';
+ strncpy(s, k->text,
+ (unsigned)i);
+ s += i;
+ }
+ if (s+2 >= be)
break;
- *s++ = '"';
- *s = '\0';
+ *s++ = '"';
+ *s = '\0';
- ctl_putdata(buf, (unsigned)( s - buf ), 0);
- }
- break;
+ ctl_putdata(buf, (unsigned)( s - buf ),
+ 0);
+ }
+ break;
+
+#ifdef PUBKEY
+ case CS_FLAGS:
+ if (crypto_flags)
+ ctl_puthex(sys_var[CS_FLAGS].text,
+ crypto_flags);
+ break;
+
+ case CS_HOST:
+ ctl_putstr(sys_var[CS_HOST].text, sys_hostname,
+ strlen(sys_hostname));
+ if (host.fstamp != 0)
+ ctl_putuint(sys_var[CS_PUBLIC].text,
+ ntohl(host.fstamp));
+ break;
+
+ case CS_CERTIF:
+ if (certif.fstamp != 0)
+ ctl_putuint(sys_var[CS_CERTIF].text,
+ ntohl(certif.fstamp));
+ break;
+
+ case CS_DHPARAMS:
+ if (dhparam.fstamp != 0)
+ ctl_putuint(sys_var[CS_DHPARAMS].text,
+ ntohl(dhparam.fstamp));
+ break;
+
+ case CS_REVTIME:
+ if (host.tstamp != 0)
+ ctl_putuint(sys_var[CS_REVTIME].text,
+ ntohl(host.tstamp));
+ break;
+
+ case CS_LEAPTAB:
+ if (tai_leap.fstamp != 0)
+ ctl_putuint(sys_var[CS_LEAPTAB].text,
+ ntohl(tai_leap.fstamp));
+ if (sys_tai != 0)
+ ctl_putuint(sys_var[CS_TAI].text, sys_tai);
+ break;
+#endif /* PUBKEY */
}
}
@@ -1264,186 +1383,266 @@ ctl_putpeer(
)
{
switch (varid) {
- case CP_CONFIG:
+
+ case CP_CONFIG:
ctl_putuint(peer_var[CP_CONFIG].text,
- (unsigned)((peer->flags & FLAG_CONFIG) != 0));
+ (unsigned)((peer->flags & FLAG_CONFIG) != 0));
break;
- case CP_AUTHENABLE:
+
+ case CP_AUTHENABLE:
ctl_putuint(peer_var[CP_AUTHENABLE].text,
- (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
+ (unsigned)((peer->flags & FLAG_AUTHENABLE) != 0));
break;
- case CP_AUTHENTIC:
+
+ case CP_AUTHENTIC:
ctl_putuint(peer_var[CP_AUTHENTIC].text,
- (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
+ (unsigned)((peer->flags & FLAG_AUTHENTIC) != 0));
break;
- case CP_SRCADR:
+
+ case CP_SRCADR:
ctl_putadr(peer_var[CP_SRCADR].text,
- peer->srcadr.sin_addr.s_addr);
+ peer->srcadr.sin_addr.s_addr);
break;
- case CP_SRCPORT:
+
+ case CP_SRCPORT:
ctl_putuint(peer_var[CP_SRCPORT].text,
- ntohs(peer->srcadr.sin_port));
+ ntohs(peer->srcadr.sin_port));
break;
- case CP_DSTADR:
+
+ case CP_DSTADR:
ctl_putadr(peer_var[CP_DSTADR].text,
- peer->processed ?
- peer->cast_flags & MDF_BCAST ?
- peer->dstadr->bcast.sin_addr.s_addr:
- peer->cast_flags ?
- peer->dstadr->sin.sin_addr.s_addr ?
- peer->dstadr->sin.sin_addr.s_addr:
- peer->dstadr->bcast.sin_addr.s_addr:
- 8 : 12);
- break;
- case CP_DSTPORT:
+ peer->dstadr->sin.sin_addr.s_addr);
+ break;
+
+ case CP_DSTPORT:
ctl_putuint(peer_var[CP_DSTPORT].text,
- (u_long)(peer->dstadr
- ? ntohs(peer->dstadr->sin.sin_port)
- : 0
- )
- );
+ (u_long)(peer->dstadr ?
+ ntohs(peer->dstadr->sin.sin_port) : 0));
break;
- case CP_LEAP:
+
+ case CP_LEAP:
ctl_putuint(peer_var[CP_LEAP].text, peer->leap);
break;
- case CP_HMODE:
+
+ case CP_HMODE:
ctl_putuint(peer_var[CP_HMODE].text, peer->hmode);
break;
- case CP_STRATUM:
+
+ case CP_STRATUM:
ctl_putuint(peer_var[CP_STRATUM].text, peer->stratum);
break;
- case CP_PPOLL:
+
+ case CP_PPOLL:
ctl_putuint(peer_var[CP_PPOLL].text, peer->ppoll);
break;
- case CP_HPOLL:
+
+ case CP_HPOLL:
ctl_putuint(peer_var[CP_HPOLL].text, peer->hpoll);
break;
- case CP_PRECISION:
- ctl_putint(peer_var[CP_PRECISION].text, peer->precision);
+
+ case CP_PRECISION:
+ ctl_putint(peer_var[CP_PRECISION].text,
+ peer->precision);
break;
- case CP_ROOTDELAY:
- ctl_putdbl(peer_var[CP_ROOTDELAY].text, peer->rootdelay * 1e3);
+
+ case CP_ROOTDELAY:
+ ctl_putdbl(peer_var[CP_ROOTDELAY].text,
+ peer->rootdelay * 1e3);
break;
- case CP_ROOTDISPERSION:
+
+ case CP_ROOTDISPERSION:
ctl_putdbl(peer_var[CP_ROOTDISPERSION].text,
- peer->rootdispersion * 1e3);
+ peer->rootdispersion * 1e3);
break;
- case CP_REFID:
- if (peer->stratum > 1)
- {
+
+ case CP_REFID:
+ if (peer->stratum > 1) {
if (peer->flags & FLAG_REFCLOCK)
ctl_putadr(peer_var[CP_REFID].text,
- peer->srcadr.sin_addr.s_addr);
+ peer->srcadr.sin_addr.s_addr);
else
ctl_putadr(peer_var[CP_REFID].text,
- peer->refid);
- }
- else
+ peer->refid);
+ } else {
ctl_putid(peer_var[CP_REFID].text,
- (char *)&peer->refid);
+ (char *)&peer->refid);
+ }
break;
- case CP_REFTIME:
+
+ case CP_REFTIME:
ctl_putts(peer_var[CP_REFTIME].text, &peer->reftime);
break;
- case CP_ORG:
+
+ case CP_ORG:
ctl_putts(peer_var[CP_ORG].text, &peer->org);
break;
- case CP_REC:
+
+ case CP_REC:
ctl_putts(peer_var[CP_REC].text, &peer->rec);
break;
- case CP_XMT:
+
+ case CP_XMT:
ctl_putts(peer_var[CP_XMT].text, &peer->xmt);
break;
- case CP_REACH:
+
+ case CP_REACH:
ctl_puthex(peer_var[CP_REACH].text, peer->reach);
break;
- case CP_FLASH:
+
+ case CP_FLASH:
ctl_puthex(peer_var[CP_FLASH].text, peer->flash);
break;
- case CP_VALID:
- ctl_putuint(peer_var[CP_VALID].text, peer->valid);
+
+ case CP_TTL:
+ if (!(peer->cast_flags & MDF_ACAST))
+ break;
+ ctl_putint(peer_var[CP_TTL].text, peer->ttl);
break;
- case CP_TIMER:
+
+ case CP_TTLMAX:
+ if (!(peer->cast_flags & (MDF_MCAST | MDF_ACAST)))
+ break;
+ ctl_putint(peer_var[CP_TTLMAX].text, peer->ttlmax);
+ break;
+
+ case CP_VALID:
+ ctl_putuint(peer_var[CP_VALID].text, peer->unreach);
+ break;
+
+ case CP_TIMER:
ctl_putuint(peer_var[CP_TIMER].text,
peer->nextdate - current_time);
break;
- case CP_DELAY:
+
+ case CP_DELAY:
ctl_putdbl(peer_var[CP_DELAY].text, peer->delay * 1e3);
break;
- case CP_OFFSET:
- ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset * 1e3);
+
+ case CP_OFFSET:
+ ctl_putdbl(peer_var[CP_OFFSET].text, peer->offset *
+ 1e3);
break;
- case CP_JITTER:
+
+ case CP_JITTER:
ctl_putdbl(peer_var[CP_JITTER].text,
- SQRT(peer->variance) * 1e3);
+ SQRT(peer->jitter) * 1e3);
break;
- case CP_DISPERSION:
- ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp * 1e3);
+
+ case CP_DISPERSION:
+ ctl_putdbl(peer_var[CP_DISPERSION].text, peer->disp *
+ 1e3);
break;
- case CP_KEYID:
+
+ case CP_KEYID:
ctl_putuint(peer_var[CP_KEYID].text, peer->keyid);
break;
- case CP_FILTDELAY:
+
+ case CP_FILTDELAY:
ctl_putarray(peer_var[CP_FILTDELAY].text,
peer->filter_delay, (int)peer->filter_nextpt);
break;
- case CP_FILTOFFSET:
+
+ case CP_FILTOFFSET:
ctl_putarray(peer_var[CP_FILTOFFSET].text,
peer->filter_offset, (int)peer->filter_nextpt);
break;
- case CP_FILTERROR:
+
+ case CP_FILTERROR:
ctl_putarray(peer_var[CP_FILTERROR].text,
peer->filter_disp, (int)peer->filter_nextpt);
break;
- case CP_PMODE:
+
+ case CP_PMODE:
ctl_putuint(peer_var[CP_PMODE].text, peer->pmode);
break;
- case CP_RECEIVED:
+
+ case CP_RECEIVED:
ctl_putuint(peer_var[CP_RECEIVED].text, peer->received);
break;
- case CP_SENT:
+
+ case CP_SENT:
ctl_putuint(peer_var[CP_SENT].text, peer->sent);
break;
- case CP_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf) - strlen(peer_var[CP_VARLIST].text) - 4;
- if (s > be)
- break; /* really long var name 8-( - Killer */
-
- strcpy(s, peer_var[CP_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
-
- for (k = peer_var; !(k->flags &EOV); k++)
- {
- if (k->flags & PADDING)
+
+ case CP_VARLIST:
+ {
+ char buf[CTL_MAX_DATA_LEN];
+ register char *s, *t, *be;
+ register int i;
+ register struct ctl_var *k;
+
+ s = buf;
+ be = buf + sizeof(buf) -
+ strlen(peer_var[CP_VARLIST].text) - 4;
+ if (s > be)
+ break; /* really long var name */
+
+ strcpy(s, peer_var[CP_VARLIST].text);
+ strcat(s, "=\"");
+ s += strlen(s);
+ t = s;
+ for (k = peer_var; !(k->flags &EOV); k++) {
+ if (k->flags & PADDING)
continue;
- i = strlen(k->text);
- if (s+i+1 >= be)
- break;
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
+ i = strlen(k->text);
+ if (s + i + 1 >= be)
+ break;
- if (s+2 >= be)
+ if (s != t)
+ *s++ = ',';
+ strcpy(s, k->text);
+ s += i;
+ }
+ if (s+2 >= be)
break;
- *s++ = '"';
- *s = '\0';
+ *s++ = '"';
+ *s = '\0';
+ ctl_putdata(buf, (unsigned)(s - buf), 0);
+ }
+ break;
+#ifdef PUBKEY
+ case CP_FLAGS:
+ if (peer->crypto)
+ ctl_puthex(peer_var[CP_FLAGS].text, peer->crypto);
+ break;
- ctl_putdata(buf, (unsigned)(s - buf), 0);
- }
+ case CP_HOST:
+ if (peer->keystr != NULL)
+ ctl_putstr(peer_var[CP_HOST].text, peer->keystr,
+ strlen(peer->keystr));
+ if (peer->pubkey.fstamp != 0)
+ ctl_putuint(peer_var[CP_PUBLIC].text,
+ peer->pubkey.fstamp);
+ break;
+
+ case CP_CERTIF:
+ if (peer->certif.fstamp != 0)
+ ctl_putuint(peer_var[CP_CERTIF].text,
+ peer->certif.fstamp);
+ break;
+
+ case CP_SESKEY:
+ if (peer->pcookie.key != 0)
+ ctl_puthex(peer_var[CP_SESKEY].text,
+ peer->pcookie.key);
+ if (peer->hcookie != 0)
+ ctl_puthex(peer_var[CP_SASKEY].text,
+ peer->hcookie);
+ break;
+
+ case CP_INITSEQ:
+ if (peer->recauto.key == 0)
break;
+ ctl_putint(peer_var[CP_INITSEQ].text,
+ peer->recauto.seq);
+ ctl_puthex(peer_var[CP_INITKEY].text,
+ peer->recauto.key);
+ ctl_putuint(peer_var[CP_INITTSP].text,
+ peer->recauto.tstamp);
+ break;
+#endif /* PUBKEY */
}
}
@@ -1460,132 +1659,148 @@ ctl_putclock(
)
{
switch(varid) {
- case CC_TYPE:
+
+ case CC_TYPE:
if (mustput || clock_stat->clockdesc == NULL
|| *(clock_stat->clockdesc) == '\0') {
ctl_putuint(clock_var[CC_TYPE].text, clock_stat->type);
}
break;
- case CC_TIMECODE:
- ctl_putstr(clock_var[CC_TIMECODE].text, clock_stat->p_lastcode,
- (unsigned)clock_stat->lencode);
+ case CC_TIMECODE:
+ ctl_putstr(clock_var[CC_TIMECODE].text,
+ clock_stat->p_lastcode,
+ (unsigned)clock_stat->lencode);
break;
- case CC_POLL:
+
+ case CC_POLL:
ctl_putuint(clock_var[CC_POLL].text, clock_stat->polls);
break;
- case CC_NOREPLY:
- ctl_putuint(clock_var[CC_NOREPLY].text, clock_stat->noresponse);
+
+ case CC_NOREPLY:
+ ctl_putuint(clock_var[CC_NOREPLY].text,
+ clock_stat->noresponse);
break;
- case CC_BADFORMAT:
- ctl_putuint(clock_var[CC_BADFORMAT].text, clock_stat->badformat);
+
+ case CC_BADFORMAT:
+ ctl_putuint(clock_var[CC_BADFORMAT].text,
+ clock_stat->badformat);
break;
- case CC_BADDATA:
- ctl_putuint(clock_var[CC_BADDATA].text, clock_stat->baddata);
+
+ case CC_BADDATA:
+ ctl_putuint(clock_var[CC_BADDATA].text,
+ clock_stat->baddata);
break;
- case CC_FUDGETIME1:
- if (mustput || (clock_stat->haveflags & CLK_HAVETIME1)) {
+
+ case CC_FUDGETIME1:
+ if (mustput || (clock_stat->haveflags & CLK_HAVETIME1))
ctl_putdbl(clock_var[CC_FUDGETIME1].text,
- clock_stat->fudgetime1 * 1e3);
- }
+ clock_stat->fudgetime1 * 1e3);
break;
- case CC_FUDGETIME2:
- if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) {
- ctl_putdbl(clock_var[CC_FUDGETIME2].text,
- clock_stat->fudgetime2 * 1e3);
- }
+
+ case CC_FUDGETIME2:
+ if (mustput || (clock_stat->haveflags & CLK_HAVETIME2)) ctl_putdbl(clock_var[CC_FUDGETIME2].text,
+ clock_stat->fudgetime2 * 1e3);
break;
- case CC_FUDGEVAL1:
+
+ case CC_FUDGEVAL1:
if (mustput || (clock_stat->haveflags & CLK_HAVEVAL1))
ctl_putint(clock_var[CC_FUDGEVAL1].text,
- clock_stat->fudgeval1);
+ clock_stat->fudgeval1);
break;
- case CC_FUDGEVAL2:
+
+ case CC_FUDGEVAL2:
if (mustput || (clock_stat->haveflags & CLK_HAVEVAL2)) {
if (clock_stat->fudgeval1 > 1)
- ctl_putadr(clock_var[CC_FUDGEVAL2].text,
- (u_int32)clock_stat->fudgeval2);
+ ctl_putadr(clock_var[CC_FUDGEVAL2].text,
+ (u_int32)clock_stat->fudgeval2);
else
- ctl_putid(clock_var[CC_FUDGEVAL2].text,
- (char *)&clock_stat->fudgeval2);
+ ctl_putid(clock_var[CC_FUDGEVAL2].text,
+ (char *)&clock_stat->fudgeval2);
}
break;
- case CC_FLAGS:
- if (mustput || (clock_stat->haveflags &
- (CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4)))
- ctl_putuint(clock_var[CC_FLAGS].text, clock_stat->flags);
+
+ case CC_FLAGS:
+ if (mustput || (clock_stat->haveflags & (CLK_HAVEFLAG1 |
+ CLK_HAVEFLAG2 | CLK_HAVEFLAG3 | CLK_HAVEFLAG4)))
+ ctl_putuint(clock_var[CC_FLAGS].text,
+ clock_stat->flags);
break;
- case CC_DEVICE:
- if (clock_stat->clockdesc == NULL || *(clock_stat->clockdesc) == '\0') {
+
+ case CC_DEVICE:
+ if (clock_stat->clockdesc == NULL ||
+ *(clock_stat->clockdesc) == '\0') {
if (mustput)
- ctl_putstr(clock_var[CC_DEVICE].text, "", 0);
+ ctl_putstr(clock_var[CC_DEVICE].text,
+ "", 0);
} else {
- ctl_putstr(clock_var[CC_DEVICE].text, clock_stat->clockdesc,
- strlen(clock_stat->clockdesc));
+ ctl_putstr(clock_var[CC_DEVICE].text,
+ clock_stat->clockdesc,
+ strlen(clock_stat->clockdesc));
}
break;
- case CC_VARLIST:
- {
- char buf[CTL_MAX_DATA_LEN];
- register char *s, *t, *be;
- register const char *ss;
- register int i;
- register struct ctl_var *k;
-
- s = buf;
- be = buf + sizeof(buf);
- if (s + strlen(clock_var[CC_VARLIST].text) + 4 > be)
- break; /* really long var name 8-( - Killer */
-
- strcpy(s, clock_var[CC_VARLIST].text);
- strcat(s, "=\"");
- s += strlen(s);
- t = s;
-
- for (k = clock_var; !(k->flags &EOV); k++)
- {
- if (k->flags & PADDING)
+
+ case CC_VARLIST:
+ {
+ char buf[CTL_MAX_DATA_LEN];
+ register char *s, *t, *be;
+ register const char *ss;
+ register int i;
+ register struct ctl_var *k;
+
+ s = buf;
+ be = buf + sizeof(buf);
+ if (s + strlen(clock_var[CC_VARLIST].text) + 4 >
+ be)
+ break; /* really long var name */
+
+ strcpy(s, clock_var[CC_VARLIST].text);
+ strcat(s, "=\"");
+ s += strlen(s);
+ t = s;
+
+ for (k = clock_var; !(k->flags &EOV); k++) {
+ if (k->flags & PADDING)
continue;
- i = strlen(k->text);
- if (s+i+1 >= be)
+ i = strlen(k->text);
+ if (s + i + 1 >= be)
break;
- if (s != t)
- *s++ = ',';
- strcpy(s, k->text);
- s += i;
- }
- for (k = clock_stat->kv_list; k && !(k->flags &EOV); k++)
- {
- if (k->flags & PADDING)
+ if (s != t)
+ *s++ = ',';
+ strcpy(s, k->text);
+ s += i;
+ }
+
+ for (k = clock_stat->kv_list; k && !(k->flags &
+ EOV); k++) {
+ if (k->flags & PADDING)
continue;
- ss = k->text;
- if (!ss)
+ ss = k->text;
+ if (!ss)
continue;
- while (*ss && *ss != '=')
+ while (*ss && *ss != '=')
ss++;
-
- i = ss - k->text;
- if (s+i+1 >= be)
+ i = ss - k->text;
+ if (s+i+1 >= be)
break;
- if (s != t)
- *s++ = ',';
- strncpy(s, k->text, (unsigned)i);
- s += i;
- *s = '\0';
- }
-
- if (s+2 >= be)
- break;
- *s++ = '"';
+ if (s != t)
+ *s++ = ',';
+ strncpy(s, k->text, (unsigned)i);
+ s += i;
*s = '\0';
-
- ctl_putdata(buf, (unsigned)( s - buf ), 0);
}
- break;
+ if (s+2 >= be)
+ break;
+
+ *s++ = '"';
+ *s = '\0';
+ ctl_putdata(buf, (unsigned)( s - buf ), 0);
+ }
+ break;
}
}
#endif
@@ -1610,15 +1825,14 @@ ctl_getitem(
/*
* Delete leading commas and white space
*/
- while (reqpt < reqend && (*reqpt == ',' || isspace((int)*reqpt))) {
+ while (reqpt < reqend && (*reqpt == ',' ||
+ isspace((int)*reqpt)))
reqpt++;
- }
-
if (reqpt >= reqend)
- return 0;
+ return (0);
if (var_list == (struct ctl_var *)0)
- return &eol;
+ return (&eol);
/*
* Look for a first character match on the tag. If we find
@@ -1629,7 +1843,8 @@ ctl_getitem(
while (!(v->flags & EOV)) {
if (!(v->flags & PADDING) && *cp == *(v->text)) {
tp = v->text;
- while (*tp != '\0' && *tp != '=' && cp < reqend && *cp == *tp) {
+ while (*tp != '\0' && *tp != '=' && cp <
+ reqend && *cp == *tp) {
cp++;
tp++;
}
@@ -1649,16 +1864,29 @@ ctl_getitem(
tp = buf;
while (cp < reqend && isspace((int)*cp))
cp++;
- while (cp < reqend && *cp != ',')
+ while (cp < reqend && *cp != ',') {
*tp++ = *cp++;
+ if (tp >= buf + sizeof(buf)) {
+ ctl_error(CERR_BADFMT);
+ numctlbadpkts++;
+ msyslog(LOG_WARNING,
+ "Possible 'ntpdx' exploit from %s:%d (possibly spoofed)\n",
+ inet_ntoa(rmt_addr->sin_addr), ntohs(rmt_addr->sin_port)
+ );
+ return (0);
+ }
+ }
if (cp < reqend)
cp++;
- *tp = '\0';
- while (isspace((int)(*(tp-1))))
- *(--tp) = '\0';
+ *tp-- = '\0';
+ while (tp > buf) {
+ *tp-- = '\0';
+ if (!isspace((int)(*tp)))
+ break;
+ }
reqpt = cp;
*data = buf;
- return v;
+ return (v);
}
}
cp = reqpt;
@@ -1687,7 +1915,7 @@ control_unspec(
* doesn't exist.
*/
if (res_associd != 0) {
- if ((peer = findpeerbyassoc((int)res_associd)) == 0) {
+ if ((peer = findpeerbyassoc(res_associd)) == 0) {
ctl_error(CERR_BADASSOC);
return;
}
@@ -1701,7 +1929,7 @@ control_unspec(
/*
* read_status - return either a list of associd's, or a particular
- * peer's status.
+ * peer's status.
*/
/*ARGSUSED*/
static void
@@ -1712,14 +1940,14 @@ read_status(
{
register int i;
register struct peer *peer;
- u_short ass_stat[CTL_MAX_DATA_LEN/sizeof(u_short)];
+ u_short ass_stat[CTL_MAX_DATA_LEN / sizeof(u_short)];
#ifdef DEBUG
- if (debug >= 2)
+ if (debug > 2)
printf("read_status: ID %d\n", res_associd);
#endif
/*
- * Two choices here. If the specified association ID is
+ * Two choices here. If the specified association ID is
* zero we return all known assocation ID's. Otherwise
* we return a bunch of stuff about the particular peer.
*/
@@ -1730,22 +1958,25 @@ read_status(
rpkt.status = htons(ctlsysstatus());
for (i = 0; i < HASH_SIZE; i++) {
for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
+ peer = peer->ass_next) {
ass_stat[n++] = htons(peer->associd);
- ass_stat[n++] = htons(ctlpeerstatus(peer));
- if (n == CTL_MAX_DATA_LEN/sizeof(u_short)) {
+ ass_stat[n++] =
+ htons(ctlpeerstatus(peer));
+ if (n ==
+ CTL_MAX_DATA_LEN/sizeof(u_short)) {
ctl_putdata((char *)ass_stat,
- n * sizeof(u_short), 1);
+ n * sizeof(u_short), 1);
n = 0;
}
}
}
if (n != 0)
- ctl_putdata((char *)ass_stat, n * sizeof(u_short), 1);
+ ctl_putdata((char *)ass_stat, n *
+ sizeof(u_short), 1);
ctl_flushpkt(0);
} else {
- peer = findpeerbyassoc((int)res_associd);
+ peer = findpeerbyassoc(res_associd);
if (peer == 0) {
ctl_error(CERR_BADASSOC);
} else {
@@ -1755,8 +1986,8 @@ read_status(
if (res_authokay)
peer->num_events = 0;
/*
- * For now, output everything we know about the peer.
- * May be more selective later.
+ * For now, output everything we know about the
+ * peer. May be more selective later.
*/
for (cp = def_peer_var; *cp != 0; cp++)
ctl_putpeer((int)*cp, peer);
@@ -1780,11 +2011,11 @@ read_variables(
register int i;
char *valuep;
u_char *wants;
- unsigned int gotvar = (CS_MAXCODE>CP_MAXCODE) ? (CS_MAXCODE+1) : (CP_MAXCODE+1);
-
+ unsigned int gotvar = (CS_MAXCODE > CP_MAXCODE) ? (CS_MAXCODE +
+ 1) : (CP_MAXCODE + 1);
if (res_associd == 0) {
/*
- * Wants system variables. Figure out which he wants
+ * Wants system variables. Figure out which he wants
* and give them to him.
*/
rpkt.status = htons(ctlsysstatus());
@@ -1796,13 +2027,15 @@ read_variables(
gotvar = 0;
while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
if (v->flags & EOV) {
- if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) {
+ if ((v = ctl_getitem(ext_sys_var,
+ &valuep)) != 0) {
if (v->flags & EOV) {
ctl_error(CERR_UNKNOWNVAR);
free((char *)wants);
return;
}
- wants[CS_MAXCODE+1+v->code] = 1;
+ wants[CS_MAXCODE + 1 +
+ v->code] = 1;
gotvar = 1;
continue;
} else {
@@ -1815,35 +2048,38 @@ read_variables(
if (gotvar) {
for (i = 1; i <= CS_MAXCODE; i++)
if (wants[i])
- ctl_putsys(i);
- for (i = 0; ext_sys_var && !(ext_sys_var[i].flags & EOV); i++)
- if (wants[i+CS_MAXCODE+1])
- ctl_putdata(ext_sys_var[i].text,
- strlen(ext_sys_var[i].text), 0);
+ ctl_putsys(i);
+ for (i = 0; ext_sys_var &&
+ !(ext_sys_var[i].flags & EOV); i++)
+ if (wants[i + CS_MAXCODE + 1])
+ ctl_putdata(ext_sys_var[i].text,
+ strlen(ext_sys_var[i].text),
+ 0);
} else {
register u_char *cs;
register struct ctl_var *kv;
for (cs = def_sys_var; *cs != 0; cs++)
ctl_putsys((int)*cs);
- for (kv = ext_sys_var; kv && !(kv->flags & EOV); kv++)
+ for (kv = ext_sys_var; kv && !(kv->flags & EOV);
+ kv++)
if (kv->flags & DEF)
- ctl_putdata(kv->text, strlen(kv->text), 0);
+ ctl_putdata(kv->text,
+ strlen(kv->text), 0);
}
free((char *)wants);
} else {
register struct peer *peer;
/*
- * Wants info for a particular peer. See if we know
+ * Wants info for a particular peer. See if we know
* the guy.
*/
- peer = findpeerbyassoc((int)res_associd);
+ peer = findpeerbyassoc(res_associd);
if (peer == 0) {
ctl_error(CERR_BADASSOC);
return;
}
-
rpkt.status = htons(ctlpeerstatus(peer));
if (res_authokay)
peer->num_events = 0;
@@ -1862,7 +2098,7 @@ read_variables(
if (gotvar) {
for (i = 1; i <= CP_MAXCODE; i++)
if (wants[i])
- ctl_putpeer(i, peer);
+ ctl_putpeer(i, peer);
} else {
register u_char *cp;
@@ -1876,8 +2112,8 @@ read_variables(
/*
- * write_variables - write into variables. We only allow leap bit writing
- * this way.
+ * write_variables - write into variables. We only allow leap bit
+ * writing this way.
*/
/*ARGSUSED*/
static void
@@ -1890,7 +2126,6 @@ write_variables(
register int ext_var;
char *valuep;
long val;
- /*int leapind, leapwarn;*/
/*
* If he's trying to write into a peer tell him no way
@@ -1906,20 +2141,14 @@ write_variables(
rpkt.status = htons(ctlsysstatus());
/*
- * Set flags to not-in-sync so we can tell when we get something.
- */
- /*
- leapind = ~0;
- leapwarn = ~0;
- */
-
- /*
- * Look through the variables. Dump out at the first sign of trouble.
+ * Look through the variables. Dump out at the first sign of
+ * trouble.
*/
while ((v = ctl_getitem(sys_var, &valuep)) != 0) {
ext_var = 0;
if (v->flags & EOV) {
- if ((v = ctl_getitem(ext_sys_var, &valuep)) != 0) {
+ if ((v = ctl_getitem(ext_sys_var, &valuep)) !=
+ 0) {
if (v->flags & EOV) {
ctl_error(CERR_UNKNOWNVAR);
return;
@@ -1933,7 +2162,8 @@ write_variables(
ctl_error(CERR_PERMISSION);
return;
}
- if (!ext_var && (*valuep == '\0' || !atoint(valuep, &val))) {
+ if (!ext_var && (*valuep == '\0' || !atoint(valuep,
+ &val))) {
ctl_error(CERR_BADFMT);
return;
}
@@ -1943,7 +2173,8 @@ write_variables(
}
if (ext_var) {
- char *s = (char *)emalloc(strlen(v->text)+strlen(valuep)+2);
+ char *s = (char *)emalloc(strlen(v->text) +
+ strlen(valuep) + 2);
const char *t;
char *tt = s;
@@ -1953,24 +2184,24 @@ write_variables(
*tt++ = '=';
strcat(tt, valuep);
-
set_sys_var(s, strlen(s)+1, v->flags);
free(s);
} else {
/*
- * This one seems sane. Save it.
+ * This one seems sane. Save it.
*/
switch(v->code) {
- case CS_LEAP:
- default:
- ctl_error(CERR_UNSPEC); /* our fault, really */
+
+ case CS_LEAP:
+ default:
+ ctl_error(CERR_UNSPEC); /* really */
return;
}
}
}
/*
- * If we got anything, do it.
+ * If we got anything, do it. xxx nothing to do ***
*/
/*
if (leapind != ~0 || leapwarn != ~0) {
@@ -2009,18 +2240,20 @@ read_clock_status(
struct refclockstat clock_stat;
if (res_associd == 0) {
+
/*
* Find a clock for this jerk. If the system peer
* is a clock use it, else search the hash tables
* for one.
*/
- if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK)) {
+ if (sys_peer != 0 && (sys_peer->flags & FLAG_REFCLOCK))
+ {
peer = sys_peer;
} else {
peer = 0;
for (i = 0; peer == 0 && i < HASH_SIZE; i++) {
for (peer = assoc_hash[i]; peer != 0;
- peer = peer->ass_next) {
+ peer = peer->ass_next) {
if (peer->flags & FLAG_REFCLOCK)
break;
}
@@ -2031,7 +2264,7 @@ read_clock_status(
}
}
} else {
- peer = findpeerbyassoc((int)res_associd);
+ peer = findpeerbyassoc(res_associd);
if (peer == 0 || !(peer->flags & FLAG_REFCLOCK)) {
ctl_error(CERR_BADASSOC);
return;
@@ -2039,30 +2272,32 @@ read_clock_status(
}
/*
- * If we got here we have a peer which is a clock. Get his status.
+ * If we got here we have a peer which is a clock. Get his
+ * status.
*/
clock_stat.kv_list = (struct ctl_var *)0;
-
- refclock_control(&peer->srcadr, (struct refclockstat *)0, &clock_stat);
+ refclock_control(&peer->srcadr, (struct refclockstat *)0,
+ &clock_stat);
/*
* Look for variables in the packet.
*/
rpkt.status = htons(ctlclkstatus(&clock_stat));
- gotvar = CC_MAXCODE+1+count_var(clock_stat.kv_list);
+ gotvar = CC_MAXCODE + 1 + count_var(clock_stat.kv_list);
wants = (u_char *)emalloc(gotvar);
memset((char*)wants, 0, gotvar);
gotvar = 0;
while ((v = ctl_getitem(clock_var, &valuep)) != 0) {
if (v->flags & EOV) {
- if ((v = ctl_getitem(clock_stat.kv_list, &valuep)) != 0) {
+ if ((v = ctl_getitem(clock_stat.kv_list,
+ &valuep)) != 0) {
if (v->flags & EOV) {
ctl_error(CERR_UNKNOWNVAR);
free((char*)wants);
free_varlist(clock_stat.kv_list);
return;
}
- wants[CC_MAXCODE+1+v->code] = 1;
+ wants[CC_MAXCODE + 1 + v->code] = 1;
gotvar = 1;
continue;
} else {
@@ -2077,19 +2312,23 @@ read_clock_status(
for (i = 1; i <= CC_MAXCODE; i++)
if (wants[i])
ctl_putclock(i, &clock_stat, 1);
- for (i = 0; clock_stat.kv_list && !(clock_stat.kv_list[i].flags & EOV); i++)
- if (wants[i+CC_MAXCODE+1])
- ctl_putdata(clock_stat.kv_list[i].text,
- strlen(clock_stat.kv_list[i].text), 0);
+ for (i = 0; clock_stat.kv_list &&
+ !(clock_stat.kv_list[i].flags & EOV); i++)
+ if (wants[i + CC_MAXCODE + 1])
+ ctl_putdata(clock_stat.kv_list[i].text,
+ strlen(clock_stat.kv_list[i].text),
+ 0);
} else {
register u_char *cc;
register struct ctl_var *kv;
for (cc = def_clock_var; *cc != 0; cc++)
ctl_putclock((int)*cc, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++)
+ for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV);
+ kv++)
if (kv->flags & DEF)
- ctl_putdata(kv->text, strlen(kv->text), 0);
+ ctl_putdata(kv->text, strlen(kv->text),
+ 0);
}
free((char*)wants);
@@ -2114,11 +2353,10 @@ write_clock_status(
}
/*
- * Trap support from here on down. We send async trap messages when the
- * upper levels report trouble. Traps can by set either by control
+ * Trap support from here on down. We send async trap messages when the
+ * upper levels report trouble. Traps can by set either by control
* messages or by configuration.
*/
-
/*
* set_trap - set a trap in response to a control message
*/
@@ -2150,7 +2388,7 @@ set_trap(
* an error if it can't assign the trap.
*/
if (!ctlsettrap(&rbufp->recv_srcadr, rbufp->dstadr, traptype,
- (int)res_version))
+ (int)res_version))
ctl_error(CERR_NORESOURCE);
ctl_flushpkt(0);
}
@@ -2168,11 +2406,10 @@ unset_trap(
int traptype;
/*
- * We don't prevent anyone from removing his own
- * trap unless the trap is configured. Note we also
- * must be aware of the possibility that restriction
- * flags were changed since this guy last set his trap.
- * Set the trap type based on this.
+ * We don't prevent anyone from removing his own trap unless the
+ * trap is configured. Note we also must be aware of the
+ * possibility that restriction flags were changed since this
+ * guy last set his trap. Set the trap type based on this.
*/
traptype = TRAP_TYPE_PRIO;
if (restrict_mask & RES_LPTRAP)
@@ -2207,69 +2444,77 @@ ctlsettrap(
*/
if ((tp = ctlfindtrap(raddr, linter)) != NULL) {
switch (traptype) {
- case TRAP_TYPE_CONFIG:
+
+ case TRAP_TYPE_CONFIG:
tp->tr_flags = TRAP_INUSE|TRAP_CONFIGURED;
break;
- case TRAP_TYPE_PRIO:
+
+ case TRAP_TYPE_PRIO:
if (tp->tr_flags & TRAP_CONFIGURED)
- return 1; /* don't change anything */
+ return (1); /* don't change anything */
tp->tr_flags = TRAP_INUSE;
break;
- case TRAP_TYPE_NONPRIO:
+
+ case TRAP_TYPE_NONPRIO:
if (tp->tr_flags & TRAP_CONFIGURED)
- return 1; /* don't change anything */
+ return (1); /* don't change anything */
tp->tr_flags = TRAP_INUSE|TRAP_NONPRIO;
break;
}
tp->tr_settime = current_time;
tp->tr_resets++;
- return 1;
+ return (1);
}
/*
* First we heard of this guy. Try to find a trap structure
* for him to use, clearing out lesser priority guys if we
- * have to. Clear out anyone who's expired while we're at it.
+ * have to. Clear out anyone who's expired while we're at it.
*/
tptouse = NULL;
for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
if ((tp->tr_flags & TRAP_INUSE) &&
- !(tp->tr_flags & TRAP_CONFIGURED) &&
- ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
+ !(tp->tr_flags & TRAP_CONFIGURED) &&
+ ((tp->tr_settime + CTL_TRAPTIME) > current_time)) {
tp->tr_flags = 0;
num_ctl_traps--;
}
-
if (!(tp->tr_flags & TRAP_INUSE)) {
tptouse = tp;
} else if (!(tp->tr_flags & TRAP_CONFIGURED)) {
switch (traptype) {
- case TRAP_TYPE_CONFIG:
+
+ case TRAP_TYPE_CONFIG:
if (tptouse == NULL) {
tptouse = tp;
break;
}
- if (tptouse->tr_flags & TRAP_NONPRIO
- && !(tp->tr_flags & TRAP_NONPRIO))
+ if (tptouse->tr_flags & TRAP_NONPRIO &&
+ !(tp->tr_flags & TRAP_NONPRIO))
break;
+
if (!(tptouse->tr_flags & TRAP_NONPRIO)
- && tp->tr_flags & TRAP_NONPRIO) {
+ && tp->tr_flags & TRAP_NONPRIO) {
tptouse = tp;
break;
}
- if (tptouse->tr_origtime < tp->tr_origtime)
+ if (tptouse->tr_origtime <
+ tp->tr_origtime)
tptouse = tp;
break;
- case TRAP_TYPE_PRIO:
+
+ case TRAP_TYPE_PRIO:
if (tp->tr_flags & TRAP_NONPRIO) {
if (tptouse == NULL ||
- (tptouse->tr_flags & TRAP_INUSE
- && tptouse->tr_origtime
- < tp->tr_origtime))
+ (tptouse->tr_flags &
+ TRAP_INUSE &&
+ tptouse->tr_origtime <
+ tp->tr_origtime))
tptouse = tp;
}
break;
- case TRAP_TYPE_NONPRIO:
+
+ case TRAP_TYPE_NONPRIO:
break;
}
}
@@ -2279,7 +2524,7 @@ ctlsettrap(
* If we don't have room for him return an error.
*/
if (tptouse == NULL)
- return 0;
+ return (0);
/*
* Set up this structure for him.
@@ -2290,19 +2535,18 @@ ctlsettrap(
tptouse->tr_addr = *raddr;
tptouse->tr_localaddr = linter;
tptouse->tr_version = version;
-
tptouse->tr_flags = TRAP_INUSE;
if (traptype == TRAP_TYPE_CONFIG)
tptouse->tr_flags |= TRAP_CONFIGURED;
else if (traptype == TRAP_TYPE_NONPRIO)
tptouse->tr_flags |= TRAP_NONPRIO;
num_ctl_traps++;
- return 1;
+ return (1);
}
/*
- * ctlclrtrap - called to clr a trap
+ * ctlclrtrap - called to clear a trap
*/
int
ctlclrtrap(
@@ -2314,15 +2558,15 @@ ctlclrtrap(
register struct ctl_trap *tp;
if ((tp = ctlfindtrap(raddr, linter)) == NULL)
- return 0;
+ return (0);
if (tp->tr_flags & TRAP_CONFIGURED
&& traptype != TRAP_TYPE_CONFIG)
- return 0;
+ return (0);
tp->tr_flags = 0;
num_ctl_traps--;
- return 1;
+ return (1);
}
@@ -2338,11 +2582,11 @@ ctlfindtrap(
register struct ctl_trap *tp;
for (tp = ctl_trap; tp < &ctl_trap[CTL_MAXTRAPS]; tp++) {
- if (tp->tr_flags & TRAP_INUSE
- && NSRCADR(raddr) == NSRCADR(&tp->tr_addr)
- && NSRCPORT(raddr) == NSRCPORT(&tp->tr_addr)
- && linter == tp->tr_localaddr)
- return tp;
+ if (tp->tr_flags & TRAP_INUSE && NSRCADR(raddr) ==
+ NSRCADR(&tp->tr_addr) && NSRCPORT(raddr) ==
+ NSRCPORT(&tp->tr_addr) && linter ==
+ tp->tr_localaddr)
+ return (tp);
}
return (struct ctl_trap *)NULL;
}
@@ -2368,14 +2612,15 @@ report_event(
ctl_sys_num_events++;
if (ctl_sys_last_event != (u_char)err) {
NLOG(NLOG_SYSEVENT)
- msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()), ctlsysstatus());
+ msyslog(LOG_INFO, "system event '%s' (0x%02x) status '%s' (0x%02x)",
+ eventstr(err), err,
+ sysstatstr(ctlsysstatus()), ctlsysstatus());
#ifdef DEBUG
if (debug)
printf("report_event: system event '%s' (0x%02x) status '%s' (0x%02x)\n",
- eventstr(err), err,
- sysstatstr(ctlsysstatus()), ctlsysstatus());
+ eventstr(err), err,
+ sysstatstr(ctlsysstatus()),
+ ctlsysstatus());
#endif
ctl_sys_last_event = (u_char)err;
}
@@ -2393,19 +2638,25 @@ report_event(
if (peer->num_events < CTL_PEER_MAXEVENTS)
peer->num_events++;
NLOG(NLOG_PEEREVENT)
- msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)), ctlpeerstatus(peer));
+ msyslog(LOG_INFO, "peer %s event '%s' (0x%02x) status '%s' (0x%02x)",
+ src, eventstr(err), err,
+ peerstatstr(ctlpeerstatus(peer)),
+ ctlpeerstatus(peer));
#ifdef DEBUG
if (debug)
printf( "peer %s event '%s' (0x%02x) status '%s' (0x%02x)\n",
- src, eventstr(err), err,
- peerstatstr(ctlpeerstatus(peer)), ctlpeerstatus(peer));
+ src, eventstr(err), err,
+ peerstatstr(ctlpeerstatus(peer)),
+ ctlpeerstatus(peer));
#endif
} else {
- msyslog(LOG_ERR, "report_event: err '%s' (0x%02x), no peer", eventstr(err), err);
+ msyslog(LOG_ERR,
+ "report_event: err '%s' (0x%02x), no peer",
+ eventstr(err), err);
#ifdef DEBUG
- printf("report_event: peer event '%s' (0x%02x), no peer\n", eventstr(err), err);
+ printf(
+ "report_event: peer event '%s' (0x%02x), no peer\n",
+ eventstr(err), err);
#endif
return;
}
@@ -2425,38 +2676,42 @@ report_event(
res_authenticate = 0;
datapt = rpkt.data;
dataend = &(rpkt.data[CTL_MAX_DATA_LEN]);
-
if (!(err & PEER_EVENT)) {
rpkt.associd = 0;
rpkt.status = htons(ctlsysstatus());
/*
* For now, put everything we know about system
- * variables. Maybe more selective later
+ * variables. Don't send crypto strings.
*/
- for (i = 1; i <= CS_MAXCODE; i++)
+ for (i = 1; i <= CS_MAXCODE; i++) {
+#ifdef PUBKEY
+ if (i > CS_VARLIST)
+ continue;
+#endif /* PUBKEY */
ctl_putsys(i);
+ }
#ifdef REFCLOCK
/*
- * for clock exception events:
- * add clock variables to reflect info on exception
+ * for clock exception events: add clock variables to
+ * reflect info on exception
*/
if (err == EVNT_CLOCKEXCPT) {
struct refclockstat clock_stat;
struct ctl_var *kv;
clock_stat.kv_list = (struct ctl_var *)0;
-
refclock_control(&peer->srcadr,
- (struct refclockstat *)0, &clock_stat);
- ctl_puthex("refclockstatus", ctlclkstatus(&clock_stat));
-
+ (struct refclockstat *)0, &clock_stat);
+ ctl_puthex("refclockstatus",
+ ctlclkstatus(&clock_stat));
for (i = 1; i <= CC_MAXCODE; i++)
ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++)
+ for (kv = clock_stat.kv_list; kv &&
+ !(kv->flags & EOV); kv++)
if (kv->flags & DEF)
- ctl_putdata(kv->text, strlen(kv->text), 0);
-
+ ctl_putdata(kv->text,
+ strlen(kv->text), 0);
free_varlist(clock_stat.kv_list);
}
#endif /*REFCLOCK*/
@@ -2465,34 +2720,37 @@ report_event(
rpkt.status = htons(ctlpeerstatus(peer));
/*
- * Dump it all. Later, maybe less.
+ * Dump it all. Later, maybe less.
*/
for (i = 1; i <= CP_MAXCODE; i++)
+#ifdef PUBKEY
+ if (i > CP_VARLIST)
+ continue;
+#endif /* PUBKEY */
ctl_putpeer(i, peer);
#ifdef REFCLOCK
/*
- * for clock exception events:
- * add clock variables to reflect info on exception
+ * for clock exception events: add clock variables to
+ * reflect info on exception
*/
if (err == EVNT_PEERCLOCK) {
struct refclockstat clock_stat;
struct ctl_var *kv;
clock_stat.kv_list = (struct ctl_var *)0;
-
refclock_control(&peer->srcadr,
- (struct refclockstat *)0,
- &clock_stat);
+ (struct refclockstat *)0, &clock_stat);
ctl_puthex("refclockstatus",
- ctlclkstatus(&clock_stat));
+ ctlclkstatus(&clock_stat));
for (i = 1; i <= CC_MAXCODE; i++)
ctl_putclock(i, &clock_stat, 0);
- for (kv = clock_stat.kv_list; kv && !(kv->flags & EOV); kv++)
+ for (kv = clock_stat.kv_list; kv &&
+ !(kv->flags & EOV); kv++)
if (kv->flags & DEF)
- ctl_putdata(kv->text, strlen(kv->text), 0);
-
+ ctl_putdata(kv->text,
+ strlen(kv->text), 0);
free_varlist(clock_stat.kv_list);
}
#endif /*REFCLOCK*/
@@ -2537,14 +2795,12 @@ count_var(
register u_long c;
if (!k)
- return 0;
+ return (0);
c = 0;
-
while (!(k++->flags & EOV))
- c++;
-
- return c;
+ c++;
+ return (c);
}
char *
@@ -2561,12 +2817,11 @@ add_var(
k = *kv;
*kv = (struct ctl_var *)emalloc((c+2)*sizeof(struct ctl_var));
- if (k)
- {
- memmove((char *)*kv, (char *)k, sizeof(struct ctl_var)*c);
+ if (k) {
+ memmove((char *)*kv, (char *)k,
+ sizeof(struct ctl_var)*c);
free((char *)k);
}
-
(*kv)[c].code = (u_short) c;
(*kv)[c].text = (char *)emalloc(size);
(*kv)[c].flags = def;
@@ -2592,21 +2847,16 @@ set_var(
if (!data || !size)
return;
- if ((k = *kv))
- {
- while (!(k->flags & EOV))
- {
+ if ((k = *kv)) {
+ while (!(k->flags & EOV)) {
s = data;
t = k->text;
- if (t)
- {
- while (*t != '=' && *s - *t == 0)
- {
+ if (t) {
+ while (*t != '=' && *s - *t == 0) {
s++;
t++;
}
- if (*s == *t && ((*t == '=') || !*t))
- {
+ if (*s == *t && ((*t == '=') || !*t)) {
free((void *)k->text);
td = (char *)emalloc(size);
memmove(td, data, size);
@@ -2614,9 +2864,7 @@ set_var(
k->flags = def;
return;
}
- }
- else
- {
+ } else {
td = (char *)emalloc(size);
memmove(td, data, size);
k->text = td;
@@ -2646,10 +2894,9 @@ free_varlist(
)
{
struct ctl_var *k;
- if (kv)
- {
+ if (kv) {
for (k = kv; !(k->flags & EOV); k++)
- free((void *)k->text);
+ free((void *)k->text);
free((void *)kv);
}
}
diff --git a/contrib/ntp/ntpd/ntp_crypto.c b/contrib/ntp/ntpd/ntp_crypto.c
new file mode 100644
index 0000000..d8516b5
--- /dev/null
+++ b/contrib/ntp/ntpd/ntp_crypto.c
@@ -0,0 +1,2060 @@
+/*
+ * ntp_crypto.c - NTP version 4 public key routines
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef AUTOKEY
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "ntpd.h"
+#include "ntp_stdlib.h"
+#include "ntp_string.h"
+#include "ntp_crypto.h"
+
+#ifdef KERNEL_PLL
+#include "ntp_syscall.h"
+#endif /* KERNEL_PLL */
+
+/*
+ * Extension field message formats
+ *
+ * +-------+-------+ +-------+-------+ +-------+-------+
+ * 0 | 3 | len | | 2,4 | len | | 5-9 | len |
+ * +-------+-------+ +-------+-------+ +-------+-------+
+ * 1 | assocID | | assocID | | assocID |
+ * +---------------+ +---------------+ +---------------+
+ * 2 | timestamp | | timestamp | | timestamp |
+ * +---------------+ +---------------+ +---------------+
+ * 3 | final seq | | cookie/flags | | filestamp |
+ * +---------------+ +---------------+ +---------------+
+ * 4 | final key | | signature len | | value len |
+ * +---------------+ +---------------+ +---------------+
+ * 5 | signature len | | | | |
+ * +---------------+ = signature = = value =
+ * 6 | | | | | |
+ * = signature = +---------------+ +---------------+
+ * 7 | | CRYPTO_ASSOC rsp | signature len |
+ * +---------------+ CRYPTO_PRIV rsp +---------------+
+ * CRYPTO_AUTO rsp | |
+ * = signature =
+ * | |
+ * +---------------+
+ * CRYPTO_DHPAR rsp
+ * CRYPTO_DH rsp
+ * CRYPTO_NAME rsp
+ * CRYPTO_CERT rsp
+ * CRYPTO_TAI rsp
+ *
+ * CRYPTO_STAT 1 - offer/select
+ * CRYPTO_ASSOC 2 20 association ID
+ * CRYPTO_AUTO 3 88 autokey values
+ * CRYPTO_PRIV 4 84 cookie value
+ * CRYPTO_DHPAR 5 220 agreement parameters
+ * CRYPTO_DH 6 152 public value
+ * CRYPTO_NAME 7 460 host name/public key
+ * CRYPTO_CERT 8 ? certificate
+ * CRYPTO_TAI 9 144 leapseconds table
+ *
+ * Note: requests carry the association ID of the receiver; responses
+ * carry the association ID of the sender.
+ */
+/*
+ * Minimum sizes of fields
+ */
+#define COOKIE_LEN (5 * 4)
+#define AUTOKEY_LEN (6 * 4)
+#define VALUE_LEN (6 * 4)
+
+/*
+ * Global cryptodata in host byte order.
+ */
+u_int crypto_flags; /* status word */
+u_int sys_tai; /* current UTC offset from TAI */
+
+#ifdef PUBKEY
+/*
+ * Cryptodefines
+ */
+#define TAI_1972 10 /* initial TAI offset */
+#define MAX_LEAP 100 /* max UTC leapseconds */
+#define MAX_LINLEN 1024 /* max line */
+#define MAX_KEYLEN 1024 /* max key */
+#define MAX_ENCLEN (ENCODED_CONTENT_LEN(1024)) /* max enc key */
+
+/*
+ * Private cryptodata in network byte order.
+ */
+static R_RSA_PRIVATE_KEY private_key; /* private key */
+static R_RSA_PUBLIC_KEY public_key; /* public key */
+static R_DH_PARAMS dh_params; /* agreement parameters */
+static u_char *dh_private; /* private value */
+static u_int dh_keyLen; /* private value length */
+static char *keysdir = NTP_KEYSDIR; /* crypto keys directory */
+static char *private_key_file = NULL; /* private key file */
+static char *public_key_file = NULL; /* public key file */
+static char *certif_file = NULL; /* certificate file */
+static char *dh_params_file = NULL; /* agreement parameters file */
+static char *tai_leap_file = NULL; /* leapseconds file */
+
+/*
+ * Global cryptodata in network byte order
+ */
+struct value host; /* host name/public key */
+struct value certif; /* certificate */
+struct value dhparam; /* agreement parameters */
+struct value dhpub; /* public value */
+struct value tai_leap; /* leapseconds table */
+
+/*
+ * Cryptotypes
+ */
+static u_int crypto_rsa P((char *, u_char *, u_int));
+static void crypto_cert P((char *));
+static void crypto_dh P((char *));
+static void crypto_tai P((char *));
+#endif /* PUBKEY */
+
+/*
+ * Autokey protocol status codes
+ */
+#define RV_OK 0 /* success */
+#define RV_LEN 1 /* invalid field length */
+#define RV_TSP 2 /* invalid timestamp */
+#define RV_FSP 3 /* invalid filestamp */
+#define RV_PUB 4 /* missing public key */
+#define RV_KEY 5 /* invalid RSA modulus */
+#define RV_SIG 6 /* invalid signature length */
+#define RV_DH 7 /* invalid agreement parameters */
+#define RV_FIL 8 /* missing or corrupted key file */
+#define RV_DAT 9 /* missing or corrupted data */
+#define RV_DEC 10 /* PEM decoding error */
+#define RV_DUP 11 /* duplicate flags */
+#define RV_VN 12 /* incorrect version */
+
+/*
+ * session_key - generate session key
+ *
+ * This routine generates a session key from the source address,
+ * destination address, key ID and private value. The value of the
+ * session key is the MD5 hash of these values, while the next key ID is
+ * the first four octets of the hash.
+ */
+keyid_t /* returns next key ID */
+session_key(
+ struct sockaddr_in *srcadr, /* source address */
+ struct sockaddr_in *dstadr, /* destination address */
+ keyid_t keyno, /* key ID */
+ keyid_t private, /* private value */
+ u_long lifetime /* key lifetime */
+ )
+{
+ MD5_CTX ctx; /* MD5 context */
+ keyid_t keyid; /* key identifer */
+ u_int32 header[4]; /* data in network byte order */
+ u_char digest[16]; /* message digest */
+
+ /*
+ * Generate the session key and key ID. If the lifetime is
+ * greater than zero, install the key and call it trusted.
+ */
+ header[0] = srcadr->sin_addr.s_addr;
+ header[1] = dstadr->sin_addr.s_addr;
+ header[2] = htonl(keyno);
+ header[3] = htonl(private);
+ MD5Init(&ctx);
+ MD5Update(&ctx, (u_char *)header, sizeof(header));
+ MD5Final(digest, &ctx);
+ memcpy(&keyid, digest, 4);
+ keyid = ntohl(keyid);
+ if (lifetime != 0) {
+ MD5auth_setkey(keyno, digest, 16);
+ authtrust(keyno, lifetime);
+ }
+#ifdef DEBUG
+ if (debug > 1)
+ printf(
+ "session_key: %s > %s %08x %08x hash %08x life %lu\n",
+ numtoa(header[0]), numtoa(header[1]), keyno,
+ private, keyid, lifetime);
+#endif
+ return (keyid);
+}
+
+
+/*
+ * make_keylist - generate key list
+ *
+ * This routine constructs a pseudo-random sequence by repeatedly
+ * hashing the session key starting from a given source address,
+ * destination address, private value and the next key ID of the
+ * preceeding session key. The last entry on the list is saved along
+ * with its sequence number and public signature.
+ */
+void
+make_keylist(
+ struct peer *peer, /* peer structure pointer */
+ struct interface *dstadr /* interface */
+ )
+{
+ struct autokey *ap; /* autokey pointer */
+ keyid_t keyid; /* next key ID */
+ keyid_t cookie; /* private value */
+ l_fp tstamp; /* NTP timestamp */
+ u_long ltemp;
+ int i;
+#ifdef PUBKEY
+ R_SIGNATURE_CTX ctx; /* signature context */
+ int rval; /* return value */
+ u_int len;
+#endif /* PUBKEY */
+
+ /*
+ * Allocate the key list if necessary.
+ */
+ L_CLR(&tstamp);
+ if (sys_leap != LEAP_NOTINSYNC)
+ get_systime(&tstamp);
+ if (peer->keylist == NULL)
+ peer->keylist = (keyid_t *)emalloc(sizeof(keyid_t) *
+ NTP_MAXSESSION);
+
+ /*
+ * Generate an initial key ID which is unique and greater than
+ * NTP_MAXKEY.
+ */
+ while (1) {
+ keyid = (u_long)RANDOM & 0xffffffff;
+ if (keyid <= NTP_MAXKEY)
+ continue;
+ if (authhavekey(keyid))
+ continue;
+ break;
+ }
+
+ /*
+ * Generate up to NTP_MAXSESSION session keys. Stop if the
+ * next one would not be unique or not a session key ID or if
+ * it would expire before the next poll. The private value
+ * included in the hash is zero if broadcast mode, the peer
+ * cookie if client mode or the host cookie if symmetric modes.
+ */
+ ltemp = min(sys_automax, NTP_MAXSESSION * (1 << (peer->kpoll)));
+ peer->hcookie = session_key(&dstadr->sin, &peer->srcadr, 0,
+ sys_private, 0);
+ if (peer->hmode == MODE_BROADCAST)
+ cookie = 0;
+ else
+ cookie = peer->pcookie.key;
+ for (i = 0; i < NTP_MAXSESSION; i++) {
+ peer->keylist[i] = keyid;
+ peer->keynumber = i;
+ keyid = session_key(&dstadr->sin, &peer->srcadr, keyid,
+ cookie, ltemp);
+ ltemp -= 1 << peer->kpoll;
+ if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
+ ltemp <= (1 << (peer->kpoll)))
+ break;
+ }
+
+ /*
+ * Save the last session key ID, sequence number and timestamp,
+ * then sign these values for later retrieval by the clients. Be
+ * careful not to use invalid key media.
+ */
+ ap = &peer->sndauto;
+ ap->tstamp = htonl(tstamp.l_ui);
+ ap->seq = htonl(peer->keynumber);
+ ap->key = htonl(keyid);
+ ap->siglen = 0;
+#if DEBUG
+ if (debug)
+ printf("make_keys: %d %08x %08x ts %u poll %d\n",
+ ntohl(ap->seq), ntohl(ap->key), cookie,
+ ntohl(ap->tstamp), peer->kpoll);
+#endif
+#ifdef PUBKEY
+ if(!crypto_flags)
+ return;
+ if (ap->sig == NULL)
+ ap->sig = emalloc(private_key.bits / 8);
+ EVP_SignInit(&ctx, DA_MD5);
+ EVP_SignUpdate(&ctx, (u_char *)ap, 12);
+ rval = EVP_SignFinal(&ctx, ap->sig, &len, &private_key);
+ if (rval != RV_OK)
+ msyslog(LOG_ERR, "crypto: keylist signature fails %x",
+ rval);
+ else
+ ap->siglen = htonl(len);
+ peer->flags |= FLAG_ASSOC;
+#endif /* PUBKEY */
+}
+
+
+/*
+ * crypto_recv - parse extension fields
+ *
+ * This routine is called when the packet has been matched to an
+ * association and passed sanity, format and MAC checks. We believe the
+ * extension field values only if the field has proper format and
+ * length, the timestamp and filestamp are valid and the signature has
+ * valid length and is verified. There are a few cases where some values
+ * are believed even if the signature fails, but only if the authentic
+ * bit is not set.
+ */
+void
+crypto_recv(
+ struct peer *peer, /* peer structure pointer */
+ struct recvbuf *rbufp /* packet buffer pointer */
+ )
+{
+ u_int32 *pkt; /* packet pointer */
+ struct autokey *ap; /* autokey pointer */
+ struct cookie *cp; /* cookie pointer */
+ int has_mac; /* length of MAC field */
+ int authlen; /* offset of MAC field */
+ int len; /* extension field length */
+ u_int code; /* extension field opcode */
+ tstamp_t tstamp; /* timestamp */
+ int i, rval;
+ u_int temp;
+#ifdef PUBKEY
+ R_SIGNATURE_CTX ctx; /* signature context */
+ struct value *vp; /* value pointer */
+ u_char dh_key[MAX_KEYLEN]; /* agreed key */
+ R_RSA_PUBLIC_KEY *kp; /* temporary public key pointer */
+ tstamp_t fstamp; /* filestamp */
+ u_int32 *pp; /* packet pointer */
+ u_int rsalen = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int) + 4;
+ u_int bits;
+ int j;
+#ifdef KERNEL_PLL
+#if NTP_API > 3
+ struct timex ntv; /* kernel interface structure */
+#endif /* NTP_API */
+#endif /* KERNEL_PLL */
+#endif /* PUBKEY */
+
+ /*
+ * Initialize. Note that the packet has already been checked for
+ * valid format and extension field lengths. We first extract
+ * the field length, command code and timestamp in host byte
+ * order. These are used with all commands and modes. We discard
+ * old timestamps and filestamps; but, for duplicate timestamps
+ * we discard only if the authentic bit is set. Cute.
+ */
+ pkt = (u_int32 *)&rbufp->recv_pkt;
+ authlen = LEN_PKT_NOMAC;
+ while ((has_mac = rbufp->recv_length - authlen) > MAX_MAC_LEN) {
+ i = authlen / 4;
+ len = ntohl(pkt[i]) & 0xffff;
+ code = (ntohl(pkt[i]) >> 16) & 0xffff;
+ temp = (code >> 8) & 0x3f;
+ if (temp != CRYPTO_VN) {
+ sys_unknownversion++;
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: incorrect version %d should be %d\n",
+ temp, CRYPTO_VN);
+#endif
+ return;
+ }
+ tstamp = ntohl(pkt[i + 2]);
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: ext offset %d len %d code %x assocID %d\n",
+ authlen, len, code, (u_int32)ntohl(pkt[i +
+ 1]));
+#endif
+ switch (code) {
+
+ /*
+ * Install association ID and status word.
+ */
+ case CRYPTO_ASSOC | CRYPTO_RESP:
+ cp = (struct cookie *)&pkt[i + 2];
+ temp = ntohl(cp->key);
+ if (len < COOKIE_LEN) {
+ rval = RV_LEN;
+ } else if (tstamp == 0) {
+ rval = RV_TSP;
+ } else {
+ if (!peer->crypto)
+ peer->crypto = temp;
+ if (ntohl(pkt[i + 1]) != 0)
+ peer->assoc = ntohl(pkt[i + 1]);
+ rval = RV_OK;
+ }
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: verify %d flags 0x%x ts %u\n",
+ rval, temp, tstamp);
+#endif
+ break;
+
+ /*
+ * Install autokey values in broadcast client and
+ * symmetric modes.
+ */
+ case CRYPTO_AUTO | CRYPTO_RESP:
+ if (!(peer->flags & FLAG_AUTOKEY) &&
+ ntohl(pkt[i + 1]) != 0)
+ peer->assoc = ntohl(pkt[i + 1]);
+ ap = (struct autokey *)&pkt[i + 2];
+#ifdef PUBKEY
+ temp = ntohl(ap->siglen);
+ kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
+ if (len < AUTOKEY_LEN) {
+ rval = RV_LEN;
+ } else if (tstamp == 0 || tstamp <
+ peer->recauto.tstamp || (tstamp ==
+ peer->recauto.tstamp && (peer->flags &
+ FLAG_AUTOKEY))) {
+ rval = RV_TSP;
+ } else if (!crypto_flags) {
+ rval = RV_OK;
+ } else if (kp == NULL) {
+ rval = RV_PUB;
+ } else if (temp != kp->bits / 8) {
+ rval = RV_SIG;
+ } else {
+ EVP_VerifyInit(&ctx, DA_MD5);
+ EVP_VerifyUpdate(&ctx, (u_char *)ap,
+ 12);
+ rval = EVP_VerifyFinal(&ctx,
+ (u_char *)ap->pkt, temp, kp);
+ }
+#else /* PUBKEY */
+ if (tstamp < peer->recauto.tstamp || (tstamp ==
+ peer->recauto.tstamp && (peer->flags &
+ FLAG_AUTOKEY)))
+ rval = RV_TSP;
+ else
+ rval = RV_OK;
+#endif /* PUBKEY */
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: verify %x autokey %d %08x ts %u (%u)\n",
+ rval, ntohl(ap->seq),
+ ntohl(ap->key), tstamp,
+ peer->recauto.tstamp);
+#endif
+ if (rval != RV_OK) {
+ if (rval != RV_TSP)
+ msyslog(LOG_ERR,
+ "crypto: %x autokey %d %08x ts %u (%u)\n",
+ rval, ntohl(ap->seq),
+ ntohl(ap->key), tstamp,
+ peer->recauto.tstamp);
+ break;
+ }
+ peer->flags |= FLAG_AUTOKEY;
+ peer->flash &= ~TEST10;
+ peer->assoc = ntohl(pkt[i + 1]);
+ peer->recauto.tstamp = tstamp;
+ peer->recauto.seq = ntohl(ap->seq);
+ peer->recauto.key = ntohl(ap->key);
+ peer->pkeyid = peer->recauto.key;
+ break;
+
+ /*
+ * Install session cookie in client mode. Use this also
+ * in symmetric modes for test when rsaref20 has not
+ * been installed.
+ */
+ case CRYPTO_PRIV:
+ peer->cmmd = ntohl(pkt[i]);
+ /* fall through */
+
+ case CRYPTO_PRIV | CRYPTO_RESP:
+ cp = (struct cookie *)&pkt[i + 2];
+#ifdef PUBKEY
+ temp = ntohl(cp->siglen);
+ kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
+ if (len < COOKIE_LEN) {
+ rval = RV_LEN;
+ } else if (tstamp == 0 || tstamp <
+ peer->pcookie.tstamp || (tstamp ==
+ peer->pcookie.tstamp && (peer->flags &
+ FLAG_AUTOKEY))) {
+ rval = RV_TSP;
+ } else if (!crypto_flags) {
+ rval = RV_OK;
+ } else if (kp == NULL) {
+ rval = RV_PUB;
+ } else if (temp != kp->bits / 8) {
+ rval = RV_SIG;
+ } else {
+ EVP_VerifyInit(&ctx, DA_MD5);
+ EVP_VerifyUpdate(&ctx, (u_char *)cp, 8);
+ rval = EVP_VerifyFinal(&ctx,
+ (u_char *)cp->pkt, temp, kp);
+ }
+#else /* PUBKEY */
+ if (tstamp <= peer->pcookie.tstamp || (tstamp ==
+ peer->pcookie.tstamp && (peer->flags &
+ FLAG_AUTOKEY)))
+ rval = RV_TSP;
+ else
+ rval = RV_OK;
+#endif /* PUBKEY */
+
+ /*
+ * Tricky here. If in client mode, use the
+ * server cookie; otherwise, use EXOR of both
+ * peer cookies. We call this Daffy-Hooligan
+ * agreement.
+ */
+ if (peer->hmode == MODE_CLIENT)
+ temp = ntohl(cp->key);
+ else
+ temp = ntohl(cp->key) ^ peer->hcookie;
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: verify %x cookie %08x ts %u (%u)\n",
+ rval, temp, tstamp,
+ peer->pcookie.tstamp);
+#endif
+ if (rval != RV_OK) {
+ if (rval != RV_TSP)
+ msyslog(LOG_ERR,
+ "crypto: %x cookie %08x ts %u (%u)\n",
+ rval, temp, tstamp,
+ peer->pcookie.tstamp);
+ peer->cmmd |= CRYPTO_ERROR;
+ break;
+ }
+ if (!(peer->cast_flags & MDF_BCLNT))
+ peer->flags |= FLAG_AUTOKEY;
+ peer->flash &= ~TEST10;
+ peer->assoc = ntohl(pkt[i + 1]);
+ peer->pcookie.tstamp = tstamp;
+ if (temp != peer->pcookie.key) {
+ peer->pcookie.key = temp;
+ key_expire(peer);
+ }
+ break;
+
+ /*
+ * The following commands and responses work only when
+ * public-key cryptography has been configured. If
+ * configured, but disabled due to no crypto command in
+ * the configuration file, they are ignored.
+ */
+#ifdef PUBKEY
+ /*
+ * Install public key and host name.
+ */
+ case CRYPTO_NAME | CRYPTO_RESP:
+ if (!crypto_flags)
+ break;
+ vp = (struct value *)&pkt[i + 2];
+ fstamp = ntohl(vp->fstamp);
+ temp = ntohl(vp->vallen);
+ j = i + 5 + ntohl(vp->vallen) / 4;
+ bits = ntohl(pkt[i + 5]);
+ if (len < VALUE_LEN) {
+ rval = RV_LEN;
+ } else if (temp < rsalen || bits <
+ MIN_RSA_MODULUS_BITS || bits >
+ MAX_RSA_MODULUS_BITS) {
+ rval = RV_KEY;
+ } else if (ntohl(pkt[j]) != bits / 8) {
+ rval = RV_SIG;
+ } else if (tstamp == 0 || tstamp <
+ peer->pubkey.tstamp || (tstamp ==
+ peer->pubkey.tstamp && (peer->flags &
+ FLAG_AUTOKEY))) {
+ rval = RV_TSP;
+ } else if (tstamp < peer->pubkey.fstamp ||
+ fstamp < peer->pubkey.fstamp) {
+ rval = RV_FSP;
+ } else if (fstamp == peer->pubkey.fstamp &&
+ (peer->flags & FLAG_AUTOKEY)) {
+ rval = RV_FSP;
+ } else {
+ EVP_VerifyInit(&ctx, DA_MD5);
+ EVP_VerifyUpdate(&ctx, (u_char *)vp,
+ temp + 12);
+ kp = emalloc(sizeof(R_RSA_PUBLIC_KEY));
+ kp->bits = bits;
+ memcpy(kp->modulus, &pkt[i + 6],
+ rsalen - 4);
+ rval = EVP_VerifyFinal(&ctx,
+ (u_char *)&pkt[j + 1],
+ ntohl(pkt[j]), kp);
+ if (rval != 0) {
+ free(kp);
+ } else {
+ j = i + 5 + rsalen / 4;
+ peer->pubkey.ptr = (u_char *)kp;
+ temp = strlen((char *)&pkt[j]);
+ peer->keystr = emalloc(temp +
+ 1);
+ strcpy(peer->keystr,
+ (char *)&pkt[j]);
+ peer->pubkey.tstamp = tstamp;
+ peer->pubkey.fstamp = fstamp;
+ peer->flash &= ~TEST10;
+ if (!(peer->crypto &
+ CRYPTO_FLAG_CERT))
+ peer->flags |=
+ FLAG_PROVEN;
+ }
+ }
+#ifdef DEBUG
+ if (debug)
+
+ printf(
+ "crypto_recv: verify %x host %s ts %u fs %u\n",
+ rval, (char *)&pkt[i + 5 + rsalen /
+ 4], tstamp, fstamp);
+#endif
+ if (rval != RV_OK) {
+ if (rval != RV_TSP)
+ msyslog(LOG_ERR,
+ "crypto: %x host %s ts %u fs %u\n",
+ rval, (char *)&pkt[i + 5 +
+ rsalen / 4], tstamp,
+ fstamp);
+ }
+ break;
+
+ /*
+ * Install certificate.
+ */
+ case CRYPTO_CERT | CRYPTO_RESP:
+ if (!crypto_flags)
+ break;
+ vp = (struct value *)&pkt[i + 2];
+ fstamp = ntohl(vp->fstamp);
+ temp = ntohl(vp->vallen);
+ kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
+ j = i + 5 + temp / 4;
+ if (len < VALUE_LEN) {
+ rval = RV_LEN;
+ } else if (kp == NULL) {
+ rval = RV_PUB;
+ } else if (ntohl(pkt[j]) != kp->bits / 8) {
+ rval = RV_SIG;
+ } else if (tstamp == 0) {
+ rval = RV_TSP;
+ } else if (tstamp <
+ ntohl(peer->certif.fstamp) || fstamp <
+ ntohl(peer->certif.fstamp)) {
+ rval = RV_FSP;
+ } else if (fstamp ==
+ ntohl(peer->certif.fstamp) && (peer->flags &
+ FLAG_AUTOKEY)) {
+ peer->crypto &= ~CRYPTO_FLAG_CERT;
+ rval = RV_FSP;
+ } else {
+ EVP_VerifyInit(&ctx, DA_MD5);
+ EVP_VerifyUpdate(&ctx, (u_char *)vp,
+ temp + 12);
+ rval = EVP_VerifyFinal(&ctx,
+ (u_char *)&pkt[j + 1],
+ ntohl(pkt[j]), kp);
+ }
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: verify %x certificate %u ts %u fs %u\n",
+ rval, temp, tstamp, fstamp);
+#endif
+
+ /*
+ * If the peer data are newer than the host
+ * data, replace the host data. Otherwise,
+ * wait for the peer to fetch the host data.
+ */
+ if (rval != RV_OK || temp == 0) {
+ if (rval != RV_TSP)
+ msyslog(LOG_ERR,
+ "crypto: %x certificate %u ts %u fs %u\n",
+ rval, temp, tstamp, fstamp);
+ break;
+ }
+ peer->flash &= ~TEST10;
+ peer->flags |= FLAG_PROVEN;
+ peer->crypto &= ~CRYPTO_FLAG_CERT;
+
+ /*
+ * Initialize agreement parameters and extension
+ * field in network byte order. Note the private
+ * key length is set arbitrarily at half the
+ * prime length.
+ */
+ peer->certif.tstamp = vp->tstamp;
+ peer->certif.fstamp = vp->fstamp;
+ peer->certif.vallen = vp->vallen;
+ if (peer->certif.ptr == NULL)
+ free(peer->certif.ptr);
+ peer->certif.ptr = emalloc(temp);
+ memcpy(peer->certif.ptr, vp->pkt, temp);
+ crypto_agree();
+ break;
+
+ /*
+ * Install agreement parameters in symmetric modes.
+ */
+ case CRYPTO_DHPAR | CRYPTO_RESP:
+ if (!crypto_flags)
+ break;
+ vp = (struct value *)&pkt[i + 2];
+ fstamp = ntohl(vp->fstamp);
+ temp = ntohl(vp->vallen);
+ kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
+ j = i + 5 + temp / 4;
+ if (len < VALUE_LEN) {
+ rval = RV_LEN;
+ } else if (kp == NULL) {
+ rval = RV_PUB;
+ } else if (ntohl(pkt[j]) != kp->bits / 8) {
+ rval = RV_SIG;
+ } else if (tstamp == 0) {
+ rval = RV_TSP;
+ } else if (tstamp < ntohl(dhparam.fstamp) ||
+ fstamp < ntohl(dhparam.fstamp)) {
+ rval = RV_FSP;
+ } else if (fstamp == ntohl(dhparam.fstamp) &&
+ (peer->flags & FLAG_AUTOKEY)) {
+ peer->crypto &= ~CRYPTO_FLAG_DH;
+ rval = RV_FSP;
+ } else {
+ EVP_VerifyInit(&ctx, DA_MD5);
+ EVP_VerifyUpdate(&ctx, (u_char *)vp,
+ temp + 12);
+ rval = EVP_VerifyFinal(&ctx,
+ (u_char *)&pkt[j + 1],
+ ntohl(pkt[j]), kp);
+ }
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: verify %x parameters %u ts %u fs %u\n",
+ rval, temp, tstamp, fstamp);
+#endif
+
+ /*
+ * If the peer data are newer than the host
+ * data, replace the host data. Otherwise,
+ * wait for the peer to fetch the host data.
+ */
+ if (rval != RV_OK || temp == 0) {
+ if (rval != RV_TSP)
+ msyslog(LOG_ERR,
+ "crypto: %x parameters %u ts %u fs %u\n",
+ rval, temp, tstamp, fstamp);
+ break;
+ }
+ peer->flash &= ~TEST10;
+ crypto_flags |= CRYPTO_FLAG_DH;
+ peer->crypto &= ~CRYPTO_FLAG_DH;
+
+ /*
+ * Initialize agreement parameters and extension
+ * field in network byte order. Note the private
+ * key length is set arbitrarily at half the
+ * prime length.
+ */
+ dhparam.tstamp = vp->tstamp;
+ dhparam.fstamp = vp->fstamp;
+ dhparam.vallen = vp->vallen;
+ if (dhparam.ptr != NULL)
+ free(dhparam.ptr);
+ pp = emalloc(temp);
+ dhparam.ptr = (u_char *)pp;
+ memcpy(pp, vp->pkt, temp);
+ dh_params.primeLen = ntohl(*pp++);
+ dh_params.prime = (u_char *)pp;
+ pp += dh_params.primeLen / 4;
+ dh_params.generatorLen = ntohl(*pp++);
+ dh_params.generator = (u_char *)pp;
+ dh_keyLen = dh_params.primeLen / 2;
+ if (dh_private != NULL)
+ free(dh_private);
+ dh_private = emalloc(dh_keyLen);
+ if (dhparam.sig == NULL)
+ dhparam.sig = emalloc(private_key.bits /
+ 8);
+
+ /*
+ * Initialize public value extension field.
+ */
+ dhpub.tstamp = vp->tstamp;
+ dhpub.fstamp = vp->fstamp;
+ dhpub.vallen = htonl(dh_params.primeLen);
+ if (dhpub.ptr != NULL)
+ free(dhpub.ptr);
+ dhpub.ptr = emalloc(dh_params.primeLen);
+ if (dhpub.sig == NULL)
+ dhpub.sig = emalloc(private_key.bits /
+ 8);
+ crypto_agree();
+ break;
+
+ /*
+ * Verify public value and compute agreed key in
+ * symmetric modes.
+ */
+ case CRYPTO_DH:
+ peer->cmmd = ntohl(pkt[i]);
+ if (!crypto_flags)
+ peer->cmmd |= CRYPTO_ERROR;
+ /* fall through */
+
+ case CRYPTO_DH | CRYPTO_RESP:
+ if (!crypto_flags)
+ break;
+ vp = (struct value *)&pkt[i + 2];
+ fstamp = ntohl(vp->fstamp);
+ temp = ntohl(vp->vallen);
+ kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
+ j = i + 5 + temp / 4;
+ if (len < VALUE_LEN) {
+ rval = RV_LEN;
+ } else if (temp != dh_params.primeLen) {
+ rval = RV_DH;
+ } else if (kp == NULL) {
+ rval = RV_PUB;
+ } else if (ntohl(pkt[j]) != kp->bits / 8) {
+ rval = RV_SIG;
+ } else if (tstamp == 0 || tstamp <
+ peer->pcookie.tstamp || (tstamp ==
+ peer->pcookie.tstamp && (peer->flags &
+ FLAG_AUTOKEY))) {
+ rval = RV_TSP;
+ } else {
+ EVP_VerifyInit(&ctx, DA_MD5);
+ EVP_VerifyUpdate(&ctx, (u_char *)vp,
+ temp + 12);
+ rval = EVP_VerifyFinal(&ctx,
+ (u_char *)&pkt[j + 1],
+ ntohl(pkt[j]), kp);
+ }
+
+ /*
+ * Run the agreement algorithm and stash the key
+ * value. We use only the first u_int32 for the
+ * host cookie. Wasteful. If the association ID
+ * is zero, the other guy hasn't seen us as
+ * synchronized, in which case both of us should
+ * be using a zero cookie.
+ */
+ if (rval != RV_OK) {
+ temp = 0;
+ } else if (fstamp > dhparam.fstamp) {
+ crypto_flags &= ~CRYPTO_FLAG_DH;
+ rval = RV_FSP;
+ } else {
+ rval = R_ComputeDHAgreedKey(dh_key,
+ (u_char *)&pkt[i + 5], dh_private,
+ dh_keyLen, &dh_params);
+ temp = ntohl(*(u_int32 *)dh_key);
+ }
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: verify %x agreement %08x ts %u (%u) fs %u\n",
+ rval, temp, tstamp,
+ peer->pcookie.tstamp, fstamp);
+#endif
+ if (rval != RV_OK) {
+ if (rval != RV_TSP)
+ msyslog(LOG_ERR,
+ "crypto: %x agreement %08x ts %u (%u) fs %u\n",
+ rval, temp, tstamp,
+ peer->pcookie.tstamp,
+ fstamp);
+ peer->cmmd |= CRYPTO_ERROR;
+ break;
+ }
+ peer->flash &= ~TEST10;
+ peer->flags &= ~FLAG_AUTOKEY;
+ peer->assoc = ntohl(pkt[i + 1]);
+ peer->pcookie.tstamp = tstamp;
+ if (temp != peer->pcookie.key) {
+ peer->pcookie.key = temp;
+ key_expire(peer);
+ }
+ break;
+
+ /*
+ * Install leapseconds table.
+ */
+ case CRYPTO_TAI | CRYPTO_RESP:
+ if (!crypto_flags)
+ break;
+ vp = (struct value *)&pkt[i + 2];
+ fstamp = ntohl(vp->fstamp);
+ temp = ntohl(vp->vallen);
+ kp = (R_RSA_PUBLIC_KEY *)peer->pubkey.ptr;
+ j = i + 5 + temp / 4;
+ if (len < VALUE_LEN) {
+ rval = RV_LEN;
+ } if (kp == NULL) {
+ rval = RV_PUB;
+ } else if (ntohl(pkt[j]) != kp->bits / 8) {
+ rval = RV_SIG;
+ } else if (tstamp == 0) {
+ rval = RV_TSP;
+ } else if (tstamp < ntohl(tai_leap.fstamp) ||
+ fstamp < ntohl(tai_leap.fstamp)) {
+ rval = RV_FSP;
+ } else if (fstamp == ntohl(tai_leap.fstamp) &&
+ (peer->flags & FLAG_AUTOKEY)) {
+ peer->crypto &= ~CRYPTO_FLAG_TAI;
+ rval = RV_FSP;
+ } else {
+ EVP_VerifyInit(&ctx, DA_MD5);
+ EVP_VerifyUpdate(&ctx, (u_char *)vp,
+ temp + 12);
+ rval = EVP_VerifyFinal(&ctx,
+ (u_char *)&pkt[j + 1],
+ ntohl(pkt[j]), kp);
+ }
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_recv: verify %x leapseconds %u ts %u fs %u\n",
+ rval, temp, tstamp, fstamp);
+#endif
+
+ /*
+ * If the peer data are newer than the host
+ * data, replace the host data. Otherwise,
+ * wait for the peer to fetch the host data.
+ */
+ if (rval != RV_OK || temp == 0) {
+ if (rval != RV_TSP)
+ msyslog(LOG_ERR,
+ "crypto: %x leapseconds %u ts %u fs %u\n",
+ rval, temp, tstamp, fstamp);
+ break;
+ }
+ peer->flash &= ~TEST10;
+ crypto_flags |= CRYPTO_FLAG_TAI;
+ peer->crypto &= ~CRYPTO_FLAG_TAI;
+ sys_tai = temp / 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_ERR,
+ "kernel TAI update failed");
+#endif /* NTP_API */
+#endif /* KERNEL_PLL */
+
+ /*
+ * Initialize leapseconds table and extension
+ * field in network byte order.
+ */
+ tai_leap.tstamp = vp->tstamp;
+ tai_leap.fstamp = vp->fstamp;
+ tai_leap.vallen = vp->vallen;
+ if (tai_leap.ptr == NULL)
+ free(tai_leap.ptr);
+ tai_leap.ptr = emalloc(temp);
+ memcpy(tai_leap.ptr, vp->pkt, temp);
+ if (tai_leap.sig == NULL)
+ tai_leap.sig =
+ emalloc(private_key.bits / 8);
+ crypto_agree();
+ break;
+#endif /* PUBKEY */
+
+ /*
+ * For other requests, save the request code for later;
+ * for unknown responses or errors, just ignore for now.
+ */
+ default:
+ if (code & (CRYPTO_RESP | CRYPTO_ERROR))
+ break;
+ peer->cmmd = ntohl(pkt[i]);
+ break;
+
+ }
+ authlen += len;
+ }
+}
+
+
+/*
+ * crypto_xmit - construct extension fields
+ *
+ * This routine is called both when an association is configured and
+ * when one is not. The only case where this matters now is to retrieve
+ * the autokey information, in which case the caller has to provide the
+ * association ID to match the association.
+ */
+int /* return length of extension field */
+crypto_xmit(
+ u_int32 *xpkt, /* packet pointer */
+ int start, /* offset to extension field */
+ u_int code, /* extension field code */
+ keyid_t cookie, /* session cookie */
+ u_int associd /* association ID */
+ )
+{
+ struct peer *peer; /* peer structure pointer */
+ struct autokey *ap; /* autokey pointer */
+ struct cookie *cp; /* cookie pointer */
+ int len; /* extension field length */
+ u_int opcode; /* extension field opcode */
+ int i;
+#ifdef PUBKEY
+ R_SIGNATURE_CTX ctx; /* signature context */
+ struct value *vp; /* value pointer */
+ int rval; /* return value */
+ u_int temp;
+ int j;
+#endif /* PUBKEY */
+
+ /*
+ * Generate the requested extension field request code, length
+ * and association ID. Note that several extension fields are
+ * used with and without public-key cryptography. If public-key
+ * cryptography has not been configured, we do the same thing,
+ * but leave off the signature.
+ */
+ i = start / 4;
+ opcode = code;
+ xpkt[i + 1] = htonl(associd);
+ len = 8;
+ switch (opcode) {
+
+ /*
+ * Send association ID, timestamp and status word.
+ */
+ case CRYPTO_ASSOC | CRYPTO_RESP:
+ cp = (struct cookie *)&xpkt[i + 2];
+#ifdef PUBKEY
+ cp->tstamp = host.tstamp;
+#else
+ cp->tstamp = 0;
+#endif /* PUBKEY */
+ cp->key = htonl(crypto_flags);
+ cp->siglen = 0;
+ len += 12;
+ break;
+
+ /*
+ * Find peer and send autokey data and signature in broadcast
+ * server and symmetric modes. If no association is found,
+ * either the server has restarted with new associations or some
+ * perp has replayed an old message.
+ */
+ case CRYPTO_AUTO | CRYPTO_RESP:
+ peer = findpeerbyassoc(associd);
+ if (peer == NULL) {
+ opcode |= CRYPTO_ERROR;
+ break;
+ }
+ peer->flags &= ~FLAG_ASSOC;
+ ap = (struct autokey *)&xpkt[i + 2];
+ ap->tstamp = peer->sndauto.tstamp;
+ ap->seq = peer->sndauto.seq;
+ ap->key = peer->sndauto.key;
+ ap->siglen = peer->sndauto.siglen;
+ len += 16;
+#ifdef PUBKEY
+ if (!crypto_flags)
+ break;
+ temp = ntohl(ap->siglen);
+ if (temp != 0)
+ memcpy(ap->pkt, peer->sndauto.sig, temp);
+ len += temp;
+#endif /* PUBKEY */
+ break;
+
+ /*
+ * Send peer cookie and signature in server mode.
+ */
+ case CRYPTO_PRIV:
+ case CRYPTO_PRIV | CRYPTO_RESP:
+ cp = (struct cookie *)&xpkt[i + 2];
+ cp->key = htonl(cookie);
+ cp->siglen = 0;
+ len += 12;
+#ifdef PUBKEY
+ cp->tstamp = host.tstamp;
+ if (!crypto_flags)
+ break;
+ EVP_SignInit(&ctx, DA_MD5);
+ EVP_SignUpdate(&ctx, (u_char *)cp, 8);
+ rval = EVP_SignFinal(&ctx, (u_char *)cp->pkt, &temp,
+ &private_key);
+ if (rval != RV_OK) {
+ msyslog(LOG_ERR,
+ "crypto: cookie signature fails %x", rval);
+ break;
+ }
+ cp->siglen = htonl(temp);
+ len += temp;
+#endif /* PUBKEY */
+ break;
+
+#ifdef PUBKEY
+ /*
+ * The following commands and responses work only when public-
+ * key cryptography has been configured. If configured, but
+ * disabled due to no crypto command in the configuration file,
+ * they are ignored and an error response is returned.
+ */
+ /*
+ * Send certificate, timestamp and signature.
+ */
+ case CRYPTO_CERT | CRYPTO_RESP:
+ if (!crypto_flags) {
+ opcode |= CRYPTO_ERROR;
+ break;
+ }
+ vp = (struct value *)&xpkt[i + 2];
+ vp->tstamp = certif.tstamp;
+ vp->fstamp = certif.fstamp;
+ vp->vallen = 0;
+ len += 12;
+ temp = ntohl(certif.vallen);
+ if (temp == 0)
+ break;
+ vp->vallen = htonl(temp);
+ memcpy(vp->pkt, certif.ptr, temp);
+ len += temp;
+ j = i + 5 + temp / 4;
+ temp = public_key.bits / 8;
+ xpkt[j++] = htonl(temp);
+ memcpy(&xpkt[j], certif.sig, temp);
+ len += temp + 4;
+ break;
+
+ /*
+ * Send agreement parameters, timestamp and signature.
+ */
+ case CRYPTO_DHPAR | CRYPTO_RESP:
+ if (!crypto_flags) {
+ opcode |= CRYPTO_ERROR;
+ break;
+ }
+ vp = (struct value *)&xpkt[i + 2];
+ vp->tstamp = dhparam.tstamp;
+ vp->fstamp = dhparam.fstamp;
+ vp->vallen = 0;
+ len += 12;
+ temp = ntohl(dhparam.vallen);
+ if (temp == 0)
+ break;
+ vp->vallen = htonl(temp);
+ memcpy(vp->pkt, dhparam.ptr, temp);
+ len += temp;
+ j = i + 5 + temp / 4;
+ temp = public_key.bits / 8;
+ xpkt[j++] = htonl(temp);
+ memcpy(&xpkt[j], dhparam.sig, temp);
+ len += temp + 4;
+ break;
+
+ /*
+ * Send public value, timestamp and signature.
+ */
+ case CRYPTO_DH:
+ case CRYPTO_DH | CRYPTO_RESP:
+ if (!crypto_flags) {
+ opcode |= CRYPTO_ERROR;
+ break;
+ }
+ vp = (struct value *)&xpkt[i + 2];
+ vp->tstamp = dhpub.tstamp;
+ vp->fstamp = dhpub.fstamp;
+ vp->vallen = 0;
+ len += 12;
+ temp = ntohl(dhpub.vallen);
+ if (temp == 0)
+ break;
+ vp->vallen = htonl(temp);
+ memcpy(vp->pkt, dhpub.ptr, temp);
+ len += temp;
+ j = i + 5 + temp / 4;
+ temp = public_key.bits / 8;
+ xpkt[j++] = htonl(temp);
+ memcpy(&xpkt[j], dhpub.sig, temp);
+ len += temp + 4;
+ break;
+
+ /*
+ * Send public key, host name, timestamp and signature.
+ */
+ case CRYPTO_NAME | CRYPTO_RESP:
+ if (!crypto_flags) {
+ opcode |= CRYPTO_ERROR;
+ break;
+ }
+ vp = (struct value *)&xpkt[i + 2];
+ vp->tstamp = host.tstamp;
+ vp->fstamp = host.fstamp;
+ vp->vallen = 0;
+ len += 12;
+ temp = ntohl(host.vallen);
+ if (temp == 0)
+ break;
+ vp->vallen = htonl(temp);
+ memcpy(vp->pkt, host.ptr, temp);
+ len += temp;
+ j = i + 5 + temp / 4;
+ temp = public_key.bits / 8;
+ xpkt[j++] = htonl(temp);
+ memcpy(&xpkt[j], host.sig, temp);
+ len += temp + 4;
+ break;
+
+ /*
+ * Send leapseconds table, timestamp and signature.
+ */
+ case CRYPTO_TAI | CRYPTO_RESP:
+ if (!crypto_flags) {
+ opcode |= CRYPTO_ERROR;
+ break;
+ }
+ vp = (struct value *)&xpkt[i + 2];
+ vp->tstamp = tai_leap.tstamp;
+ vp->fstamp = tai_leap.fstamp;
+ vp->vallen = 0;
+ len += 12;
+ temp = ntohl(tai_leap.vallen);
+ if (temp == 0)
+ break;
+ vp->vallen = htonl(temp);
+ memcpy(vp->pkt, tai_leap.ptr, temp);
+ len += temp;
+ j = i + 5 + temp / 4;
+ temp = public_key.bits / 8;
+ xpkt[j++] = htonl(temp);
+ memcpy(&xpkt[j], tai_leap.sig, temp);
+ len += temp + 4;
+ break;
+#endif /* PUBKEY */
+
+ /*
+ * Default - Fall through for requests; for unknown responses,
+ * flag as error.
+ */
+ default:
+ if (opcode & CRYPTO_RESP)
+ opcode |= CRYPTO_ERROR;
+ break;
+ }
+
+ /*
+ * Round up the field length to a multiple of 8 octets and save
+ * the request code and length.
+ */
+ len = ((len + 7) / 8) * 8;
+ if (len >= 4) {
+ xpkt[i] = htonl((u_int32)((opcode << 16) | len));
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_xmit: ext offset %d len %d code %x assocID %d\n",
+ start, len, code, associd);
+#endif
+ }
+ return (len);
+}
+
+#ifdef PUBKEY
+/*
+ * crypto_setup - load private key, public key, optional agreement
+ * parameters and optional leapseconds table, then initialize extension
+ * fields for later signatures.
+ */
+void
+crypto_setup(void)
+{
+ char filename[MAXFILENAME];
+ u_int fstamp; /* filestamp */
+ u_int len, temp;
+ u_int32 *pp;
+
+ /*
+ * Initialize structures.
+ */
+ memset(&private_key, 0, sizeof(private_key));
+ memset(&public_key, 0, sizeof(public_key));
+ memset(&certif, 0, sizeof(certif));
+ memset(&dh_params, 0, sizeof(dh_params));
+ memset(&host, 0, sizeof(host));
+ memset(&dhparam, 0, sizeof(dhparam));
+ memset(&dhpub, 0, sizeof(dhpub));
+ memset(&tai_leap, 0, sizeof(tai_leap));
+ if (!crypto_flags)
+ return;
+
+ /*
+ * Load required private key from file, default "ntpkey".
+ */
+ if (private_key_file == NULL)
+ private_key_file = "ntpkey";
+ host.fstamp = htonl(crypto_rsa(private_key_file,
+ (u_char *)&private_key, sizeof(R_RSA_PRIVATE_KEY)));
+
+ /*
+ * Load required public key from file, default
+ * "ntpkey_host", where "host" is the canonical name of this
+ * machine.
+ */
+ if (public_key_file == NULL) {
+ snprintf(filename, MAXFILENAME, "ntpkey_%s",
+ sys_hostname);
+ public_key_file = emalloc(strlen(filename) + 1);
+ strcpy(public_key_file, filename);
+ }
+ fstamp = htonl(crypto_rsa(public_key_file,
+ (u_char *)&public_key, sizeof(R_RSA_PUBLIC_KEY)));
+ if (fstamp != host.fstamp || strstr(public_key_file,
+ sys_hostname) == NULL) {
+ msyslog(LOG_ERR,
+ "crypto: public/private key files mismatch");
+ exit (-1);
+ }
+ crypto_flags |= CRYPTO_FLAG_RSA;
+
+ /*
+ * Assemble public key and host name in network byte order.
+ * These data will later be signed and sent in response to
+ * a client request. Note that the modulus must be a u_int32 in
+ * network byte order independent of the host order or u_int
+ * size.
+ */
+ strcpy(filename, sys_hostname);
+ for (len = strlen(filename) + 1; len % 4 != 0; len++)
+ filename[len - 1] = 0;
+ temp = sizeof(R_RSA_PUBLIC_KEY) - sizeof(u_int) + 4;
+ host.vallen = htonl(temp + len);
+ pp = emalloc(temp + len);
+ host.ptr = (u_char *)pp;
+ *pp++ = htonl(public_key.bits);
+ memcpy(pp--, public_key.modulus, temp - 4);
+ pp += temp / 4;
+ memcpy(pp, filename, len);
+ host.sig = emalloc(private_key.bits / 8);
+
+ /*
+ * Load optional certificate from file, default "ntpkey_certif".
+ * If the file is missing or defective, the values can later be
+ * retrieved from a server.
+ */
+ if (certif_file == NULL)
+ snprintf(filename, MAXFILENAME, "ntpkey_certif_%s",
+ sys_hostname);
+ certif_file = emalloc(strlen(filename) + 1);
+ strcpy(certif_file, filename);
+ crypto_cert(certif_file);
+
+ /*
+ * Load optional agreement parameters from file, default
+ * "ntpkey_dh". If the file is missing or defective, the values
+ * can later be retrieved from a server.
+ */
+ if (dh_params_file == NULL)
+ dh_params_file = "ntpkey_dh";
+ crypto_dh(dh_params_file);
+
+ /*
+ * Load optional leapseconds from file, default "ntpkey_leap".
+ * If the file is missing or defective, the values can later be
+ * retrieved from a server.
+ */
+ if (tai_leap_file == NULL)
+ tai_leap_file = "ntpkey_leap";
+ crypto_tai(tai_leap_file);
+}
+
+
+/*
+ * crypto_agree - compute new public value and sign extension fields.
+ */
+void
+crypto_agree(void)
+{
+ R_RANDOM_STRUCT randomstr; /* wiggle bits */
+ R_SIGNATURE_CTX ctx; /* signature context */
+ l_fp lstamp; /* NTP time */
+ tstamp_t tstamp; /* seconds timestamp */
+ u_int len, temp;
+ int rval, i;
+
+ /*
+ * Sign host name and timestamps, but only if the clock is
+ * synchronized.
+ */
+ if (sys_leap == LEAP_NOTINSYNC)
+ return;
+ get_systime(&lstamp);
+ tstamp = lstamp.l_ui;
+ host.tstamp = htonl(tstamp);
+ if (!crypto_flags)
+ return;
+ EVP_SignInit(&ctx, DA_MD5);
+ EVP_SignUpdate(&ctx, (u_char *)&host, 12);
+ EVP_SignUpdate(&ctx, host.ptr, ntohl(host.vallen));
+ rval = EVP_SignFinal(&ctx, host.sig, &len, &private_key);
+ if (rval != RV_OK || len != private_key.bits / 8) {
+ msyslog(LOG_ERR, "crypto: host signature fails %x",
+ rval);
+ exit (-1);
+ }
+ host.siglen = ntohl(len);
+
+ /*
+ * Sign certificate and timestamps.
+ */
+ if (certif.vallen != 0) {
+ certif.tstamp = htonl(tstamp);
+ EVP_SignInit(&ctx, DA_MD5);
+ EVP_SignUpdate(&ctx, (u_char *)&certif, 12);
+ EVP_SignUpdate(&ctx, certif.ptr,
+ ntohl(certif.vallen));
+ rval = EVP_SignFinal(&ctx, certif.sig, &len,
+ &private_key);
+ if (rval != RV_OK || len != private_key.bits / 8) {
+ msyslog(LOG_ERR,
+ "crypto: certificate signature fails %x",
+ rval);
+ exit (-1);
+ }
+ certif.siglen = ntohl(len);
+ }
+
+ /*
+ * Sign agreement parameters and timestamps.
+ */
+ if (dhparam.vallen != 0) {
+ dhparam.tstamp = htonl(tstamp);
+ EVP_SignInit(&ctx, DA_MD5);
+ EVP_SignUpdate(&ctx, (u_char *)&dhparam, 12);
+ EVP_SignUpdate(&ctx, dhparam.ptr,
+ ntohl(dhparam.vallen));
+ rval = EVP_SignFinal(&ctx, dhparam.sig, &len,
+ &private_key);
+ if (rval != RV_OK || len != private_key.bits / 8) {
+ msyslog(LOG_ERR,
+ "crypto: parameters signature fails %x",
+ rval);
+ exit (-11);
+ }
+ dhparam.siglen = ntohl(len);
+
+ /*
+ * Compute public value.
+ */
+ R_RandomInit(&randomstr);
+ R_GetRandomBytesNeeded(&len, &randomstr);
+ for (i = 0; i < len; i++) {
+ temp = RANDOM;
+ R_RandomUpdate(&randomstr, (u_char *)&temp, 1);
+ }
+ rval = R_SetupDHAgreement(dhpub.ptr, dh_private,
+ dh_keyLen, &dh_params, &randomstr);
+ if (rval != RV_OK) {
+ msyslog(LOG_ERR,
+ "crypto: invalid public value");
+ exit (-1);
+ }
+
+ /*
+ * Sign public value and timestamps.
+ */
+ dhpub.tstamp = htonl(tstamp);
+ EVP_SignInit(&ctx, DA_MD5);
+ EVP_SignUpdate(&ctx, (u_char *)&dhpub, 12);
+ EVP_SignUpdate(&ctx, dhpub.ptr, ntohl(dhpub.vallen));
+ rval = EVP_SignFinal(&ctx, dhpub.sig, &len,
+ &private_key);
+ if (rval != RV_OK || len != private_key.bits / 8) {
+ msyslog(LOG_ERR,
+ "crypto: public value signature fails %x",
+ rval);
+ exit (-1);
+ }
+ dhpub.siglen = ntohl(len);
+ }
+
+ /*
+ * Sign leapseconds table and timestamps.
+ */
+ if (tai_leap.vallen != 0) {
+ tai_leap.tstamp = htonl(tstamp);
+ EVP_SignInit(&ctx, DA_MD5);
+ EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
+ EVP_SignUpdate(&ctx, tai_leap.ptr,
+ ntohl(tai_leap.vallen));
+ rval = EVP_SignFinal(&ctx, tai_leap.sig, &len,
+ &private_key);
+ if (rval != RV_OK || len != private_key.bits / 8) {
+ msyslog(LOG_ERR,
+ "crypto: leapseconds signature fails %x",
+ rval);
+ exit (-1);
+ }
+ tai_leap.siglen = ntohl(len);
+ }
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "cypto_agree: ts %u host %u par %u pub %u leap %u\n",
+ tstamp, ntohl(host.fstamp), ntohl(dhparam.fstamp),
+ ntohl(dhpub.fstamp), ntohl(tai_leap.fstamp));
+#endif
+}
+
+
+/*
+ * crypto_rsa - read RSA key, decode and check for errors.
+ */
+static u_int
+crypto_rsa(
+ char *cp, /* file name */
+ u_char *key, /* key pointer */
+ u_int keylen /* key length */
+ )
+{
+ FILE *str; /* file handle */
+ u_char buf[MAX_LINLEN]; /* file line buffer */
+ u_char encoded_key[MAX_ENCLEN]; /* encoded key buffer */
+ char filename[MAXFILENAME]; /* name of parameter file */
+ char linkname[MAXFILENAME]; /* file link (for filestamp) */
+ u_int fstamp; /* filestamp */
+ u_int bits, len;
+ char *rptr;
+ int rval;
+
+ /*
+ * Open the file and discard comment lines. If the first
+ * character of the file name is not '/', prepend the keys
+ * directory string.
+ */
+ if (*cp == '/')
+ strcpy(filename, cp);
+ else
+ snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
+ str = fopen(filename, "r");
+ if (str == NULL) {
+ msyslog(LOG_ERR, "crypto: RSA file %s not found",
+ filename);
+ exit (-1);
+ }
+
+ /*
+ * Ignore initial comments and empty lines.
+ */
+ while ((rptr = fgets(buf, MAX_LINLEN - 1, str)) != NULL) {
+ len = strlen(buf);
+ if (len < 1)
+ continue;
+ if (*buf == '#' || *buf == '\r' || *buf == '\0')
+ continue;
+ break;
+ }
+
+ /*
+ * We are rather paranoid here, since an intruder might cause a
+ * coredump by infiltrating a naughty key. The line must contain
+ * a single integer followed by a PEM encoded, null-terminated
+ * string.
+ */
+ if (rptr == NULL)
+ rval = RV_DAT;
+ else if (sscanf(buf, "%d %s", &bits, encoded_key) != 2)
+ rval = RV_DAT;
+ else if (R_DecodePEMBlock(&buf[sizeof(u_int)], &len,
+ encoded_key, strlen(encoded_key)))
+ rval = RV_DEC;
+ else if ((len += sizeof(u_int)) != keylen)
+ rval = RV_KEY;
+ else if (bits < MIN_RSA_MODULUS_BITS || bits >
+ MAX_RSA_MODULUS_BITS)
+ rval = RV_KEY;
+ else
+ rval = RV_OK;
+ if (rval != RV_OK) {
+ fclose(str);
+ msyslog(LOG_ERR, "crypto: RSA file %s error %x", cp,
+ rval);
+ exit (-1);
+ }
+ fclose(str);
+ *(u_int *)buf = bits;
+ memcpy(key, buf, keylen);
+
+ /*
+ * Extract filestamp if present.
+ */
+ rval = readlink(filename, linkname, MAXFILENAME - 1);
+ if (rval > 0) {
+ linkname[rval] = '\0';
+ rptr = strrchr(linkname, '.');
+ } else {
+ rptr = strrchr(filename, '.');
+ }
+ if (rptr != NULL)
+ sscanf(++rptr, "%u", &fstamp);
+ else
+ fstamp = 0;
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_rsa: key file %s link %d fs %u modulus %d\n",
+ cp, rval, fstamp, bits);
+#endif
+ return (fstamp);
+}
+
+
+/*
+ * crypto_cert - read certificate
+ */
+static void
+crypto_cert(
+ char *cp /* file name */
+ )
+{
+ u_char buf[5000]; /* file line buffer */
+ char filename[MAXFILENAME]; /* name of certificate file */
+ char linkname[MAXFILENAME]; /* file link (for filestamp) */
+ u_int fstamp; /* filestamp */
+ u_int32 *pp;
+ u_int len;
+ char *rptr;
+ int rval, fd;
+
+ /*
+ * Open the file and discard comment lines. If the first
+ * character of the file name is not '/', prepend the keys
+ * directory string. If the file is not found, not to worry; it
+ * can be retrieved over the net. But, if it is found with
+ * errors, we crash and burn.
+ */
+ if (*cp == '/')
+ strcpy(filename, cp);
+ else
+ snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
+ fd = open(filename, O_RDONLY, 0777);
+ if (fd <= 0) {
+ msyslog(LOG_INFO,
+ "crypto: certificate file %s not found",
+ filename);
+ return;
+ }
+
+ /*
+ * We are rather paranoid here, since an intruder might cause a
+ * coredump by infiltrating naughty values.
+ */
+ rval = RV_OK;
+ len = read(fd, buf, 5000);
+ close(fd);
+ if (rval != RV_OK) {
+ msyslog(LOG_ERR,
+ "crypto: certificate file %s error %d", cp,
+ rval);
+ exit (-1);
+ }
+
+ /*
+ * The extension field entry consists of the raw certificate.
+ */
+ certif.vallen = htonl(200); /* xxxxxxxxxxxxxxxxxx */
+ pp = emalloc(len);
+ certif.ptr = (u_char *)pp;
+ memcpy(pp, buf, len);
+ certif.sig = emalloc(private_key.bits / 8);
+ crypto_flags |= CRYPTO_FLAG_CERT;
+
+ /*
+ * Extract filestamp if present.
+ */
+ rval = readlink(filename, linkname, MAXFILENAME - 1);
+ if (rval > 0) {
+ linkname[rval] = '\0';
+ rptr = strrchr(linkname, '.');
+ } else {
+ rptr = strrchr(filename, '.');
+ }
+ if (rptr != NULL)
+ sscanf(++rptr, "%u", &fstamp);
+ else
+ fstamp = 0;
+ certif.fstamp = htonl(fstamp);
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_cert: certif file %s link %d fs %u len %d\n",
+ cp, rval, fstamp, len);
+#endif
+}
+
+
+/*
+ * crypto_dh - read agreement parameters, decode and check for errors.
+ */
+static void
+crypto_dh(
+ char *cp /* file name */
+ )
+{
+ FILE *str; /* file handle */
+ u_char buf[MAX_LINLEN]; /* file line buffer */
+ u_char encoded_key[MAX_ENCLEN]; /* encoded key buffer */
+ u_char prime[MAX_KEYLEN]; /* decoded prime */
+ u_char generator[MAX_KEYLEN]; /* decode generator */
+ u_int primelen; /* prime length (octets) */
+ u_int generatorlen; /* generator length (octets) */
+ char filename[MAXFILENAME]; /* name of parameter file */
+ char linkname[MAXFILENAME]; /* file link (for filestamp) */
+ u_int fstamp; /* filestamp */
+ u_int32 *pp;
+ u_int len;
+ char *rptr;
+ int rval;
+
+ /*
+ * Open the file and discard comment lines. If the first
+ * character of the file name is not '/', prepend the keys
+ * directory string. If the file is not found, not to worry; it
+ * can be retrieved over the net. But, if it is found with
+ * errors, we crash and burn.
+ */
+ if (*cp == '/')
+ strcpy(filename, cp);
+ else
+ snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
+ str = fopen(filename, "r");
+ if (str == NULL) {
+ msyslog(LOG_INFO,
+ "crypto: parameters file %s not found", filename);
+ return;
+ }
+
+ /*
+ * Ignore initial comments and empty lines.
+ */
+ while ((rptr = fgets(buf, MAX_LINLEN - 1, str)) != NULL) {
+ if (strlen(buf) < 1)
+ continue;
+ if (*buf == '#' || *buf == '\r' || *buf == '\0')
+ continue;
+ break;
+ }
+
+ /*
+ * We are rather paranoid here, since an intruder might cause a
+ * coredump by infiltrating a naughty key. There must be two
+ * lines; the first contains the prime, the second the
+ * generator. Each line must contain a single integer followed
+ * by a PEM encoded, null-terminated string.
+ */
+ if (rptr == NULL)
+ rval = RV_DAT;
+ else if (sscanf(buf, "%u %s", &primelen, encoded_key) != 2)
+ rval = RV_DAT;
+ else if (primelen > MAX_KEYLEN)
+ rval = RV_KEY;
+ else if (R_DecodePEMBlock(prime, &len, encoded_key,
+ strlen(encoded_key)))
+ rval = RV_DEC;
+ else if (primelen != len || primelen >
+ DECODED_CONTENT_LEN(strlen(encoded_key)))
+ rval = RV_DAT;
+ else if (fscanf(str, "%u %s", &generatorlen, encoded_key) != 2)
+ rval = RV_DAT;
+ else if (generatorlen > MAX_KEYLEN)
+ rval = RV_KEY;
+ else if (R_DecodePEMBlock(generator, &len, encoded_key,
+ strlen(encoded_key)))
+ rval = RV_DEC;
+ else if (generatorlen != len || generatorlen >
+ DECODED_CONTENT_LEN(strlen(encoded_key)))
+ rval = RV_DAT;
+ else
+ rval = RV_OK;
+ if (rval != RV_OK) {
+ msyslog(LOG_ERR,
+ "crypto: parameters file %s error %x", cp,
+ rval);
+ exit (-1);
+ }
+ fclose(str);
+
+ /*
+ * Initialize agreement parameters and extension field in
+ * network byte order. Note the private key length is set
+ * arbitrarily at half the prime length.
+ */
+ len = 4 + primelen + 4 + generatorlen;
+ dhparam.vallen = htonl(len);
+ pp = emalloc(len);
+ dhparam.ptr = (u_char *)pp;
+ *pp++ = htonl(primelen);
+ memcpy(pp, prime, primelen);
+ dh_params.prime = (u_char *)pp;
+ pp += primelen / 4;
+ *pp++ = htonl(generatorlen);
+ memcpy(pp, &generator, generatorlen);
+ dh_params.generator = (u_char *)pp;
+
+ dh_params.primeLen = primelen;
+ dh_params.generatorLen = generatorlen;
+ dh_keyLen = primelen / 2;
+ dh_private = emalloc(dh_keyLen);
+ dhparam.sig = emalloc(private_key.bits / 8);
+ crypto_flags |= CRYPTO_FLAG_DH;
+
+ /*
+ * Initialize public value extension field.
+ */
+ dhpub.vallen = htonl(dh_params.primeLen);
+ dhpub.ptr = emalloc(dh_params.primeLen);
+ dhpub.sig = emalloc(private_key.bits / 8);
+
+ /*
+ * Extract filestamp if present.
+ */
+ rval = readlink(filename, linkname, MAXFILENAME - 1);
+ if (rval > 0) {
+ linkname[rval] = '\0';
+ rptr = strrchr(linkname, '.');
+ } else {
+ rptr = strrchr(filename, '.');
+ }
+ if (rptr != NULL)
+ sscanf(++rptr, "%u", &fstamp);
+ else
+ fstamp = 0;
+ dhparam.fstamp = htonl(fstamp);
+ dhpub.fstamp = htonl(fstamp);
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_dh: pars file %s link %d fs %u prime %u gen %u\n",
+ cp, rval, fstamp, dh_params.primeLen,
+ dh_params.generatorLen);
+#endif
+}
+
+
+/*
+ * crypto_tai - read leapseconds table and check for errors.
+ */
+static void
+crypto_tai(
+ char *cp /* file name */
+ )
+{
+ FILE *str; /* file handle */
+ u_char buf[MAX_LINLEN]; /* file line buffer */
+ u_int leapsec[MAX_LEAP]; /* NTP time at leaps */
+ u_int offset; /* offset at leap (s) */
+ char filename[MAXFILENAME]; /* name of leapseconds file */
+ char linkname[MAXFILENAME]; /* file link (for filestamp) */
+ u_int fstamp; /* filestamp */
+ u_int32 *pp;
+ u_int len;
+ char *rptr;
+ int rval, i;
+#ifdef KERNEL_PLL
+#if NTP_API > 3
+ struct timex ntv; /* kernel interface structure */
+#endif /* NTP_API */
+#endif /* KERNEL_PLL */
+
+ /*
+ * Open the file and discard comment lines. If the first
+ * character of the file name is not '/', prepend the keys
+ * directory string. If the file is not found, not to worry; it
+ * can be retrieved over the net. But, if it is found with
+ * errors, we crash and burn.
+ */
+ if (*cp == '/')
+ strcpy(filename, cp);
+ else
+ snprintf(filename, MAXFILENAME, "%s/%s", keysdir, cp);
+ str = fopen(filename, "r");
+ if (str == NULL) {
+ msyslog(LOG_INFO,
+ "crypto: leapseconds file %s not found",
+ filename);
+ return;
+ }
+
+ /*
+ * We are rather paranoid here, since an intruder might cause a
+ * coredump by infiltrating naughty values. Empty lines and
+ * comments are ignored. Other lines must begin with two
+ * integers followed by junk or comments. The first integer is
+ * the NTP seconds of leap insertion, the second is the offset
+ * of TAI relative to UTC after that insertion. The second word
+ * must equal the initial insertion of ten seconds on 1 January
+ * 1972 plus one second for each succeeding insertion.
+ */
+ i = 0;
+ rval = RV_OK;
+ while (i < MAX_LEAP) {
+ rptr = fgets(buf, MAX_LINLEN - 1, str);
+ if (rptr == NULL)
+ break;
+ if (strlen(buf) < 1)
+ continue;
+ if (*buf == '#')
+ continue;
+ if (sscanf(buf, "%u %u", &leapsec[i], &offset) != 2)
+ continue;
+ if (i != offset - TAI_1972) {
+ rval = RV_DAT;
+ break;
+ }
+ i++;
+ }
+ fclose(str);
+ if (rval != RV_OK || i == 0) {
+ msyslog(LOG_ERR,
+ "crypto: leapseconds file %s error %d", cp,
+ rval);
+ exit (-1);
+ }
+
+ /*
+ * The extension field table entries consists of the NTP seconds
+ * of leap insertion in reverse order, so that the most recent
+ * insertion is the first entry in the table.
+ */
+ len = i * 4;
+ tai_leap.vallen = htonl(len);
+ pp = emalloc(len);
+ tai_leap.ptr = (u_char *)pp;
+ for (; i >= 0; i--) {
+ *pp++ = htonl(leapsec[i]);
+ }
+ tai_leap.sig = emalloc(private_key.bits / 8);
+ crypto_flags |= CRYPTO_FLAG_TAI;
+ sys_tai = len / 4 + TAI_1972 - 1;
+#ifdef KERNEL_PLL
+#if NTP_API > 3
+ ntv.modes = MOD_TAI;
+ ntv.constant = sys_tai;
+ if (ntp_adjtime(&ntv) == TIME_ERROR)
+ msyslog(LOG_ERR,
+ "crypto: kernel TAI update failed");
+#endif /* NTP_API */
+#endif /* KERNEL_PLL */
+
+
+ /*
+ * Extract filestamp if present.
+ */
+ rval = readlink(filename, linkname, MAXFILENAME - 1);
+ if (rval > 0) {
+ linkname[rval] = '\0';
+ rptr = strrchr(linkname, '.');
+ } else {
+ rptr = strrchr(filename, '.');
+ }
+ if (rptr != NULL)
+ sscanf(++rptr, "%u", &fstamp);
+ else
+ fstamp = 0;
+ tai_leap.fstamp = htonl(fstamp);
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "crypto_tai: leapseconds file %s link %d fs %u offset %u\n",
+ cp, rval, fstamp, ntohl(tai_leap.vallen) / 4 +
+ TAI_1972);
+#endif
+}
+
+
+/*
+ * crypto_config - configure crypto data from crypto configuration
+ * command.
+ */
+void
+crypto_config(
+ int item, /* configuration item */
+ char *cp /* file name */
+ )
+{
+ switch (item) {
+
+ /*
+ * Initialize flags
+ */
+ case CRYPTO_CONF_FLAGS:
+ sscanf(cp, "%x", &crypto_flags);
+ break;
+
+ /*
+ * Set private key file name.
+ */
+ case CRYPTO_CONF_PRIV:
+ private_key_file = emalloc(strlen(cp) + 1);
+ strcpy(private_key_file, cp);
+ break;
+
+ /*
+ * Set public key file name.
+ */
+ case CRYPTO_CONF_PUBL:
+ public_key_file = emalloc(strlen(cp) + 1);
+ strcpy(public_key_file, cp);
+ break;
+
+ /*
+ * Set certificate file name.
+ */
+ case CRYPTO_CONF_CERT:
+ certif_file = emalloc(strlen(cp) + 1);
+ strcpy(certif_file, cp);
+ break;
+
+ /*
+ * Set agreement parameter file name.
+ */
+ case CRYPTO_CONF_DH:
+ dh_params_file = emalloc(strlen(cp) + 1);
+ strcpy(dh_params_file, cp);
+ break;
+
+ /*
+ * Set leapseconds table file name.
+ */
+ case CRYPTO_CONF_LEAP:
+ tai_leap_file = emalloc(strlen(cp) + 1);
+ strcpy(tai_leap_file, cp);
+ break;
+
+ /*
+ * Set crypto keys directory.
+ */
+ case CRYPTO_CONF_KEYS:
+ keysdir = emalloc(strlen(cp) + 1);
+ strcpy(keysdir, cp);
+ break;
+ }
+ crypto_flags |= CRYPTO_FLAG_ENAB;
+}
+# else
+int ntp_crypto_bs_pubkey;
+# endif /* PUBKEY */
+#else
+int ntp_crypto_bs_autokey;
+#endif /* AUTOKEY */
diff --git a/contrib/ntp/ntpd/ntp_intres.c b/contrib/ntp/ntpd/ntp_intres.c
index e9a387e..9653fdd 100644
--- a/contrib/ntp/ntpd/ntp_intres.c
+++ b/contrib/ntp/ntpd/ntp_intres.c
@@ -20,19 +20,25 @@
# include <config.h>
#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <netdb.h>
-#include <signal.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_request.h"
#include "ntp_stdlib.h"
#include "ntp_syslog.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <signal.h>
+
+/**/
+#include <netinet/in.h>
+#include <arpa/inet.h>
+/**/
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h> /* MAXHOSTNAMELEN (often) */
+#endif
+
#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
/*
@@ -52,6 +58,7 @@ struct conf_entry {
#define ce_flags ce_config.flags
#define ce_ttl ce_config.ttl
#define ce_keyid ce_config.keyid
+#define ce_keystr ce_config.keystr
/*
* confentries is a pointer to the list of configuration entries
@@ -73,7 +80,6 @@ static struct conf_entry *confentries = NULL;
#define MAXRESOLVE 32
#define CONFIG_TIME 2
#define ALARM_TIME 30
-
#define SLEEPTIME 2
static volatile int config_timer = 0;
@@ -107,7 +113,8 @@ static int resolve_value; /* next value of resolve timer */
#define TOK_FLAGS 5
#define TOK_TTL 6
#define TOK_KEYID 7
-#define NUMTOK 8
+#define TOK_KEYSTR 8
+#define NUMTOK 9
#define MAXLINESIZE 512
@@ -120,7 +127,7 @@ static int sockfd = -1;
/* stuff to be filled in by caller */
-u_long req_keyid; /* request keyid */
+keyid_t req_keyid; /* request keyid */
char *req_file; /* name of the file with configuration info */
/* end stuff to be filled in */
@@ -129,7 +136,8 @@ char *req_file; /* name of the file with configuration info */
static RETSIGTYPE bong P((int));
static void checkparent P((void));
static void removeentry P((struct conf_entry *));
-static void addentry P((char *, int, int, int, int, int, int, u_long));
+static void addentry P((char *, int, int, int, int, u_int,
+ int, keyid_t, char *));
static int findhostaddr P((struct conf_entry *));
static void openntp P((void));
static int request P((struct conf_peer *));
@@ -137,10 +145,48 @@ static char * nexttoken P((char **));
static void readconf P((FILE *, char *));
static void doconfigure P((int));
+struct ntp_res_t_pkt { /* Tagged packet: */
+ void *tag; /* For the caller */
+ u_int32 paddr; /* IP to look up, or 0 */
+ char name[MAXHOSTNAMELEN]; /* Name to look up (if 1st byte is not 0) */
+};
+
+struct ntp_res_c_pkt { /* Control packet: */
+ char name[MAXHOSTNAMELEN];
+ u_int32 paddr;
+ int mode;
+ int version;
+ int minpoll;
+ int maxpoll;
+ u_int flags;
+ int ttl;
+ keyid_t keyid;
+ u_char keystr[MAXFILENAME];
+};
+
+
/*
- * assumes: req_key, req_keyid, conffile valid
- * syslog still open
+ * ntp_res_recv: Process an answer from the resolver
*/
+
+void
+ntp_res_recv(void)
+{
+ /*
+ We have data ready on our descriptor.
+ It may be an EOF, meaning the resolver process went away.
+ Otherwise, it will be an "answer".
+ */
+}
+
+
+/*
+ * ntp_intres needs;
+ *
+ * req_key(???), req_keyid, req_file valid
+ * syslog still open
+ */
+
void
ntp_intres(void)
{
@@ -149,7 +195,7 @@ ntp_intres(void)
sigset_t set;
sigemptyset(&set);
-#endif /* NTP_POSIX_SOURCE */
+#endif /* HAVE_SIGSUSPEND */
#ifdef DEBUG
if (debug > 1) {
@@ -160,7 +206,7 @@ ntp_intres(void)
/* check out auth stuff */
if (sys_authenticate) {
if (!authistrusted(req_keyid)) {
- msyslog(LOG_ERR, "invalid request keyid %lu",
+ msyslog(LOG_ERR, "invalid request keyid %08x",
req_keyid );
exit(1);
}
@@ -180,7 +226,7 @@ ntp_intres(void)
(void) fclose(in);
if (!debug )
- (void) unlink(req_file);
+ (void) unlink(req_file);
/*
* Sleep a little to make sure the server is completely up
@@ -192,12 +238,13 @@ ntp_intres(void)
* Make a first cut at resolving the bunch
*/
doconfigure(1);
- if (confentries == NULL)
+ if (confentries == NULL) {
#if defined SYS_WINNT
- ExitThread(0); /* Don't want to kill whole NT process */
+ ExitThread(0); /* Don't want to kill whole NT process */
#else
- exit(0); /* done that quick */
+ exit(0); /* done that quick */
#endif
+ }
/*
* Here we've got some problem children. Set up the timer
@@ -221,7 +268,8 @@ ntp_intres(void)
resolve_value <<= 1;
resolve_timer = resolve_value;
#ifdef DEBUG
- msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
+ if (debug > 2)
+ msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
#endif
config_timer = CONFIG_TIME;
doconfigure(1);
@@ -229,7 +277,8 @@ ntp_intres(void)
} else if (config_timer == 0) {
config_timer = CONFIG_TIME;
#ifdef DEBUG
- msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
+ if (debug > 2)
+ msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
#endif
doconfigure(0);
continue;
@@ -239,11 +288,11 @@ ntp_intres(void)
* There is a race in here. Is okay, though, since
* all it does is delay things by 30 seconds.
*/
-#ifdef HAVE_SIGSUSPEND
+# ifdef HAVE_SIGSUSPEND
sigsuspend(&set);
-#else
+# else
sigpause(0);
-#endif /* HAVE_SIGSUSPEND */
+# endif /* HAVE_SIGSUSPEND */
#else
if (config_timer > 0)
config_timer--;
@@ -336,17 +385,25 @@ addentry(
int version,
int minpoll,
int maxpoll,
- int flags,
+ u_int flags,
int ttl,
- u_long keyid
+ keyid_t keyid,
+ char *keystr
)
{
register char *cp;
register struct conf_entry *ce;
unsigned int len;
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO,
+ "intres: <%s> %d %d %d %d %x %d %x %s\n", name,
+ mode, version, minpoll, maxpoll, flags, ttl, keyid,
+ keystr);
+#endif
len = strlen(name) + 1;
- cp = (char*)emalloc(len);
+ cp = (char *)emalloc(len);
memmove(cp, name, len);
ce = (struct conf_entry *)emalloc(sizeof(struct conf_entry));
@@ -359,6 +416,7 @@ addentry(
ce->ce_flags = (u_char)flags;
ce->ce_ttl = (u_char)ttl;
ce->ce_keyid = keyid;
+ strncpy((char *)ce->ce_keystr, keystr, MAXFILENAME);
ce->ce_next = NULL;
if (confentries == NULL) {
@@ -375,12 +433,12 @@ addentry(
/*
- * findhostaddr - resolve a host name into an address
+ * findhostaddr - resolve a host name into an address (Or vice-versa)
*
- * The routine sticks the address into the entry's ce_peeraddr if it
- * gets one. It returns 1 for "success" and 0 for an uncorrectable
- * failure. Note that "success" includes try again errors. You can
- * tell that you got a try again since ce_peeraddr will still be zero.
+ * Given one of {ce_peeraddr,ce_name}, find the other one.
+ * It returns 1 for "success" and 0 for an uncorrectable failure.
+ * Note that "success" includes try again errors. You can tell that you
+ * got a "try again" since {ce_peeraddr,ce_name} will still be zero.
*/
static int
findhostaddr(
@@ -388,31 +446,80 @@ findhostaddr(
)
{
struct hostent *hp;
+ struct in_addr in;
checkparent(); /* make sure our guy is still running */
- hp = gethostbyname(entry->ce_name);
+ if (entry->ce_name && entry->ce_peeraddr) {
+ /* HMS: Squawk? */
+ msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");
+ return 1;
+ }
+
+ if (!entry->ce_name && !entry->ce_peeraddr) {
+ msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
+ return 0;
+ }
+
+ if (entry->ce_name) {
+#ifdef DEBUG
+ if (debug > 2)
+ msyslog(LOG_INFO, "findhostaddr: Resolving <%s>",
+ entry->ce_name);
+#endif /* DEBUG */
+ hp = gethostbyname(entry->ce_name);
+ } else {
+#ifdef DEBUG
+ if (debug > 2)
+ msyslog(LOG_INFO, "findhostaddr: Resolving %x>",
+ entry->ce_peeraddr);
+#endif
+ in.s_addr = entry->ce_peeraddr;
+ hp = gethostbyaddr((const char *)&in,
+ sizeof entry->ce_peeraddr,
+ AF_INET);
+ }
if (hp == NULL) {
-#ifndef NODNS
/*
* If the resolver is in use, see if the failure is
* temporary. If so, return success.
*/
if (h_errno == TRY_AGAIN)
return (1);
-#endif
return (0);
}
- /*
- * Use the first address. We don't have any way to
- * tell preferences and older gethostbyname() implementations
- * only return one.
- */
- memmove((char *)&(entry->ce_peeraddr),
- (char *)hp->h_addr,
- sizeof(struct in_addr));
+ if (entry->ce_name) {
+#ifdef DEBUG
+ if (debug > 2)
+ msyslog(LOG_INFO, "findhostaddr: name resolved.");
+#endif
+ /*
+ * Use the first address. We don't have any way to tell
+ * preferences and older gethostbyname() implementations
+ * only return one.
+ */
+ memmove((char *)&(entry->ce_peeraddr),
+ (char *)hp->h_addr,
+ sizeof(struct in_addr));
+ if (entry->ce_keystr[0] == '*')
+ strncpy((char *)&(entry->ce_keystr), hp->h_name,
+ MAXFILENAME);
+ } else {
+ char *cp;
+ size_t s;
+
+#ifdef DEBUG
+ if (debug > 2)
+ msyslog(LOG_INFO, "findhostaddr: address resolved.");
+#endif
+ s = strlen(hp->h_name) + 1;
+ cp = emalloc(s);
+ strcpy(cp, hp->h_name);
+ entry->ce_name = cp;
+ }
+
return (1);
}
@@ -460,7 +567,7 @@ openntp(void)
#endif /* O_NONBLOCK */
#else /* SYS_WINNT */
{
- int on=1;
+ 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 */
@@ -470,7 +577,7 @@ openntp(void)
if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
- msyslog(LOG_ERR, "connect() failed: %m");
+ msyslog(LOG_ERR, "openntp: connect() failed: %m");
exit(1);
}
}
@@ -531,6 +638,11 @@ request(
reqpkt.request = REQ_CONFIG; /* configure a new peer */
reqpkt.err_nitems = ERR_NITEMS(0, 1); /* one item */
reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer));
+ /* Make sure mbz_itemsize <= sizeof reqpkt.data */
+ if (sizeof(struct conf_peer) > sizeof (reqpkt.data)) {
+ msyslog(LOG_ERR, "Bletch: conf_peer is too big for reqpkt.data!");
+ exit(1);
+ }
memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer));
reqpkt.keyid = htonl(req_keyid);
@@ -552,7 +664,7 @@ request(
}
#else
/* In the NT world, documentation seems to indicate that there
- * exist _write and _read routines that can be used to so blocking
+ * exist _write and _read routines that can be used to do blocking
* I/O on sockets. Problem is these routines require a socket
* handle obtained through the _open_osf_handle C run-time API
* of which there is no explanation in the documentation. We need
@@ -603,8 +715,8 @@ request(
}
else if (n == 0)
{
- if(debug)
- msyslog(LOG_DEBUG, "select() returned 0.");
+ if (debug)
+ msyslog(LOG_INFO, "select() returned 0.");
return 0;
}
@@ -814,7 +926,7 @@ readconf(
register int i;
char *token[NUMTOK];
u_long intval[NUMTOK];
- int flags;
+ u_int flags;
char buf[MAXLINESIZE];
char *bp;
@@ -830,7 +942,7 @@ readconf(
}
}
- for (i = 1; i < NUMTOK; i++) {
+ for (i = 1; i < NUMTOK - 1; i++) {
if (!atouint(token[i], &intval[i])) {
msyslog(LOG_ERR,
"format error for integer token `%s', file `%s', quitting",
@@ -868,7 +980,7 @@ readconf(
}
if ((intval[TOK_FLAGS] & ~(FLAG_AUTHENABLE | FLAG_PREFER |
- FLAG_NOSELECT | FLAG_BURST | FLAG_SKEY))
+ FLAG_NOSELECT | FLAG_BURST | FLAG_IBURST | FLAG_SKEY))
!= 0) {
msyslog(LOG_ERR, "invalid flags (%ld) in file %s",
intval[TOK_FLAGS], name);
@@ -884,6 +996,8 @@ readconf(
flags |= CONF_FLAG_NOSELECT;
if (intval[TOK_FLAGS] & FLAG_BURST)
flags |= CONF_FLAG_BURST;
+ if (intval[TOK_FLAGS] & FLAG_IBURST)
+ flags |= CONF_FLAG_IBURST;
if (intval[TOK_FLAGS] & FLAG_SKEY)
flags |= CONF_FLAG_SKEY;
@@ -893,7 +1007,7 @@ readconf(
addentry(token[TOK_HOSTNAME], (int)intval[TOK_HMODE],
(int)intval[TOK_VERSION], (int)intval[TOK_MINPOLL],
(int)intval[TOK_MAXPOLL], flags, (int)intval[TOK_TTL],
- intval[TOK_KEYID]);
+ intval[TOK_KEYID], token[TOK_KEYSTR]);
}
}
@@ -909,16 +1023,12 @@ doconfigure(
register struct conf_entry *ce;
register struct conf_entry *ceremove;
-#ifdef DEBUG
- if (debug > 1)
- msyslog(LOG_INFO, "doconfigure(%d)", dores);
-#endif
-
ce = confentries;
while (ce != NULL) {
#ifdef DEBUG
if (debug > 1)
- msyslog(LOG_INFO, "doconfigure: <%s> has peeraddr %#x",
+ msyslog(LOG_INFO,
+ "doconfigure: <%s> has peeraddr %#x",
ce->ce_name, ce->ce_peeraddr);
#endif
if (dores && ce->ce_peeraddr == 0) {
@@ -931,28 +1041,10 @@ doconfigure(
removeentry(ceremove);
continue;
}
-#ifdef DEBUG
- if (debug > 1) {
- msyslog(LOG_INFO,
- "doconfigure:findhostaddr() worked");
- }
-#endif
}
if (ce->ce_peeraddr != 0) {
-#ifdef DEBUG
- if (debug > 1) {
- msyslog(LOG_INFO,
- "doconfigure: calling request()");
- }
-#endif
if (request(&ce->ce_config)) {
-#ifdef DEBUG
- if (debug > 1) {
- msyslog(LOG_INFO,
- "doconfigure: request() OK, removing this entry");
- }
-#endif
ceremove = ce;
ce = ceremove->ce_next;
removeentry(ceremove);
@@ -961,7 +1053,7 @@ doconfigure(
#ifdef DEBUG
if (debug > 1) {
msyslog(LOG_INFO,
- "doconfigure: request() FAILED, maybe next time.");
+ "doconfigure: request() FAILED, maybe next time.");
}
#endif
}
diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c
index e209d6d..23c0cb7 100644
--- a/contrib/ntp/ntpd/ntp_io.c
+++ b/contrib/ntp/ntpd/ntp_io.c
@@ -7,15 +7,19 @@
# include <config.h>
#endif
+#include "ntp_machine.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "iosignal.h"
+#include "ntp_refclock.h"
+#include "ntp_if.h"
+#include "ntp_stdlib.h"
+
#include <stdio.h>
#include <signal.h>
-#include <sys/types.h>
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
@@ -37,14 +41,6 @@
# include <ifaddrs.h>
#endif
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "iosignal.h"
-#include "ntp_refclock.h"
-#include "ntp_if.h"
-#include "ntp_stdlib.h"
-
#if defined(VMS) /* most likely UCX-specific */
#include <UCX$INETDEF.H>
@@ -116,10 +112,10 @@ u_long io_timereset; /* time counters were reset */
/*
* Interface stuff
*/
-struct interface *any_interface; /* pointer to default interface */
-struct interface *loopback_interface; /* point to loopback interface */
-static struct interface inter_list[MAXINTERFACES];
-static int ninterfaces;
+struct interface *any_interface; /* default interface */
+struct interface *loopback_interface; /* loopback interface */
+struct interface inter_list[MAXINTERFACES];
+int ninterfaces;
#ifdef REFCLOCK
/*
@@ -241,6 +237,7 @@ create_sockets(
inter_list[0].sent = 0;
inter_list[0].notsent = 0;
inter_list[0].flags = INT_BROADCAST;
+ any_interface = &inter_list[0];
#if _BSDI_VERSION >= 199510
#if _BSDI_VERSION >= 199701
@@ -274,46 +271,32 @@ create_sockets(
if ((ifap->ifa_flags & IFF_UP) == 0)
continue;
- if (ifap->ifa_flags & IFF_LOOPBACK)
- {
+ if (ifap->ifa_flags & IFF_LOOPBACK) {
sin = (struct sockaddr_in *)ifap->ifa_addr;
if (ntohl(sin->sin_addr.s_addr) != 0x7f000001)
- {
continue;
- }
}
-
inter_list[i].flags = 0;
if (ifap->ifa_flags & IFF_BROADCAST)
- inter_list[i].flags |= INT_BROADCAST;
-
- (void)strcpy(inter_list[i].name, ifap->ifa_name);
-
+ inter_list[i].flags |= INT_BROADCAST;
+ strcpy(inter_list[i].name, ifap->ifa_name);
sin = (struct sockaddr_in *)ifap->ifa_addr;
inter_list[i].sin = *sin;
inter_list[i].sin.sin_port = port;
-
- if (ifap->ifa_flags & IFF_LOOPBACK)
- {
+ if (ifap->ifa_flags & IFF_LOOPBACK) {
inter_list[i].flags = INT_LOOPBACK;
if (loopback_interface == NULL
|| ntohl(sin->sin_addr.s_addr) != 0x7f000001)
loopback_interface = &inter_list[i];
}
-
- if (inter_list[i].flags & INT_BROADCAST)
- {
+ if (inter_list[i].flags & INT_BROADCAST) {
sin = (struct sockaddr_in *)ifap->ifa_broadaddr;
inter_list[i].bcast = *sin;
inter_list[i].bcast.sin_port = port;
}
-
- if (ifap->ifa_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
- {
+ if (ifap->ifa_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) {
inter_list[i].mask.sin_addr.s_addr = 0xffffffff;
- }
- else
- {
+ } else {
sin = (struct sockaddr_in *)ifap->ifa_netmask;
inter_list[i].mask = *sin;
}
@@ -444,7 +427,7 @@ create_sockets(
continue;
}
# endif /* SYS_WINNT */
- memcpy(&ifreq, ifr, sizeof(ifreq));
+ ifreq = *ifr;
inter_list[i].flags = 0;
/* is it broadcast capable? */
# ifndef SYS_WINNT
@@ -614,9 +597,8 @@ create_sockets(
maxactivefd = 0;
FD_ZERO(&activefds);
for (i = 0; i < ninterfaces; i++) {
- inter_list[i].fd =
- open_socket(&inter_list[i].sin,
- inter_list[i].flags & INT_BROADCAST, 0);
+ inter_list[i].fd = open_socket(&inter_list[i].sin,
+ inter_list[i].flags & INT_BROADCAST, 0);
}
/*
@@ -653,12 +635,10 @@ create_sockets(
*/
resmask.sin_addr.s_addr = ~ (u_int32)0;
for (i = 1; i < ninterfaces; i++)
- hack_restrict(RESTRICT_FLAGS, &inter_list[i].sin, &resmask,
- RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
-
- any_interface = &inter_list[0];
+ hack_restrict(RESTRICT_FLAGS, &inter_list[i].sin, &resmask,
+ RESM_NTPONLY|RESM_INTERFACE, RES_IGNORE);
#ifdef DEBUG
- if (debug > 2) {
+ 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",
@@ -694,17 +674,19 @@ io_setbclient(void)
{
int i;
- for (i = 1; i < ninterfaces; i++)
- {
+ for (i = 1; i < ninterfaces; i++) {
if (!(inter_list[i].flags & INT_BROADCAST))
- continue;
+ continue;
+
if (inter_list[i].flags & INT_BCASTOPEN)
- continue;
+ continue;
+
#ifdef SYS_SOLARIS
inter_list[i].bcast.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
#ifdef OPEN_BCAST_SOCKET /* Was: !SYS_DOMAINOS && !SYS_LINUX */
- inter_list[i].bfd = open_socket(&inter_list[i].bcast, INT_BROADCAST, 1);
+ inter_list[i].bfd = open_socket(&inter_list[i].bcast,
+ INT_BROADCAST, 1);
inter_list[i].flags |= INT_BCASTOPEN;
#endif
}
@@ -728,50 +710,47 @@ io_multicast_add(
struct sockaddr_in *sinp;
iaddr.s_addr = addr;
-
- if (!IN_CLASSD(haddr))
- {
+ if (!IN_CLASSD(haddr)) {
msyslog(LOG_ERR,
- "cannot add multicast address %s as it is not class D",
+ "multicast address %s not class D",
inet_ntoa(iaddr));
return;
}
-
- for (i = 0; i < ninterfaces; i++)
- {
+ for (i = 0; i < ninterfaces; i++) {
/* Already have this address */
- if (inter_list[i].sin.sin_addr.s_addr == addr) return;
+ if (inter_list[i].sin.sin_addr.s_addr == addr)
+ return;
/* found a free slot */
if (inter_list[i].sin.sin_addr.s_addr == 0 &&
inter_list[i].fd <= 0 && inter_list[i].bfd <= 0 &&
- inter_list[i].flags == 0) break;
+ inter_list[i].flags == 0)
+ break;
}
sinp = &(inter_list[i].sin);
-
memset((char *)&mreq, 0, sizeof(mreq));
memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
sinp->sin_family = AF_INET;
sinp->sin_addr = iaddr;
sinp->sin_port = htons(123);
+ /*
+ * Try opening a socket for the specified class D address. This
+ * works under SunOS 4.x, but not OSF1 .. :-(
+ */
s = open_socket(sinp, 0, 1);
- /* Try opening a socket for the specified class D address */
- /* This works under SunOS 4.x, but not OSF1 .. :-( */
- if (s < 0)
- {
+ if (s < 0) {
memset((char *)&inter_list[i], 0, sizeof inter_list[0]);
i = 0;
/* HACK ! -- stuff in an address */
inter_list[i].bcast.sin_addr.s_addr = addr;
- msyslog(LOG_ERR, "...multicast address %s using wildcard socket",
- inet_ntoa(iaddr));
- }
- else
- {
+ msyslog(LOG_ERR,
+ "...multicast address %s using wildcard socket",
+ inet_ntoa(iaddr));
+ } else {
inter_list[i].fd = s;
inter_list[i].bfd = -1;
(void) strncpy(inter_list[i].name, "multicast",
- sizeof(inter_list[i].name));
+ sizeof(inter_list[i].name));
inter_list[i].mask.sin_addr.s_addr = htonl(~(u_int32)0);
}
@@ -781,19 +760,21 @@ io_multicast_add(
mreq.imr_multiaddr = iaddr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(inter_list[i].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *)&mreq, sizeof(mreq)) == -1)
- msyslog(LOG_ERR,
+ (char *)&mreq, sizeof(mreq)) == -1)
+ msyslog(LOG_ERR,
"setsockopt IP_ADD_MEMBERSHIP fails: %m for %x / %x (%s)",
- mreq.imr_multiaddr.s_addr, mreq.imr_interface.s_addr,
- inet_ntoa(iaddr));
+ mreq.imr_multiaddr.s_addr,
+ mreq.imr_interface.s_addr, inet_ntoa(iaddr));
inter_list[i].flags |= INT_MULTICAST;
- if (i >= ninterfaces) ninterfaces = i+1;
+ if (i >= ninterfaces)
+ ninterfaces = i+1;
#else /* MCAST */
struct in_addr iaddr;
iaddr.s_addr = addr;
- msyslog(LOG_ERR, "cannot add multicast address %s as no MCAST support",
- inet_ntoa(iaddr));
+ msyslog(LOG_ERR,
+ "cannot add multicast address %s as no MCAST support",
+ inet_ntoa(iaddr));
#endif /* MCAST */
}
@@ -886,8 +867,11 @@ open_socket(
int turn_off_reuse
)
{
- int fd, tos;
+ int fd;
int on = 1, off = 0;
+#if defined(IPTOS_LOWDELAY) && defined(IPPROTO_IP) && defined(IP_TOS)
+ int tos;
+#endif /* IPTOS_LOWDELAY && IPPROTO_IP && IP_TOS */
/* create a datagram (UDP) socket */
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0))
@@ -1071,12 +1055,11 @@ close_socket(
(void) closesocket(fd);
FD_CLR( (u_int) fd, &activefds);
- if (fd >= maxactivefd)
- {
+ if (fd >= maxactivefd) {
newmax = 0;
for (i = 0; i < maxactivefd; i++)
- if (FD_ISSET(i, &activefds))
- newmax = i;
+ if (FD_ISSET(i, &activefds))
+ newmax = i;
maxactivefd = newmax;
}
}
@@ -1096,45 +1079,16 @@ close_file(
(void) close(fd);
FD_CLR( (u_int) fd, &activefds);
- if (fd >= maxactivefd)
- {
+ if (fd >= maxactivefd) {
newmax = 0;
for (i = 0; i < maxactivefd; i++)
- if (FD_ISSET(i, &activefds))
- newmax = i;
+ if (FD_ISSET(i, &activefds))
+ newmax = i;
maxactivefd = newmax;
}
}
-/*
- * findbcastinter - find broadcast interface corresponding to address
- */
-struct interface *
-findbcastinter(
- struct sockaddr_in *addr
- )
-{
-#if defined(SIOCGIFCONF) || defined(SYS_WINNT)
- register int i;
- register u_int32 netnum;
-
- netnum = NSRCADR(addr);
- for (i = 1; i < ninterfaces; i++)
- {
- if (!(inter_list[i].flags & INT_BROADCAST))
- continue;
- if (NSRCADR(&inter_list[i].bcast) == netnum)
- return &inter_list[i];
- if ((NSRCADR(&inter_list[i].sin) & NSRCADR(&inter_list[i].mask))
- == (netnum & NSRCADR(&inter_list[i].mask)))
- return &inter_list[i];
- }
-#endif /* SIOCGIFCONF */
- return any_interface;
-}
-
-
/* XXX ELIMINATE sendpkt similar in ntpq.c, ntpdc.c, ntp_io.c, ntptrace.c */
/*
* sendpkt - send a packet to the specified destination. Maintain a
@@ -1172,13 +1126,6 @@ sendpkt(
#else
#define badaddrs ((struct cache *)0) /* Only used in empty loops! */
#endif
-
- /*
- * check if the source address is a multicast address - replace
- * interface with any-interface if so.
- */
- if (IN_MULTICAST(ntohl(inter->sin.sin_addr.s_addr)))
- inter = any_interface;
#ifdef DEBUG
if (debug > 1)
printf("%ssendpkt(fd=%d dst=%s, src=%s, ttl=%d, len=%d)\n",
@@ -1188,18 +1135,20 @@ sendpkt(
#endif
#ifdef MCAST
- /* 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) {
char mttl = ttl;
- /* set the multicast ttl for outgoing packets */
+ /*
+ * set the multicast ttl for outgoing packets
+ */
if (setsockopt(inter->fd, IPPROTO_IP, IP_MULTICAST_TTL,
- &mttl, sizeof(mttl)) == -1)
- {
+ &mttl, sizeof(mttl)) == -1)
msyslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL fails: %m");
- }
- else inter->last_ttl = ttl;
+ else
+ inter->last_ttl = ttl;
}
#endif /* MCAST */
@@ -1212,7 +1161,7 @@ sendpkt(
err = io_completion_port_sendto(inter, pkt, len, dest);
if (err != ERROR_SUCCESS)
#else
- cc = sendto(inter->fd, (char *)pkt, len, 0, (struct sockaddr *)dest,
+ cc = sendto(inter->fd, (char *)pkt, (size_t)len, 0, (struct sockaddr *)dest,
sizeof(struct sockaddr_in));
if (cc == -1)
#endif
@@ -1480,7 +1429,8 @@ input_handler(
}
else if (rb->recv_length < 0)
{
- msyslog(LOG_ERR, "recvfrom() fd=%d: %m", fd);
+ msyslog(LOG_ERR, "recvfrom(%s) fd=%d: %m",
+ inet_ntoa(rb->recv_srcadr.sin_addr), fd);
#ifdef DEBUG
if (debug)
printf("input_handler: fd=%d dropped (bad recvfrom)\n", fd);
@@ -1490,8 +1440,8 @@ input_handler(
}
#ifdef DEBUG
if (debug > 2)
- printf("input_handler: fd=%d length %d from %08lx %s\n",
- fd, rb->recv_length,
+ printf("input_handler: if=%d fd=%d length %d from %08lx %s\n",
+ i, fd, rb->recv_length,
(u_long)ntohl(rb->recv_srcadr.sin_addr.s_addr) &
0x00000000ffffffff,
inet_ntoa(rb->recv_srcadr.sin_addr));
@@ -1580,27 +1530,85 @@ input_handler(
#endif
/*
- * findinterface - utility used by other modules to find an interface
- * given an address.
+ * findinterface - find interface corresponding to address
*/
struct interface *
findinterface(
struct sockaddr_in *addr
)
{
- register int i;
- register u_int32 saddr;
+ int s, rtn, i;
+ struct sockaddr_in saddr;
+ int saddrlen = sizeof(saddr);
+ u_int32 xaddr;
/*
- * Just match the address portion.
+ * This is considerably hoke. We open a socket, connect to it
+ * and slap a getsockname() on it. If anything breaks, as it
+ * probably will in some j-random knockoff, we just return the
+ * wildcard interface.
*/
- saddr = addr->sin_addr.s_addr;
- for (i = 0; i < ninterfaces; i++)
- {
- if (inter_list[i].sin.sin_addr.s_addr == saddr)
- return &inter_list[i];
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = addr->sin_addr.s_addr;
+ saddr.sin_port = htons(2000);
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return (any_interface);
+
+ rtn = connect(s, (struct sockaddr *)&saddr, sizeof(saddr));
+ if (rtn < 0)
+ return (any_interface);
+
+ rtn = getsockname(s, (struct sockaddr *)&saddr, &saddrlen);
+ if (rtn < 0)
+ return (any_interface);
+
+ close(s);
+ xaddr = NSRCADR(&saddr);
+ for (i = 1; i < ninterfaces; i++) {
+
+ /*
+ * We match the unicast address only.
+ */
+ if (NSRCADR(&inter_list[i].sin) == xaddr)
+ return (&inter_list[i]);
}
- return (struct interface *)0;
+ return (any_interface);
+}
+
+
+/*
+ * findbcastinter - find broadcast interface corresponding to address
+ */
+struct interface *
+findbcastinter(
+ struct sockaddr_in *addr
+ )
+{
+#if defined(SIOCGIFCONF) || defined(SYS_WINNT)
+ register int i;
+ register u_int32 xaddr;
+
+ xaddr = NSRCADR(addr);
+ for (i = 1; i < ninterfaces; i++) {
+
+ /*
+ * 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 (NSRCADR(&inter_list[i].bcast) == xaddr)
+ return (&inter_list[i]);
+ if ((NSRCADR(&inter_list[i].sin) &
+ NSRCADR(&inter_list[i].mask)) == (xaddr &
+ NSRCADR(&inter_list[i].mask)))
+ return (&inter_list[i]);
+ }
+#endif /* SIOCGIFCONF */
+ return (any_interface);
}
diff --git a/contrib/ntp/ntpd/ntp_loopfilter.c b/contrib/ntp/ntpd/ntp_loopfilter.c
index 15b625d..c8a86cf 100644
--- a/contrib/ntp/ntpd/ntp_loopfilter.c
+++ b/contrib/ntp/ntpd/ntp_loopfilter.c
@@ -6,19 +6,17 @@
# include <config.h>
#endif
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_unixtime.h"
+#include "ntp_stdlib.h"
+
#include <stdio.h>
#include <ctype.h>
-#include <sys/time.h>
-
#include <signal.h>
#include <setjmp.h>
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_stdlib.h"
-
#if defined(VMS) && defined(VMS_LOCALUNIT) /*wjm*/
#include "ntp_refclock.h"
#endif /* VMS */
@@ -36,8 +34,9 @@
*/
#define CLOCK_MAX .128 /* default max offset (s) */
#define CLOCK_PANIC 1000. /* default panic offset (s) */
-#define CLOCK_MAXSTAB 2e-6 /* max frequency stability */
+#define CLOCK_MAXSTAB 2e-6 /* max frequency stability (s/s) */
#define CLOCK_MAXERR 1e-2 /* max phase jitter (s) */
+#define CLOCK_PHI 15e-6 /* max frequency error (s/s) */
#define SHIFT_PLL 4 /* PLL loop gain (shift) */
#define CLOCK_AVG 4. /* FLL loop gain */
#define CLOCK_MINSEC 256. /* min FLL update interval (s) */
@@ -51,7 +50,26 @@
/*
* Clock discipline state machine. This is used to control the
* synchronization behavior during initialization and following a
- * timewarp.
+ * timewarp.
+ *
+ * State < max > max Comments
+ * ====================================================
+ * NSET FREQ FREQ no ntp.drift
+ *
+ * FSET TSET if (allow) TSET, ntp.drift
+ * else FREQ
+ *
+ * TSET SYNC FREQ time set
+ *
+ * FREQ SYNC if (mu < 900) FREQ calculate frequency
+ * else if (allow) TSET
+ * else FREQ
+ *
+ * SYNC SYNC if (mu < 900) SYNC normal state
+ * else SPIK
+ *
+ * SPIK SYNC if (allow) TSET spike detector
+ * else FREQ
*/
#define S_NSET 0 /* clock never set */
#define S_FSET 1 /* frequency set from the drift file */
@@ -72,10 +90,10 @@
* support is used as described above; if false, the kernel is bypassed
* entirely and the daemon PLL used instead.
*
- * Each update to a prefer peer sets pps_update if it survives the
+ * Each update to a prefer peer sets pps_stratum if it survives the
* intersection algorithm and its time is within range. The PPS time
* discipline is enabled (STA_PPSTIME bit set in the status word) when
- * pps_update is true and the PPS frequency discipline is enabled. If
+ * pps_stratum is true and the PPS frequency discipline is enabled. If
* the PPS time discipline is enabled and the kernel reports a PPS
* signal is present, the pps_control variable is set to the current
* time. If the current time is later than pps_control by PPS_MAXAGE
@@ -91,18 +109,27 @@
#define PPS_MAXAGE 120 /* kernel pps signal timeout (s) */
/*
+ * Program variables that can be tinkered.
+ */
+double clock_max = CLOCK_MAX; /* max offset before step (s) */
+double clock_panic = CLOCK_PANIC; /* max offset before panic (s) */
+double clock_phi = CLOCK_PHI; /* dispersion rate (s/s) */
+double clock_minstep = CLOCK_MINSTEP; /* step timeout (s) */
+double allan_xpt = CLOCK_ALLAN; /* minimum Allan intercept (s) */
+
+/*
* Program variables
*/
static double clock_offset; /* clock offset adjustment (s) */
-double drift_comp; /* clock frequency (ppm) */
-double clock_stability; /* clock stability (ppm) */
-double clock_max = CLOCK_MAX; /* max offset allowed before step (s) */
-static double clock_panic = CLOCK_PANIC; /* max offset allowed before panic */
+double drift_comp; /* clock frequency (s/s) */
+double clock_stability; /* clock stability (s/s) */
u_long pps_control; /* last pps sample time */
-static void rstclock P((int)); /* state transition function */
+static void rstclock P((int, double, double)); /* transition function */
#ifdef KERNEL_PLL
-int pll_status; /* status bits for 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 */
/*
@@ -111,32 +138,38 @@ int pll_status; /* status bits for kernel pll */
int ntp_enable; /* clock discipline enabled */
int pll_control; /* kernel support available */
int kern_enable; /* kernel support enabled */
+int pps_enable; /* kernel PPS discipline enabled */
int ext_enable; /* external clock enabled */
-int pps_update; /* pps update valid */
-int allow_set_backward = TRUE; /* step corrections allowed */
-int correct_any = FALSE; /* corrections > 1000 s allowed */
-
-#ifdef STA_NANO
-int pll_nano; /* nanosecond kernel switch */
-#endif /* STA_NANO */
+int pps_stratum; /* pps stratum */
+int allow_step = TRUE; /* allow step correction */
+int allow_panic = FALSE; /* allow panic correction */
+int mode_ntpdate = FALSE; /* exit on first clock set */
/*
* Clock state machine variables
*/
-u_char sys_poll; /* log2 of system poll interval */
+u_char sys_minpoll = NTP_MINDPOLL; /* min sys poll interval (log2 s) */
+u_char sys_poll = NTP_MINDPOLL; /* system poll interval (log2 s) */
int state; /* clock discipline state */
int tc_counter; /* poll-adjust counter */
u_long last_time; /* time of last clock update (s) */
double last_offset; /* last clock offset (s) */
-double allan_xpt; /* Allan intercept (s) */
-double sys_error; /* system standard error (s) */
+double sys_jitter; /* system RMS jitter (s) */
+
+/*
+ * Huff-n'-puff filter variables
+ */
+static double *sys_huffpuff; /* huff-n'-puff filter */
+static int sys_hufflen; /* huff-n'-puff filter stages */
+static int sys_huffptr; /* huff-n'-puff filter pointer */
+static double sys_mindly; /* huff-n'-puff filter min delay */
#if defined(KERNEL_PLL)
/* Emacs cc-mode goes nuts if we split the next line... */
#define MOD_BITS (MOD_OFFSET | MOD_MAXERROR | MOD_ESTERROR | \
MOD_STATUS | MOD_TIMECONST)
-static void pll_trap P((int)); /* configuration trap */
#ifdef SIGSYS
+static void pll_trap P((int)); /* configuration trap */
static struct sigaction sigsys; /* current sigaction status */
static struct sigaction newsigsys; /* new sigaction status */
static sigjmp_buf env; /* environment var. for pll_trap() */
@@ -153,7 +186,7 @@ init_loopfilter(void)
* Initialize state variables. Initially, we expect no drift
* file, so set the state to S_NSET.
*/
- rstclock(S_NSET);
+ rstclock(S_NSET, current_time, 0);
}
/*
@@ -175,30 +208,70 @@ local_clock(
double dtemp, etemp; /* double temps */
int retval; /* return value */
-#if defined(KERNEL_PLL)
- struct timex ntv; /* kernel interface structure */
-#endif /* KERNEL_PLL */
-
+ /*
+ * If the loop is opened, monitor and record the offsets
+ * anyway in order to determine the open-loop response.
+ */
#ifdef DEBUG
if (debug)
printf(
- "local_clock: offset %.6f jitter %.6f state %d\n",
- fp_offset, SQRT(epsil), state);
+ "local_clock: assocID %d off %.6f jit %.6f sta %d\n",
+ peer->associd, fp_offset, SQRT(epsil), state);
#endif
- if (!ntp_enable)
- return(0);
+ if (!ntp_enable) {
+ record_loop_stats(fp_offset, drift_comp, SQRT(epsil),
+ clock_stability, sys_poll);
+ return (0);
+ }
/*
- * If the clock is way off, don't tempt fate by correcting it.
+ * If the clock is way off, panic is declared. The clock_panic
+ * defaults to 1000 s; if set to zero, the panic will never
+ * occur. The allow_panic defaults to FALSE, so the first panic
+ * will exit. It can be set TRUE by a command line option, in
+ * which case the clock will be set anyway and time marches on.
+ * But, allow_panic will be set it FALSE when the update is
+ * within the step range; so, subsequent panics will exit.
*/
-#ifndef SYS_WINNT
- if (fabs(fp_offset) >= clock_panic && !correct_any) {
+ if (fabs(fp_offset) > clock_panic && clock_panic > 0 &&
+ !allow_panic) {
msyslog(LOG_ERR,
- "time error %.0f over %d seconds; set clock manually",
- fp_offset, (int)clock_panic);
+ "time correction of %.0f seconds exceeds sanity limit (%.0f); set clock manually to the correct UTC time.",
+ fp_offset, clock_panic);
return (-1);
}
-#endif
+
+ /*
+ * If simulating ntpdate, set the clock directly, rather than
+ * using the discipline. The clock_max defines the step
+ * threshold, above which the clock will be stepped instead of
+ * slewed. The value defaults to 128 ms, but can be set to even
+ * unreasonable values. If set to zero, the clock will never be
+ * stepped.
+ *
+ * Note that if ntpdate is active, the terminal does not detach,
+ * so the termination comments print directly to the console.
+ */
+ if (mode_ntpdate) {
+ if (allow_step && fabs(fp_offset) > clock_max &&
+ clock_max > 0) {
+ step_systime(fp_offset);
+ NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
+ msyslog(LOG_NOTICE, "time reset %.6f s",
+ fp_offset);
+ printf("ntpd: time reset %.6fs\n", fp_offset);
+ } else {
+ adj_systime(fp_offset);
+ NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
+ msyslog(LOG_NOTICE, "time slew %.6f s",
+ fp_offset);
+ printf("ntpd: time slew %.6fs\n", fp_offset);
+ }
+ record_loop_stats(fp_offset, drift_comp, SQRT(epsil),
+ clock_stability, sys_poll);
+ exit (0);
+ }
+
/*
* If the clock has never been set, set it and initialize the
* discipline parameters. We then switch to frequency mode to
@@ -210,29 +283,60 @@ local_clock(
step_systime(fp_offset);
NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
msyslog(LOG_NOTICE, "time set %.6f s", fp_offset);
- rstclock(S_TSET);
- rstclock(S_FREQ);
+ rstclock(S_FREQ, peer->epoch, fp_offset);
return (1);
}
/*
* Update the jitter estimate.
*/
- oerror = sys_error;
- dtemp = SQUARE(sys_error);
- sys_error = SQRT(dtemp + (epsil - dtemp) / CLOCK_AVG);
+ oerror = sys_jitter;
+ dtemp = SQUARE(sys_jitter);
+ sys_jitter = SQRT(dtemp + (epsil - dtemp) / CLOCK_AVG);
+
+ /*
+ * The huff-n'-puff filter finds the lowest delay in the recent
+ * interval. This is used to correct the offset by one-half the
+ * difference between the sample delay and minimum delay. This
+ * is most effective if the delays are highly assymetric and
+ * clockhopping is avoided and the clock frequency wander is
+ * relatively small.
+ */
+ if (sys_huffpuff != NULL) {
+ if (peer->delay < sys_huffpuff[sys_huffptr])
+ sys_huffpuff[sys_huffptr] = peer->delay;
+ if (peer->delay < sys_mindly)
+ sys_mindly = peer->delay;
+ if (fp_offset > 0)
+ dtemp = -(peer->delay - sys_mindly) / 2;
+ else
+ dtemp = (peer->delay - sys_mindly) / 2;
+ fp_offset += dtemp;
+#ifdef DEBUG
+ if (debug)
+ printf(
+ "local_clock: size %d mindly %.6f huffpuff %.6f\n",
+ sys_hufflen, sys_mindly, dtemp);
+#endif
+ }
/*
* Clock state machine transition function. This is where the
* action is and defines how the system reacts to large phase
* and frequency errors. There are two main regimes: when the
- * phase error exceeds the maximum allowed for ordinary tracking
- * and otherwise when it does not.
+ * offset exceeds the step threshold and when it does not.
+ * However, if the step threshold is set to zero, a step will
+ * never occur. See the instruction manual for the details how
+ * these actions interact with the command line options.
*/
retval = 0;
+ if (sys_poll > peer->maxpoll)
+ sys_poll = peer->maxpoll;
+ else if (sys_poll < peer->minpoll)
+ sys_poll = peer->minpoll;
clock_frequency = flladj = plladj = 0;
- mu = current_time - last_time;
- if (fabs(fp_offset) > clock_max) {
+ mu = peer->epoch - last_time;
+ if (fabs(fp_offset) > clock_max && clock_max > 0) {
switch (state) {
/*
@@ -243,32 +347,29 @@ local_clock(
* to S_FREQ state.
*/
case S_TSET:
- rstclock(S_FREQ);
- last_offset = clock_offset = fp_offset;
- return (0);
+ state = S_FREQ;
+ break;
/*
* In S_SYNC state we ignore outlyers. At the first
- * outlyer after CLOCK_MINSTEP (900 s), switch to S_SPIK
+ * outlyer after the stepout threshold, switch to S_SPIK
* state.
*/
case S_SYNC:
- if (mu < CLOCK_MINSTEP)
+ if (mu < clock_minstep)
return (0);
- rstclock(S_SPIK);
+ state = S_SPIK;
return (0);
/*
* In S_FREQ state we ignore outlyers. At the first
- * outlyer after CLOCK_MINSTEP (900 s), compute the
- * apparent phase and frequency correction.
+ * outlyer after 900 s, compute the apparent phase and
+ * frequency correction.
*/
case S_FREQ:
- if (mu < CLOCK_MINSTEP)
+ if (mu < clock_minstep)
return (0);
- clock_frequency = (fp_offset - clock_offset) /
- mu;
- /* fall through to default */
+ /* fall through to S_SPIK */
/*
* In S_SPIK state a large correction is necessary.
@@ -286,19 +387,19 @@ local_clock(
* reset or shaken, but never stirred.
*/
default:
- if (allow_set_backward | correct_any) {
+ if (allow_step) {
step_systime(fp_offset);
NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
msyslog(LOG_NOTICE, "time reset %.6f s",
fp_offset);
- rstclock(S_TSET);
+ rstclock(S_TSET, peer->epoch, 0);
retval = 1;
} else {
NLOG(NLOG_SYNCEVENT|NLOG_SYSEVENT)
msyslog(LOG_NOTICE, "time slew %.6f s",
fp_offset);
- rstclock(S_FREQ);
- last_offset = clock_offset = fp_offset;
+ rstclock(S_FREQ, peer->epoch,
+ fp_offset);
}
break;
}
@@ -306,28 +407,25 @@ local_clock(
switch (state) {
/*
- * If this is the first update, initialize the
- * discipline parameters and pretend we had just set the
- * clock. We don't want to step the clock unless we have
- * to.
+ * In S_FSET state this is the first update. Adjust the
+ * phase, but don't adjust the frequency until the next
+ * update.
*/
case S_FSET:
- rstclock(S_TSET);
- last_offset = clock_offset = fp_offset;
- return (0);
+ rstclock(S_TSET, peer->epoch, fp_offset);
+ break;
/*
- * In S_FREQ state we ignore updates until CLOCK_MINSTEP
- * (900 s). After that, correct the phase and frequency
- * and switch to S_SYNC state.
+ * In S_FREQ state ignore updates until the stepout
+ * threshold. After that, correct the phase and
+ * frequency and switch to S_SYNC state.
*/
case S_FREQ:
- if (mu < CLOCK_MINSTEP)
+ if (mu < clock_minstep)
return (0);
clock_frequency = (fp_offset - clock_offset) /
mu;
- clock_offset = fp_offset;
- rstclock(S_SYNC);
+ rstclock(S_SYNC, peer->epoch, fp_offset);
break;
/*
@@ -337,7 +435,7 @@ local_clock(
*/
case S_TSET:
case S_SPIK:
- rstclock(S_SYNC);
+ state = S_SYNC;
/* fall through to default */
/*
@@ -349,14 +447,17 @@ local_clock(
* and ignore it.
*/
default:
+ allow_panic = TRUE;
if (fabs(fp_offset - last_offset) >
CLOCK_SGATE * oerror && mu <
ULOGTOD(sys_poll + 1)) {
#ifdef DEBUG
if (debug)
printf(
- "local_clock: popcorn %.6f %.6f\n",
- fp_offset, last_offset);
+ "local_clock: popcorn %.6f %.6f\n",
+ fabs(fp_offset -
+ last_offset), CLOCK_SGATE *
+ oerror);
#endif
last_offset = fp_offset;
return (0);
@@ -366,29 +467,32 @@ local_clock(
* Compute the FLL and PLL frequency adjustments
* conditioned on intricate weighting factors.
* For the FLL, the averaging interval is
- * clamped not to decrease below the Allan
- * intercept and the gain is decreased from
- * unity for mu above CLOCK_MINSEC (1024 s) to
- * zero below CLOCK_MINSEC (256 s). For the PLL,
- * the averaging interval is clamped not to
- * exceed the sustem poll interval. These
- * measures insure stability of the clock
- * discipline even when the rules of fair
- * engagement are broken.
+ * clamped to a minimum of 1024 s and the gain
+ * is decreased from unity for mu above 1024 s
+ * to zero below 256 s. For the PLL, the
+ * averaging interval is clamped not to exceed
+ * the sustem poll interval. No gain factor is
+ * necessary, since the frequency steering above
+ * 1024 s is negligible. Particularly for the
+ * PLL, these measures allow oversampling, but
+ * not undersampling and insure stability even
+ * when the rules of fair engagement are broken.
*/
dtemp = max(mu, allan_xpt);
etemp = min(max(0, mu - CLOCK_MINSEC) /
- CLOCK_ALLAN, 1.);
+ allan_xpt, 1.);
flladj = fp_offset * etemp / (dtemp *
CLOCK_AVG);
dtemp = ULOGTOD(SHIFT_PLL + 2 + sys_poll);
etemp = min(mu, ULOGTOD(sys_poll));
plladj = fp_offset * etemp / (dtemp * dtemp);
- clock_offset = fp_offset;
+ last_time = peer->epoch;
+ last_offset = clock_offset = fp_offset;
break;
}
}
+#if defined(KERNEL_PLL)
/*
* This code segment works when clock adjustments are made using
* precision time kernel support and the ntp_adjtime() system
@@ -399,7 +503,6 @@ local_clock(
* modifications provide a true microsecond clock and nanosecond
* clock, respectively.
*/
-#if defined(KERNEL_PLL)
if (pll_control && kern_enable) {
/*
@@ -413,7 +516,7 @@ local_clock(
* frequency offsets for jitter and stability values and
* to update the drift file.
*/
- memset((char *)&ntv, 0, sizeof ntv);
+ memset(&ntv, 0, sizeof(ntv));
if (ext_enable) {
ntv.modes = MOD_STATUS;
} else {
@@ -422,25 +525,21 @@ local_clock(
dtemp = -.5;
else
dtemp = .5;
-#ifdef STA_NANO
- if (pll_nano)
+ if (pll_nano) {
ntv.offset = (int32)(clock_offset *
1e9 + dtemp);
- else
-#endif /* STA_NANO */
+ ntv.constant = sys_poll;
+ } else {
ntv.offset = (int32)(clock_offset *
1e6 + dtemp);
+ ntv.constant = sys_poll - 4;
+ }
if (clock_frequency != 0) {
ntv.modes |= MOD_FREQUENCY;
ntv.freq = (int32)((clock_frequency +
drift_comp) * 65536e6);
}
-#ifdef STA_NANO
- ntv.constant = sys_poll;
-#else
- ntv.constant = sys_poll - 4;
-#endif /* STA_NANO */
- ntv.esterror = (u_int32)(sys_error * 1e6);
+ ntv.esterror = (u_int32)(sys_jitter * 1e6);
ntv.maxerror = (u_int32)((sys_rootdelay / 2 +
sys_rootdispersion) * 1e6);
ntv.status = STA_PLL;
@@ -467,63 +566,53 @@ local_clock(
*/
if (sys_poll > NTP_MAXDPOLL)
ntv.status |= STA_FLL;
- }
- /*
- * Wiggle the PPS bits according to the health of the
- * prefer peer.
- */
- if (pll_status & STA_PPSSIGNAL)
- ntv.status |= STA_PPSFREQ;
- if (pll_status & STA_PPSFREQ && pps_update)
- ntv.status |= STA_PPSTIME;
+ /*
+ * If the PPS signal is up and enabled, light
+ * the frequency bit. If the PPS driver is
+ * working, light the phase bit as well. If not,
+ * douse the lights, since somebody else may
+ * have left the switch on.
+ */
+ if (pps_enable && pll_status & STA_PPSSIGNAL) {
+ ntv.status |= STA_PPSFREQ;
+ if (pps_stratum < STRATUM_UNSPEC)
+ ntv.status |= STA_PPSTIME;
+ } else {
+ ntv.status &= ~(STA_PPSFREQ |
+ STA_PPSTIME);
+ }
+ }
/*
- * Update the offset and frequency from the kernel
- * variables.
+ * Pass the stuff to the kernel. If it squeals, turn off
+ * the pigs. In any case, fetch the kernel offset and
+ * frequency and pretend we did it here.
*/
if (ntp_adjtime(&ntv) == TIME_ERROR) {
if (ntv.status != pll_status)
msyslog(LOG_ERR,
- "kernel pll status change %x",
+ "kernel time discipline status change %x",
ntv.status);
+ ntv.status &= ~(STA_PPSFREQ | STA_PPSTIME);
}
pll_status = ntv.status;
-#ifdef STA_NANO
if (pll_nano)
clock_offset = ntv.offset / 1e9;
else
-#endif /* STA_NANO */
clock_offset = ntv.offset / 1e6;
-#ifdef STA_NANO
- sys_poll = ntv.constant;
-#else
- sys_poll = ntv.constant + 4;
-#endif /* STA_NANO */
clock_frequency = ntv.freq / 65536e6 - drift_comp;
flladj = plladj = 0;
/*
- * If the kernel pps discipline is working, monitor its
- * performance.
+ * If the kernel PPS is lit, monitor its performance.
*/
if (ntv.status & STA_PPSTIME) {
- if (!pps_control)
- NLOG(NLOG_SYSEVENT)msyslog(LOG_INFO,
- "pps sync enabled");
pps_control = current_time;
-#ifdef STA_NANO
if (pll_nano)
- record_peer_stats(
- &loopback_interface->sin,
- ctlsysstatus(), ntv.offset / 1e9,
- 0., ntv.jitter / 1e9, 0.);
+ sys_jitter = ntv.jitter / 1e9;
else
-#endif /* STA_NANO */
- record_peer_stats(
- &loopback_interface->sin,
- ctlsysstatus(), ntv.offset / 1e6,
- 0., ntv.jitter / 1e6, 0.);
+ sys_jitter = ntv.jitter / 1e6;
}
}
#endif /* KERNEL_PLL */
@@ -537,21 +626,26 @@ local_clock(
*/
etemp = clock_frequency + flladj + plladj;
drift_comp += etemp;
- if (drift_comp > sys_maxfreq)
- drift_comp = sys_maxfreq;
- else if (drift_comp <= -sys_maxfreq)
- drift_comp = -sys_maxfreq;
+ if (drift_comp > NTP_MAXFREQ)
+ drift_comp = NTP_MAXFREQ;
+ else if (drift_comp <= -NTP_MAXFREQ)
+ drift_comp = -NTP_MAXFREQ;
dtemp = SQUARE(clock_stability);
etemp = SQUARE(etemp) - dtemp;
clock_stability = SQRT(dtemp + etemp / CLOCK_AVG);
- allan_xpt = max(CLOCK_ALLAN, clock_stability * CLOCK_ADF);
/*
- * In SYNC state, adjust the poll interval.
+ * In SYNC state, adjust the poll interval. The trick here is to
+ * compare the apparent frequency change induced by the system
+ * jitter over the poll interval, or fritter, to the frequency
+ * stability. If the fritter is greater than the stability,
+ * phase noise predominates and the averaging interval is
+ * increased; otherwise, it is decreased. A bit of hysteresis
+ * helps calm the dance. Works best using burst mode.
*/
if (state == S_SYNC) {
- if (clock_stability < CLOCK_MAXSTAB &&
- fabs(clock_offset) < CLOCK_PGATE * sys_error) {
+ 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;
@@ -575,25 +669,17 @@ local_clock(
/*
* Update the system time variables.
*/
- last_time = current_time;
- last_offset = clock_offset;
- dtemp = peer->disp + SQRT(peer->variance + SQUARE(sys_error));
+ dtemp = peer->disp + sys_jitter;
if ((peer->flags & FLAG_REFCLOCK) == 0 && dtemp < MINDISPERSE)
dtemp = MINDISPERSE;
sys_rootdispersion = peer->rootdispersion + dtemp;
- (void)record_loop_stats();
-#ifdef DEBUG
- if (debug)
- printf(
- "local_clock: mu %.0f allan %.0f fadj %.3f fll %.3f pll %.3f\n",
- mu, allan_xpt, clock_frequency * 1e6, flladj * 1e6,
- plladj * 1e6);
-#endif /* DEBUG */
+ record_loop_stats(last_offset, drift_comp, sys_jitter,
+ clock_stability, sys_poll);
#ifdef DEBUG
if (debug)
printf(
- "local_clock: jitter %.6f freq %.3f stab %.3f poll %d count %d\n",
- sys_error, drift_comp * 1e6, clock_stability * 1e6,
+ "local_clock: mu %.0f noi %.3f stb %.3f pol %d cnt %d\n",
+ mu, sys_jitter * 1e6 / mu, clock_stability * 1e6,
sys_poll, tc_counter);
#endif /* DEBUG */
return (retval);
@@ -620,7 +706,7 @@ adj_host_clock(
* maximum error and the local clock driver will pick it up and
* pass to the common refclock routines. Very elegant.
*/
- sys_rootdispersion += CLOCK_PHI;
+ sys_rootdispersion += clock_phi;
/*
* Declare PPS kernel unsync if the pps signal has not been
@@ -665,51 +751,35 @@ adj_host_clock(
*/
static void
rstclock(
- int trans /* new state */
+ int trans, /* new state */
+ double epoch, /* last time */
+ double offset /* last offset */
)
{
- correct_any = FALSE;
+ tc_counter = 0;
+ sys_poll = NTP_MINPOLL;
state = trans;
- switch (state) {
-
- /*
- * Frequency mode. The clock has ben set, but the frequency has
- * not yet been determined. Note that the Allan intercept is set
- * insure the clock filter considers only the most recent
- * measurements.
- */
- case S_FREQ:
- sys_poll = NTP_MINDPOLL;
- allan_xpt = CLOCK_ALLAN;
- last_time = current_time;
- break;
+ last_time = epoch;
+ last_offset = clock_offset = offset;
+}
- /*
- * Synchronized mode. Discipline the poll interval.
- */
- case S_SYNC:
- sys_poll = NTP_MINDPOLL;
- allan_xpt = CLOCK_ALLAN;
- tc_counter = 0;
- break;
- /*
- * Don't do anything in S_SPIK state; just continue from S_SYNC
- * state.
- */
- case S_SPIK:
- break;
+/*
+ * huff-n'-puff filter
+ */
+void
+huffpuff()
+{
+ int i;
- /*
- * S_NSET, S_FSET and S_TSET states. These transient states set
- * the time reference for future frequency updates.
- */
- default:
- sys_poll = NTP_MINDPOLL;
- allan_xpt = CLOCK_ALLAN;
- last_time = current_time;
- last_offset = clock_offset = 0;
- break;
+ if (sys_huffpuff == NULL)
+ return;
+ sys_huffptr = (sys_huffptr + 1) % sys_hufflen;
+ sys_huffpuff[sys_huffptr] = 1e9;
+ sys_mindly = 1e9;
+ for (i = 0; i < sys_hufflen; i++) {
+ if (sys_huffpuff[i] < sys_mindly)
+ sys_mindly = sys_huffpuff[i];
}
}
@@ -723,111 +793,148 @@ loop_config(
double freq
)
{
-#if defined(KERNEL_PLL)
- struct timex ntv;
-#endif /* KERNEL_PLL */
+ int i;
-#ifdef DEBUG
- if (debug)
- printf("loop_config: state %d freq %.3f\n", item, freq *
- 1e6);
-#endif
switch (item) {
- case LOOP_DRIFTINIT:
- case LOOP_DRIFTCOMP:
+ case LOOP_DRIFTINIT:
- /*
- * The drift file is present and the initial frequency
- * is available, so set the state to S_FSET
- */
- rstclock(S_FSET);
- drift_comp = freq;
- if (drift_comp > sys_maxfreq)
- drift_comp = sys_maxfreq;
- if (drift_comp < -sys_maxfreq)
- drift_comp = -sys_maxfreq;
#ifdef KERNEL_PLL
/*
- * If the phase-lock code is implemented in the kernel,
- * give the time_constant and saved frequency offset to
- * the kernel. If not, no harm is done. Note the initial
- * time constant is zero, but the first clock update
- * will fix that.
+ * Assume the kernel supports the ntp_adjtime() syscall.
+ * If that syscall works, initialize the kernel
+ * variables. Otherwise, continue leaving no harm
+ * behind. While at it, ask to set nanosecond mode. If
+ * the kernel agrees, rejoice; othewise, it does only
+ * microseconds.
*/
- memset((char *)&ntv, 0, sizeof ntv);
pll_control = 1;
-#ifdef MOD_NANO
- ntv.modes = MOD_NANO;
-#endif /* MOD_NANO */
+ memset(&ntv, 0, sizeof(ntv));
+#ifdef STA_NANO
+ ntv.modes = MOD_BITS | MOD_NANO;
+#else
+ ntv.modes = MOD_BITS;
+#endif /* STA_NANO */
+ ntv.maxerror = MAXDISPERSE;
+ ntv.esterror = MAXDISPERSE;
+ ntv.status = STA_UNSYNC;
#ifdef SIGSYS
+ /*
+ * Use sigsetjmp() to save state and then call
+ * ntp_adjtime(); if it fails, then siglongjmp() is used
+ * to return control
+ */
newsigsys.sa_handler = pll_trap;
newsigsys.sa_flags = 0;
if (sigaction(SIGSYS, &newsigsys, &sigsys)) {
msyslog(LOG_ERR,
"sigaction() fails to save SIGSYS trap: %m");
pll_control = 0;
- return;
}
-
- /*
- * Use sigsetjmp() to save state and then call
- * ntp_adjtime(); if it fails, then siglongjmp() is used
- * to return control
- */
if (sigsetjmp(env, 1) == 0)
- (void)ntp_adjtime(&ntv);
+ ntp_adjtime(&ntv);
if ((sigaction(SIGSYS, &sigsys,
(struct sigaction *)NULL))) {
msyslog(LOG_ERR,
"sigaction() fails to restore SIGSYS trap: %m");
pll_control = 0;
- return;
}
#else /* SIGSYS */
- if (ntp_adjtime(&ntv) < 0) {
- msyslog(LOG_ERR,
- "loop_config: ntp_adjtime() failed: %m");
- pll_control = 0;
- }
+ ntp_adjtime(&ntv);
#endif /* SIGSYS */
-
- /*
- * If the kernel support is available and enabled,
- * initialize the parameters, but only if the external
- * clock is not present.
- */
- if (pll_control && kern_enable) {
- msyslog(LOG_NOTICE,
- "using kernel phase-lock loop %04x",
- ntv.status);
+ pll_status = ntv.status;
+ if (pll_control) {
#ifdef STA_NANO
- if (ntv.status & STA_NANO)
+ if (pll_status & STA_NANO)
pll_nano = 1;
+ if (pll_status & STA_CLK)
+ ext_enable = 1;
#endif /* STA_NANO */
-#ifdef STA_CLK
+ msyslog(LOG_NOTICE,
+ "kernel time discipline status %04x",
+ pll_status);
+ }
+#endif /* KERNEL_PLL */
+ break;
- if (ntv.status & STA_CLK) {
- ext_enable = 1;
- } else {
- ntv.modes = MOD_BITS | MOD_FREQUENCY;
+ case LOOP_DRIFTCOMP:
+
+ /*
+ * Initialize the kernel frequency and clamp to
+ * reasonable value. Also set the initial state to
+ * S_FSET to indicated the frequency has been
+ * initialized from the previously saved drift file.
+ */
+ rstclock(S_FSET, current_time, 0);
+ drift_comp = freq;
+ if (drift_comp > NTP_MAXFREQ)
+ drift_comp = NTP_MAXFREQ;
+ if (drift_comp < -NTP_MAXFREQ)
+ drift_comp = -NTP_MAXFREQ;
+
+#ifdef KERNEL_PLL
+ /*
+ * Sanity check. If the kernel is enabled, load the
+ * frequency and light up the loop. If not, set the
+ * kernel frequency to zero and leave the loop dark. In
+ * either case set the time to zero to cancel any
+ * previous nonsense.
+ */
+ if (pll_control) {
+ memset((char *)&ntv, 0, sizeof(ntv));
+ ntv.modes = MOD_OFFSET | MOD_FREQUENCY;
+ if (kern_enable) {
+ ntv.modes |= MOD_STATUS;
+ ntv.status = STA_PLL;
ntv.freq = (int32)(drift_comp *
65536e6);
- ntv.maxerror = MAXDISPERSE;
- ntv.esterror = MAXDISPERSE;
- ntv.status = STA_UNSYNC | STA_PLL;
- (void)ntp_adjtime(&ntv);
}
-#else
- ntv.modes = MOD_BITS | MOD_FREQUENCY;
- ntv.freq = (int32)(drift_comp * 65536e6);
- ntv.maxerror = MAXDISPERSE;
- ntv.esterror = MAXDISPERSE;
- ntv.status = STA_UNSYNC | STA_PLL;
(void)ntp_adjtime(&ntv);
-#endif /* STA_CLK */
}
#endif /* KERNEL_PLL */
+ break;
+
+ /*
+ * Special tinker variables for Ulrich Windl. Very dangerous.
+ */
+ case LOOP_MAX: /* step threshold */
+ clock_max = freq;
+ break;
+
+ case LOOP_PANIC: /* panic exit threshold */
+ clock_panic = freq;
+ break;
+
+ case LOOP_PHI: /* dispersion rate */
+ clock_phi = freq;
+ break;
+
+ case LOOP_MINSTEP: /* watchdog bark */
+ clock_minstep = freq;
+ break;
+
+ case LOOP_MINPOLL: /* ephemeral association poll */
+ if (freq < NTP_MINPOLL)
+ freq = NTP_MINPOLL;
+ sys_minpoll = (u_char)freq;
+ break;
+
+ case LOOP_ALLAN: /* minimum Allan intercept */
+ if (freq < CLOCK_ALLAN)
+ freq = CLOCK_ALLAN;
+ allan_xpt = freq;
+ break;
+
+ case LOOP_HUFFPUFF: /* huff-n'-puff filter length */
+ if (freq < HUFFPUFF)
+ freq = HUFFPUFF;
+ sys_hufflen = (int)(freq / HUFFPUFF);
+ sys_huffpuff = (double *)emalloc(sizeof(double) *
+ sys_hufflen);
+ for (i = 0; i < sys_hufflen; i++)
+ sys_huffpuff[i] = 1e9;
+ sys_mindly = 1e9;
+ break;
}
}
diff --git a/contrib/ntp/ntpd/ntp_monitor.c b/contrib/ntp/ntpd/ntp_monitor.c
index 64dfb3e..8526aac 100644
--- a/contrib/ntp/ntpd/ntp_monitor.c
+++ b/contrib/ntp/ntpd/ntp_monitor.c
@@ -1,23 +1,22 @@
/*
* ntp_monitor.c - monitor who is using the ntpd server
*/
+
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
-#include <stdio.h>
-#include <sys/types.h>
-#include <signal.h>
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-# endif
-# include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <signal.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
/*
* I'm still not sure I like what I've done here. It certainly consumes
* memory like it is going out of style, and also may not be as low
diff --git a/contrib/ntp/ntpd/ntp_peer.c b/contrib/ntp/ntpd/ntp_peer.c
index 90646ab..b164181 100644
--- a/contrib/ntp/ntpd/ntp_peer.c
+++ b/contrib/ntp/ntpd/ntp_peer.c
@@ -10,6 +10,9 @@
#include "ntpd.h"
#include "ntp_stdlib.h"
+#ifdef AUTOKEY
+#include "ntp_crypto.h"
+#endif /* AUTOKEY */
/*
* Table of valid association combinations
@@ -27,15 +30,13 @@
* CONTROL | e 0 0 0 0 0
* PRIVATE | e 0 0 0 0 0
* BCLIENT | e 0 0 0 e 1
- * MCLIENT | e 0 0 0 0 0
*
- * One point to note here:
- * a packet in BCAST mode can potentially match a peer in CLIENT
- * mode, but we that is a special case and we check for that early
- * in the decision process. This avoids having to keep track of
- * what kind of associations are possible etc... We actually
- * circumvent that problem by requiring that the first b(m)roadcast
- * received after the change back to BCLIENT mode sets the clock.
+ * One point to note here: a packet in BCAST mode can potentially match
+ * a peer in CLIENT mode, but we that is a special case and we check for
+ * that early in the decision process. This avoids having to keep track
+ * of what kind of associations are possible etc... We actually
+ * circumvent that problem by requiring that the first b(m)roadcast
+ * received after the change back to BCLIENT mode sets the clock.
*/
int AM[AM_MODES][AM_MODES] = {
@@ -58,82 +59,59 @@ int AM[AM_MODES][AM_MODES] = {
/*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},
-
-/*MCL*/ { AM_ERR, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH, AM_NOMATCH}
};
#define MATCH_ASSOC(x,y) AM[(x)][(y)]
/*
* These routines manage the allocation of memory to peer structures
- * and the maintenance of the peer hash table. The two main entry
- * points are findpeer(), which looks for corresponding peer data
- * in the peer list, newpeer(), which allocates a new peer structure
- * and adds it to the list, and unpeer(), which demobilizes the association
+ * and the maintenance of the peer hash table. The two main entry
+ * points are findpeer(), which looks for matching peer sturctures in
+ * the peer list, newpeer(), which allocates a new peer structure and
+ * adds it to the list, and unpeer(), which demobilizes the association
* and deallocates the structure.
*/
-
-/*
- * The peer hash table (imported by the protocol module).
- */
-struct peer *peer_hash[HASH_SIZE];
-int peer_hash_count[HASH_SIZE]; /* count of peers in each bucket */
-
/*
- * The association ID hash table. Used for lookups by association ID
+ * Peer hash tables
*/
-struct peer *assoc_hash[HASH_SIZE];
-int assoc_hash_count[HASH_SIZE];
+struct peer *peer_hash[HASH_SIZE]; /* peer hash table */
+int peer_hash_count[HASH_SIZE]; /* peers in each bucket */
+struct peer *assoc_hash[HASH_SIZE]; /* association ID hash table */
+int assoc_hash_count[HASH_SIZE]; /* peers in each bucket */
+static struct peer *peer_free; /* peer structures free list */
+int peer_free_count; /* count of free structures */
/*
- * The free list. Clean structures only, please.
- */
-static struct peer *peer_free;
-int peer_free_count;
-
-/*
- * Association ID. We initialize this value randomly, the assign a new
+ * Association ID. We initialize this value randomly, then assign a new
* value every time the peer structure is incremented.
*/
-static u_short current_association_ID;
+static associd_t current_association_ID; /* association ID */
/*
* Memory allocation watermarks.
*/
-#define INIT_PEER_ALLOC 15 /* initialize space for 15 peers */
-#define INC_PEER_ALLOC 5 /* when we run out, add 5 more */
+#define INIT_PEER_ALLOC 15 /* initialize for 15 peers */
+#define INC_PEER_ALLOC 5 /* when run out, add 5 more */
/*
* Miscellaneous statistic counters which may be queried.
*/
-u_long peer_timereset; /* time stat counters were zeroed */
-u_long findpeer_calls; /* number of calls to findpeer */
-u_long assocpeer_calls; /* number of calls to findpeerbyassoc */
-u_long peer_allocations; /* number of allocations from the free list */
-u_long peer_demobilizations; /* number of structs freed to free list */
-int total_peer_structs; /* number of peer structs in circulation */
-int peer_associations; /* number of active associations */
-
-/*
- * Our initial allocation of peer space
- */
-static struct peer init_peer_alloc[INIT_PEER_ALLOC];
-
-/*
- * Initialization data. When configuring peers at initialization time,
- * we try to get their poll update timers initialized to different values
- * to prevent us from sending big clumps of data all at once.
- */
-/* static u_long init_peer_starttime; */
+u_long peer_timereset; /* time stat counters zeroed */
+u_long findpeer_calls; /* calls to findpeer */
+u_long assocpeer_calls; /* calls to findpeerbyassoc */
+u_long peer_allocations; /* allocations from free list */
+u_long peer_demobilizations; /* structs freed to free list */
+int total_peer_structs; /* peer structs */
+int peer_associations; /* active associations */
+static struct peer init_peer_alloc[INIT_PEER_ALLOC]; /* init alloc */
static void getmorepeermem P((void));
-static void key_expire P((struct peer *));
/*
* init_peer - initialize peer data structures and counters
*
- * N.B. We use the random number routine in here. It had better be
- * initialized prior to getting here.
+ * N.B. We use the random number routine in here. It had better be
+ * initialized prior to getting here.
*/
void
init_peer(void)
@@ -157,11 +135,6 @@ init_peer(void)
assocpeer_calls = peer_demobilizations = 0;
/*
- * Initialization counter.
- */
- /* init_peer_starttime = 0; */
-
- /*
* Initialize peer memory.
*/
peer_free = 0;
@@ -175,7 +148,7 @@ init_peer(void)
/*
* Initialize our first association ID
*/
- current_association_ID = (u_short)ranp2(16);
+ current_association_ID = (associd_t)ranp2(16);
if (current_association_ID == 0)
current_association_ID = 1;
}
@@ -190,7 +163,8 @@ getmorepeermem(void)
register int i;
register struct peer *peer;
- peer = (struct peer *)emalloc(INC_PEER_ALLOC*sizeof(struct peer));
+ peer = (struct peer *)emalloc(INC_PEER_ALLOC *
+ sizeof(struct peer));
for (i = 0; i < INC_PEER_ALLOC; i++) {
peer->next = peer_free;
peer_free = peer;
@@ -202,7 +176,6 @@ getmorepeermem(void)
}
-
/*
* findexistingpeer - return a pointer to a peer in the hash table
*/
@@ -220,22 +193,21 @@ findexistingpeer(
* same peer through different interfaces in the hash table.
*/
if (start_peer == 0)
- peer = peer_hash[HASH_ADDR(addr)];
+ peer = peer_hash[HASH_ADDR(addr)];
else
- peer = start_peer->next;
+ peer = start_peer->next;
while (peer != 0) {
if (NSRCADR(addr) == NSRCADR(&peer->srcadr)
&& NSRCPORT(addr) == NSRCPORT(&peer->srcadr)) {
if (mode == -1)
- return peer;
+ return (peer);
else if (peer->hmode == mode)
break;
}
peer = peer->next;
}
-
- return peer;
+ return (peer);
}
@@ -259,50 +231,46 @@ findpeer(
for (peer = peer_hash[hash]; peer != 0; peer = peer->next) {
if (NSRCADR(srcadr) == NSRCADR(&peer->srcadr)
&& NSRCPORT(srcadr) == NSRCPORT(&peer->srcadr)) {
+
/*
- * if the association matching rules determine that
- * this is not a valid combination, then look for
- * the next valid peer association.
+ * if the association matching rules determine
+ * that this is not a valid combination, then
+ * look for the next valid peer association.
*/
*action = MATCH_ASSOC(peer->hmode, pkt_mode);
/*
* Sigh! Check if BCLIENT peer in client
- * server mode, else return error
+ * server mode, else return error.
*/
- if ((*action == AM_POSSBCL) &&
- !(peer->cast_flags & FLAG_MCAST1)) {
+ if ((*action == AM_POSSBCL) && !(peer->flags &
+ FLAG_MCAST))
*action = AM_ERR;
- }
- /* if an error was returned, exit back right here */
+ /*
+ * if an error was returned, exit back right
+ * here.
+ */
if (*action == AM_ERR)
- return (struct peer *)0;
+ return ((struct peer *)0);
- /* if a match is found, we stop our search */
+ /*
+ * if a match is found, we stop our search.
+ */
if (*action != AM_NOMATCH)
break;
}
}
-#ifdef DEBUG
- if (debug > 1)
- printf("pkt_mode %d action %d\n", pkt_mode, *action);
-#endif
- /* if no matching association is found */
+ /*
+ * If no matching association is found
+ */
if (peer == 0) {
*action = MATCH_ASSOC(NO_PEER, pkt_mode);
-#ifdef DEBUG
- if (debug > 1)
- printf("pkt_mode %d action %d\n", pkt_mode, *action);
-#endif
- return (struct peer *)0;
+ return ((struct peer *)0);
}
-
- /* reset the default interface to something more meaningful */
- if ((peer->dstadr == any_interface))
- peer->dstadr = dstadr;
- return peer;
+ peer->dstadr = dstadr;
+ return (peer);
}
/*
@@ -310,7 +278,7 @@ findpeer(
*/
struct peer *
findpeerbyassoc(
- int assoc
+ u_int assoc
)
{
register struct peer *peer;
@@ -319,101 +287,41 @@ findpeerbyassoc(
assocpeer_calls++;
hash = assoc & HASH_MASK;
- for (peer = assoc_hash[hash]; peer != 0; peer = peer->ass_next) {
- if ((u_short)assoc == peer->associd)
- return peer; /* got it! */
+ for (peer = assoc_hash[hash]; peer != 0; peer =
+ peer->ass_next) {
+ if (assoc == peer->associd)
+ return (peer);
}
-
- /*
- * Out of luck. Return 0.
- */
- return (struct peer *)0;
+ return (NULL);
}
-/*
- * findmanycastpeer - find and return an manycast peer if it exists
- *
- *
- * the current implementation loops across all hash-buckets
- *
- * *** THERE IS AN URGENT NEED TO CHANGE THIS ***
- */
-struct peer *
-findmanycastpeer(
- l_fp *p_org
- )
-{
- register struct peer *peer;
- register struct peer *manycast_peer = 0;
- int i = 0;
-
- 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->flags & FLAG_CONFIG) {
- if (L_ISEQU(&peer->xmt, p_org))
- return peer; /* got it */
- else
- manycast_peer = peer;
- }
- }
- }
-
- /*
- * Out of luck. Return the manycastpeer for what it is worth.
- */
- return manycast_peer;
-}
-
-/*
- * key_expire - garbage collect keys
- */
-static void
-key_expire(
- struct peer *peer
- )
-{
- int i;
-
- if (peer->keylist != 0) {
- for (i = 0; i <= peer->keynumber; i++)
- authtrust(peer->keylist[i], 0);
- free(peer->keylist);
- peer->keylist = 0;
- }
- if (peer->keyid > NTP_MAXKEY) {
- authtrust(peer->keyid, 0);
- peer->keyid = 0;
- }
-}
/*
- * key_rekey - expire all keys and roll a new private value. Note the
- * 32-bit mask is necessary for 64-bit u_longs.
+ * clear_all - flush all time values for all associations
*/
void
-key_expire_all(
- )
+clear_all(void)
{
struct peer *peer, *next_peer;
int n;
+ /*
+ * This routine is called when the clock is stepped, and so all
+ * previously saved time values are untrusted.
+ */
for (n = 0; n < HASH_SIZE; n++) {
for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
next_peer = peer->next;
- key_expire(peer);
+ peer_clear(peer);
}
}
- sys_private = (u_long)RANDOM & 0xffffffff;
#ifdef DEBUG
if (debug)
- printf("key_expire_all: at %lu private %08lx\n",
- current_time, sys_private);
+ printf("clear_all: at %lu\n", current_time);
#endif
}
+
+
/*
* unpeer - remove peer structure from hash table and free structure
*/
@@ -424,16 +332,16 @@ unpeer(
{
int hash;
+ peer_associations--;
#ifdef DEBUG
- if (debug > 1)
- printf("demobilize %u\n", peer_to_remove->associd);
+ if (debug)
+ printf("demobilize %u %d\n", peer_to_remove->associd,
+ peer_associations);
#endif
- key_expire(peer_to_remove);
+ peer_clear(peer_to_remove);
hash = HASH_ADDR(&peer_to_remove->srcadr);
peer_hash_count[hash]--;
peer_demobilizations++;
- peer_associations--;
-
#ifdef REFCLOCK
/*
* If this peer is actually a clock, shut it down first
@@ -490,7 +398,7 @@ unpeer(
/*
- * peer_config - configure a new peer
+ * peer_config - configure a new association
*/
struct peer *
peer_config(
@@ -500,63 +408,83 @@ peer_config(
int version,
int minpoll,
int maxpoll,
- int flags,
+ u_int flags,
int ttl,
- u_long key
+ keyid_t key,
+ u_char *keystr
)
{
register struct peer *peer;
+ u_int cast_flags;
/*
- * See if we have this guy in the tables already. If
- * so just mark him configured.
+ * First search from the beginning for an association with given
+ * remote address and mode. If an interface is given, search
+ * from there to find the association which matches that
+ * destination.
*/
peer = findexistingpeer(srcadr, (struct peer *)0, hmode);
if (dstadr != 0) {
while (peer != 0) {
if (peer->dstadr == dstadr)
- break;
+ break;
peer = findexistingpeer(srcadr, peer, hmode);
}
}
/*
- * If we found one, just change his mode and mark him configured.
+ * We do a dirty little jig to figure the cast flags. This is
+ * probably not the best place to do this, at least until the
+ * configure code is rebuilt. Note only one flag can be set.
+ */
+ switch (hmode) {
+
+ case MODE_BROADCAST:
+ if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
+ cast_flags = MDF_MCAST;
+ else
+ cast_flags = MDF_BCAST;
+ break;
+
+ case MODE_CLIENT:
+ if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
+ cast_flags = MDF_ACAST;
+ else
+ cast_flags = MDF_UCAST;
+ break;
+
+ default:
+ cast_flags = MDF_UCAST;
+ break;
+ }
+
+ /*
+ * If the peer is already configured, some dope has a duplicate
+ * configureation entry or another dope is wiggling from afar.
*/
if (peer != 0) {
peer->hmode = (u_char)hmode;
peer->version = (u_char)version;
peer->minpoll = (u_char)minpoll;
peer->maxpoll = (u_char)maxpoll;
- peer->hpoll = peer->minpoll;
- peer->ppoll = peer->minpoll;
+ peer->hpoll = peer->kpoll = peer->minpoll;
+ peer->ppoll = peer->maxpoll;
peer->flags = flags | FLAG_CONFIG |
(peer->flags & FLAG_REFCLOCK);
- peer->cast_flags = (hmode == MODE_BROADCAST) ?
- IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)) ? MDF_MCAST : MDF_BCAST : MDF_UCAST;
- peer->ttl = (u_char)ttl;
+ peer->cast_flags = cast_flags;
+ peer->ttlmax = ttl;
peer->keyid = key;
- peer->keynumber = 0;
- return peer;
+ return (peer);
}
/*
- * If we're here this guy is unknown to us. Make a new peer
- * structure for him.
+ * Here no match has been found, so presumably this is a new
+ * persistent association. Mobilize the thing and initialize its
+ * variables.
*/
peer = newpeer(srcadr, dstadr, hmode, version, minpoll, maxpoll,
- ttl, key);
- if (peer != 0) {
- peer->flags |= flags | FLAG_CONFIG;
-#ifdef DEBUG
- if (debug)
- printf("peer_config: %s mode %d vers %d min %d max %d flags 0x%04x ttl %d key %lu\n",
- ntoa(&peer->srcadr), peer->hmode, peer->version,
- peer->minpoll, peer->maxpoll, peer->flags,
- peer->ttl, peer->keyid);
-#endif
- }
- return peer;
+ flags | FLAG_CONFIG, cast_flags, ttl, key);
+ return (peer);
}
@@ -571,74 +499,63 @@ newpeer(
int version,
int minpoll,
int maxpoll,
+ u_int flags,
+ u_int cast_flags,
int ttl,
- u_long key
+ keyid_t key
)
{
register struct peer *peer;
register int i;
/*
- * Some dirt here. Some of the initialization requires
- * knowlege of our system state.
+ * Allocate a new peer structure. Some dirt here, since some of
+ * the initialization requires knowlege of our system state.
*/
if (peer_free_count == 0)
- getmorepeermem();
-
+ getmorepeermem();
peer = peer_free;
peer_free = peer->next;
peer_free_count--;
peer_associations++;
+ memset((char *)peer, 0, sizeof(struct peer));
/*
- * Initialize the structure. This stuff is sort of part of
- * the receive procedure and part of the clear procedure rolled
- * into one.
- *
- * Zero the whole thing for now. We might be pickier later.
+ * 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.
*/
- memset((char *)peer, 0, sizeof(struct peer));
-
- peer->srcadr = *srcadr;
- if (dstadr != 0)
- peer->dstadr = dstadr;
- else if (hmode == MODE_BROADCAST)
+ if (ISREFCLOCKADR(srcadr))
+ peer->dstadr = loopback_interface;
+ else if (cast_flags & MDF_BCLNT)
peer->dstadr = findbcastinter(srcadr);
+ else if (dstadr != any_interface)
+ peer->dstadr = dstadr;
else
- peer->dstadr = any_interface;
- peer->cast_flags = (hmode == MODE_BROADCAST) ?
- (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr))) ? MDF_MCAST :
- MDF_BCAST : (hmode == MODE_BCLIENT || hmode == MODE_MCLIENT) ?
- (peer->dstadr->flags & INT_MULTICAST) ? MDF_MCAST : MDF_BCAST :
- MDF_UCAST;
- /* Set manycast flags if appropriate */
- if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)) && hmode == MODE_CLIENT)
- peer->cast_flags = MDF_ACAST;
+ peer->dstadr = findinterface(srcadr);
+ peer->srcadr = *srcadr;
peer->hmode = (u_char)hmode;
- peer->keyid = key;
peer->version = (u_char)version;
- peer->minpoll = (u_char)minpoll;
- peer->maxpoll = (u_char)maxpoll;
- peer->hpoll = peer->minpoll;
- peer->ppoll = peer->minpoll;
- peer->ttl = ttl;
- peer->leap = LEAP_NOTINSYNC;
+ peer->minpoll = (u_char)max(NTP_MINPOLL, minpoll);
+ peer->maxpoll = (u_char)min(NTP_MAXPOLL, maxpoll);
+ peer->flags = flags | (key > NTP_MAXKEY ? FLAG_SKEY : 0);
+ peer->cast_flags = cast_flags;
+ peer->ttlmax = ttl;
+ peer->keyid = key;
peer->precision = sys_precision;
- peer->variance = MAXDISPERSE;
- peer->epoch = current_time;
- peer->stratum = STRATUM_UNSPEC;
peer_clear(peer);
- peer->update = peer->outdate = current_time;
- peer->nextdate = peer->outdate + RANDPOLL(NTP_MINPOLL);
- if (peer->flags & FLAG_BURST)
- peer->burst = NTP_SHIFT;
+ if (mode_ntpdate)
+ peer_ntpdate++;
/*
- * Assign him an association ID and increment the system variable
+ * Assign an association ID and increment the system variable.
*/
peer->associd = current_association_ID;
if (++current_association_ID == 0)
- ++current_association_ID;
+ ++current_association_ID;
/*
* Note time on statistics timers.
@@ -646,7 +563,6 @@ newpeer(
peer->timereset = current_time;
peer->timereachable = current_time;
peer->timereceived = current_time;
-
#ifdef REFCLOCK
if (ISREFCLOCKADR(&peer->srcadr)) {
/*
@@ -662,29 +578,32 @@ newpeer(
peer->next = peer_free;
peer_free = peer;
peer_free_count++;
- return 0;
+ return (NULL);
}
}
#endif
/*
- * Put him in the hash tables.
+ * Put the new peer in the hash tables.
*/
i = HASH_ADDR(&peer->srcadr);
peer->next = peer_hash[i];
peer_hash[i] = peer;
peer_hash_count[i]++;
-
i = peer->associd & HASH_MASK;
peer->ass_next = assoc_hash[i];
assoc_hash[i] = peer;
assoc_hash_count[i]++;
#ifdef DEBUG
- if (debug > 1)
- printf("mobilize %u next %lu\n", peer->associd,
- peer->nextdate - peer->outdate);
+ if (debug)
+ printf(
+ "newpeer: %s->%s mode %d vers %d poll %d %d flags %x %x ttl %d key %08x\n",
+ ntoa(&peer->dstadr->sin), ntoa(&peer->srcadr),
+ peer->hmode, peer->version, peer->minpoll,
+ peer->maxpoll, peer->flags, peer->cast_flags,
+ peer->ttlmax, peer->keyid);
#endif
- return peer;
+ return (peer);
}
@@ -707,14 +626,15 @@ peer_unconfig(
if (peer->flags & FLAG_CONFIG
&& (dstadr == 0 || peer->dstadr == dstadr)) {
num_found++;
+
/*
- * Tricky stuff here. If the peer is polling us
- * in active mode, turn off the configuration bit
- * and make the mode passive. This allows us to
- * avoid dumping a lot of history for peers we
- * might choose to keep track of in passive mode.
- * The protocol will eventually terminate undesirables
- * on its own.
+ * Tricky stuff here. If the peer is polling us
+ * in active mode, turn off the configuration
+ * bit and make the mode passive. This allows us
+ * to avoid dumping a lot of history for peers
+ * we might choose to keep track of in passive
+ * mode. The protocol will eventually terminate
+ * undesirables on its own.
*/
if (peer->hmode == MODE_ACTIVE
&& peer->pmode == MODE_ACTIVE) {
@@ -727,21 +647,7 @@ peer_unconfig(
}
peer = findexistingpeer(srcadr, peer, mode);
}
- return num_found;
-}
-
-/*
- * peer_copy_manycast - copy manycast peer variables to new association
- * (right now it simply copies the transmit timestamp)
- */
-void
-peer_config_manycast(
- struct peer *peer1,
- struct peer *peer2
- )
-{
- peer2->cast_flags = MDF_ACAST;
- peer2->xmt = peer1->xmt;
+ return (num_found);
}
/*
@@ -775,7 +681,6 @@ peer_reset(
peer->oldpkt = 0;
peer->seldisptoolarge = 0;
peer->selbroken = 0;
- peer->seltooold = 0;
peer->timereset = current_time;
}
@@ -793,3 +698,114 @@ peer_all_reset(void)
for (peer = peer_hash[hash]; peer != 0; peer = peer->next)
peer_reset(peer);
}
+
+
+#ifdef AUTOKEY
+/*
+ * expire_all - flush all crypto data and update timestamps.
+ */
+void
+expire_all(void)
+{
+ struct peer *peer, *next_peer;
+ int n;
+
+ /*
+ * This routine is called about once per day from the timer
+ * routine and when the client is first synchronized. Search the
+ * peer list for all associations and flush only the key list
+ * and cookie. If a manycast client association, flush
+ * everything. Then, recompute and sign the agreement public
+ * value, if present.
+ */
+ for (n = 0; n < HASH_SIZE; n++) {
+ for (peer = peer_hash[n]; peer != 0; peer = next_peer) {
+ next_peer = peer->next;
+ if (peer->cast_flags & MDF_ACAST) {
+ peer_clear(peer);
+#ifdef AUTOKEY
+ } else {
+ key_expire(peer);
+ peer->pcookie.tstamp = 0;
+#endif /* AUTOKEY */
+ }
+
+ }
+ }
+ sys_private = (u_int32)RANDOM & 0xffffffff;
+#ifdef PUBKEY
+ crypto_agree();
+#endif /* PUBKEY */
+#ifdef DEBUG
+ if (debug)
+ printf("expire_all: at %lu\n", current_time);
+#endif
+}
+#endif /* AUTOKEY */
+
+
+/*
+ * findmanycastpeer - find and return a manycast peer
+ */
+struct peer *
+findmanycastpeer(
+ struct recvbuf *rbufp
+ )
+{
+ register struct peer *peer;
+ struct pkt *pkt;
+ l_fp p_org;
+ int i;
+
+ /*
+ * This routine is called upon arrival of a client-mode message
+ * from a manycast server. Search the peer list for a manycast
+ * client association where the last transmit timestamp matches
+ * the originate timestamp. This assumes the transmit timestamps
+ * for possibly more than one manycast association are unique.
+ */
+ pkt = &rbufp->recv_pkt;
+ for (i = 0; i < HASH_SIZE; i++) {
+ if (peer_hash_count[i] == 0)
+ continue;
+
+ for (peer = peer_hash[i]; peer != 0; peer =
+ peer->next) {
+ if (peer->cast_flags & MDF_ACAST) {
+ NTOHL_FP(&pkt->org, &p_org);
+ if (L_ISEQU(&peer->xmt, &p_org))
+ return (peer);
+ }
+ }
+ }
+ return (NULL);
+}
+
+
+/*
+ * resetmanycast - reset all manycast clients
+ */
+void
+resetmanycast(void)
+{
+ register struct peer *peer;
+ int i;
+
+ /*
+ * This routine is called when the number of client associations
+ * falls below the minimum. Search the peer list for manycast
+ * client associations and reset the ttl and poll interval.
+ */
+ for (i = 0; i < HASH_SIZE; i++) {
+ if (peer_hash_count[i] == 0)
+ continue;
+
+ for (peer = peer_hash[i]; peer != 0; peer =
+ peer->next) {
+ if (peer->cast_flags & MDF_ACAST) {
+ peer->ttl = 0;
+ poll_update(peer, peer->hpoll);
+ }
+ }
+ }
+}
diff --git a/contrib/ntp/ntpd/ntp_proto.c b/contrib/ntp/ntpd/ntp_proto.c
index a24c0e3..4962057 100644
--- a/contrib/ntp/ntpd/ntp_proto.c
+++ b/contrib/ntp/ntpd/ntp_proto.c
@@ -5,15 +5,14 @@
#include <config.h>
#endif
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_stdlib.h"
#include "ntp_unixtime.h"
#include "ntp_control.h"
#include "ntp_string.h"
+#include "ntp_crypto.h"
+
+#include <stdio.h>
#if defined(VMS) && defined(VMS_LOCALUNIT) /*wjm*/
#include "ntp_refclock.h"
@@ -24,19 +23,22 @@
#endif
/*
- * System variables are declared here. See Section 3.2 of the
+ * System variables are declared here. See Section 3.2 of the
* specification.
*/
u_char sys_leap; /* system leap indicator */
u_char sys_stratum; /* stratum of system */
s_char sys_precision; /* local clock precision */
-double sys_rootdelay; /* distance to current sync source */
-double sys_rootdispersion; /* dispersion of system clock */
+double sys_rootdelay; /* roundtrip delay to primary source */
+double sys_rootdispersion; /* dispersion to primary source */
u_int32 sys_refid; /* reference source for local clock */
static double sys_offset; /* current local clock offset */
l_fp sys_reftime; /* time we were last updated */
struct peer *sys_peer; /* our current peer */
+struct peer *sys_prefer; /* our cherished peer */
+#ifdef AUTOKEY
u_long sys_automax; /* maximum session key lifetime */
+#endif /* AUTOKEY */
/*
* Nonspecified system state variables.
@@ -47,10 +49,15 @@ 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_maxd; /* select error (squares) */
-static double sys_epsil; /* system error (squares) */
-u_long sys_private; /* private value for session seed */
-int sys_manycastserver; /* 1 => respond to manycast client pkts */
+static double sys_selerr; /* select error (squares) */
+static double sys_syserr; /* system error (squares) */
+keyid_t sys_private; /* private value for session seed */
+int sys_manycastserver; /* respond to manycast client pkts */
+u_int sys_survivors; /* truest of the truechimers */
+int peer_ntpdate; /* active peers in ntpdate mode */
+#ifdef AUTOKEY
+char *sys_hostname; /* gethostname() name */
+#endif /* AUTOKEY */
/*
* Statistics counters
@@ -68,12 +75,10 @@ u_long sys_limitrejected; /* pkts rejected due to client count per net */
static double root_distance P((struct peer *));
static double clock_combine P((struct peer **, int));
static void peer_xmit P((struct peer *));
-static void fast_xmit P((struct recvbuf *, int, u_long));
+static void fast_xmit P((struct recvbuf *, int, keyid_t, int));
static void clock_update P((void));
int default_get_precision P((void));
-#ifdef MD5
-static void make_keylist P((struct peer *));
-#endif /* MD5 */
+
/*
* transmit - Transmit Procedure. See Section 3.4.2 of the
@@ -91,116 +96,173 @@ transmit(
u_char oreach;
/*
- * Determine reachability and diddle things if we
- * haven't heard from the host for a while. If the peer
- * is not configured and not likely to stay around,
- * we exhaust it.
+ * 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...
*/
+ if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {
+
+ /*
+ * In broadcast mode the poll interval is fixed
+ * at minpoll and the ttl at ttlmax.
+ */
+ hpoll = peer->minpoll;
+ peer->ttl = peer->ttlmax;
+#ifdef AUTOKEY
+ } else if (peer->cast_flags & MDF_ACAST) {
+
+ /*
+ * In manycast mode we start with the minpoll
+ * interval and ttl. However, the actual poll
+ * interval is eight times the nominal poll
+ * interval shown here. If fewer than three
+ * servers are found, the ttl is increased by
+ * one and we try again. If this continues to
+ * the max ttl, the poll interval is bumped by
+ * one and we try again. If at least three
+ * servers are found, the poll interval
+ * increases with the system poll interval to
+ * the max and we continue indefinately.
+ * However, about once per day when the
+ * agreement parameters are refreshed, the
+ * manycast clients are reset and we start from
+ * the beginning. This is to catch and clamp the
+ * ttl to the lowest practical value and avoid
+ * knocking on spurious doors.
+ */
+ if (sys_survivors < NTP_MINCLOCK && peer->ttl <
+ peer->ttlmax)
+ peer->ttl++;
+ hpoll = sys_poll;
+#endif /* AUTOKEY */
+ } else {
+
+ /*
+ * For associations expecting a reply, the
+ * watchdog counter is bumped by one if the peer
+ * has not been heard since the previous poll.
+ * If the counter reaches the max, the peer is
+ * demobilized if not configured and just
+ * cleared if it is, but in this case the poll
+ * interval is bumped by one.
+ */
+ if (peer->unreach < NTP_UNREACH) {
+ peer->unreach++;
+ } else if (!(peer->flags & FLAG_CONFIG)) {
+ unpeer(peer);
+ clock_select();
+ return;
+
+ } else {
+ peer_clear(peer);
+ hpoll++;
+ }
+ }
oreach = peer->reach;
- if (oreach & 0x01)
- peer->valid++;
- if (oreach & 0x80)
- peer->valid--;
- if (!(peer->flags & FLAG_CONFIG) && peer->valid >
- NTP_SHIFT / 2 && (peer->reach & 0x80) &&
- peer->status < CTL_PST_SEL_SYNCCAND)
- peer->reach = 0;
peer->reach <<= 1;
if (peer->reach == 0) {
/*
- * If this is an uncofigured association and
- * has become unreachable, demobilize it.
+ * If this association has become unreachable,
+ * clear it and raise a trap.
*/
if (oreach != 0) {
report_event(EVNT_UNREACH, peer);
peer->timereachable = current_time;
- peer_clear(peer);
if (!(peer->flags & FLAG_CONFIG)) {
unpeer(peer);
+ clock_select();
return;
+ } else {
+ peer_clear(peer);
+ hpoll = peer->minpoll;
}
}
-
- /*
- * We would like to respond quickly when the
- * peer comes back to life. If the probes since
- * becoming unreachable are less than
- * NTP_UNREACH, clamp the poll interval to the
- * minimum. In order to minimize the network
- * traffic, the interval gradually ramps up the
- * the maximum after that.
- */
- peer->ppoll = peer->maxpoll;
- if (peer->unreach < NTP_UNREACH) {
- if (peer->hmode == MODE_CLIENT)
- peer->unreach++;
- hpoll = peer->minpoll;
- } else {
- hpoll++;
- }
- if (peer->flags & FLAG_BURST)
- peer->burst = 2;
-
+ if (peer->flags & FLAG_IBURST)
+ peer->burst = NTP_SHIFT;
} else {
/*
- * Here the peer is reachable. If there is no
- * system peer or if the stratum of the system
- * peer is greater than this peer, clamp the
- * poll interval to the minimum. If less than
- * two samples are in the reachability register,
- * reduce the interval; if more than six samples
- * are in the register, increase the interval.
+ * Here the peer is reachable. If it has not
+ * been heard for three consecutive polls, stuff
+ * the clock filter. Next, determine the poll
+ * interval. If the peer is a synchronization
+ * candidate, use the system poll interval. If
+ * the peer is not sane, increase it by one. If
+ * the number of valid updates is not greater
+ * than half the register size, clamp it to the
+ * minimum. This is to quickly recover the time
+ * variables when a noisy peer shows life.
*/
- peer->unreach = 0;
- if (sys_peer == 0)
- hpoll = peer->minpoll;
- else if (sys_peer->stratum > peer->stratum)
- hpoll = peer->minpoll;
- if ((peer->reach & 0x03) == 0) {
+ if (!(peer->reach & 0x07)) {
clock_filter(peer, 0., 0., MAXDISPERSE);
clock_select();
}
- if (peer->valid <= 2)
- hpoll--;
- else if (peer->valid >= NTP_SHIFT - 2)
+ if ((peer->stratum > 1 && peer->refid ==
+ peer->dstadr->sin.sin_addr.s_addr) ||
+ peer->stratum >= STRATUM_UNSPEC)
hpoll++;
+ else
+ hpoll = sys_poll;
if (peer->flags & FLAG_BURST)
peer->burst = NTP_SHIFT;
}
} else {
peer->burst--;
if (peer->burst == 0) {
- if (peer->flags & FLAG_MCAST2) {
- peer->flags &= ~FLAG_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->cast_flags & MDF_BCLNT) {
peer->hmode = MODE_BCLIENT;
+#ifdef AUTOKEY
+ key_expire(peer);
+#endif /* AUTOKEY */
}
- clock_select();
poll_update(peer, hpoll);
+ clock_select();
+
+ /*
+ * If ntpdate mode and the clock has not been
+ * set and all peers have completed the burst,
+ * we declare a successful failure.
+ */
+ if (mode_ntpdate) {
+ peer_ntpdate--;
+ if (peer_ntpdate > 0)
+ return;
+ NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
+ msyslog(LOG_NOTICE,
+ "no reply; clock not set");
+ printf(
+ "ntpd: no reply; clock not set\n");
+ exit(0);
+ }
return;
+
}
}
+ peer->outdate = current_time;
+ poll_update(peer, hpoll);
/*
- * We need to be very careful about honking uncivilized time. If
- * not operating in broadcast mode, honk in all except broadcast
- * client mode. If operating in broadcast mode and synchronized
- * to a real source, honk except when the peer is the local-
- * clock driver and the prefer flag is not set. In other words,
- * in broadcast mode we never honk unless known to be
- * synchronized to real time.
+ * We need to be very careful about honking uncivilized time.
+ * Never transmit if in broadcast client mode or access denied.
+ * If in broadcast mode, transmit only if synchronized to a
+ * valid source.
*/
- if (peer->hmode != MODE_BROADCAST) {
- if (peer->hmode != MODE_BCLIENT)
- peer_xmit(peer);
- } else if (sys_peer != 0 && sys_leap != LEAP_NOTINSYNC) {
- if (!(sys_peer->refclktype == REFCLK_LOCALCLOCK &&
- !(sys_peer->flags & FLAG_PREFER)))
- peer_xmit(peer);
+ if (peer->hmode == MODE_BCLIENT || peer->flash & TEST4) {
+ return;
+ } else if (peer->hmode == MODE_BROADCAST) {
+ if (sys_peer == NULL)
+ return;
}
- peer->outdate = current_time;
- poll_update(peer, hpoll);
+ peer_xmit(peer);
}
/*
@@ -216,482 +278,552 @@ receive(
int hismode;
int oflags;
int restrict_mask;
- int has_mac; /* has MAC field */
- int authlen; /* length of MAC field */
+ int has_mac; /* length of MAC field */
+ int authlen; /* offset of MAC field */
int is_authentic; /* cryptosum ok */
- int is_mystic; /* session key exists */
- int is_error; /* parse error */
-/* u_long pkeyid; */
- u_long skeyid, tkeyid;
+ keyid_t skeyid; /* cryptographic keys */
+ struct sockaddr_in *dstadr_sin; /* active runway */
+#ifdef AUTOKEY
+ keyid_t pkeyid, tkeyid; /* cryptographic keys */
+#endif /* AUTOKEY */
struct peer *peer2;
int retcode = AM_NOMATCH;
/*
- * Monitor the packet and get restrictions
+ * Monitor the packet and get restrictions. Note that the packet
+ * length for control and private mode packets must be checked
+ * by the service routines. Note that no statistics counters are
+ * recorded for restrict violations, since these counters are in
+ * the restriction routine. Note the careful distinctions here
+ * between a packet with a format error and a packet that is
+ * simply discarded without prejudice. Some restrictions have to
+ * be handled later in order to generate a kiss-of-death packet.
*/
ntp_monitor(rbufp);
restrict_mask = restrictions(&rbufp->recv_srcadr);
#ifdef DEBUG
- if (debug > 1)
- printf("receive: from %s restrict %02x\n",
+ if (debug > 2)
+ printf("receive: at %ld %s<-%s restrict %02x\n",
+ current_time, ntoa(&rbufp->dstadr->sin),
ntoa(&rbufp->recv_srcadr), restrict_mask);
#endif
if (restrict_mask & RES_IGNORE)
- return;
-
- /*
- * Discard packets with invalid version number.
- */
+ return; /* no anything */
+ if (!(SRCPORT(&rbufp->recv_srcadr) == NTP_PORT ||
+ SRCPORT(&rbufp->recv_srcadr) >= IPPORT_RESERVED)) {
+ sys_badlength++;
+ return; /* invalid port */
+ }
pkt = &rbufp->recv_pkt;
- if (PKT_VERSION(pkt->li_vn_mode) >= NTP_VERSION)
- sys_newversionpkt++;
- else if (PKT_VERSION(pkt->li_vn_mode) >= NTP_OLDVERSION)
- sys_oldversionpkt++;
- else {
+ if (PKT_VERSION(pkt->li_vn_mode) == NTP_VERSION) {
+ sys_newversionpkt++; /* new version */
+ } else if (!(restrict_mask & RES_VERSION) &&
+ PKT_VERSION(pkt->li_vn_mode) >= NTP_OLDVERSION) {
+ sys_oldversionpkt++; /* old version */
+ } else {
sys_unknownversion++;
- return;
+ return; /* invalid version */
}
-
- /*
- * Restrict control/private mode packets. Note that packet
- * length has to be checked in the control/private mode protocol
- * module.
- */
if (PKT_MODE(pkt->li_vn_mode) == MODE_PRIVATE) {
if (restrict_mask & RES_NOQUERY)
- return;
+ return; /* no query private */
process_private(rbufp, ((restrict_mask &
RES_NOMODIFY) == 0));
return;
}
if (PKT_MODE(pkt->li_vn_mode) == MODE_CONTROL) {
if (restrict_mask & RES_NOQUERY)
- return;
+ return; /* no query control */
process_control(rbufp, restrict_mask);
return;
}
+ if (rbufp->recv_length < LEN_PKT_NOMAC) {
+ sys_badlength++;
+ return; /* runt packet */
+ }
/*
- * Restrict revenue packets.
- */
- if (restrict_mask & RES_DONTSERVE)
- return;
-
- /*
- * See if we only accept limited number of clients from the net
- * this guy is from. Note: the flag is determined dynamically
- * within restrictions()
+ * Validate mode. Note that NTPv1 is no longer supported.
*/
- if (restrict_mask & RES_LIMITED) {
- sys_limitrejected++;
- return;
- }
+ hismode = (int)PKT_MODE(pkt->li_vn_mode);
+ if (hismode == MODE_UNSPEC) {
+ sys_badlength++;
+ return; /* invalid mode */
+ }
/*
- * If we are not a broadcast client, ignore broadcast packets.
+ * Discard broadcast packets received on the wildcard interface
+ * or if not enabled as broadcast client.
*/
- if ((PKT_MODE(pkt->li_vn_mode) == MODE_BROADCAST &&
- !sys_bclient))
+ if (PKT_MODE(pkt->li_vn_mode) == MODE_BROADCAST &&
+ (rbufp->dstadr == any_interface || !sys_bclient))
return;
/*
- * This is really awful ugly. We figure out whether an extension
- * field is present and then measure the MAC size. If the number
- * of words following the packet header is less than or equal to
- * 5, no extension field is present and these words constitute
- * the MAC. If the number of words is greater than 5, an
- * extension field is present and the first word contains the
- * length of the extension field and the MAC follows that.
+ * 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.
*/
- has_mac = 0;
-/* pkeyid = 0; */
- skeyid = tkeyid = 0;
+ skeyid = 0;
+#ifdef AUTOKEY
+ pkeyid = tkeyid = 0;
+#endif /* AUTOKEY */
authlen = LEN_PKT_NOMAC;
- has_mac = rbufp->recv_length - authlen;
- if (has_mac <= 5 * sizeof(u_int32)) {
- skeyid = (u_long)ntohl(pkt->keyid1) & 0xffffffff;
- } else {
- authlen += (u_long)ntohl(pkt->keyid1) & 0xffffffff;
- has_mac = rbufp->recv_length - authlen;
- if (authlen <= 0) {
+ while ((has_mac = rbufp->recv_length - authlen) > 0) {
+ int temp;
+
+ if (has_mac % 4 != 0 || has_mac < 0) {
sys_badlength++;
return;
}
+ if (has_mac == 1 * 4 || has_mac == 3 * 4 || has_mac ==
+ MAX_MAC_LEN) {
+ skeyid = ntohl(((u_int32 *)pkt)[authlen / 4]);
+ break;
- /*
- * Note that keyid3 is actually the key ident of the
- * MAC itself.
- */
-/* pkeyid = (u_long)ntohl(pkt->keyid2) & 0xffffffff; */
- skeyid = tkeyid = (u_long)ntohl(pkt->keyid3) &
- 0xffffffff;
- }
-
- /*
- * Figure out his mode and validate it.
- */
- hismode = (int)PKT_MODE(pkt->li_vn_mode);
- if (PKT_VERSION(pkt->li_vn_mode) == NTP_OLDVERSION && hismode ==
- 0) {
- /*
- * Easy. If it is from the NTP port it is
- * a sym act, else client.
- */
- if (SRCPORT(&rbufp->recv_srcadr) == NTP_PORT)
- hismode = MODE_ACTIVE;
- else
- hismode = MODE_CLIENT;
- } else {
- if (hismode != MODE_ACTIVE && hismode != MODE_PASSIVE &&
- hismode != MODE_SERVER && hismode != MODE_CLIENT &&
- hismode != MODE_BROADCAST)
+ } else if (has_mac > MAX_MAC_LEN) {
+ temp = ntohl(((u_int32 *)pkt)[authlen / 4]) &
+ 0xffff;
+ if (temp < 4 || temp % 4 != 0) {
+ sys_badlength++;
+ return;
+ }
+ authlen += temp;
+ } else {
+ sys_badlength++;
return;
+ }
}
/*
- * If he included a mac field, decrypt it to see if it is
- * authentic.
+ * We have tossed out as many buggy packets as possible early in
+ * the game to reduce the exposure to a clogging attack. Now we
+ * have to burn some cycles to find the association and
+ * authenticate the packet if required. Note that we burn only
+ * MD5 or DES cycles, again to reduce exposure. There may be no
+ * matching association and that's okay.
+ *
+ * More on the autokey mambo. Normally the local interface is
+ * found when the association was mobilized with respect to a
+ * designated remote address. We assume packets arriving from
+ * the remote address arrive via this interface and the local
+ * address used to construct the autokey is the unicast address
+ * of the interface. However, if the sender is a broadcaster,
+ * the interface broadcast address is used instead.
+ * Notwithstanding this technobabble, if the sender is a
+ * multicaster, the broadcast address is null, so we use the
+ * unicast address anyway. Don't ask.
*/
- is_authentic = is_mystic = 0;
+ peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, rbufp->fd,
+ hismode, &retcode);
+ is_authentic = 0;
+ dstadr_sin = &rbufp->dstadr->sin;
if (has_mac == 0) {
#ifdef DEBUG
if (debug)
- printf("receive: at %ld from %s mode %d\n",
- current_time, ntoa(&rbufp->recv_srcadr),
- hismode);
+ printf("receive: at %ld %s<-%s mode %d code %d\n",
+ current_time, ntoa(&rbufp->dstadr->sin),
+ ntoa(&rbufp->recv_srcadr), hismode, retcode);
#endif
} else {
- is_mystic = authistrusted(skeyid);
-#ifdef MD5
- if (skeyid > NTP_MAXKEY && !is_mystic) {
-
+#ifdef AUTOKEY
+ /*
+ * For autokey modes, generate the session key
+ * and install in the key cache. Use the socket
+ * broadcast or unicast address as appropriate.
+ */
+ if (skeyid > NTP_MAXKEY) {
+
/*
- * For multicast mode, generate the session key
- * and install in the key cache. For client
- * mode, generate the session key for the
- * unicast address. For server mode, the session
- * key should already be in the key cache, since
- * it was generated when the last request was
- * sent.
+ * More on the autokey dance (AKD). A cookie is
+ * constructed from public and private values.
+ * For broadcast packets, the cookie is public
+ * (zero). For packets that match no
+ * association, the cookie is hashed from the
+ * addresses and private value. For server
+ * packets, the cookie was previously obtained
+ * from the server. For symmetric modes, the
+ * cookie was previously constructed using an
+ * agreement protocol; however, should PKI be
+ * unavailable, we construct a fake agreement as
+ * the EXOR of the peer and host cookies.
+ *
+ * hismode ephemeral persistent
+ * =======================================
+ * active 0 cookie#
+ * passive 0% cookie#
+ * client sys cookie 0%
+ * server 0% sys cookie
+ * broadcast 0 0
+ *
+ * # if unsync, 0
+ * % can't happen
*/
if (hismode == MODE_BROADCAST) {
+
+ /*
+ * For broadcaster, use the interface
+ * broadcast address when available;
+ * otherwise, use the unicast address
+ * found when the association was
+ * mobilized.
+ */
+ pkeyid = 0;
+ if (rbufp->dstadr->bcast.sin_addr.s_addr
+ != 0)
+ dstadr_sin =
+ &rbufp->dstadr->bcast;
+ } else if (peer == NULL) {
+ pkeyid = session_key(
+ &rbufp->recv_srcadr, dstadr_sin, 0,
+ sys_private, 0);
+ } else {
+ pkeyid = peer->pcookie.key;
+ }
+
+ /*
+ * The session key includes both the public
+ * values and cookie. In case of an extension
+ * field, the cookie used for authentication
+ * purposes is zero. Note the hash is saved for
+ * use later in the autokey mambo.
+ */
+ if (authlen > LEN_PKT_NOMAC && pkeyid != 0) {
+ session_key(&rbufp->recv_srcadr,
+ dstadr_sin, skeyid, 0, 2);
tkeyid = session_key(
- ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
- ntohl(rbufp->dstadr->bcast.sin_addr.s_addr),
- skeyid, (u_long)(4 * (1 << pkt->ppoll)));
- } else if (hismode != MODE_SERVER) {
+ &rbufp->recv_srcadr, dstadr_sin,
+ skeyid, pkeyid, 0);
+ } else {
tkeyid = session_key(
- ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
- ntohl(rbufp->dstadr->sin.sin_addr.s_addr),
- skeyid, (u_long)(4 * (1 << pkt->ppoll)));
+ &rbufp->recv_srcadr, dstadr_sin,
+ skeyid, pkeyid, 2);
}
}
-#endif /* MD5 */
+#endif /* AUTOKEY */
/*
* Compute the cryptosum. Note a clogging attack may
- * succceed in bloating the key cache.
+ * succeed in bloating the key cache. If an autokey,
+ * purge it immediately, since we won't be needing it
+ * again.
*/
if (authdecrypt(skeyid, (u_int32 *)pkt, authlen,
has_mac))
is_authentic = 1;
else
sys_badauth++;
+#ifdef AUTOKEY
+ if (skeyid > NTP_MAXKEY)
+ authtrust(skeyid, 0);
+#endif /* AUTOKEY */
#ifdef DEBUG
if (debug)
printf(
- "receive: at %ld %s mode %d keyid %08lx mac %d auth %d\n",
- current_time, ntoa(&rbufp->recv_srcadr),
- hismode, skeyid, has_mac, is_authentic);
+ "receive: at %ld %s<-%s mode %d code %d keyid %08x len %d mac %d auth %d\n",
+ current_time, ntoa(dstadr_sin),
+ ntoa(&rbufp->recv_srcadr), hismode, retcode,
+ skeyid, authlen, has_mac,
+ is_authentic);
#endif
}
/*
- * Find the peer. This will return a null if this guy isn't in
- * the database.
+ * The association matching rules are implemented by a set of
+ * routines and a table in ntp_peer.c. A packet matching an
+ * association is processed by that association. If not and
+ * certain conditions prevail, then an ephemeral association is
+ * mobilized: a broadcast packet mobilizes a broadcast client
+ * aassociation; a server packet mobilizes a client association;
+ * a symmetric active packet mobilizes a symmetric passive
+ * association. And, the adventure continues...
*/
- peer = findpeer(&rbufp->recv_srcadr, rbufp->dstadr, rbufp->fd,
- hismode, &retcode);
- /*
- * The new association matching rules are driven by a table
- * specified in ntp.h. We have replaced the *default* behaviour
- * of replying to bogus packets in server mode in this version.
- * A packet must now match an association in order to be
- * processed. In the event that no association exists, then an
- * association is mobilized if need be. Two different
- * associations can be mobilized a) passive associations b)
- * client associations due to broadcasts or manycasts.
- */
- is_error = 0;
switch (retcode) {
case AM_FXMIT:
/*
- * If the client is configured purely as a broadcast
- * client and not as an manycast server, it has no
- * business being a server. Simply go home. Otherwise,
- * send a MODE_SERVER response and go home. Note that we
- * don't do a authentication check here, since we can't
- * set the system clock; but, we do set the key ID to
- * zero to tell the caller about this.
+ * This is a client mode packet not matching a known
+ * association. If from a manycast client we run a few
+ * sanity checks before deciding to send a unicast
+ * server response. Otherwise, it must be a client
+ * request, so send a server response and go home.
*/
- if (!sys_bclient || sys_manycastserver) {
- if (is_authentic)
- fast_xmit(rbufp, MODE_SERVER, skeyid);
- else
- fast_xmit(rbufp, MODE_SERVER, 0);
+ if (sys_manycastserver && (rbufp->dstadr->flags &
+ INT_MULTICAST)) {
+
+ /*
+ * We are picky about responding to a
+ * manycaster. There is no reason to respond to
+ * a request if our time is worse than the
+ * manycaster. We certainly don't reply if not
+ * synchronized to proventic time.
+ */
+ if (sys_peer == NULL)
+ return;
+
+ /*
+ * We don't reply if the our stratum is greater
+ * than the manycaster.
+ */
+ if (PKT_TO_STRATUM(pkt->stratum) < sys_stratum)
+ return;
}
/*
- * We can't get here if an association is mobilized, so
- * just toss the key, if appropriate.
+ * Note that we don't require an authentication check
+ * here, since we can't set the system clock; but, we do
+ * set the key ID to zero to tell the caller about this.
*/
- if (!is_mystic && skeyid > NTP_MAXKEY)
- authtrust(skeyid, 0);
- return;
+ if (is_authentic)
+ fast_xmit(rbufp, MODE_SERVER, skeyid,
+ restrict_mask);
+ else
+ fast_xmit(rbufp, MODE_SERVER, 0, restrict_mask);
+ return;
case AM_MANYCAST:
/*
- * This could be in response to a multicast packet sent
- * by the "manycast" mode association. Find peer based
- * on the originate timestamp in the packet. Note that
- * we don't mobilize a new association, unless the
- * packet is properly authenticated. The response must
- * be properly authenticated and it's darn funny of the
- * manycaster isn't around now.
+ * 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. If so and
+ * the manycast association is found, we mobilize a
+ * client mode association, copy pertinent variables
+ * from the manycast to the client mode association and
+ * wind up the spring.
+ *
+ * There is an implosion hazard at the manycast client,
+ * since the manycast servers send the server packet
+ * immediately.
*/
- if ((sys_authenticate && !is_authentic)) {
- is_error = 1;
- break;
- }
- peer2 = (struct peer *)findmanycastpeer(&pkt->org);
- if (peer2 == 0) {
- is_error = 1;
- break;
- }
+ if ((restrict_mask & (RES_DONTSERVE | RES_LIMITED |
+ RES_NOPEER)) || (sys_authenticate &&
+ !is_authentic))
+ return;
+
+ peer2 = findmanycastpeer(rbufp);
+ if (peer2 == 0)
+ return;
- /*
- * Create a new association and copy the peer variables
- * to it. If something goes wrong, carefully pry the new
- * association away and return its marbles to the candy
- * store.
- */
peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid);
- if (peer == 0) {
- is_error = 1;
- break;
- }
- peer_config_manycast(peer2, peer);
- break;
-
- case AM_ERR:
-
- /*
- * Something bad happened. Dirty floor will be mopped by
- * the code at the end of this adventure.
- */
- is_error = 1;
+ sys_minpoll, NTP_MAXDPOLL, FLAG_IBURST |
+ (peer2->flags & (FLAG_AUTHENABLE | FLAG_SKEY)),
+ MDF_UCAST, 0, skeyid);
+ if (peer == NULL)
+ return;
break;
case AM_NEWPASS:
/*
- * Okay, we're going to keep him around. Allocate him
- * some memory. But, don't do that unless the packet is
- * properly authenticated.
+ * This is the first packet received from a symmetric
+ * active peer. First, make sure the packet is
+ * authentic. If so, mobilize a symmetric passive
+ * association.
*/
- if ((sys_authenticate && !is_authentic)) {
- is_error = 1;
- break;
+ if ((restrict_mask & (RES_DONTSERVE | RES_LIMITED |
+ RES_NOPEER)) || (sys_authenticate &&
+ !is_authentic)) {
+ fast_xmit(rbufp, MODE_PASSIVE, 0,
+ restrict_mask);
+ return;
}
peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid);
+ sys_minpoll, NTP_MAXDPOLL, sys_authenticate ?
+ FLAG_AUTHENABLE : 0, MDF_UCAST, 0, skeyid);
+ if (peer == NULL)
+ return;
break;
case AM_NEWBCL:
/*
- * Broadcast client being set up now. Do this only if
- * the packet is properly authenticated.
+ * This is the first packet received from a broadcast
+ * server. First, make sure the packet is authentic, not
+ * restricted and that we are a broadcast or multicast
+ * client. If so, mobilize a broadcast client
+ * association.
*/
- if ((restrict_mask & RES_NOPEER) || !sys_bclient ||
- (sys_authenticate && !is_authentic)) {
- is_error = 1;
- break;
- }
+ if ((restrict_mask & (RES_DONTSERVE | RES_LIMITED |
+ RES_NOPEER)) || (sys_authenticate &&
+ !is_authentic) || !sys_bclient)
+ return;
+
peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
- MODE_MCLIENT, PKT_VERSION(pkt->li_vn_mode),
- NTP_MINDPOLL, NTP_MAXDPOLL, 0, skeyid);
- if (peer == 0)
- break;
- peer->flags |= FLAG_MCAST1 | FLAG_MCAST2 | FLAG_BURST;
- peer->hmode = MODE_CLIENT;
- break;
+ MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
+ sys_minpoll, NTP_MAXDPOLL, FLAG_MCAST |
+ FLAG_IBURST | (sys_authenticate ?
+ FLAG_AUTHENABLE : 0), MDF_BCLNT, 0, skeyid);
+#ifdef AUTOKEY
+#ifdef PUBKEY
+ if (peer == NULL)
+ return;
+ if (peer->flags & FLAG_SKEY)
+ crypto_recv(peer, rbufp);
+#endif /* PUBKEY */
+#endif /* AUTOKEY */
+ return;
case AM_POSSBCL:
case AM_PROCPKT:
/*
- * It seems like it is okay to process the packet now
+ * Happiness and nothing broke. Earn some revenue.
*/
break;
default:
/*
- * shouldn't be getting here, but simply return anyway!
+ * Invalid mode combination. Leave the island
+ * immediately.
*/
- is_error = 1;
- }
- if (is_error) {
-
- /*
- * Error stub. If we get here, something broke. We
- * scuttle the autokey if necessary and sink the ship.
- * This can occur only upon mobilization, so we can
- * throw the structure away without fear of breaking
- * anything.
- */
- if (!is_mystic && skeyid > NTP_MAXKEY)
- authtrust(skeyid, 0);
- if (peer != 0)
- if (!(peer->flags & FLAG_CONFIG))
- unpeer(peer);
#ifdef DEBUG
if (debug)
- printf("match error code %d assoc %d\n",
- retcode, peer_associations);
+ printf("receive: bad protocol %d\n", retcode);
#endif
return;
}
/*
- * If the peer isn't configured, set his keyid and authenable
- * status based on the packet.
+ * If the peer isn't configured, set his authenable and autokey
+ * status based on the packet. Once the status is set, it can't
+ * be unset. It seems like a silly idea to do this here, rather
+ * in the configuration routine, but in some goofy cases the
+ * first packet sent cannot be authenticated and we need a way
+ * for the dude to change his mind.
*/
oflags = peer->flags;
peer->timereceived = current_time;
+ peer->received++;
if (!(peer->flags & FLAG_CONFIG) && has_mac) {
peer->flags |= FLAG_AUTHENABLE;
- if (skeyid > NTP_MAXKEY) {
- if (peer->flags & FLAG_MCAST2)
- peer->keyid = skeyid;
- else
- peer->flags |= FLAG_SKEY;
- }
+#ifdef AUTOKEY
+ if (skeyid > NTP_MAXKEY)
+ peer->flags |= FLAG_SKEY;
+#endif /* AUTOKEY */
}
/*
- * Determine if this guy is basically trustable. If not, flush
- * the bugger. If this is the first packet that is
- * authenticated, flush the clock filter. This is to foil
- * clogging attacks that might starve the poor dear.
+ * A valid packet must be from an authentic and allowed source.
+ * All packets must pass the authentication allowed tests.
+ * Autokey authenticated packets must pass additional tests and
+ * public-key authenticated packets must have the credentials
+ * verified. If all tests are passed, the packet is forwarded
+ * for processing. If not, the packet is discarded and the
+ * association demobilized if appropriate.
*/
peer->flash = 0;
- if (is_authentic)
+ if (is_authentic) {
peer->flags |= FLAG_AUTHENTIC;
- else
+ } else {
peer->flags &= ~FLAG_AUTHENTIC;
- if (peer->hmode == MODE_BROADCAST && (restrict_mask &
- RES_DONTTRUST))
- peer->flash |= TEST10; /* access denied */
+ }
+ if (peer->hmode == MODE_BROADCAST &&
+ (restrict_mask & RES_DONTTRUST)) /* test 4 */
+ peer->flash |= TEST4; /* access denied */
if (peer->flags & FLAG_AUTHENABLE) {
- if (!(peer->flags & FLAG_AUTHENTIC))
+ if (!(peer->flags & FLAG_AUTHENTIC)) /* test 5 */
peer->flash |= TEST5; /* auth failed */
- else if (skeyid == 0)
- peer->flash |= TEST9; /* peer not auth */
- else if (!(oflags & FLAG_AUTHENABLE)) {
- peer_clear(peer);
+ else if (!(oflags & FLAG_AUTHENABLE))
report_event(EVNT_PEERAUTH, peer);
- }
}
- if ((peer->flash & ~(u_int)TEST9) != 0) {
-
- /*
- * The packet is bogus, so we throw it away before
- * becoming a denial-of-service hazard. We don't throw
- * the current association away if it is configured or
- * if it has prior reachable friends.
- */
- if (!is_mystic && skeyid > NTP_MAXKEY)
- authtrust(skeyid, 0);
- if (!(peer->flags & FLAG_CONFIG) && peer->reach == 0)
- unpeer(peer);
+ if (peer->flash) {
#ifdef DEBUG
if (debug)
- printf(
- "invalid packet 0x%02x code %d assoc %d\n",
- peer->flash, retcode, peer_associations);
+ printf("receive: bad auth %03x\n", peer->flash);
#endif
return;
}
-#ifdef MD5
+#ifdef AUTOKEY
/*
- * The autokey dance. The cha-cha requires that the hash of the
- * current session key matches the previous key identifier.
- * Heaps of trouble if the steps falter.
+ * More autokey dance. The rules of the cha-cha are as follows:
+ *
+ * 1. If there is no key or the key is not auto, do nothing.
+ *
+ * 2. If an extension field contains a verified signature, it is
+ * self-authenticated and we sit the dance.
+ *
+ * 3. If this is a server reply, check only to see that the
+ * transmitted key ID matches the received key ID.
+ *
+ * 4. Check to see that one or more hashes of the current key ID
+ * matches the previous key ID or ultimate original key ID
+ * obtained from the broadcaster or symmetric peer. If no
+ * match, sit the dance and wait for timeout.
*/
- if (skeyid > NTP_MAXKEY) {
- int i;
-
- /*
- * In the case of a new autokey, verify the hash matches
- * one of the previous four hashes. If not, raise the
- * authentication flasher and hope the next one works.
- */
+ if (peer->flags & FLAG_SKEY) {
+ peer->flash |= TEST10;
+ crypto_recv(peer, rbufp);
+ poll_update(peer, peer->hpoll);
if (hismode == MODE_SERVER) {
- peer->pkeyid = peer->keyid;
- } else if (peer->flags & FLAG_MCAST2) {
- if (peer->pkeyid > NTP_MAXKEY)
- authtrust(peer->pkeyid, 0);
- for (i = 0; i < 4 && tkeyid != peer->pkeyid;
- i++) {
- tkeyid = session_key(
- ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
- ntohl(rbufp->dstadr->bcast.sin_addr.s_addr),
- tkeyid, 0);
- }
+ if (skeyid == peer->keyid)
+ peer->flash &= ~TEST10;
+ } else if (!peer->flash & TEST10) {
+ peer->pkeyid = skeyid;
} else {
- if (peer->pkeyid > NTP_MAXKEY)
- authtrust(peer->pkeyid, 0);
- for (i = 0; i < 4 && tkeyid != peer->pkeyid;
- i++) {
+ int i;
+
+ for (i = 0; ; i++) {
+ if (tkeyid == peer->pkeyid ||
+ tkeyid == peer->recauto.key) {
+ peer->flash &= ~TEST10;
+ peer->pkeyid = skeyid;
+ break;
+ }
+ if (i > peer->recauto.seq)
+ break;
tkeyid = session_key(
- ntohl((&rbufp->recv_srcadr)->sin_addr.s_addr),
- ntohl(rbufp->dstadr->sin.sin_addr.s_addr),
- tkeyid, 0);
+ &rbufp->recv_srcadr, dstadr_sin,
+ tkeyid, pkeyid, 0);
}
}
-#ifdef XXX /* temp until certificate code is mplemented */
- if (tkeyid != peer->pkeyid)
- peer->flash |= TEST9; /* peer not authentic */
+#ifdef PUBKEY
+
+ /*
+ * This is delicious. Ordinarily, we kick out all errors
+ * at this point; however, in symmetric mode and just
+ * warming up, an unsynchronized peer must inject the
+ * timestamps, even if it fails further up the road. So,
+ * let the dude by here, but only if the jerk is not yet
+ * reachable. After that, he's on his own.
+ */
+ if (!(peer->flags & FLAG_PROVEN))
+ peer->flash |= TEST11;
+ if (peer->flash && peer->reach) {
+#ifdef DEBUG
+ if (debug)
+ printf("packet: bad autokey %03x\n",
+ peer->flash);
#endif
- peer->pkeyid = skeyid;
+ return;
+ }
+#endif /* PUBKEY */
}
-#endif /* MD5 */
+#endif /* AUTOKEY */
/*
- * Gawdz, it's come to this. Process the dang packet. If
- * something breaks and the association doesn't deserve to live,
- * toss it. Be careful in active mode and return a packet
- * anyway.
+ * 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.
*/
- process_packet(peer, pkt, &(rbufp->recv_time));
- if (!(peer->flags & FLAG_CONFIG) && peer->reach == 0) {
- if (peer->hmode == MODE_PASSIVE) {
- if (is_authentic)
- fast_xmit(rbufp, MODE_PASSIVE, skeyid);
- else
- fast_xmit(rbufp, MODE_PASSIVE, 0);
- }
- unpeer(peer);
- }
+ process_packet(peer, pkt, &rbufp->recv_time);
}
@@ -701,7 +833,7 @@ receive(
* reasonable expectation that we will be having a long term
* relationship with this host.
*/
-int
+void
process_packet(
register struct peer *peer,
register struct pkt *pkt,
@@ -713,10 +845,13 @@ process_packet(
double dtemp;
l_fp p_rec, p_xmt, p_org, p_reftime;
l_fp ci;
- int pmode;
+ int pmode, pleap, pstratum;
/*
- * Swap header fields and keep the books.
+ * 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++;
@@ -729,84 +864,115 @@ process_packet(
NTOHL_FP(&pkt->org, &p_org);
else
p_org = peer->rec;
- peer->rec = *recv_ts;
- peer->ppoll = pkt->ppoll;
- pmode = PKT_MODE(pkt->li_vn_mode);
/*
- * Test for old or duplicate packets (tests 1 through 3).
+ * Test for old, duplicate or unsynch packets (tests 1-3).
*/
+ peer->rec = *recv_ts;
+ pmode = PKT_MODE(pkt->li_vn_mode);
+ pleap = PKT_LEAP(pkt->li_vn_mode);
+ pstratum = PKT_TO_STRATUM(pkt->stratum);
if (L_ISHIS(&peer->org, &p_xmt)) /* count old packets */
peer->oldpkt++;
- if (L_ISEQU(&peer->org, &p_xmt)) /* test 1 */
- peer->flash |= TEST1; /* duplicate packet */
- if (PKT_MODE(pkt->li_vn_mode) != MODE_BROADCAST) {
- if (!L_ISEQU(&peer->xmt, &p_org)) { /* test 2 */
- peer->bogusorg++;
- peer->flash |= TEST2; /* bogus packet */
- }
- if (L_ISZERO(&p_rec) || L_ISZERO(&p_org))
- peer->flash |= TEST3; /* unsynchronized */
- } else {
- if (L_ISZERO(&p_org))
- peer->flash |= TEST3; /* unsynchronized */
+ if (L_ISEQU(&peer->org, &p_xmt)) /* 1 */
+ peer->flash |= TEST1; /* dupe */
+ if (pmode != MODE_BROADCAST) {
+ if (!L_ISEQU(&peer->xmt, &p_org)) /* 2 */
+ peer->flash |= TEST2; /* bogus */
+ if (L_ISZERO(&p_rec) || L_ISZERO(&p_org)) /* test 3 */
+ peer->flash |= TEST3; /* unsynch */
}
+ if (L_ISZERO(&p_xmt)) /* 3 */
+ peer->flash |= TEST3; /* unsynch */
peer->org = p_xmt;
/*
- * Test for valid header (tests 5 through 10)
+ * If tests 1-3 fail, the packet is discarded leaving only the
+ * receive and origin timestamps and poll interval, which is
+ * enough to get the protocol started.
+ */
+ if (peer->flash) {
+#ifdef DEBUG
+ if (debug)
+ printf("packet: bad data %03x\n",
+ peer->flash);
+#endif
+ return;
+ }
+
+ /*
+ * A kiss-of-death (kod) packet is returned by a server in case
+ * the client is denied access. It consists of the client
+ * request packet with the leap bits indicating never
+ * synchronized, stratum zero and reference ID field the ASCII
+ * string "DENY". If the packet originate timestamp matches the
+ * association transmit timestamp the kod is legitimate. If the
+ * peer leap bits indicate never synchronized, this must be
+ * access deny and the association is disabled; otherwise this
+ * must be a limit reject. In either case a naughty message is
+ * forced to the system log.
+ */
+ if (pleap == LEAP_NOTINSYNC && pstratum >= STRATUM_UNSPEC &&
+ memcmp(&pkt->refid, "DENY", 4) == 0) {
+ if (peer->leap == LEAP_NOTINSYNC) {
+ peer->stratum = STRATUM_UNSPEC;
+ peer->flash |= TEST4;
+ memcpy(&peer->refid, &pkt->refid, 4);
+ msyslog(LOG_INFO, "access denied");
+ } else {
+ msyslog(LOG_INFO, "limit reject");
+ }
+ return;
+ }
+
+ /*
+ * Test for valid peer data (tests 6-8)
*/
ci = p_xmt;
L_SUB(&ci, &p_reftime);
LFPTOD(&ci, dtemp);
- if (PKT_LEAP(pkt->li_vn_mode) == LEAP_NOTINSYNC || /* test 6 */
- PKT_TO_STRATUM(pkt->stratum) >= NTP_MAXSTRATUM ||
- dtemp < 0)
- peer->flash |= TEST6; /* peer clock unsynchronized */
- if (!(peer->flags & FLAG_CONFIG) && sys_peer != 0) { /* test 7 */
- if (PKT_TO_STRATUM(pkt->stratum) > sys_stratum) {
- peer->flash |= TEST7; /* peer stratum too high */
+ if (pleap == LEAP_NOTINSYNC || /* 6 */
+ pstratum >= STRATUM_UNSPEC || dtemp < 0)
+ peer->flash |= TEST6; /* bad synch */
+ if (!(peer->flags & FLAG_CONFIG) && sys_peer != NULL) { /* 7 */
+ if (pstratum > sys_stratum && pmode != MODE_ACTIVE) {
+ peer->flash |= TEST7; /* bad stratum */
sys_badstratum++;
}
}
- if (fabs(p_del) >= MAXDISPERSE /* test 8 */
- || p_disp >= MAXDISPERSE)
- peer->flash |= TEST8; /* delay/dispersion too high */
-
- /*
- * If the packet header is invalid (tests 5 through 10), exit.
- * XXX we let TEST9 sneak by until the certificate code is
- * implemented, but only to mobilize the association.
- */
- if (peer->flash & (TEST5 | TEST6 | TEST7 | TEST8 | TEST10)) {
+ if (p_del < 0 || p_disp < 0 || p_del / /* 8 */
+ 2 + p_disp >= MAXDISPERSE)
+ peer->flash |= TEST8; /* bad peer distance */
+ if (peer->flash) {
#ifdef DEBUG
if (debug)
- printf(
- "invalid packet header 0x%02x mode %d\n",
- peer->flash, pmode);
+ printf("packet: bad header %03x\n",
+ peer->flash);
#endif
- return (0);
+ return;
}
/*
- * Valid header; update our state.
+ * 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->leap = PKT_LEAP(pkt->li_vn_mode);
- peer->pmode = pmode; /* unspec */
- peer->stratum = PKT_TO_STRATUM(pkt->stratum);
+ record_raw_stats(&peer->srcadr, &peer->dstadr->sin, &p_org,
+ &p_rec, &p_xmt, &peer->rec);
+ peer->leap = pleap;
+ peer->pmode = pmode;
+ peer->stratum = pstratum;
+ peer->ppoll = pkt->ppoll;
peer->precision = pkt->precision;
peer->rootdelay = p_del;
peer->rootdispersion = p_disp;
peer->refid = pkt->refid;
peer->reftime = p_reftime;
- if (peer->reach == 0) {
+ if (!(peer->reach)) {
report_event(EVNT_REACH, peer);
peer->timereachable = current_time;
}
peer->reach |= 1;
+ peer->unreach = 0;
poll_update(peer, peer->hpoll);
/*
@@ -827,34 +993,25 @@ process_packet(
t23 = p_rec; /* compute t2 - t3 */
L_SUB(&t23, &p_org);
ci = t10;
- p_disp = CLOCK_PHI * (peer->rec.l_ui - p_org.l_ui);
+ p_disp = clock_phi * (peer->rec.l_ui - p_org.l_ui);
/*
* If running in a broadcast association, the clock offset is
* (t1 - t0) corrected by the one-way delay, but we can't
- * measure that directly; therefore, we start up in
- * client/server mode, calculate the clock offset, using the
- * engineered refinement algorithms, while also receiving
- * broadcasts. When a broadcast is received in client/server
- * mode, we calculate a correction factor to use after switching
- * back to broadcast mode. We know NTP_SKEWFACTOR == 16, which
- * accounts for the simplified ei calculation.
- *
- * If FLAG_MCAST2 is set, we are a broadcast/multicast client.
- * If FLAG_MCAST1 is set, we haven't calculated the propagation
- * delay. If hmode is MODE_CLIENT, we haven't set the local
- * clock in client/server mode. Initially, we come up
- * MODE_CLIENT. When the clock is first updated and FLAG_MCAST2
- * is set, we switch from MODE_CLIENT to MODE_BCLIENT.
+ * measure that directly. Therefore, we start up in MODE_CLIENT
+ * mode, set FLAG_MCAST and exchange eight messages to determine
+ * the clock offset. When the last message is sent, we switch to
+ * MODE_BCLIENT mode. The next broadcast message after that
+ * computes the broadcast offset and clears FLAG_MCAST.
*/
if (pmode == MODE_BROADCAST) {
- if (peer->flags & FLAG_MCAST1) {
- if (peer->hmode == MODE_BCLIENT)
- peer->flags &= ~FLAG_MCAST1;
+ if (peer->flags & FLAG_MCAST) {
LFPTOD(&ci, p_offset);
peer->estbdelay = peer->offset - p_offset;
- return (1);
+ if (peer->hmode == MODE_CLIENT)
+ return;
+ peer->flags &= ~FLAG_MCAST;
}
DTOLFP(peer->estbdelay, &t10);
L_ADD(&ci, &t10);
@@ -865,32 +1022,29 @@ process_packet(
L_SUB(&t23, &t10);
LFPTOD(&t23, p_del);
}
+ p_del = max(p_del, LOGTOD(sys_precision));
LFPTOD(&ci, p_offset);
- if (fabs(p_del) >= MAXDISPERSE || p_disp >= MAXDISPERSE) /* test 4 */
- peer->flash |= TEST4; /* delay/dispersion too big */
+ if ((peer->rootdelay + p_del) / 2. + peer->rootdispersion +
+ p_disp >= MAXDISPERSE) /* 9 */
+ peer->flash |= TEST9; /* bad peer distance */
/*
- * If the packet data are invalid (tests 1 through 4), exit.
+ * 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("invalid packet data 0x%02x mode %d\n",
- peer->flash, pmode);
+ printf("packet: bad packet data %03x\n",
+ peer->flash);
#endif
- return(1);
+ return;
}
-
-
- /*
- * This one is valid. Mark it so, give it to clock_filter().
- */
- clock_filter(peer, p_offset, p_del, fabs(p_disp));
+ 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->variance));
- return(1);
+ SQRT(peer->jitter));
}
@@ -902,15 +1056,13 @@ clock_update(void)
{
u_char oleap;
u_char ostratum;
- int i;
- struct peer *peer;
/*
* Reset/adjust the system clock. Do this only if there is a
* system peer and we haven't seen that peer lately. Watch for
* timewarps here.
*/
- if (sys_peer == 0)
+ if (sys_peer == NULL)
return;
if (sys_peer->pollsw == FALSE || sys_peer->burst > 0)
return;
@@ -922,60 +1074,58 @@ clock_update(void)
#endif
oleap = sys_leap;
ostratum = sys_stratum;
- switch (local_clock(sys_peer, sys_offset, sys_epsil)) {
+ switch (local_clock(sys_peer, sys_offset, sys_syserr)) {
- case -1:
- /*
- * Clock is too screwed up. Just exit for now.
- */
+ /*
+ * Clock is too screwed up. Just exit for now.
+ */
+ case -1:
report_event(EVNT_SYSFAULT, (struct peer *)0);
exit(1);
/*NOTREACHED*/
- case 1:
- /*
- * Clock was stepped. Clear filter registers
- * of all peers.
- */
- for (i = 0; i < HASH_SIZE; i++) {
- for (peer = peer_hash[i]; peer != 0;
- peer =peer->next)
- peer_clear(peer);
- }
- NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO, "synchronisation lost");
- sys_peer = 0;
+ /*
+ * Clock was stepped. Flush all time values of all peers.
+ */
+ case 1:
+ clear_all();
+ sys_peer = NULL;
sys_stratum = STRATUM_UNSPEC;
+ sys_poll = NTP_MINPOLL;
+ NLOG(NLOG_SYNCSTATUS)
+ msyslog(LOG_INFO, "synchronisation lost");
report_event(EVNT_CLOCKRESET, (struct peer *)0);
break;
- default:
- /*
- * Update the system stratum, leap bits, root delay,
- * root dispersion, reference ID and reference time. We
- * also update select dispersion and max frequency
- * error.
- */
+ /*
+ * Update the system stratum, leap bits, root delay, root
+ * dispersion, reference ID and reference time. We also update
+ * select dispersion and max frequency error. If the leap
+ * changes, we gotta reroll the keys.
+ */
+ default:
sys_stratum = sys_peer->stratum + 1;
if (sys_stratum == 1)
sys_refid = sys_peer->refid;
else
sys_refid = sys_peer->srcadr.sin_addr.s_addr;
sys_reftime = sys_peer->rec;
- sys_rootdelay = sys_peer->rootdelay +
- fabs(sys_peer->delay);
+ sys_rootdelay = sys_peer->rootdelay + sys_peer->delay;
sys_leap = leap_consensus;
}
- if (oleap != sys_leap)
+ if (oleap == LEAP_NOTINSYNC) {
report_event(EVNT_SYNCCHG, (struct peer *)0);
+#ifdef AUTOKEY
+ expire_all();
+#endif /* AUTOKEY */
+ }
if (ostratum != sys_stratum)
report_event(EVNT_PEERSTCHG, (struct peer *)0);
}
/*
- * poll_update - update peer poll interval. See Section 3.4.9 of the
- * spec.
+ * poll_update - update peer poll interval
*/
void
poll_update(
@@ -983,46 +1133,83 @@ poll_update(
int hpoll
)
{
- long update;
+#ifdef AUTOKEY
+ int oldpoll;
+#endif /* AUTOKEY */
/*
- * The wiggle-the-poll-interval dance. Broadcasters dance only
- * the minpoll beat. Reference clock partners sit this one out.
- * Dancers surviving the clustering algorithm beat to the system
- * clock. Broadcast clients are usually lead by their broadcast
- * partner, but faster in the initial mating dance.
+ * 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.
*/
- if (peer->hmode == MODE_BROADCAST) {
+#ifdef AUTOKEY
+ oldpoll = peer->kpoll;
+#endif /* AUTOKEY */
+ if (hpoll > peer->maxpoll)
+ peer->hpoll = peer->maxpoll;
+ else if (hpoll < peer->minpoll)
peer->hpoll = peer->minpoll;
- } else if (peer->flags & FLAG_SYSPEER) {
- peer->hpoll = sys_poll;
- } else {
- if (hpoll > peer->maxpoll)
- peer->hpoll = peer->maxpoll;
- else if (hpoll < peer->minpoll)
- peer->hpoll = peer->minpoll;
- else
- peer->hpoll = hpoll;
- }
+ else
+ peer->hpoll = hpoll;
+
+ /*
+ * Bit of adventure here. If during a burst and not timeout,
+ * just slink away. If timeout, figure what the next timeout
+ * should be. If IBURST or a reference clock, use one second. If
+ * not and the dude was reachable during the previous poll
+ * interval, randomize over 1-4 seconds; otherwise, randomize
+ * over 15-18 seconds. This is to give time for a modem to
+ * complete the call, for example. If not during a burst,
+ * randomize over the poll interval -1 to +2 seconds.
+ *
+ * In case of manycast server, make the poll interval, which is
+ * axtually the manycast beacon interval, eight times the system
+ * poll interval. Normally when the host poll interval settles
+ * up to 17.1 s, the beacon interval settles up to 2.3 hours.
+ */
if (peer->burst > 0) {
if (peer->nextdate != current_time)
return;
- if (peer->flags & FLAG_REFCLOCK)
+#ifdef REFCLOCK
+ else if (peer->flags & FLAG_REFCLOCK)
peer->nextdate++;
+#endif
else if (peer->reach & 0x1)
peer->nextdate += RANDPOLL(BURST_INTERVAL2);
else
peer->nextdate += RANDPOLL(BURST_INTERVAL1);
+ } else if (peer->cast_flags & MDF_ACAST) {
+ if (sys_survivors < NTP_MINCLOCK)
+ peer->kpoll = peer->hpoll;
+ else
+ peer->kpoll = peer->hpoll + 3;
+ peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
} else {
- update = max(min(peer->ppoll, peer->hpoll),
+ peer->kpoll = max(min(peer->ppoll, peer->hpoll),
peer->minpoll);
- peer->nextdate = peer->outdate + RANDPOLL(update);
+ peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
}
+ if (peer->nextdate < current_time)
+ peer->nextdate = current_time;
+#ifdef AUTOKEY
+ /*
+ * Bit of crass arrogance at this point. If the poll interval
+ * has changed and we have a keylist, the lifetimes in the
+ * keylist are probably bogus. In this case purge the keylist
+ * and regenerate it later.
+ */
+ if (peer->kpoll != oldpoll)
+ key_expire(peer);
+#endif /* AUTOKEY */
#ifdef DEBUG
if (debug > 1)
- printf("poll_update: at %lu %s poll %d burst %d last %lu next %lu\n",
- current_time, ntoa(&peer->srcadr), hpoll,
- peer->burst, peer->outdate, peer->nextdate);
+ printf("poll_update: at %lu %s flags %04x poll %d burst %d last %lu next %lu\n",
+ current_time, ntoa(&peer->srcadr), peer->flags,
+ peer->kpoll, peer->burst, peer->outdate,
+ peer->nextdate);
#endif
}
@@ -1036,28 +1223,72 @@ peer_clear(
)
{
register int i;
+ u_long u_rand;
+ /*
+ * If cryptographic credentials have been acquired, toss them to
+ * Valhalla. Note that autokeys are ephemeral, in that they are
+ * tossed immediately upon use. Therefore, the keylist can be
+ * purged anytime without needing to preserve random keys. Note
+ * that, if the peer is purged, the cryptographic variables are
+ * purged, too. This makes it much harder to sneak in some
+ * unauthenticated data in the clock filter.
+ */
+#ifdef DEBUG
+ if (debug)
+ printf("peer_clear: at %ld assoc ID %d\n", current_time,
+ peer->associd);
+#endif
+#ifdef AUTOKEY
+ key_expire(peer);
+#ifdef PUBKEY
+ if (peer->keystr != NULL)
+ free(peer->keystr);
+ if (peer->pubkey.ptr != NULL)
+ free(peer->pubkey.ptr);
+ if (peer->certif.ptr != NULL)
+ free(peer->certif.ptr);
+#endif /* PUBKEY */
+#endif /* AUTOKEY */
memset(CLEAR_TO_ZERO(peer), 0, LEN_CLEAR_TO_ZERO);
+
+ /*
+ * If he dies as a broadcast client, he comes back to life as
+ * a broadcast client in client mode in order to recover the
+ * initial autokey values. Note that there is no need to call
+ * clock_select(), since the perp has already been voted off
+ * the island at this point.
+ */
+ if (peer->cast_flags & MDF_BCLNT) {
+ peer->flags |= FLAG_MCAST;
+ peer->hmode = MODE_CLIENT;
+ }
+ peer->flags &= ~(FLAG_AUTOKEY | FLAG_ASSOC);
peer->estbdelay = sys_bdelay;
- peer->hpoll = peer->minpoll;
+ peer->hpoll = peer->kpoll = peer->minpoll;
+ peer->ppoll = peer->maxpoll;
peer->pollsw = FALSE;
- peer->variance = MAXDISPERSE;
+ peer->jitter = MAXDISPERSE;
peer->epoch = current_time;
+#ifdef REFCLOCK
+ if (!(peer->flags & FLAG_REFCLOCK)) {
+ peer->leap = LEAP_NOTINSYNC;
+ peer->stratum = STRATUM_UNSPEC;
+ }
+#endif
for (i = 0; i < NTP_SHIFT; i++) {
peer->filter_order[i] = i;
peer->filter_disp[i] = MAXDISPERSE;
peer->filter_epoch[i] = current_time;
}
- poll_update(peer, peer->minpoll);
/*
- * Since we have a chance to correct possible funniness in
- * our selection of interfaces on a multihomed host, do so
- * by setting us to no particular interface.
- * WARNING: do so only in non-broadcast mode!
+ * Randomize the first poll over 1-16s to avoid bunching.
*/
- if (peer->hmode != MODE_BROADCAST)
- peer->dstadr = any_interface;
+ peer->update = peer->outdate = current_time;
+ u_rand = RANDOM;
+ peer->nextdate = current_time + (u_rand & ((1 <<
+ BURST_INTERVAL1) - 1)) + 1;
}
@@ -1067,130 +1298,172 @@ peer_clear(
*/
void
clock_filter(
- register struct peer *peer,
- double sample_offset,
- double sample_delay,
- double sample_disp
+ register struct peer *peer, /* peer structure pointer */
+ double sample_offset, /* clock offset */
+ double sample_delay, /* roundtrip delay */
+ double sample_disp /* dispersion */
)
{
- register int i, j, k, n = 0;
- register u_char *ord;
- double distance[NTP_SHIFT];
- double x, y, z, off;
+ double dst[NTP_SHIFT]; /* distance vector */
+ int ord[NTP_SHIFT]; /* index vector */
+ register int i, j, k, m;
+ double dsp, jit, dtemp, etemp;
/*
- * Update error bounds and calculate distances. Also initialize
- * sort index vector.
+ * Shift the new sample into the register and discard the oldest
+ * one. The new offset and delay come directly from the
+ * timestamp calculations. The dispersion grows from the last
+ * outbound packet or reference clock update to the present time
+ * and increased by the sum of the peer precision and the system
+ * precision. The delay can sometimes swing negative due to
+ * frequency skew, so it is clamped non-negative.
*/
- x = CLOCK_PHI * (current_time - peer->update);
- peer->update = current_time;
- ord = peer->filter_order;
+ dsp = min(LOGTOD(peer->precision) + LOGTOD(sys_precision) +
+ sample_disp, MAXDISPERSE);
j = peer->filter_nextpt;
- for (i = 0; i < NTP_SHIFT; i++) {
- peer->filter_disp[j] += x;
- if (peer->filter_disp[j] > MAXDISPERSE)
- peer->filter_disp[j] = MAXDISPERSE;
- distance[i] = fabs(peer->filter_delay[j]) / 2 +
- peer->filter_disp[j];
- ord[i] = j;
- if (--j < 0)
- j += NTP_SHIFT;
- }
+ peer->filter_offset[j] = sample_offset;
+ peer->filter_delay[j] = max(0, sample_delay);
+ peer->filter_disp[j] = dsp;
+ peer->filter_epoch[j] = current_time;
+ j++; j %=NTP_SHIFT;
+ peer->filter_nextpt = j;
/*
- * Insert the new sample at the beginning of the register.
+ * Update dispersions since the last update and at the same
+ * time initialize the distance and index lists. The distance
+ * list uses a compound metric. If the sample is valid and
+ * younger than the minimum Allan intercept, use delay;
+ * otherwise, use biased dispersion.
*/
- peer->filter_offset[peer->filter_nextpt] = sample_offset;
- peer->filter_delay[peer->filter_nextpt] = sample_delay;
- x = LOGTOD(peer->precision) + LOGTOD(sys_precision) +
- sample_disp;
- peer->filter_disp[peer->filter_nextpt] = min(x, MAXDISPERSE);
- peer->filter_epoch[peer->filter_nextpt] = current_time;
- distance[0] = min(x + fabs(sample_delay) / 2, MAXDISTANCE);
- peer->filter_nextpt++;
- if (peer->filter_nextpt >= NTP_SHIFT)
- peer->filter_nextpt = 0;
+ dtemp = clock_phi * (current_time - peer->update);
+ peer->update = current_time;
+ for (i = NTP_SHIFT - 1; i >= 0; i--) {
+ if (i != 0) {
+ peer->filter_disp[j] += dtemp;
+ if (peer->filter_disp[j] > MAXDISPERSE)
+ peer->filter_disp[j] = MAXDISPERSE;
+ }
+ if (peer->filter_disp[j] >= MAXDISPERSE)
+ dst[i] = MAXDISPERSE;
+ else if (peer->update - peer->filter_epoch[j] >
+ allan_xpt)
+ dst[i] = MAXDISTANCE + peer->filter_disp[j];
+ else
+ dst[i] = peer->filter_delay[j];
+ ord[i] = j;
+ j++; j %= NTP_SHIFT;
+ }
- /*
- * Sort the samples in the register by distance. The winning
- * sample will be in ord[0]. Sort the samples only if they
- * are younger than the Allen intercept.
+ /*
+ * Sort the samples in both lists by distance.
*/
- y = min(allan_xpt, NTP_SHIFT * ULOGTOD(sys_poll));
- for (n = 0; n < NTP_SHIFT && current_time -
- peer->filter_epoch[ord[n]] <= y; n++) {
- for (j = 0; j < n; j++) {
- if (distance[j] > distance[n]) {
- x = distance[j];
+ for (i = 1; i < NTP_SHIFT; i++) {
+ for (j = 0; j < i; j++) {
+ if (dst[j] > dst[i]) {
k = ord[j];
- distance[j] = distance[n];
- ord[j] = ord[n];
- distance[n] = x;
- ord[n] = k;
+ ord[j] = ord[i];
+ ord[i] = k;
+ etemp = dst[j];
+ dst[j] = dst[i];
+ dst[i] = etemp;
}
}
- }
+ }
+
+ /*
+ * Copy the index list to the association structure so ntpq
+ * can see it later. Prune the distance list to samples less
+ * than MAXDISTANCE, but keep at least two valid samples for
+ * jitter calculation.
+ */
+ m = 0;
+ for (i = 0; i < NTP_SHIFT; i++) {
+ peer->filter_order[i] = ord[i];
+ if (dst[i] >= MAXDISPERSE || (m >= 2 && dst[i] >=
+ MAXDISTANCE))
+ continue;
+ m++;
+ }
/*
- * Compute the error bound and standard error.
+ * 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.
*/
- x = y = z = off = 0.;
+ jit = 0;
+ peer->disp = 0;
+ k = ord[0];
for (i = NTP_SHIFT - 1; i >= 0; i--) {
- x = NTP_FWEIGHT * (x + peer->filter_disp[ord[i]]);
- if (i < n) {
- z += 1. / distance[i];
- off += peer->filter_offset[ord[i]] /
- distance[i];
- y += DIFF(peer->filter_offset[ord[i]],
- peer->filter_offset[ord[0]]);
- }
+
+ j = ord[i];
+ peer->disp = NTP_FWEIGHT * (peer->disp +
+ peer->filter_disp[j]);
+ if (i < m)
+ jit += DIFF(peer->filter_offset[j],
+ peer->filter_offset[k]);
}
- peer->delay = peer->filter_delay[ord[0]];
- peer->variance = min(y / n, MAXDISPERSE);
- peer->disp = min(x, MAXDISPERSE);
- peer->epoch = current_time;
- x = peer->offset;
- if (peer->flags & FLAG_BURST)
- peer->offset = off / z;
- else
- peer->offset = peer->filter_offset[ord[0]];
+
+ /*
+ * If no acceptable samples remain in the shift register,
+ * quietly tiptoe home leaving only the dispersion. Otherwise,
+ * save the offset, delay and jitter average. Note the jitter
+ * must not be less than the system precision.
+ */
+ if (m == 0)
+ return;
+ etemp = peer->offset;
+ peer->offset = peer->filter_offset[k];
+ peer->delay = peer->filter_delay[k];
+ if (m > 1)
+ jit /= m - 1;
+ peer->jitter = max(jit, SQUARE(LOGTOD(sys_precision)));
/*
* A new sample is useful only if it is younger than the last
* one used.
*/
- if (peer->filter_epoch[ord[0]] > peer->epoch) {
+ if (peer->filter_epoch[k] <= peer->epoch) {
#ifdef DEBUG
if (debug)
printf("clock_filter: discard %lu\n",
- peer->filter_epoch[ord[0]] - peer->epoch);
+ peer->epoch - peer->filter_epoch[k]);
#endif
return;
}
/*
- * If the offset exceeds the dispersion by CLOCK_SGATE and the
- * interval since the last update is less than twice the system
- * poll interval, consider the update a popcorn spike and ignore
- * it.
+ * If the difference between the last offset and the current one
+ * exceeds the jitter by CLOCK_SGATE (4) and the interval since
+ * the last update is less than twice the system poll interval,
+ * consider the update a popcorn spike and ignore it.
*/
- if (fabs(x - peer->offset) > CLOCK_SGATE &&
- peer->filter_epoch[ord[0]] - peer->epoch < (1 <<
- (sys_poll + 1))) {
+ if (m > 1 && fabs(peer->offset - etemp) > SQRT(peer->jitter) *
+ CLOCK_SGATE && peer->filter_epoch[k] - peer->epoch <
+ (1 << (sys_poll + 1))) {
#ifdef DEBUG
if (debug)
- printf("clock_filter: popcorn spike %.6f\n", x);
+ printf("clock_filter: n %d popcorn spike %.6f jitter %.6f\n",
+ m, peer->offset, SQRT(peer->jitter));
#endif
return;
}
- peer->epoch = peer->filter_epoch[ord[0]];
+
+ /*
+ * The mitigated sample statistics are saved for later
+ * processing, but can be processed only once.
+ */
+ peer->epoch = peer->filter_epoch[k];
peer->pollsw = TRUE;
#ifdef DEBUG
if (debug)
printf(
- "clock_filter: offset %.6f delay %.6f disp %.6f std %.6f, age %lu\n",
- peer->offset, peer->delay, peer->disp,
- SQRT(peer->variance), current_time - peer->epoch);
+ "clock_filter: n %d off %.6f del %.6f dsp %.6f jit %.6f, age %lu\n",
+ m, peer->offset, peer->delay, peer->disp,
+ SQRT(peer->jitter), peer->update - peer->epoch);
#endif
}
@@ -1202,35 +1475,34 @@ void
clock_select(void)
{
register struct peer *peer;
- int i;
- int nlist, nl3;
+ int i, j, k, n;
+ int nreach, nlist, nl3;
double d, e, f;
- int j;
- int n;
- int allow, found, k;
+ int allow, found, sw;
double high, low;
double synch[NTP_MAXCLOCK], error[NTP_MAXCLOCK];
struct peer *osys_peer;
- struct peer *typeacts = 0;
- struct peer *typelocal = 0;
- struct peer *typepps = 0;
- struct peer *typeprefer = 0;
- struct peer *typesystem = 0;
+ struct peer *typeacts = NULL;
+ struct peer *typelocal = NULL;
+ struct peer *typepps = NULL;
+ struct peer *typesystem = NULL;
static int list_alloc = 0;
static struct endpoint *endpoint = NULL;
- static int *index = NULL;
+ static int *indx = NULL;
static struct peer **peer_list = NULL;
static u_int endpoint_size = 0;
- static u_int index_size = 0;
+ static u_int indx_size = 0;
static u_int peer_list_size = 0;
/*
- * Initialize. If a prefer peer does not survive this thing,
- * the pps_update switch will remain zero.
+ * Initialize and create endpoint, index and peer lists big
+ * enough to handle all associations.
*/
- pps_update = 0;
- nlist = 0;
+ osys_peer = sys_peer;
+ sys_peer = NULL;
+ sys_prefer = NULL;
+ nreach = nlist = 0;
low = 1e9;
high = -1e9;
for (n = 0; n < HASH_SIZE; n++)
@@ -1238,49 +1510,58 @@ clock_select(void)
if (nlist > list_alloc) {
if (list_alloc > 0) {
free(endpoint);
- free(index);
+ free(indx);
free(peer_list);
}
while (list_alloc < nlist) {
list_alloc += 5;
- endpoint_size += 5 * 3 * sizeof *endpoint;
- index_size += 5 * 3 * sizeof *index;
- peer_list_size += 5 * sizeof *peer_list;
+ endpoint_size += 5 * 3 * sizeof(*endpoint);
+ indx_size += 5 * 3 * sizeof(*indx);
+ peer_list_size += 5 * sizeof(*peer_list);
}
endpoint = (struct endpoint *)emalloc(endpoint_size);
- index = (int *)emalloc(index_size);
+ indx = (int *)emalloc(indx_size);
peer_list = (struct peer **)emalloc(peer_list_size);
}
/*
- * This first chunk of code is supposed to go through all
- * peers we know about to find the peers which are most likely
- * to succeed. We run through the list doing the sanity checks
- * and trying to insert anyone who looks okay.
+ * Initially, we populate the island with all the rifraff peers
+ * that happen to be lying around. Those with seriously
+ * defective clocks are immediately booted off the island. Then,
+ * the falsetickers are culled and put to sea. The truechimers
+ * remaining are subject to repeated rounds where the most
+ * unpopular at each round is kicked off. When the population
+ * has dwindled to NTP_MINCLOCK (3), the survivors split a
+ * million bucks and collectively crank the chimes.
*/
nlist = nl3 = 0; /* none yet */
for (n = 0; n < HASH_SIZE; n++) {
- for (peer = peer_hash[n]; peer != 0; peer = peer->next) {
+ for (peer = peer_hash[n]; peer != NULL; peer =
+ peer->next) {
peer->flags &= ~FLAG_SYSPEER;
peer->status = CTL_PST_SEL_REJECT;
- if (peer->flags & FLAG_NOSELECT)
- continue; /* noselect (survey) */
- if (peer->reach == 0)
- continue; /* unreachable */
- if (peer->stratum > 1 && peer->refid ==
- peer->dstadr->sin.sin_addr.s_addr)
- continue; /* sync loop */
- if (root_distance(peer) >= MAXDISTANCE + 2 *
- CLOCK_PHI * ULOGTOD(sys_poll)) {
- peer->seldisptoolarge++;
- continue; /* noisy or broken */
- }
/*
- * Don't allow the local-clock or acts drivers
+ * A peer leaves the island immediately if
+ * unreachable, synchronized to us or suffers
+ * excessive root distance. Careful with the
+ * root distance, since the poll interval can
+ * increase to a day and a half.
+ */
+ if (!peer->reach || (peer->stratum > 1 &&
+ peer->refid ==
+ peer->dstadr->sin.sin_addr.s_addr) ||
+ peer->stratum >= STRATUM_UNSPEC ||
+ (root_distance(peer) >= MAXDISTANCE + 2 *
+ clock_phi * ULOGTOD(sys_poll)))
+ continue;
+
+ /*
+ * Don't allow the local clock or modem drivers
* in the kitchen at this point, unless the
* prefer peer. Do that later, but only if
- * nobody else is around.
+ * nobody else is around. These guys are all
+ * configured, so we never throw them away.
*/
if (peer->refclktype == REFCLK_LOCALCLOCK
#if defined(VMS) && defined(VMS_LOCALUNIT)
@@ -1299,9 +1580,11 @@ clock_select(void)
}
/*
- * If we get this far, we assume the peer is
- * acceptable.
+ * If we get this far, the peer can stay on the
+ * island, but does not yet have the immunity
+ * idol.
*/
+ nreach++;
peer->status = CTL_PST_SEL_SANE;
peer_list[nlist++] = peer;
@@ -1313,40 +1596,41 @@ clock_select(void)
f = root_distance(peer);
e = e + f;
for (i = nl3 - 1; i >= 0; i--) {
- if (e >= endpoint[index[i]].val)
+ if (e >= endpoint[indx[i]].val)
break;
- index[i + 3] = index[i];
+ indx[i + 3] = indx[i];
}
- index[i + 3] = nl3;
+ indx[i + 3] = nl3;
endpoint[nl3].type = 1;
endpoint[nl3++].val = e;
e = e - f; /* Center point */
for ( ; i >= 0; i--) {
- if (e >= endpoint[index[i]].val)
+ if (e >= endpoint[indx[i]].val)
break;
- index[i + 2] = index[i];
+ indx[i + 2] = indx[i];
}
- index[i + 2] = nl3;
+ indx[i + 2] = nl3;
endpoint[nl3].type = 0;
endpoint[nl3++].val = e;
e = e - f; /* Lower end */
for ( ; i >= 0; i--) {
- if (e >= endpoint[index[i]].val)
+ if (e >= endpoint[indx[i]].val)
break;
- index[i + 1] = index[i];
+ indx[i + 1] = indx[i];
}
- index[i + 1] = nl3;
+ indx[i + 1] = nl3;
endpoint[nl3].type = -1;
endpoint[nl3++].val = e;
}
}
#ifdef DEBUG
- if (debug > 1)
+ if (debug > 2)
for (i = 0; i < nl3; i++)
- printf("select: endpoint %2d %.6f\n",
- endpoint[index[i]].type, endpoint[index[i]].val);
+ printf("select: endpoint %2d %.6f\n",
+ endpoint[indx[i]].type,
+ endpoint[indx[i]].val);
#endif
i = 0;
j = nl3 - 1;
@@ -1355,30 +1639,30 @@ clock_select(void)
while (allow > 0) {
allow--;
for (n = 0; i <= j; i++) {
- n += endpoint[index[i]].type;
+ n += endpoint[indx[i]].type;
if (n < 0)
break;
- if (endpoint[index[i]].type == 0)
+ if (endpoint[indx[i]].type == 0)
found++;
}
for (n = 0; i <= j; j--) {
- n += endpoint[index[j]].type;
+ n += endpoint[indx[j]].type;
if (n > 0)
break;
- if (endpoint[index[j]].type == 0)
+ if (endpoint[indx[j]].type == 0)
found++;
}
if (found > allow)
break;
- low = endpoint[index[i++]].val;
- high = endpoint[index[j--]].val;
+ low = endpoint[indx[i++]].val;
+ high = endpoint[indx[j--]].val;
}
/*
- * If no survivors remain at this point, check if the acts or
- * local clock drivers have been found. If so, nominate one of
- * them as the only survivor. Otherwise, give up and declare us
- * unsynchronized.
+ * If no survivors remain at this point, check if the local
+ * clock or modem drivers have been found. If so, nominate one
+ * of them as the only survivor. Otherwise, give up and declare
+ * us unsynchronized.
*/
if ((allow << 1) >= nlist) {
if (typeacts != 0) {
@@ -1390,35 +1674,45 @@ clock_select(void)
peer_list[0] = typelocal;
nlist = 1;
} else {
- if (sys_peer != 0) {
- report_event(EVNT_PEERSTCHG,
- (struct peer *)0);
+ if (osys_peer != NULL) {
+ sys_poll = NTP_MINPOLL;
NLOG(NLOG_SYNCSTATUS)
- msyslog(LOG_INFO,
+ msyslog(LOG_INFO,
"synchronisation lost");
+ report_event(EVNT_PEERSTCHG,
+ (struct peer *)0);
}
- sys_peer = 0;
+ sys_survivors = 0;
+#ifdef AUTOKEY
+ resetmanycast();
+#endif /* AUTOKEY */
return;
}
}
#ifdef DEBUG
- if (debug > 1)
+ if (debug > 2)
printf("select: low %.6f high %.6f\n", low, high);
#endif
/*
- * Clustering algorithm. Process intersection list to discard
- * outlyers. Construct candidate list in cluster order
- * determined by the sum of peer synchronization distance plus
- * scaled stratum. We must find at least one peer.
+ * Clustering algorithm. Construct candidate list in order first
+ * by stratum then by root distance. If we have more than
+ * MAXCLOCK peers, keep only the best MAXCLOCK of them. Scan the
+ * list to find falsetickers, who leave the island immediately.
+ * If a falseticker is not configured, his association raft is
+ * drowned as well. We must leave at least one peer to collect
+ * the million bucks.
*/
j = 0;
for (i = 0; i < nlist; i++) {
peer = peer_list[i];
- if (nlist > 1 && (low >= peer->offset ||
- peer->offset >= high))
+ if (nlist > 1 && (low >= peer->offset || peer->offset >=
+ high)) {
+ if (!(peer->flags & FLAG_CONFIG))
+ unpeer(peer);
continue;
- peer->status = CTL_PST_SEL_CORRECT;
+ }
+ peer->status = CTL_PST_SEL_DISTSYSPEER;
d = root_distance(peer) + peer->stratum * MAXDISPERSE;
if (j >= NTP_MAXCLOCK) {
if (d >= synch[j - 1])
@@ -1429,77 +1723,98 @@ clock_select(void)
for (k = j; k > 0; k--) {
if (d >= synch[k - 1])
break;
- synch[k] = synch[k - 1];
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;
+ for (i = 0; i < nlist; i++) {
+ peer_list[i]->status = CTL_PST_SEL_SELCAND;
#ifdef DEBUG
- if (debug > 1)
- for (i = 0; i < nlist; i++)
+ if (debug > 2)
printf("select: %s distance %.6f\n",
ntoa(&peer_list[i]->srcadr), synch[i]);
#endif
+ }
/*
- * Now, prune outlyers by root dispersion. Continue as long as
- * there are more than NTP_MINCLOCK survivors and the minimum
- * select dispersion is greater than the maximum peer
- * dispersion. Stop if we are about to discard a prefer peer.
+ * Now, vote outlyers off the island by select jitter weighted
+ * by root dispersion. Continue voting as long as there are more
+ * than NTP_MINCLOCK survivors and the minimum select jitter
+ * 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.
*/
- for (i = 0; i < nlist; i++) {
- peer = peer_list[i];
- error[i] = peer->variance;
- if (i < NTP_CANCLOCK)
- peer->status = CTL_PST_SEL_SELCAND;
- else
- peer->status = CTL_PST_SEL_DISTSYSPEER;
- }
while (1) {
- sys_maxd = 0;
- d = error[0];
- for (k = i = nlist - 1; i >= 0; i--) {
- double sdisp = 0;
-
- for (j = nlist - 1; j > 0; j--) {
- sdisp = NTP_SWEIGHT * (sdisp +
- DIFF(peer_list[i]->offset,
- peer_list[j]->offset));
+ d = 1e9;
+ e = -1e9;
+ k = 0;
+ for (i = 0; i < nlist; i++) {
+
+ if (error[i] < d)
+ d = error[i];
+ f = 0;
+ if (nlist > 1) {
+ for (j = 0; j < nlist; j++)
+ f += DIFF(peer_list[j]->offset,
+ peer_list[i]->offset);
+ f /= nlist - 1;
}
- if (sdisp > sys_maxd) {
- sys_maxd = sdisp;
+ f = max(f, SQUARE(LOGTOD(sys_precision)));
+ if (f * synch[i] > e) {
+ sys_selerr = f;
+ e = f * synch[i];
k = i;
}
- if (error[i] < d)
- d = error[i];
}
#ifdef DEBUG
- if (debug > 1)
+ if (debug > 2)
printf(
"select: survivors %d select %.6f peer %.6f\n",
- nlist, SQRT(sys_maxd), SQRT(d));
+ k, SQRT(sys_selerr), SQRT(d));
#endif
- if (nlist <= NTP_MINCLOCK || sys_maxd <= d ||
- peer_list[k]->flags & FLAG_PREFER)
+ if (nlist <= NTP_MINCLOCK || sys_selerr <= d ||
+ peer_list[k]->flags & FLAG_PREFER)
break;
+ if (!(peer_list[k]->flags & FLAG_CONFIG))
+ unpeer(peer_list[k]);
for (j = k + 1; j < nlist; j++) {
peer_list[j - 1] = peer_list[j];
error[j - 1] = error[j];
}
nlist--;
}
+
+#ifdef AUTOKEY
+ /*
+ * In manycast client mode we may have spooked a sizeable number
+ * of servers that we don't need. If there are at least
+ * NTP_MINCLOCK of them, the manycast message will be turned
+ * off. By the time we get here we nay be ready to prune some of
+ * them back, but we want to make sure all the candicates have
+ * had a chance. If they didn't pass the sanity and intersection
+ * tests, they have already been voted off the island.
+ */
+ if (sys_survivors >= NTP_MINCLOCK && nlist < NTP_MINCLOCK)
+ resetmanycast();
+#endif /* AUTOKEY */
+ sys_survivors = nlist;
+
#ifdef DEBUG
- if (debug > 1) {
+ if (debug > 2) {
for (i = 0; i < nlist; i++)
printf(
"select: %s offset %.6f, distance %.6f poll %d\n",
- ntoa(&peer_list[i]->srcadr), peer_list[i]->offset,
- synch[i], peer_list[i]->pollsw);
+ ntoa(&peer_list[i]->srcadr),
+ peer_list[i]->offset, synch[i],
+ peer_list[i]->pollsw);
}
#endif
@@ -1518,27 +1833,30 @@ clock_select(void)
* him. We note that the head of the list is at the lowest
* stratum and that unsynchronized peers cannot survive this
* far.
+ *
+ * Note that we go no further, unless the number of survivors is
+ * a majority of the suckers that have been found reachable and
+ * no prior source is available. This avoids the transient when
+ * one of a flock of sources is out to lunch and just happens
+ * to be the first survivor.
*/
+ if (osys_peer == NULL && 2 * nlist < min(nreach, NTP_MINCLOCK))
+ return;
leap_consensus = 0;
for (i = nlist - 1; i >= 0; i--) {
- peer_list[i]->status = CTL_PST_SEL_SYNCCAND;
- peer_list[i]->flags |= FLAG_SYSPEER;
- poll_update(peer_list[i], peer_list[i]->hpoll);
- if (peer_list[i]->stratum == peer_list[0]->stratum) {
- leap_consensus |= peer_list[i]->leap;
- if (peer_list[i]->refclktype == REFCLK_ATOM_PPS)
- typepps = peer_list[i];
- if (peer_list[i] == sys_peer)
- typesystem = peer_list[i];
- if (peer_list[i]->flags & FLAG_PREFER) {
- typeprefer = peer_list[i];
- if (fabs(typeprefer->offset) <
- clock_max)
- pps_update = 1;
- }
- } else {
- if (peer_list[i] == sys_peer)
- sys_peer = 0;
+ peer = peer_list[i];
+ peer->status = CTL_PST_SEL_SYNCCAND;
+ peer->flags |= FLAG_SYSPEER;
+ poll_update(peer, peer->hpoll);
+ if (peer->stratum == peer_list[0]->stratum) {
+ leap_consensus |= peer->leap;
+ if (peer->refclktype == REFCLK_ATOM_PPS &&
+ peer->stratum < STRATUM_UNSPEC)
+ typepps = peer;
+ if (peer == osys_peer)
+ typesystem = peer;
+ if (peer->flags & FLAG_PREFER)
+ sys_prefer = peer;
}
}
@@ -1554,38 +1872,45 @@ clock_select(void)
* stated. Note that all of these must be at the lowest stratum,
* i.e., the stratum of the head of the survivor list.
*/
- osys_peer = sys_peer;
- if (typeprefer && (typeprefer->refclktype == REFCLK_LOCALCLOCK
- || typeprefer->sstclktype == CTL_SST_TS_TELEPHONE ||
- !typepps)) {
- sys_peer = typeprefer;
+ if (sys_prefer)
+ sw = sys_prefer->refclktype == REFCLK_LOCALCLOCK ||
+ sys_prefer->sstclktype == CTL_SST_TS_TELEPHONE ||
+ !typepps;
+ else
+ sw = 0;
+ if (sw) {
+ sys_peer = sys_prefer;
sys_peer->status = CTL_PST_SEL_SYSPEER;
sys_offset = sys_peer->offset;
- sys_epsil = sys_peer->variance;
+ sys_syserr = sys_peer->jitter;
#ifdef DEBUG
if (debug > 1)
printf("select: prefer offset %.6f\n",
sys_offset);
#endif
- } else if (typepps && pps_update) {
+ } else if (typepps) {
sys_peer = typepps;
sys_peer->status = CTL_PST_SEL_PPS;
sys_offset = sys_peer->offset;
- sys_epsil = sys_peer->variance;
+ sys_syserr = sys_peer->jitter;
if (!pps_control)
- NLOG(NLOG_SYSEVENT) /* conditional syslog */
- msyslog(LOG_INFO, "pps sync enabled");
+ 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);
+ printf("select: pps offset %.6f\n",
+ sys_offset);
#endif
} else {
- if (!typesystem)
+ if (typesystem)
+ sys_peer = osys_peer;
+ else
sys_peer = peer_list[0];
sys_peer->status = CTL_PST_SEL_SYSPEER;
sys_offset = clock_combine(peer_list, nlist);
- sys_epsil = sys_peer->variance + sys_maxd;
+ sys_syserr = sys_peer->jitter + sys_selerr;
#ifdef DEBUG
if (debug > 1)
printf("select: combine offset %.6f\n",
@@ -1625,10 +1950,14 @@ root_distance(
struct peer *peer
)
{
- return ((fabs(peer->delay) + peer->rootdelay) / 2 +
- peer->rootdispersion + peer->disp +
- SQRT(peer->variance) + CLOCK_PHI * (current_time -
- peer->update));
+ /*
+ * Careful squeak here. The value returned must be greater than
+ * zero blamed on the peer jitter, which must be at least the
+ * square of sys_precision.
+ */
+ return ((peer->rootdelay + peer->delay) / 2 +
+ peer->rootdispersion + peer->disp + clock_phi *
+ (current_time - peer->update) + SQRT(peer->jitter));
}
/*
@@ -1639,279 +1968,518 @@ peer_xmit(
struct peer *peer /* peer structure pointer */
)
{
- struct pkt xpkt;
- int find_rtt = (peer->cast_flags & MDF_MCAST) &&
- peer->hmode != MODE_BROADCAST;
- int sendlen;
+ struct pkt xpkt; /* transmit packet */
+ int sendlen, authlen;
+ keyid_t xkeyid; /* transmit key ID */
+ l_fp xmt_tx;
/*
- * Initialize protocol fields.
+ * Initialize transmit packet header fields.
*/
- xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
- peer->version, peer->hmode);
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, peer->version,
+ peer->hmode);
xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
xpkt.ppoll = peer->hpoll;
xpkt.precision = sys_precision;
xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion +
- LOGTOD(sys_precision)));
+ 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);
/*
- * Authenticate the packet if enabled and either configured or
- * the previous packet was authenticated. If for some reason the
- * key associated with the key identifier is not in the key
- * cache, then honk key zero.
+ * If the received packet contains a MAC, the transmitted packet
+ * is authenticated and contains a MAC. If not, the transmitted
+ * packet is not authenticated.
+ *
+ * In the current I/O semantics the default interface is set
+ * until after receiving a packet and setting the right
+ * interface. So, the first packet goes out unauthenticated.
+ * That's why the really icky test next is here.
*/
sendlen = LEN_PKT_NOMAC;
- if (peer->flags & FLAG_AUTHENABLE) {
- u_long xkeyid;
- l_fp xmt_tx;
+ if (!(peer->flags & FLAG_AUTHENABLE)) {
+ get_systime(&peer->xmt);
+ HTONL_FP(&peer->xmt, &xpkt.xmt);
+ sendpkt(&peer->srcadr, peer->dstadr, peer->ttl, &xpkt,
+ sendlen);
+ peer->sent++;
+#ifdef DEBUG
+ if (debug)
+ printf("transmit: at %ld %s->%s mode %d\n",
+ current_time, ntoa(&peer->dstadr->sin),
+ ntoa(&peer->srcadr), peer->hmode);
+#endif
+ return;
+ }
+
+ /*
+ * The received packet contains a MAC, so the transmitted packet
+ * must be authenticated. If autokey is enabled, fuss with the
+ * various modes; otherwise, private key cryptography is used.
+ */
+#ifdef AUTOKEY
+ if ((peer->flags & FLAG_SKEY)) {
+ u_int cmmd;
/*
- * Transmit encrypted packet compensated for the
- * encryption delay.
+ * The Public Key Dance (PKD): Cryptographic credentials
+ * are contained in extension fields, each including a
+ * 4-octet length/code word followed by a 4-octet
+ * association ID and optional additional data. Optional
+ * data includes a 4-octet data length field followed by
+ * the data itself. Request messages are sent from a
+ * configured association; response messages can be sent
+ * from a configured association or can take the fast
+ * path without ever matching an association. Response
+ * messages have the same code as the request, but have
+ * a response bit and possibly an error bit set. In this
+ * implementation, a message may contain no more than
+ * one command and no more than one response.
+ *
+ * Cryptographic session keys include both a public and
+ * a private componet. Request and response messages
+ * using extension fields are always sent with the
+ * private component set to zero. Packets without
+ * extension fields indlude the private component when
+ * the session key is generated.
*/
-#ifdef MD5
- if (peer->flags & FLAG_SKEY) {
-
+ while (1) {
+
/*
- * In autokey mode, allocate and initialize a
- * key list if not already done. Then, use the
- * list in inverse order, discarding keys once
- * used. Keep the latest key around until the
- * next one, so clients can use client/server
- * packets to compute propagation delay. Note we
- * have to wait until the receive side of the
- * socket is bound and the server address
- * confirmed.
+ * Allocate and initialize a keylist if not
+ * already done. Then, use the list in inverse
+ * order, discarding keys once used. Keep the
+ * latest key around until the next one, so
+ * clients can use client/server packets to
+ * compute propagation delay.
+ *
+ * Note that once a key is used from the list,
+ * it is retained in the key cache until the
+ * next key is used. This is to allow a client
+ * to retrieve the encrypted session key
+ * identifier to verify authenticity.
+ *
+ * If for some reason a key is no longer in the
+ * key cache, a birthday has happened and the
+ * pseudo-random sequence is probably broken. In
+ * that case, purge the keylist and regenerate
+ * it.
*/
- if (ntohl(peer->dstadr->sin.sin_addr.s_addr) ==
- 0 &&
- ntohl(peer->dstadr->bcast.sin_addr.s_addr) == 0)
- peer->keyid = 0;
- else {
- if (peer->keylist == 0) {
- make_keylist(peer);
- } else {
- authtrust(peer->keylist[peer->keynumber], 0);
- if (peer->keynumber == 0)
- make_keylist(peer);
- else {
- peer->keynumber--;
- xkeyid = peer->keylist[peer->keynumber];
- if (!authistrusted(xkeyid))
- make_keylist(peer);
- }
- }
- peer->keyid = peer->keylist[peer->keynumber];
- xpkt.keyid1 = htonl(2 * sizeof(u_int32));
- xpkt.keyid2 = htonl(sys_private);
- sendlen += 2 * sizeof(u_int32);
- }
+ if (peer->keynumber == 0)
+ make_keylist(peer, peer->dstadr);
+ else
+ peer->keynumber--;
+ xkeyid = peer->keylist[peer->keynumber];
+ if (authistrusted(xkeyid))
+ break;
+ else
+ key_expire(peer);
}
-#endif /* MD5 */
- xkeyid = peer->keyid;
- get_systime(&peer->xmt);
- L_ADD(&peer->xmt, &sys_authdelay);
- HTONL_FP(&peer->xmt, &xpkt.xmt);
- sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt,
- sendlen);
- get_systime(&xmt_tx);
- sendpkt(&peer->srcadr, find_rtt ? any_interface :
- peer->dstadr, ((peer->cast_flags & MDF_MCAST) &&
- !find_rtt) ? ((peer->cast_flags & MDF_ACAST) ? -7 :
- peer->ttl) : -7, &xpkt, sendlen);
+ peer->keyid = xkeyid;
+ switch (peer->hmode) {
/*
- * Calculate the encryption delay. Keep the minimum over
- * the latest two samples.
+ * In broadcast mode the autokey values are required.
+ * Send them when a new keylist is generated; otherwise,
+ * send the association ID so the client can request
+ * them at other times.
*/
- L_SUB(&xmt_tx, &peer->xmt);
- L_ADD(&xmt_tx, &sys_authdelay);
- sys_authdly[1] = sys_authdly[0];
- sys_authdly[0] = xmt_tx.l_uf;
- if (sys_authdly[0] < sys_authdly[1])
- sys_authdelay.l_uf = sys_authdly[0];
- else
- sys_authdelay.l_uf = sys_authdly[1];
- peer->sent++;
-#ifdef DEBUG
- if (debug)
- printf(
- "transmit: at %ld to %s mode %d keyid %08lx index %d\n",
- current_time, ntoa(&peer->srcadr),
- peer->hmode, xkeyid, peer->keynumber);
-#endif
- } else {
+ case MODE_BROADCAST:
+ if (peer->flags & FLAG_ASSOC)
+ cmmd = CRYPTO_AUTO | CRYPTO_RESP;
+ else
+ cmmd = CRYPTO_ASSOC | CRYPTO_RESP;
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, cmmd, 0, peer->associd);
+ break;
+
/*
- * Transmit non-authenticated packet.
+ * In symmetric modes the public key, leapsecond table,
+ * agreement parameters and autokey values are required.
+ *
+ * 1. If a response is pending, always send it first.
+ *
+ * 2. Don't send anything except a public-key request
+ * until the public key has been stored.
+ *
+ * 3. Once the public key has been stored, don't send
+ * anything except an agreement parameter request
+ * until the agreement parameters have been stored.
+ *
+ * 4. Once the argeement parameters have been stored,
+ * don't send anything except a public value request
+ * until the agreed key has been stored.
+ *
+ * 5. When the agreed key has been stored and the key
+ * list is regenerated, send the autokey values
+ * gratis unless they have already been sent.
*/
- get_systime(&(peer->xmt));
- HTONL_FP(&peer->xmt, &xpkt.xmt);
- sendpkt(&(peer->srcadr), find_rtt ? any_interface :
- peer->dstadr, ((peer->cast_flags & MDF_MCAST) &&
- !find_rtt) ? ((peer->cast_flags & MDF_ACAST) ? -7 :
- peer->ttl) : -8, &xpkt, sendlen);
- peer->sent++;
+ case MODE_ACTIVE:
+ case MODE_PASSIVE:
+#ifdef PUBKEY
+ if (peer->cmmd != 0)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, (peer->cmmd >> 16) |
+ CRYPTO_RESP, peer->hcookie,
+ peer->associd);
+ if (!peer->crypto)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_ASSOC,
+ peer->hcookie, peer->assoc);
+ else if (!crypto_flags &&
+ peer->pcookie.tstamp == 0 && sys_leap !=
+ LEAP_NOTINSYNC)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_PRIV, peer->hcookie,
+ peer->assoc);
+ else if (crypto_flags && peer->pubkey.ptr ==
+ NULL)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_NAME, peer->hcookie,
+ peer->assoc);
+ else if (peer->crypto & CRYPTO_FLAG_CERT)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_CERT, peer->hcookie,
+ peer->assoc);
+ else if (crypto_flags && peer->crypto &
+ CRYPTO_FLAG_DH && sys_leap !=
+ LEAP_NOTINSYNC)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_DHPAR,
+ peer->hcookie, peer->assoc);
+ else if (crypto_flags && peer->pcookie.tstamp ==
+ 0 && sys_leap != LEAP_NOTINSYNC)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_DH, peer->hcookie,
+ peer->assoc);
+#else
+ if (peer->cmmd != 0)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, (peer->cmmd >> 16) |
+ CRYPTO_RESP, peer->hcookie,
+ peer->associd);
+ if (peer->pcookie.tstamp == 0 && sys_leap !=
+ LEAP_NOTINSYNC)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_PRIV, peer->hcookie,
+ peer->assoc);
+#endif /* PUBKEY */
+ else if (!(peer->flags & FLAG_AUTOKEY))
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_AUTO, peer->hcookie,
+ peer->assoc);
+ else if ((peer->flags & FLAG_ASSOC) &&
+ (peer->cmmd >> 16) != CRYPTO_AUTO)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_AUTO | CRYPTO_RESP,
+ peer->hcookie, peer->associd);
+#ifdef PUBKEY
+ else if (peer->crypto & CRYPTO_FLAG_TAI)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_TAI, peer->hcookie,
+ peer->assoc);
+#endif /* PUBKEY */
+ peer->cmmd = 0;
+ break;
+
+ /*
+ * In client mode, the public key, host cookie and
+ * autokey values are required. In broadcast client
+ * mode, these values must be acquired during the
+ * client/server exchange to avoid having to wait until
+ * the next key list regeneration. Otherwise, the poor
+ * dude may die a lingering death until becoming
+ * unreachable and attempting rebirth. Note that we ask
+ * for the cookie at each key list regeneration anyway.
+ */
+ case MODE_CLIENT:
+ if (peer->cmmd != 0)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, (peer->cmmd >> 16) |
+ CRYPTO_RESP, peer->hcookie,
+ peer->associd);
+ if (!peer->crypto)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_ASSOC,
+ peer->hcookie, peer->assoc);
+#ifdef PUBKEY
+ else if (crypto_flags && peer->pubkey.ptr ==
+ NULL)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_NAME, peer->hcookie,
+ peer->assoc);
+ else if (peer->crypto & CRYPTO_FLAG_CERT)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_CERT, peer->hcookie,
+ peer->assoc);
+#endif /* PUBKEY */
+ else if (peer->pcookie.tstamp == 0)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_PRIV, peer->hcookie,
+ peer->assoc);
+ else if (!(peer->flags & FLAG_AUTOKEY) &&
+ (peer->cast_flags & MDF_BCLNT))
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_AUTO, peer->hcookie,
+ peer->assoc);
+#ifdef PUBKEY
+ else if (peer->crypto & CRYPTO_FLAG_TAI)
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, CRYPTO_TAI, peer->hcookie,
+ peer->assoc);
+#endif /* PUBKEY */
+ peer->cmmd = 0;
+ break;
+ }
+
+ /*
+ * If extension fields are present, we must use a
+ * private value of zero and force min poll interval.
+ * Most intricate.
+ */
+ if (sendlen > LEN_PKT_NOMAC)
+ session_key(&peer->dstadr->sin, &peer->srcadr,
+ xkeyid, 0, 2);
+ }
+#endif /* AUTOKEY */
+ xkeyid = peer->keyid;
+ get_systime(&peer->xmt);
+ L_ADD(&peer->xmt, &sys_authdelay);
+ HTONL_FP(&peer->xmt, &xpkt.xmt);
+ authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
+ if (authlen == 0) {
+ msyslog(LOG_NOTICE,
+ "transmit: no encryption key found");
+ peer->flash |= TEST4 | TEST5;
+ return;
+ }
+ sendlen += authlen;
+#ifdef AUTOKEY
+ if (xkeyid > NTP_MAXKEY)
+ authtrust(xkeyid, 0);
+#endif /* AUTOKEY */
+ get_systime(&xmt_tx);
+ if (sendlen > sizeof(xpkt)) {
+ msyslog(LOG_ERR, "buffer overflow %u", sendlen);
+ exit(-1);
+ }
+ sendpkt(&peer->srcadr, peer->dstadr, peer->ttl, &xpkt, sendlen);
+
+ /*
+ * Calculate the encryption delay. Keep the minimum over
+ * the latest two samples.
+ */
+ L_SUB(&xmt_tx, &peer->xmt);
+ L_ADD(&xmt_tx, &sys_authdelay);
+ sys_authdly[1] = sys_authdly[0];
+ sys_authdly[0] = xmt_tx.l_uf;
+ if (sys_authdly[0] < sys_authdly[1])
+ sys_authdelay.l_uf = sys_authdly[0];
+ else
+ sys_authdelay.l_uf = sys_authdly[1];
+ peer->sent++;
+#ifdef AUTOKEY
#ifdef DEBUG
- if (debug)
- printf("transmit: at %ld to %s mode %d\n",
- current_time, ntoa(&peer->srcadr),
- peer->hmode);
+ if (debug)
+ printf(
+ "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d index %d\n",
+ current_time, ntoa(&peer->dstadr->sin),
+ ntoa(&peer->srcadr), peer->hmode, xkeyid, sendlen,
+ authlen, peer->keynumber);
#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);
+#endif
+#endif /* AUTOKEY */
}
+
/*
- * fast_xmit - Send packet for nonpersistent association.
+ * fast_xmit - Send packet for nonpersistent association. Note that
+ * neither the source or destination can be a broadcast address.
*/
static void
fast_xmit(
struct recvbuf *rbufp, /* receive packet pointer */
int xmode, /* transmit mode */
- u_long xkeyid /* transmit key ID */
+ keyid_t xkeyid, /* transmit key ID */
+ int mask /* restrict mask */
)
{
- struct pkt xpkt;
- struct pkt *rpkt;
- int sendlen;
- l_fp xmt_ts;
+ struct pkt xpkt; /* transmit packet structure */
+ struct pkt *rpkt; /* receive packet structure */
+ l_fp xmt_ts; /* transmit timestamp */
+ l_fp xmt_tx; /* transmit timestamp after authent */
+ int sendlen, authlen;
/*
- * Initialize transmit packet header fields in the receive
- * buffer provided. We leave some fields intact as received.
+ * Initialize transmit packet header fields from the receive
+ * buffer provided. We leave some fields intact as received. If
+ * the gazinta was from a multicast address, the gazouta must go
+ * out another way.
*/
rpkt = &rbufp->recv_pkt;
- xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
- PKT_VERSION(rpkt->li_vn_mode), xmode);
- xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
+ if (rbufp->dstadr->flags & INT_MULTICAST)
+ rbufp->dstadr = findinterface(&rbufp->recv_srcadr);
+
+ /*
+ * If the caller is restricted, return a kiss-of-death packet;
+ * otherwise, smooch politely.
+ */
+ if (mask & (RES_DONTSERVE | RES_LIMITED)) {
+ if (!(mask & RES_DEMOBILIZE)) {
+ return;
+ } else {
+ xpkt.li_vn_mode =
+ PKT_LI_VN_MODE(LEAP_NOTINSYNC,
+ PKT_VERSION(rpkt->li_vn_mode), xmode);
+ xpkt.stratum = STRATUM_UNSPEC;
+ memcpy(&xpkt.refid, "DENY", 4);
+ }
+ } else {
+ xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap,
+ PKT_VERSION(rpkt->li_vn_mode), xmode);
+ xpkt.stratum = STRATUM_TO_PKT(sys_stratum);
+ xpkt.refid = sys_refid;
+ }
xpkt.ppoll = rpkt->ppoll;
xpkt.precision = sys_precision;
xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
- xpkt.rootdispersion = HTONS_FP(DTOUFP(sys_rootdispersion +
- LOGTOD(sys_precision)));
- xpkt.refid = sys_refid;
+ xpkt.rootdispersion =
+ HTONS_FP(DTOUFP(sys_rootdispersion));
HTONL_FP(&sys_reftime, &xpkt.reftime);
xpkt.org = rpkt->xmt;
HTONL_FP(&rbufp->recv_time, &xpkt.rec);
- sendlen = LEN_PKT_NOMAC;
- if (rbufp->recv_length > sendlen) {
- l_fp xmt_tx;
- /*
- * Transmit encrypted packet compensated for the
- * encryption delay.
- */
- if (xkeyid > NTP_MAXKEY) {
- xpkt.keyid1 = htonl(2 * sizeof(u_int32));
- xpkt.keyid2 = htonl(sys_private);
- sendlen += 2 * sizeof(u_int32);
- }
+ /*
+ * If the received packet contains a MAC, the transmitted packet
+ * is authenticated and contains a MAC. If not, the transmitted
+ * packet is not authenticated.
+ */
+ sendlen = LEN_PKT_NOMAC;
+ if (rbufp->recv_length == sendlen) {
get_systime(&xmt_ts);
- L_ADD(&xmt_ts, &sys_authdelay);
HTONL_FP(&xmt_ts, &xpkt.xmt);
- sendlen += authencrypt(xkeyid, (u_int32 *)&xpkt,
+ sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt,
sendlen);
- get_systime(&xmt_tx);
- sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, -9, &xpkt,
- sendlen);
-
- /*
- * Calculate the encryption delay. Keep the minimum over
- * the latest two samples.
- */
- L_SUB(&xmt_tx, &xmt_ts);
- L_ADD(&xmt_tx, &sys_authdelay);
- sys_authdly[1] = sys_authdly[0];
- sys_authdly[0] = xmt_tx.l_uf;
- if (sys_authdly[0] < sys_authdly[1])
- sys_authdelay.l_uf = sys_authdly[0];
- else
- sys_authdelay.l_uf = sys_authdly[1];
#ifdef DEBUG
if (debug)
- printf(
- "transmit: at %ld to %s mode %d keyid %08lx\n",
- current_time, ntoa(&rbufp->recv_srcadr),
- xmode, xkeyid);
+ printf("transmit: at %ld %s->%s mode %d\n",
+ current_time, ntoa(&rbufp->dstadr->sin),
+ ntoa(&rbufp->recv_srcadr), xmode);
#endif
- } else {
+ return;
+ }
+
+ /*
+ * The received packet contains a MAC, so the transmitted packet
+ * must be authenticated. For private-key cryptography, use the
+ * predefined private keys to generate the cryptosum. For
+ * autokey cryptography, use the server private value to
+ * generate the cookie, which is unique for every source-
+ * destination-key ID combination.
+ */
+#ifdef AUTOKEY
+ if (xkeyid > NTP_MAXKEY) {
+ keyid_t cookie;
+ u_int code, associd;
/*
- * Transmit non-authenticated packet.
+ * The only way to get here is a reply to a legitimate
+ * client request message, so the mode must be
+ * MODE_SERVER. If an extension field is present, there
+ * can be only one and that must be a command. Do what
+ * needs, but with private value of zero so the poor
+ * jerk can decode it. If no extension field is present,
+ * use the cookie to generate the session key.
*/
- get_systime(&xmt_ts);
- HTONL_FP(&xmt_ts, &xpkt.xmt);
- sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, -10, &xpkt,
- sendlen);
+ code = (htonl(rpkt->exten[0]) >> 16) | CRYPTO_RESP;
+ cookie = session_key(&rbufp->recv_srcadr,
+ &rbufp->dstadr->sin, 0, sys_private, 0);
+ associd = htonl(rpkt->exten[1]);
+ if (rbufp->recv_length >= sendlen + MAX_MAC_LEN + 2 *
+ sizeof(u_int32)) {
+ session_key(&rbufp->dstadr->sin,
+ &rbufp->recv_srcadr, xkeyid, 0, 2);
+ sendlen += crypto_xmit((u_int32 *)&xpkt,
+ sendlen, code, cookie, associd);
+ } else {
+ session_key(&rbufp->dstadr->sin,
+ &rbufp->recv_srcadr, xkeyid, cookie, 2);
+ }
+ }
+#endif /* AUTOKEY */
+ get_systime(&xmt_ts);
+ L_ADD(&xmt_ts, &sys_authdelay);
+ HTONL_FP(&xmt_ts, &xpkt.xmt);
+ authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
+ sendlen += authlen;
+#ifdef AUTOKEY
+ if (xkeyid > NTP_MAXKEY)
+ authtrust(xkeyid, 0);
+#endif /* AUTOKEY */
+ get_systime(&xmt_tx);
+ if (sendlen > sizeof(xpkt)) {
+ msyslog(LOG_ERR, "buffer overflow %u", sendlen);
+ exit(-1);
+ }
+ sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, &xpkt, sendlen);
+
+ /*
+ * Calculate the encryption delay. Keep the minimum over the
+ * latest two samples.
+ */
+ L_SUB(&xmt_tx, &xmt_ts);
+ L_ADD(&xmt_tx, &sys_authdelay);
+ sys_authdly[1] = sys_authdly[0];
+ sys_authdly[0] = xmt_tx.l_uf;
+ if (sys_authdly[0] < sys_authdly[1])
+ sys_authdelay.l_uf = sys_authdly[0];
+ else
+ sys_authdelay.l_uf = sys_authdly[1];
#ifdef DEBUG
- if (debug)
- printf("transmit: at %ld to %s mode %d\n",
- current_time, ntoa(&rbufp->recv_srcadr),
- xmode);
+ if (debug)
+ printf(
+ "transmit: at %ld %s->%s mode %d keyid %08x len %d mac %d\n",
+ current_time, ntoa(&rbufp->dstadr->sin),
+ ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen,
+ authlen);
#endif
- }
}
-#ifdef MD5
+
+#ifdef AUTOKEY
/*
- * Compute key list
+ * key_expire - purge the key list
*/
-static void
-make_keylist(
- struct peer *peer
+void
+key_expire(
+ struct peer *peer /* peer structure pointer */
)
{
int i;
- u_long keyid;
- u_long ltemp;
- /*
- * Allocate the key list if necessary.
- */
- if (peer->keylist == 0)
- peer->keylist = (u_long *)emalloc(sizeof(u_long) *
- NTP_MAXSESSION);
-
- /*
- * Generate an initial key ID which is unique and greater than
- * NTP_MAXKEY.
- */
- while (1) {
- keyid = (u_long)RANDOM & 0xffffffff;
- if (keyid <= NTP_MAXKEY)
- continue;
- if (authhavekey(keyid))
- continue;
- break;
- }
-
- /*
- * Generate up to NTP_MAXSESSION session keys. Stop if the
- * next one would not be unique or not a session key ID or if
- * it would expire before the next poll.
- */
- ltemp = sys_automax;
- for (i = 0; i < NTP_MAXSESSION; i++) {
- peer->keylist[i] = keyid;
- peer->keynumber = i;
- keyid = session_key(
- ntohl(peer->dstadr->sin.sin_addr.s_addr),
- (peer->hmode == MODE_BROADCAST || (peer->flags &
- FLAG_MCAST2)) ?
- ntohl(peer->dstadr->bcast.sin_addr.s_addr):
- ntohl(peer->srcadr.sin_addr.s_addr), keyid, ltemp);
- ltemp -= 1 << peer->hpoll;
- if (auth_havekey(keyid) || keyid <= NTP_MAXKEY ||
- ltemp <= (1 << (peer->hpoll + 1)))
- break;
+ if (peer->keylist != NULL) {
+ for (i = 0; i <= peer->keynumber; i++)
+ authtrust(peer->keylist[i], 0);
+ free(peer->keylist);
+ peer->keylist = NULL;
}
+ peer->keynumber = peer->sndauto.seq = 0;
+#ifdef DEBUG
+ if (debug)
+ printf("key_expire: at %lu\n", current_time);
+#endif
}
-#endif /* MD5 */
+#endif /* AUTOKEY */
/*
* Find the precision of this particular machine
@@ -2031,19 +2599,17 @@ init_proto(void)
sys_leap = LEAP_NOTINSYNC;
sys_stratum = STRATUM_UNSPEC;
sys_precision = (s_char)default_get_precision();
+ sys_jitter = LOGTOD(sys_precision);
sys_rootdelay = 0;
sys_rootdispersion = 0;
sys_refid = 0;
L_CLR(&sys_reftime);
- sys_peer = 0;
+ sys_peer = NULL;
+ sys_survivors = 0;
get_systime(&dummy);
sys_bclient = 0;
sys_bdelay = DEFBROADDELAY;
-#if defined(DES) || defined(MD5)
sys_authenticate = 1;
-#else
- sys_authenticate = 0;
-#endif
L_CLR(&sys_authdelay);
sys_authdly[0] = sys_authdly[1] = 0;
sys_stattime = 0;
@@ -2055,7 +2621,9 @@ init_proto(void)
sys_processed = 0;
sys_badauth = 0;
sys_manycastserver = 0;
+#ifdef AUTOKEY
sys_automax = 1 << NTP_AUTOMAX;
+#endif /* AUTOKEY */
/*
* Default these to enable
@@ -2064,11 +2632,12 @@ init_proto(void)
#ifndef KERNEL_FLL_BUG
kern_enable = 1;
#endif
- msyslog(LOG_DEBUG, "kern_enable is %d", kern_enable);
+ pps_enable = 0;
stats_control = 1;
/*
- * Some system clocks should only be adjusted in 10ms increments.
+ * Some system clocks should only be adjusted in 10ms
+ * increments.
*/
#if defined RELIANTUNIX_CLOCK
systime_10ms_ticks = 1; /* Reliant UNIX */
@@ -2174,6 +2743,24 @@ proto_config(
sys_authenticate = (int)value;
break;
+ case PROTO_PPS:
+
+ /*
+ * Turn on/off PPS discipline
+ */
+ pps_enable = (int)value;
+ break;
+
+#ifdef REFCLOCK
+ case PROTO_CAL:
+
+ /*
+ * Turn on/off refclock calibrate
+ */
+ cal_enable = (int)value;
+ break;
+#endif
+
default:
/*
diff --git a/contrib/ntp/ntpd/ntp_refclock.c b/contrib/ntp/ntpd/ntp_refclock.c
index c47031c..2205b6c 100644
--- a/contrib/ntp/ntpd/ntp_refclock.c
+++ b/contrib/ntp/ntpd/ntp_refclock.c
@@ -5,23 +5,25 @@
# include <config.h>
#endif
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
+#include "ntp_tty.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif /* HAVE_SYS_IOCTL_H */
+
#ifdef REFCLOCK
#ifdef TTYCLK
# ifdef HAVE_SYS_CLKDEFS_H
# include <sys/clkdefs.h>
+# include <stropts.h>
# endif
# ifdef HAVE_SYS_SIO_H
# include <sys/sio.h>
@@ -32,15 +34,9 @@
#include <sys/ppsclock.h>
#endif /* HAVE_PPSCLOCK_H */
-#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
-#endif /* HAVE_PPSAPI */
+#ifdef KERNEL_PLL
+#include "ntp_syscall.h"
+#endif /* KERNEL_PLL */
/*
* Reference clock support is provided here by maintaining the fiction
@@ -72,24 +68,12 @@
* refclockproc structure pointer from the table typeunit[type][unit].
* This interface is strongly discouraged and may be abandoned in
* future.
- *
- * The routines include support for the 1-pps signal provided by some
- * radios and connected via a level converted described in the gadget
- * directory. The signal is captured using a serial port and one of
- * three STREAMS modules described in the refclock_atom.c file. For the
- * highest precision, the signal is captured using the carrier-detect
- * line of a serial port and either the ppsclock or ppsapi streams
- * module or some devilish ioctl() folks keep slipping in as a patch. Be
- * advised ALL support for other than the duly standardized ppsapi
- * interface will eventually be withdrawn.
*/
#define MAXUNIT 4 /* max units */
+#define FUDGEFAC .1 /* fudge correction factor */
-#if defined(PPS) || defined(HAVE_PPSAPI)
int fdpps; /* pps file descriptor */
-#endif /* PPS HAVE_PPSAPI */
-
-#define FUDGEFAC .1 /* fudge correction factor */
+int cal_enable; /* enable refclock calibrate */
/*
* Type/unit peer index. Used to find the peer structure for control and
@@ -108,11 +92,6 @@ static int refclock_cmpl_fp P((const double *, const double *));
#endif /* QSORT_USES_VOID_P */
static int refclock_sample P((struct refclockproc *));
-#ifdef HAVE_PPSAPI
-extern int pps_assert; /* capture edge 1:assert, 0:clear */
-extern int pps_hardpps; /* PPS kernel 1:on, 0:off */
-#endif /* HAVE_PPSAPI */
-
/*
* refclock_report - note the occurance of an event
*
@@ -222,7 +201,6 @@ refclock_newpeer(
clktype);
return (0);
}
- refclock_unpeer(peer);
/*
* Allocate and initialize interface structure
@@ -247,14 +225,6 @@ refclock_newpeer(
pp->timestarted = current_time;
/*
- * If the interface has been set to any_interface, set it to the
- * loopback address if we have one. This is so that peers which
- * are unreachable are easy to see in the peer display.
- */
- if (peer->dstadr == any_interface && loopback_interface != 0)
- peer->dstadr = loopback_interface;
-
- /*
* Set peer.pmode based on the hmode. For appearances only.
*/
switch (peer->hmode) {
@@ -273,7 +243,7 @@ refclock_newpeer(
* can be wiggled, then finish up for consistency.
*/
if (!((refclock_conf[clktype]->clock_start)(unit, peer))) {
- free(pp);
+ refclock_unpeer(peer);
return (0);
}
peer->hpoll = peer->minpoll;
@@ -354,25 +324,21 @@ refclock_transmit(
* network code.
*/
oreach = peer->reach;
- if (oreach & 0x01)
- peer->valid++;
- if (oreach & 0x80)
- peer->valid--;
- peer->reach <<= 1;
- if (peer->reach == 0) {
- if (oreach != 0) {
+ peer->reach <<= 1;
+ if (!peer->reach) {
+ if (oreach) {
report_event(EVNT_UNREACH, peer);
peer->timereachable = current_time;
peer_clear(peer);
}
} else {
- if ((oreach & 0x03) == 0) {
+ if (!(oreach & 0x03)) {
clock_filter(peer, 0., 0., MAXDISPERSE);
clock_select();
}
- if (peer->valid <= 2) {
+ if (!(oreach & 0x0f)) {
hpoll--;
- } else if (peer->valid > NTP_SHIFT - 2)
+ } else if ((oreach & 0x0f) == 0x0f)
hpoll++;
if (peer->flags & FLAG_BURST)
peer->burst = NSTAGE;
@@ -383,7 +349,6 @@ refclock_transmit(
if (refclock_conf[clktype]->clock_poll != noentry)
(refclock_conf[clktype]->clock_poll)(unit, peer);
peer->outdate = next;
- poll_update(peer, hpoll);
if (peer->burst > 0)
peer->burst--;
poll_update(peer, hpoll);
@@ -428,7 +393,9 @@ refclock_cmpl_fp(
/*
* refclock_process_offset - update median filter
*
- * This routine uses the given offset and timestamps to construct a new entry in the median filter circular buffer. Samples that overflow the filter are quietly discarded.
+ * This routine uses the given offset and timestamps to construct a new
+ * entry in the median filter circular buffer. Samples that overflow the
+ * filter are quietly discarded.
*/
void
refclock_process_offset(
@@ -442,7 +409,6 @@ refclock_process_offset(
pp->lastref = offset;
pp->lastrec = lastrec;
- pp->variance = 0;
L_SUB(&offset, &lastrec);
LFPTOD(&offset, doffset);
SAMPLE(doffset + fudge);
@@ -490,18 +456,18 @@ refclock_process(
*
* 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 mean-square variance. 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 0.
+ * calculates the mean offset and jitter (squares). A time adjustment
+ * fudgetime1 can be added to the final offset to compensate for various
+ * systematic errors. The routine returns the number of samples
+ * processed, which could be zero.
*/
static int
refclock_sample(
struct refclockproc *pp
)
{
- int i, j, k, n;
- double offset, disp;
+ int i, j, k, m, n;
+ double offset;
double off[MAXSTAGE];
/*
@@ -514,15 +480,15 @@ refclock_sample(
while (pp->codeproc != pp->coderecv)
off[n++] = pp->filter[pp->codeproc++ % MAXSTAGE];
if (n > 1)
- qsort((char *)off, n, sizeof(double), refclock_cmpl_fp);
+ qsort((char *)off, (size_t)n, sizeof(double), refclock_cmpl_fp);
/*
* Reject the furthest from the median of the samples until
* approximately 60 percent of the samples remain.
*/
i = 0; j = n;
- k = n - (n * 2) / NSTAGE;
- while ((j - i) > k) {
+ m = n - (n * 2) / NSTAGE;
+ while ((j - i) > m) {
offset = off[(j + i) / 2];
if (off[j - 1] - offset < offset - off[i])
i++; /* reject low end */
@@ -531,21 +497,21 @@ refclock_sample(
}
/*
- * Determine the offset and variance.
+ * Determine the offset and jitter.
*/
- offset = disp = 0;
- for (; i < j; i++) {
- offset += off[i];
- disp += SQUARE(off[i]);
- }
- offset /= k;
- pp->offset = offset;
- pp->variance += disp / k - SQUARE(offset);
+ offset = 0;
+ for (k = i; k < j; k++)
+ offset += off[k];
+ pp->offset = offset / m;
+ if (m > 1)
+ pp->jitter = SQUARE(off[i] - off[j - 1]);
+ else
+ pp->jitter = 0;
#ifdef DEBUG
if (debug)
printf(
- "refclock_sample: n %d offset %.6f disp %.6f std %.6f\n",
- n, pp->offset, pp->disp, SQRT(pp->variance));
+ "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n",
+ n, pp->offset, pp->disp, SQRT(pp->jitter));
#endif
return (n);
}
@@ -587,21 +553,29 @@ refclock_receive(
refclock_report(peer, CEVNT_FAULT);
return;
}
- if (peer->reach == 0)
+ if (!peer->reach)
report_event(EVNT_REACH, peer);
peer->reach |= 1;
peer->reftime = peer->org = pp->lastrec;
- peer->rootdispersion = pp->disp + SQRT(pp->variance);
+ peer->rootdispersion = pp->disp + SQRT(pp->jitter);
get_systime(&peer->rec);
if (!refclock_sample(pp))
return;
- clock_filter(peer, pp->offset, 0., 0.);
+ 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->variance));
- if (pps_control && pp->sloppyclockflag & CLK_FLAG1)
- pp->fudgetime1 -= pp->offset * FUDGEFAC;
+ peer->offset, peer->delay, clock_phi * (current_time -
+ peer->epoch), SQRT(peer->jitter));
+ if (cal_enable && last_offset < MINDISPERSE) {
+#ifdef KERNEL_PLL
+ if (peer != sys_peer || pll_status & STA_PPSTIME)
+#else
+ if (peer != sys_peer)
+#endif /* KERNEL_PLL */
+ pp->fudgetime1 -= pp->offset * FUDGEFAC;
+ else
+ pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC;
+ }
}
/*
@@ -619,21 +593,13 @@ 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 */
+ l_fp *tsptr /* pointer to timestamp returned */
)
{
char *dpt, *dpend, *dp;
int i;
l_fp trtmp, tstmp;
char c;
-#ifdef TIOCDCDTIMESTAMP
- struct timeval dcd_time;
-#endif /* TIOCDCDTIMESTAMP */
-#ifdef HAVE_PPSAPI
- pps_info_t pi;
- struct timespec timeout, *tsp;
- double a;
-#endif /* HAVE_PPSAPI */
/*
* Check for the presence of a timestamp left by the tty_clock
@@ -646,58 +612,6 @@ refclock_gtlin(
dpend = dpt + rbufp->recv_length;
trtmp = rbufp->recv_time;
-#ifdef HAVE_PPSAPI
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- if ((rbufp->fd == fdpps) &&
- (time_pps_fetch(fdpps, PPS_TSFMT_TSPEC, &pi, &timeout) >= 0)) {
- if(pps_assert)
- tsp = &pi.assert_timestamp;
- else
- tsp = &pi.clear_timestamp;
- a = tsp->tv_nsec;
- a /= 1e9;
- tstmp.l_uf = a * 4294967296.0;
- tstmp.l_ui = tsp->tv_sec;
- tstmp.l_ui += JAN_1970;
- L_SUB(&trtmp, &tstmp);
- if (trtmp.l_ui == 0) {
-#ifdef DEBUG
- if (debug > 1) {
- printf(
- "refclock_gtlin: fd %d time_pps_fetch %s",
- fdpps, lfptoa(&tstmp, 6));
- printf(" sigio %s\n", lfptoa(&trtmp, 6));
- }
-#endif
- trtmp = tstmp;
- goto gotit;
- } else
- trtmp = rbufp->recv_time;
- }
-#endif /* HAVE_PPSAPI */
-#ifdef TIOCDCDTIMESTAMP
- if(ioctl(rbufp->fd, TIOCDCDTIMESTAMP, &dcd_time) != -1) {
- TVTOTS(&dcd_time, &tstmp);
- tstmp.l_ui += JAN_1970;
- L_SUB(&trtmp, &tstmp);
- if (trtmp.l_ui == 0) {
-#ifdef DEBUG
- if (debug > 1) {
- printf(
- "refclock_gtlin: fd %d DCDTIMESTAMP %s",
- rbufp->fd, lfptoa(&tstmp, 6));
- printf(" sigio %s\n", lfptoa(&trtmp, 6));
- }
-#endif
- trtmp = tstmp;
- goto gotit;
- } else
- trtmp = rbufp->recv_time;
- }
- else
- /* XXX fallback to old method if kernel refuses TIOCDCDTIMESTAMP */
-#endif /* TIOCDCDTIMESTAMP */
if (dpend >= dpt + 8) {
if (buftvtots(dpend - 8, &tstmp)) {
L_SUB(&trtmp, &tstmp);
@@ -719,9 +633,6 @@ refclock_gtlin(
}
}
-#if defined(HAVE_PPSAPI) || defined(TIOCDCDTIMESTAMP)
-gotit:
-#endif
/*
* Edit timecode to remove control chars. Don't monkey with the
* line buffer if the input buffer contains no ASCII printing
@@ -767,36 +678,42 @@ refclock_open(
{
int fd, i;
int flags;
-#ifdef HAVE_TERMIOS
- struct termios ttyb, *ttyp;
-#endif /* HAVE_TERMIOS */
-#ifdef HAVE_SYSV_TTYS
- struct termio ttyb, *ttyp;
-#endif /* HAVE_SYSV_TTYS */
-#ifdef HAVE_BSD_TTYS
- struct sgttyb ttyb, *ttyp;
-#endif /* HAVE_BSD_TTYS */
+ TTY ttyb, *ttyp;
#ifdef TIOCMGET
u_long ltemp;
#endif /* TIOCMGET */
+ int omode;
/*
* Open serial port and set default options
*/
flags = lflags;
- if (strcmp(dev, pps_device) == 0)
- flags |= LDISC_PPS;
+
+ omode = O_RDWR;
#ifdef O_NONBLOCK
- fd = open(dev, O_RDWR | O_NONBLOCK, 0777);
-#else
- fd = open(dev, O_RDWR, 0777);
-#endif /* O_NONBLOCK */
- if (fd == -1) {
+ omode |= O_NONBLOCK;
+#endif
+#ifdef O_NOCTTY
+ omode |= O_NOCTTY;
+#endif
+
+ fd = open(dev, omode, 0777);
+
+ if (fd < 0) {
msyslog(LOG_ERR, "refclock_open: %s: %m", dev);
return (0);
}
/*
+ * This little jewel lights up the PPS file descriptor if the
+ * device name matches the name in the pps line in the
+ * configuration file. This is so the atom driver can glom onto
+ * the right device. Very silly.
+ */
+ if (strcmp(dev, pps_device) == 0)
+ fdpps = fd;
+
+ /*
* The following sections initialize the serial line port in
* canonical (line-oriented) mode and set the specified line
* speed, 8 bits and no parity. The modem control, break, erase
@@ -958,9 +875,8 @@ refclock_open(
* This routine attempts to hide the internal, system-specific details
* of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD
* (sgtty) interfaces with varying degrees of success. The routine sets
- * up optional features such as tty_clk, ppsclock and ppsapi, as well as
- * their many other variants. The routine returns 1 if success and 0 if
- * failure.
+ * up optional features such as tty_clk. The routine returns 1 if
+ * success and 0 if failure.
*/
int
refclock_ioctl(
@@ -973,45 +889,13 @@ refclock_ioctl(
#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
#ifdef TTYCLK
-#ifdef HAVE_TERMIOS
- struct termios ttyb, *ttyp;
-#endif /* HAVE_TERMIOS */
-#ifdef HAVE_SYSV_TTYS
- struct termio ttyb, *ttyp;
-#endif /* HAVE_SYSV_TTYS */
-#ifdef HAVE_BSD_TTYS
- struct sgttyb ttyb, *ttyp;
-#endif /* HAVE_BSD_TTYS */
+ TTY ttyb, *ttyp;
#endif /* TTYCLK */
#ifdef DEBUG
if (debug)
printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags);
#endif
-
- /*
- * The following sections select optional features, such as
- * modem control, PPS capture and so forth. Some require
- * specific operating system support in the form of STREAMS
- * modules, which can be loaded and unloaded at run time without
- * rebooting the kernel. The STREAMS modules require System
- * V STREAMS support. The checking frenzy is attenuated here,
- * since the device is already open.
- *
- * Note that the tty_clk and ppsclock modules are optional; if
- * configured and unavailable, the dang thing still works, but
- * the accuracy improvement using them will not be available.
- * The only known implmentations of these moldules are specific
- * to SunOS 4.x. Use the ppsclock module ONLY with Sun baseboard
- * ttya or ttyb. Using it with the SPIF multipexor crashes the
- * kernel.
- *
- * The preferred way to capture PPS timestamps is using the
- * ppsapi interface, which is machine independent. The SunOS 4.x
- * and Digital Unix 4.x interfaces use STREAMS modules and
- * support both the ppsapi specification and ppsclock
- * functionality, but other systems may vary widely.
- */
if (flags == 0)
return (1);
#if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS))
@@ -1061,104 +945,6 @@ refclock_ioctl(
}
}
#endif /* TTYCLK */
-
-#if defined(PPS) && !defined(HAVE_PPSAPI)
- /*
- * The PPS option provides timestamping at the driver level.
- * It uses a 1-pps signal and level converter (gadget box) and
- * requires the ppsclock streams module and System V STREAMS
- * support. This option has been superseded by the ppsapi
- * option and may be withdrawn in future.
- */
- if (flags & LDISC_PPS) {
- int rval = 0;
-#ifdef HAVE_TIOCSPPS /* Solaris */
- int one = 1;
-#endif /* HAVE_TIOCSPPS */
-
- if (fdpps > 0) {
- msyslog(LOG_ERR,
- "refclock_ioctl: PPS already configured");
- return (0);
- }
-#ifdef HAVE_TIOCSPPS /* Solaris */
- if (ioctl(fd, TIOCSPPS, &one) < 0) {
- msyslog(LOG_NOTICE,
- "refclock_ioctl: TIOCSPPS failed: %m");
- return (0);
- }
- if (debug)
- printf("refclock_ioctl: fd %d TIOCSPPS %d\n",
- fd, rval);
-#else
- if (ioctl(fd, I_PUSH, "ppsclock") < 0) {
- msyslog(LOG_NOTICE,
- "refclock_ioctl: I_PUSH ppsclock failed: %m");
- return (0);
- }
- if (debug)
- printf("refclock_ioctl: fd %d ppsclock %d\n",
- fd, rval);
-#endif /* not HAVE_TIOCSPPS */
- fdpps = fd;
- }
-#endif /* PPS HAVE_PPSAPI */
-
-#ifdef HAVE_PPSAPI
- /*
- * The PPSAPI option provides timestamping at the driver level.
- * It uses a 1-pps signal and level converter (gadget box) and
- * requires ppsapi compiled into the kernel on non STREAMS
- * systems. This is the preferred way to capture PPS timestamps
- * and is expected to become an IETF cross-platform standard.
- */
- if (flags & (LDISC_PPS | LDISC_CLKPPS)) {
- pps_params_t pp;
- int mode, temp;
- pps_handle_t handle;
-
- memset((char *)&pp, 0, sizeof(pp));
- if (fdpps > 0) {
- msyslog(LOG_ERR,
- "refclock_ioctl: ppsapi already configured");
- return (0);
- }
- if (time_pps_create(fd, &handle) < 0) {
- msyslog(LOG_ERR,
- "refclock_ioctl: time_pps_create failed: %m");
- return (0);
- }
- if (time_pps_getcap(handle, &mode) < 0) {
- msyslog(LOG_ERR,
- "refclock_ioctl: time_pps_getcap failed: %m");
- return (0);
- }
- pp.mode = mode & PPS_CAPTUREBOTH;
- if (time_pps_setparams(handle, &pp) < 0) {
- msyslog(LOG_ERR,
- "refclock_ioctl: time_pps_setparams failed: %m");
- return (0);
- }
- if (!pps_hardpps)
- temp = 0;
- else if (pps_assert)
- temp = mode & PPS_CAPTUREASSERT;
- else
- temp = mode & PPS_CAPTURECLEAR;
- if (time_pps_kcbind(handle, PPS_KC_HARDPPS, temp,
- PPS_TSFMT_TSPEC) < 0) {
- msyslog(LOG_ERR,
- "refclock_ioctl: time_pps_kcbind failed: %m");
- return (0);
- }
- (void)time_pps_getparams(handle, &pp);
- fdpps = (int)handle;
- if (debug)
- printf(
- "refclock_ioctl: fd %d ppsapi vers %d mode 0x%x cap 0x%x\n",
- fdpps, pp.api_version, pp.mode, mode);
- }
-#endif /* HAVE_PPSAPI */
#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
#endif /* SYS_VXWORKS SYS_WINNT */
return (1);
@@ -1196,6 +982,8 @@ refclock_control(
return;
if (!(peer = typeunit[clktype][unit]))
return;
+ if (peer->procptr == NULL)
+ return;
pp = peer->procptr;
/*
diff --git a/contrib/ntp/ntpd/ntp_request.c b/contrib/ntp/ntpd/ntp_request.c
index 3743118..6f5e153 100644
--- a/contrib/ntp/ntpd/ntp_request.c
+++ b/contrib/ntp/ntpd/ntp_request.c
@@ -2,14 +2,9 @@
* ntp_request.c - respond to information requests
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
-#include <sys/types.h>
-#include <stdio.h>
-#include <signal.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_request.h"
@@ -17,6 +12,12 @@
#include "ntp_refclock.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include "recvbuff.h"
#ifdef KERNEL_PLL
@@ -60,6 +61,7 @@ static void mem_stats P((struct sockaddr_in *, struct interface *, struct req_pk
static void io_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void timer_stats P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void loop_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
+static void dns_a P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void do_conf P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void do_unconf P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void set_sys_flag P((struct sockaddr_in *, struct interface *, struct req_pkt *));
@@ -77,7 +79,7 @@ static void reset_peer P((struct sockaddr_in *, struct interface *, struct req_p
static void do_key_reread P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void trust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void untrust_key P((struct sockaddr_in *, struct interface *, struct req_pkt *));
-static void do_trustkey P((struct sockaddr_in *, struct interface *, struct req_pkt *, int));
+static void do_trustkey P((struct sockaddr_in *, struct interface *, struct req_pkt *, u_long));
static void get_auth_info P((struct sockaddr_in *, struct interface *, struct req_pkt *));
static void reset_auth_stats P((void));
static void req_get_traps P((struct sockaddr_in *, struct interface *, struct req_pkt *));
@@ -112,6 +114,7 @@ static struct req_proc ntp_codes[] = {
{ REQ_MEM_STATS, NOAUTH, 0, mem_stats },
{ REQ_LOOP_INFO, NOAUTH, 0, loop_info },
{ REQ_TIMER_STATS, NOAUTH, 0, timer_stats },
+ { REQ_HOSTNAME_ASSOCID, AUTH, sizeof(struct info_dns_assoc), dns_a },
{ REQ_CONFIG, AUTH, sizeof(struct conf_peer), do_conf },
{ REQ_UNCONFIG, AUTH, sizeof(struct conf_unpeer), do_unconf },
{ REQ_SET_SYS_FLAG, AUTH, sizeof(struct conf_sys_flags), set_sys_flag },
@@ -150,7 +153,7 @@ static struct req_proc ntp_codes[] = {
* Authentication keyid used to authenticate requests. Zero means we
* don't allow writing anything.
*/
-u_long info_auth_keyid;
+keyid_t info_auth_keyid;
/*
* Statistic counters to keep track of requests and responses.
@@ -379,6 +382,7 @@ process_private(
struct sockaddr_in *srcadr;
struct interface *inter;
struct req_proc *proc;
+ int ec;
/*
* Initialize pointers, for convenience
@@ -389,7 +393,7 @@ process_private(
#ifdef DEBUG
if (debug > 2)
- printf("prepare_pkt: impl %d req %d\n",
+ printf("process_private: impl %d req %d\n",
inpkt->implementation, inpkt->request);
#endif
@@ -397,15 +401,18 @@ process_private(
* Do some sanity checks on the packet. Return a format
* error if it fails.
*/
- if (ISRESPONSE(inpkt->rm_vn_mode)
- || ISMORE(inpkt->rm_vn_mode)
- || INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION
- || INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION
- || INFO_SEQ(inpkt->auth_seq) != 0
- || INFO_ERR(inpkt->err_nitems) != 0
- || INFO_MBZ(inpkt->mbz_itemsize) != 0
- || rbufp->recv_length > REQ_LEN_MAC
- || rbufp->recv_length < REQ_LEN_NOMAC) {
+ ec = 0;
+ if ( (++ec, ISRESPONSE(inpkt->rm_vn_mode))
+ || (++ec, ISMORE(inpkt->rm_vn_mode))
+ || (++ec, INFO_VERSION(inpkt->rm_vn_mode) > NTP_VERSION)
+ || (++ec, INFO_VERSION(inpkt->rm_vn_mode) < NTP_OLDVERSION)
+ || (++ec, INFO_SEQ(inpkt->auth_seq) != 0)
+ || (++ec, INFO_ERR(inpkt->err_nitems) != 0)
+ || (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
+ || (++ec, rbufp->recv_length > REQ_LEN_MAC)
+ || (++ec, rbufp->recv_length < REQ_LEN_NOMAC)
+ ) {
+ msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d failed", ec);
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -424,7 +431,6 @@ process_private(
return;
}
-
/*
* Search the list for the request codes. If it isn't one
* we know, return an error.
@@ -478,6 +484,8 @@ process_private(
printf("bad pkt length %d\n",
rbufp->recv_length);
#endif
+ msyslog(LOG_ERR, "process_private: bad pkt length %d",
+ rbufp->recv_length);
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -520,16 +528,21 @@ process_private(
* don't, check to see that there is none (picky, picky).
*/
if (INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem) {
+ msyslog(LOG_ERR, "INFO_ITEMSIZE(inpkt->mbz_itemsize) != proc->sizeofitem: %d != %d",
+ INFO_ITEMSIZE(inpkt->mbz_itemsize), proc->sizeofitem);
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
if (proc->sizeofitem != 0)
if (proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems)
> sizeof(inpkt->data)) {
+ msyslog(LOG_ERR, "sizeofitem(%d)*NITEMS(%d) > data: %d > %ld",
+ proc->sizeofitem, INFO_NITEMS(inpkt->err_nitems),
+ proc->sizeofitem*INFO_NITEMS(inpkt->err_nitems),
+ (long)sizeof(inpkt->data));
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
-
#ifdef DEBUG
if (debug > 3)
printf("process_private: all okay, into handler\n");
@@ -610,14 +623,16 @@ peer_list_sum(
if (debug > 3)
printf("sum: got one\n");
#endif
- ips->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- pp->dstadr->bcast.sin_addr.s_addr:
- pp->cast_flags ?
- pp->dstadr->sin.sin_addr.s_addr ?
- pp->dstadr->sin.sin_addr.s_addr:
- pp->dstadr->bcast.sin_addr.s_addr:
- 1 : 5;
+ ips->dstadr =
+ (pp->processed)
+ ? pp->cast_flags == MDF_BCAST
+ ? pp->dstadr->bcast.sin_addr.s_addr
+ : pp->cast_flags
+ ? pp->dstadr->sin.sin_addr.s_addr
+ ? pp->dstadr->sin.sin_addr.s_addr
+ : pp->dstadr->bcast.sin_addr.s_addr
+ : 1
+ : 5;
ips->srcadr = pp->srcadr.sin_addr.s_addr;
ips->srcport = pp->srcadr.sin_port;
ips->stratum = pp->stratum;
@@ -686,14 +701,16 @@ peer_info (
ipl++;
if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
continue;
- ip->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- pp->dstadr->bcast.sin_addr.s_addr:
- pp->cast_flags ?
- pp->dstadr->sin.sin_addr.s_addr ?
- pp->dstadr->sin.sin_addr.s_addr:
- pp->dstadr->bcast.sin_addr.s_addr:
- 2 : 6;
+ ip->dstadr =
+ (pp->processed)
+ ? pp->cast_flags == MDF_BCAST
+ ? pp->dstadr->bcast.sin_addr.s_addr
+ : pp->cast_flags
+ ? pp->dstadr->sin.sin_addr.s_addr
+ ? pp->dstadr->sin.sin_addr.s_addr
+ : pp->dstadr->bcast.sin_addr.s_addr
+ : 2
+ : 6;
ip->srcadr = NSRCADR(&pp->srcadr);
ip->srcport = NSRCPORT(&pp->srcadr);
ip->flags = 0;
@@ -721,7 +738,6 @@ peer_info (
ip->hpoll = pp->hpoll;
ip->precision = pp->precision;
ip->version = pp->version;
- ip->valid = pp->valid;
ip->reach = pp->reach;
ip->unreach = pp->unreach;
ip->flash = (u_char)pp->flash;
@@ -752,7 +768,7 @@ peer_info (
HTONL_FP(&ltmp, &ip->offset);
ip->delay = HTONS_FP(DTOFP(pp->delay));
ip->dispersion = HTONS_FP(DTOUFP(SQRT(pp->disp)));
- ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->variance)));
+ ip->selectdisp = HTONS_FP(DTOUFP(SQRT(pp->jitter)));
ip = (struct info_peer *)more_pkt();
}
flush_pkt();
@@ -788,14 +804,16 @@ peer_stats (
ipl++;
if ((pp = findexistingpeer(&addr, (struct peer *)0, -1)) == 0)
continue;
- ip->dstadr = (pp->processed) ?
- pp->cast_flags == MDF_BCAST ?
- pp->dstadr->bcast.sin_addr.s_addr:
- pp->cast_flags ?
- pp->dstadr->sin.sin_addr.s_addr ?
- pp->dstadr->sin.sin_addr.s_addr:
- pp->dstadr->bcast.sin_addr.s_addr:
- 3 : 7;
+ ip->dstadr =
+ (pp->processed)
+ ? pp->cast_flags == MDF_BCAST
+ ? pp->dstadr->bcast.sin_addr.s_addr
+ : pp->cast_flags
+ ? pp->dstadr->sin.sin_addr.s_addr
+ ? pp->dstadr->sin.sin_addr.s_addr
+ : pp->dstadr->bcast.sin_addr.s_addr
+ : 3
+ : 7;
ip->srcadr = NSRCADR(&pp->srcadr);
ip->srcport = NSRCPORT(&pp->srcadr);
ip->flags = 0;
@@ -860,7 +878,7 @@ sys_info(
extern double sys_bdelay;
extern l_fp sys_authdelay;
extern double clock_stability;
- extern double sys_error;
+ extern double sys_jitter;
is = (struct info_sys *)prepare_pkt(srcadr, inter, inpkt,
sizeof(struct info_sys));
@@ -877,7 +895,7 @@ sys_info(
is->precision = sys_precision;
is->rootdelay = htonl(DTOFP(sys_rootdelay));
is->rootdispersion = htonl(DTOUFP(sys_rootdispersion));
- is->frequency = htonl(DTOFP(sys_error));
+ is->frequency = htonl(DTOFP(sys_jitter));
is->stability = htonl(DTOUFP(clock_stability * 1e6));
is->refid = sys_refid;
HTONL_FP(&sys_reftime, &is->reftime);
@@ -1114,10 +1132,10 @@ do_conf(
struct req_pkt *inpkt
)
{
+ u_int fl;
register struct conf_peer *cp;
register int items;
struct sockaddr_in peeraddr;
- int fl;
/*
* Do a check of everything to see that it looks
@@ -1136,13 +1154,15 @@ do_conf(
&& cp->hmode != MODE_CLIENT
&& cp->hmode != MODE_BROADCAST)
fl = 1;
- if (cp->flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER
- | CONF_FLAG_NOSELECT | CONF_FLAG_BURST | CONF_FLAG_SKEY))
+ if (cp->flags & ~(CONF_FLAG_AUTHENABLE | CONF_FLAG_PREFER |
+ CONF_FLAG_NOSELECT | CONF_FLAG_BURST | CONF_FLAG_IBURST |
+ CONF_FLAG_SKEY))
fl = 1;
cp++;
}
if (fl) {
+ msyslog(LOG_ERR, "do_conf: fl is nonzero!");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1164,6 +1184,11 @@ do_conf(
!ISREFCLOCKADR(&peeraddr) &&
#endif
ISBADADR(&peeraddr)) {
+#ifdef REFCLOCK
+ msyslog(LOG_ERR, "do_conf: !ISREFCLOCK && ISBADADR");
+#else
+ msyslog(LOG_ERR, "do_conf: ISBADADR");
+#endif
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1171,20 +1196,22 @@ do_conf(
while (items-- > 0) {
fl = 0;
if (cp->flags & CONF_FLAG_AUTHENABLE)
- fl |= FLAG_AUTHENABLE;
+ fl |= FLAG_AUTHENABLE;
if (cp->flags & CONF_FLAG_PREFER)
- fl |= FLAG_PREFER;
+ fl |= FLAG_PREFER;
if (cp->flags & CONF_FLAG_NOSELECT)
- fl |= FLAG_NOSELECT;
+ fl |= FLAG_NOSELECT;
if (cp->flags & CONF_FLAG_BURST)
- fl |= FLAG_BURST;
+ fl |= FLAG_BURST;
+ if (cp->flags & CONF_FLAG_IBURST)
+ fl |= FLAG_IBURST;
if (cp->flags & CONF_FLAG_SKEY)
fl |= FLAG_SKEY;
peeraddr.sin_addr.s_addr = cp->peeraddr;
/* XXX W2DO? minpoll/maxpoll arguments ??? */
- if (peer_config(&peeraddr, (struct interface *)0,
- cp->hmode, cp->version, cp->minpoll, cp->maxpoll,
- fl, cp->ttl, cp->keyid) == 0) {
+ if (peer_config(&peeraddr, any_interface, cp->hmode,
+ cp->version, cp->minpoll, cp->maxpoll, fl, cp->ttl,
+ cp->keyid, cp->keystr) == 0) {
req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
return;
}
@@ -1196,6 +1223,100 @@ do_conf(
/*
+ * dns_a - Snarf DNS info for an association ID
+ */
+static void
+dns_a(
+ struct sockaddr_in *srcadr,
+ struct interface *inter,
+ struct req_pkt *inpkt
+ )
+{
+ register struct info_dns_assoc *dp;
+ register int items;
+ struct sockaddr_in peeraddr;
+
+ /*
+ * Do a check of everything to see that it looks
+ * okay. If not, complain about it. Note we are
+ * very picky here.
+ */
+ items = INFO_NITEMS(inpkt->err_nitems);
+ dp = (struct info_dns_assoc *)inpkt->data;
+
+ /*
+ * Looks okay, try it out
+ */
+ items = INFO_NITEMS(inpkt->err_nitems);
+ dp = (struct info_dns_assoc *)inpkt->data;
+ memset((char *)&peeraddr, 0, sizeof(struct sockaddr_in));
+ peeraddr.sin_family = AF_INET;
+ peeraddr.sin_port = htons(NTP_PORT);
+
+ /*
+ * Make sure the address is valid
+ */
+ if (
+#ifdef REFCLOCK
+ !ISREFCLOCKADR(&peeraddr) &&
+#endif
+ ISBADADR(&peeraddr)) {
+#ifdef REFCLOCK
+ msyslog(LOG_ERR, "dns_a: !ISREFCLOCK && ISBADADR");
+#else
+ msyslog(LOG_ERR, "dns_a: ISBADADR");
+#endif
+ req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
+ return;
+ }
+
+ while (items-- > 0) {
+ associd_t associd;
+ size_t hnl;
+ struct peer *peer;
+ int bogon = 0;
+
+ associd = dp->associd;
+ peer = findpeerbyassoc(associd);
+ if (peer == 0 || peer->flags & FLAG_REFCLOCK) {
+ msyslog(LOG_ERR, "dns_a: %s",
+ (peer == 0)
+ ? "peer == 0"
+ : "peer->flags & FLAG_REFCLOCK");
+ ++bogon;
+ }
+ peeraddr.sin_addr.s_addr = dp->peeraddr;
+ for (hnl = 0; dp->hostname[hnl] && hnl < sizeof dp->hostname; ++hnl) ;
+ if (hnl >= sizeof dp->hostname) {
+ msyslog(LOG_ERR, "dns_a: hnl (%ld) >= %ld",
+ (long)hnl, (long)sizeof dp->hostname);
+ ++bogon;
+ }
+
+ msyslog(LOG_INFO, "dns_a: <%s> for %s, AssocID %d, bogon %d",
+ dp->hostname, inet_ntoa(peeraddr.sin_addr), associd,
+ bogon);
+
+ if (bogon) {
+ /* If it didn't work */
+ req_ack(srcadr, inter, inpkt, INFO_ERR_NODATA);
+ return;
+ } else {
+#if 0
+#ifdef PUBKEY
+ crypto_public(peer, dp->hostname);
+#endif /* PUBKEY */
+#endif
+ }
+
+ dp++;
+ }
+
+ req_ack(srcadr, inter, inpkt, INFO_OKAY);
+}
+
+
+/*
* do_unconf - remove a peer from the configuration list
*/
static void
@@ -1300,26 +1421,31 @@ setclr_flags(
u_long set
)
{
- register u_long flags;
+ register u_int flags;
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
+ msyslog(LOG_ERR, "setclr_flags: err_nitems > 1");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
flags = ((struct conf_sys_flags *)inpkt->data)->flags;
- if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_AUTHENTICATE |
+ if (flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
SYS_FLAG_NTP | SYS_FLAG_KERNEL | SYS_FLAG_MONITOR |
SYS_FLAG_FILEGEN)) {
+ msyslog(LOG_ERR, "setclr_flags: extra flags: %#x",
+ flags & ~(SYS_FLAG_BCLIENT | SYS_FLAG_PPS |
+ SYS_FLAG_NTP | SYS_FLAG_KERNEL |
+ SYS_FLAG_MONITOR | SYS_FLAG_FILEGEN));
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
if (flags & SYS_FLAG_BCLIENT)
proto_config(PROTO_BROADCLIENT, set, 0.);
- if (flags & SYS_FLAG_AUTHENTICATE)
- proto_config(PROTO_AUTHENTICATE, set, 0.);
+ if (flags & SYS_FLAG_PPS)
+ proto_config(PROTO_PPS, set, 0.);
if (flags & SYS_FLAG_NTP)
proto_config(PROTO_NTP, set, 0.);
if (flags & SYS_FLAG_KERNEL)
@@ -1440,15 +1566,16 @@ do_restrict(
bad = 0;
while (items-- > 0 && !bad) {
if (cr->mflags & ~(RESM_NTPONLY))
- bad = 1;
+ bad |= 1;
if (cr->flags & ~(RES_ALLFLAGS))
- bad = 1;
+ bad |= 2;
if (cr->addr == htonl(INADDR_ANY) && cr->mask != htonl(INADDR_ANY))
- bad = 1;
+ bad |= 4;
cr++;
}
if (bad) {
+ msyslog(LOG_ERR, "do_restrict: bad = %#x", bad);
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1606,6 +1733,7 @@ reset_stats(
struct reset_entry *rent;
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
+ msyslog(LOG_ERR, "reset_stats: err_nitems > 1");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1613,6 +1741,8 @@ reset_stats(
flags = ((struct reset_flags *)inpkt->data)->flags;
if (flags & ~RESET_ALLFLAGS) {
+ msyslog(LOG_ERR, "reset_stats: reset leaves %#lx",
+ flags & ~RESET_ALLFLAGS);
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1736,7 +1866,7 @@ do_trustkey(
struct sockaddr_in *srcadr,
struct interface *inter,
struct req_pkt *inpkt,
- int trust
+ u_long trust
)
{
register u_long *kp;
@@ -1928,6 +2058,7 @@ do_setclr_trap(
* the error reporting problem.
*/
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
+ msyslog(LOG_ERR, "do_setclr_trap: err_nitems > 1");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -1980,12 +2111,13 @@ set_request_keyid(
struct req_pkt *inpkt
)
{
- u_long keyid;
+ keyid_t keyid;
/*
* Restrict ourselves to one item only.
*/
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
+ msyslog(LOG_ERR, "set_request_keyid: err_nitems > 1");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -2007,13 +2139,14 @@ set_control_keyid(
struct req_pkt *inpkt
)
{
- u_long keyid;
- extern u_long ctl_auth_keyid;
+ keyid_t keyid;
+ extern keyid_t ctl_auth_keyid;
/*
* Restrict ourselves to one item only.
*/
if (INFO_NITEMS(inpkt->err_nitems) > 1) {
+ msyslog(LOG_ERR, "set_control_keyid: err_nitems > 1");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
@@ -2256,6 +2389,7 @@ set_clock_fudge(
(CLK_HAVEFLAG1|CLK_HAVEFLAG2|CLK_HAVEFLAG3|CLK_HAVEFLAG4);
break;
default:
+ msyslog(LOG_ERR, "set_clock_fudge: default!");
req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
return;
}
diff --git a/contrib/ntp/ntpd/ntp_resolver.c b/contrib/ntp/ntpd/ntp_resolver.c
new file mode 100644
index 0000000..84b2583
--- /dev/null
+++ b/contrib/ntp/ntpd/ntp_resolver.c
@@ -0,0 +1,987 @@
+/*
+** Ancestor was ripped off from ../ntpres/ntpres.c by Greg Troxel 4/2/92
+**
+** The previous resolver only needed to do forward lookups, and all names
+** were known before we started the resolver process.
+**
+** The new code must be able to handle reverse lookups, and the requests can
+** show up at any time.
+**
+** Here's the drill for the new logic.
+**
+** We want to be able to do forward or reverse lookups. Forward lookups
+** require one set of information to be sent back to the daemon, reverse
+** lookups require a different set of information. The caller knows this.
+**
+** The daemon must not block. This includes communicating with the resolver
+** process (if the resolver process is a separate task).
+**
+** Current resolver code blocks waiting for the response, so the
+** alternatives are:
+**
+** - Find a nonblocking resolver library
+** - Do each (initial) lookup in a separate process
+** - - subsequent lookups *could* be handled by a different process that has
+** a queue of pending requests
+**
+** We could use nonblocking lookups in a separate process (just to help out
+** with timers).
+**
+** If we don't have nonblocking resolver calls we have more opportunities
+** for denial-of-service problems.
+**
+** - too many fork()s
+** - communications path
+**
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_request.h"
+#include "ntp_stdlib.h"
+#include "ntp_syslog.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <signal.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
+
+/*
+ * Each item we are to resolve and configure gets one of these
+ * structures defined for it.
+ */
+struct dns_entry {
+ int de_done;
+#define DE_NAME 001
+#define DE_ADDR 002
+#define DE_NA (DE_NAME | DE_ADDR)
+#define DE_PENDING 000
+#define DE_GOT 010
+#define DE_FAIL 020
+#define DE_RESULT (DE_PENDING | DE_GOT | DE_FAIL)
+ struct dns_entry *de_next;
+ struct info_dns_assoc de_info; /* DNS info for peer */
+};
+#define de_associd de_info.associd
+#define de_peeraddr de_info.peeraddr
+#define de_hostname de_info.hostname
+
+/*
+ * dns_entries is a pointer to the list of configuration entries
+ * we have left to do.
+ */
+static struct dns_entry *dns_entries = NULL;
+
+/*
+ * We take an interrupt every thirty seconds, at which time we decrement
+ * config_timer and resolve_timer. The former is set to 2, so we retry
+ * unsucessful reconfigurations every minute. The latter is set to
+ * an exponentially increasing value which starts at 2 and increases to
+ * 32. When this expires we retry failed name resolutions.
+ *
+ * We sleep SLEEPTIME seconds before doing anything, to give the server
+ * time to arrange itself.
+ */
+#define MINRESOLVE 2
+#define MAXRESOLVE 32
+#define CONFIG_TIME 2
+#define ALARM_TIME 30
+
+#define SLEEPTIME 2
+
+static volatile int config_timer = 0;
+static volatile int resolve_timer = 0;
+
+static int resolve_value; /* next value of resolve timer */
+
+/*
+ * Big hack attack
+ */
+#define LOCALHOST 0x7f000001 /* 127.0.0.1, in hex, of course */
+#define SKEWTIME 0x08000000 /* 0.03125 seconds as a l_fp fraction */
+
+/*
+ * Select time out. Set to 2 seconds. The server is on the local machine,
+ * after all.
+ */
+#define TIMEOUT_SEC 2
+#define TIMEOUT_USEC 0
+
+/*
+ * File descriptor for ntp request code.
+ */
+static int sockfd = -1;
+
+/*
+ * Pipe descriptors
+ */
+int p_fd[2] = { -1, -1 };
+
+/* stuff to be filled in by caller */
+
+extern keyid_t req_keyid; /* request keyid */
+
+/* end stuff to be filled in */
+
+void ntp_res P((void));
+static RETSIGTYPE bong P((int));
+static void checkparent P((void));
+static void removeentry P((struct dns_entry *));
+static void addentry P((char *, u_int32, u_short));
+static void findhostaddr P((struct dns_entry *));
+static void openntp P((void));
+static int tell_ntpd P((struct info_dns_assoc *));
+static void doconfigure P((int));
+
+struct ntp_res_t_pkt { /* Tagged packet: */
+ void *tag; /* For the caller */
+ u_int32 paddr; /* IP to look up, or 0 */
+ char name[NTP_MAXHOSTNAME]; /* Name to look up (if 1st byte is not 0) */
+};
+
+struct ntp_res_c_pkt { /* Control packet: */
+ char name[NTP_MAXHOSTNAME];
+ u_int32 paddr;
+ int mode;
+ int version;
+ int minpoll;
+ int maxpoll;
+ int flags;
+ int ttl;
+ keyid_t keyid;
+ u_char keystr[MAXFILENAME];
+};
+
+/*
+ * ntp_res_name
+ */
+
+void
+ntp_res_name(
+ u_int32 paddr, /* Address to resolve */
+ u_short associd /* Association ID */
+ )
+{
+ pid_t pid;
+
+ /*
+ * fork.
+ * - parent returns
+ * - child stuffs data and calls ntp_res()
+ */
+
+ for (pid = -1; pid == -1;) {
+#ifdef RES_TEST
+ pid = 0;
+#else
+ pid = fork();
+#endif
+ if (pid == -1) {
+ msyslog(LOG_ERR, "ntp_res_name: fork() failed: %m");
+ sleep(2);
+ }
+ }
+ switch (pid) {
+ case -1: /* Error */
+ msyslog(LOG_INFO, "ntp_res_name: error...");
+ /* Can't happen */
+ break;
+
+ case 0: /* Child */
+ closelog();
+ kill_asyncio();
+ (void) signal_no_reset(SIGCHLD, SIG_DFL);
+#ifndef LOG_DAEMON
+ openlog("ntp_res", LOG_PID);
+# else /* LOG_DAEMON */
+# ifndef LOG_NTP
+# define LOG_NTP LOG_DAEMON
+# endif
+ openlog("ntp_res_name", LOG_PID | LOG_NDELAY, LOG_NTP);
+#endif
+
+ addentry(NULL, paddr, associd);
+ ntp_res();
+ break;
+
+ default: /* Parent */
+ /* Nothing to do. (In Real Life, this never happens.) */
+ return;
+ }
+}
+
+/*
+ * ntp_res needs;
+ *
+ * req_key(???), req_keyid valid
+ * syslog still open
+ */
+
+void
+ntp_res(void)
+{
+#ifdef HAVE_SIGSUSPEND
+ sigset_t set;
+
+ sigemptyset(&set);
+#endif /* HAVE_SIGSUSPEND */
+
+#ifdef DEBUG
+ if (debug) {
+ msyslog(LOG_INFO, "NTP_RESOLVER running");
+ }
+#endif
+
+ /* check out auth stuff */
+ if (sys_authenticate) {
+ if (!authistrusted(req_keyid)) {
+ msyslog(LOG_ERR, "invalid request keyid %08x",
+ req_keyid );
+ exit(1);
+ }
+ }
+
+ /*
+ * Make a first cut at resolving the bunch
+ */
+ doconfigure(1);
+ if (dns_entries == NULL) {
+ if (debug) {
+ msyslog(LOG_INFO, "NTP_RESOLVER done!");
+ }
+#if defined SYS_WINNT
+ ExitThread(0); /* Don't want to kill whole NT process */
+#else
+ exit(0); /* done that quick */
+#endif
+ }
+
+ /*
+ * Here we've got some problem children. Set up the timer
+ * and wait for it.
+ */
+ resolve_value = resolve_timer = MINRESOLVE;
+ config_timer = CONFIG_TIME;
+#ifndef SYS_WINNT
+ (void) signal_no_reset(SIGALRM, bong);
+ alarm(ALARM_TIME);
+#endif /* SYS_WINNT */
+
+ for (;;) {
+ if (dns_entries == NULL)
+ exit(0);
+
+ checkparent();
+
+ if (resolve_timer == 0) {
+ if (resolve_value < MAXRESOLVE)
+ resolve_value <<= 1;
+ resolve_timer = resolve_value;
+#ifdef DEBUG
+ msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
+#endif
+ config_timer = CONFIG_TIME;
+ doconfigure(1);
+ continue;
+ } else if (config_timer == 0) {
+ config_timer = CONFIG_TIME;
+#ifdef DEBUG
+ msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
+#endif
+ doconfigure(0);
+ continue;
+ }
+#ifndef SYS_WINNT
+ /*
+ * There is a race in here. Is okay, though, since
+ * all it does is delay things by 30 seconds.
+ */
+# ifdef HAVE_SIGSUSPEND
+ sigsuspend(&set);
+# else
+ sigpause(0);
+# endif /* HAVE_SIGSUSPEND */
+#else
+ if (config_timer > 0)
+ config_timer--;
+ if (resolve_timer > 0)
+ resolve_timer--;
+ sleep(ALARM_TIME);
+#endif /* SYS_WINNT */
+ }
+}
+
+
+#ifndef SYS_WINNT
+/*
+ * bong - service and reschedule an alarm() interrupt
+ */
+static RETSIGTYPE
+bong(
+ int sig
+ )
+{
+ if (config_timer > 0)
+ config_timer--;
+ if (resolve_timer > 0)
+ resolve_timer--;
+ alarm(ALARM_TIME);
+}
+#endif /* SYS_WINNT */
+
+/*
+ * checkparent - see if our parent process is still running
+ *
+ * No need to worry in the Windows NT environment whether the
+ * main thread is still running, because if it goes
+ * down it takes the whole process down with it (in
+ * which case we won't be running this thread either)
+ * Turn function into NOP;
+ */
+
+static void
+checkparent(void)
+{
+#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS)
+
+ /*
+ * If our parent (the server) has died we will have been
+ * inherited by init. If so, exit.
+ */
+ if (getppid() == 1) {
+ msyslog(LOG_INFO, "parent died before we finished, exiting");
+ exit(0);
+ }
+#endif /* SYS_WINNT && SYS_VXWORKS*/
+}
+
+
+/*
+ * removeentry - we are done with an entry, remove it from the list
+ */
+static void
+removeentry(
+ struct dns_entry *entry
+ )
+{
+ register struct dns_entry *de;
+
+ de = dns_entries;
+ if (de == entry) {
+ dns_entries = de->de_next;
+ return;
+ }
+
+ while (de != NULL) {
+ if (de->de_next == entry) {
+ de->de_next = entry->de_next;
+ return;
+ }
+ de = de->de_next;
+ }
+}
+
+
+/*
+ * addentry - add an entry to the configuration list
+ */
+static void
+addentry(
+ char *name,
+ u_int32 paddr,
+ u_short associd
+ )
+{
+ register struct dns_entry *de;
+
+#ifdef DEBUG
+ if (debug > 1) {
+ struct in_addr si;
+
+ si.s_addr = paddr;
+ msyslog(LOG_INFO,
+ "ntp_res_name: <%s> %s associd %d\n",
+ (name) ? name : "", inet_ntoa(si), associd);
+ }
+#endif
+
+ de = (struct dns_entry *)emalloc(sizeof(struct dns_entry));
+ if (name) {
+ strncpy(de->de_hostname, name, sizeof de->de_hostname);
+ de->de_done = DE_PENDING | DE_ADDR;
+ } else {
+ de->de_hostname[0] = 0;
+ de->de_done = DE_PENDING | DE_NAME;
+ }
+ de->de_peeraddr = paddr;
+ de->de_associd = associd;
+ de->de_next = NULL;
+
+ if (dns_entries == NULL) {
+ dns_entries = de;
+ } else {
+ register struct dns_entry *dep;
+
+ for (dep = dns_entries; dep->de_next != NULL;
+ dep = dep->de_next)
+ /* nothing */;
+ dep->de_next = de;
+ }
+}
+
+
+/*
+ * findhostaddr - resolve a host name into an address (Or vice-versa)
+ *
+ * sets entry->de_done appropriately when we're finished. We're finished if
+ * we either successfully look up the missing name or address, or if we get a
+ * "permanent" failure on the lookup.
+ *
+ */
+static void
+findhostaddr(
+ struct dns_entry *entry
+ )
+{
+ struct hostent *hp;
+
+ checkparent(); /* make sure our guy is still running */
+
+ /*
+ * The following should never trip - this subroutine isn't
+ * called if hostname and peeraddr are "filled".
+ */
+ if (entry->de_hostname[0] && entry->de_peeraddr) {
+ struct in_addr si;
+
+ si.s_addr = entry->de_peeraddr;
+ msyslog(LOG_ERR, "findhostaddr: both de_hostname and de_peeraddr are defined: <%s>/%s: state %#x",
+ &entry->de_hostname[0], inet_ntoa(si), entry->de_done);
+ return;
+ }
+
+ /*
+ * The following should never trip.
+ */
+ if (!entry->de_hostname[0] && !entry->de_peeraddr) {
+ msyslog(LOG_ERR, "findhostaddr: both de_hostname and de_peeraddr are undefined!");
+ entry->de_done |= DE_FAIL;
+ return;
+ }
+
+ if (entry->de_hostname[0]) {
+#ifdef DEBUG
+ if (debug > 2)
+ msyslog(LOG_INFO, "findhostaddr: Resolving <%s>",
+ &entry->de_hostname[0]);
+#endif /* DEBUG */
+ hp = gethostbyname(&entry->de_hostname[0]);
+ } else {
+#ifdef DEBUG
+ if (debug > 2) {
+ struct in_addr si;
+
+ si.s_addr = entry->de_peeraddr;
+ msyslog(LOG_INFO, "findhostaddr: Resolving %s",
+ inet_ntoa(si));
+ }
+#endif
+ hp = gethostbyaddr((const char *)&entry->de_peeraddr,
+ sizeof entry->de_peeraddr,
+ AF_INET);
+ }
+
+ if (hp == NULL) {
+ /*
+ * Bail if we should TRY_AGAIN.
+ * Otherwise, we have a permanent failure.
+ */
+ if (h_errno == TRY_AGAIN)
+ return;
+ entry->de_done |= DE_FAIL;
+ } else {
+ entry->de_done |= DE_GOT;
+ }
+
+ if (entry->de_done & DE_GOT) {
+ switch (entry->de_done & DE_NA) {
+ case DE_NAME:
+#ifdef DEBUG
+ if (debug > 2)
+ msyslog(LOG_INFO,
+ "findhostaddr: name resolved.");
+#endif
+ /*
+ * Use the first address. We don't have any way to
+ * tell preferences and older gethostbyname()
+ * implementations only return one.
+ */
+ memmove((char *)&(entry->de_peeraddr),
+ (char *)hp->h_addr,
+ sizeof(struct in_addr));
+ break;
+ case DE_ADDR:
+#ifdef DEBUG
+ if (debug > 2)
+ msyslog(LOG_INFO,
+ "findhostaddr: address resolved.");
+#endif
+ strncpy(&entry->de_hostname[0], hp->h_name,
+ sizeof entry->de_hostname);
+ break;
+ default:
+ msyslog(LOG_ERR, "findhostaddr: Bogus de_done: %#x",
+ entry->de_done);
+ break;
+ }
+ } else {
+#ifdef DEBUG
+ if (debug > 2) {
+ struct in_addr si;
+ const char *hes;
+#ifndef HAVE_HSTRERROR
+ char hnum[20];
+
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+ hes = "Authoritive Answer Host not found";
+ break;
+ case TRY_AGAIN:
+ hes = "Non-Authoritative Host not found, or SERVERFAIL";
+ break;
+ case NO_RECOVERY:
+ hes = "Non recoverable errors, FORMERR, REFUSED, NOTIMP";
+ break;
+ case NO_DATA:
+ hes = "Valid name, no data record of requested type";
+ break;
+ default:
+ snprintf(hnum, sizeof hnum, "%d", h_errno);
+ hes = hnum;
+ break;
+ }
+#else
+ hes = hstrerror(h_errno);
+#endif
+
+ si.s_addr = entry->de_peeraddr;
+ msyslog(LOG_INFO,
+ "findhostaddr: Failed resolution on <%s>/%s: %s",
+ entry->de_hostname, inet_ntoa(si), hes);
+ }
+#endif
+ /* Send a NAK message back to the daemon */
+ }
+ return;
+}
+
+
+/*
+ * openntp - open a socket to the ntp server
+ */
+static void
+openntp(void)
+{
+ struct sockaddr_in saddr;
+
+ if (sockfd >= 0)
+ return;
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd == -1) {
+ msyslog(LOG_ERR, "socket() failed: %m");
+ exit(1);
+ }
+
+ memset((char *)&saddr, 0, sizeof(saddr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = htons(NTP_PORT); /* trash */
+ saddr.sin_addr.s_addr = htonl(LOCALHOST); /* garbage */
+
+ /*
+ * Make the socket non-blocking. We'll wait with select()
+ */
+#ifndef SYS_WINNT
+# if defined(O_NONBLOCK)
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
+ msyslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");
+ exit(1);
+ }
+# else
+# if defined(FNDELAY)
+ if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
+ msyslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
+ exit(1);
+ }
+# else
+# include "Bletch: NEED NON BLOCKING IO"
+# endif /* FNDDELAY */
+# endif /* O_NONBLOCK */
+#else /* SYS_WINNT */
+ {
+ int on = 1;
+
+ if (ioctlsocket(sockfd,FIONBIO,(u_long *) &on) == SOCKET_ERROR) {
+ msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
+ exit(1); /* Windows NT - set socket in non-blocking mode */
+ }
+ }
+#endif /* SYS_WINNT */
+
+ if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
+ msyslog(LOG_ERR, "openntp: connect() failed: %m");
+ exit(1);
+ }
+}
+
+
+/*
+ * tell_ntpd: Tell ntpd what we discovered.
+ */
+static int
+tell_ntpd(
+ struct info_dns_assoc *conf
+ )
+{
+ fd_set fdset;
+ struct timeval tvout;
+ struct req_pkt reqpkt;
+ l_fp ts;
+ int n;
+#ifdef SYS_WINNT
+ HANDLE hReadWriteEvent = NULL;
+ BOOL ret;
+ DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait;
+ OVERLAPPED overlap;
+#endif /* SYS_WINNT */
+
+ checkparent(); /* make sure our guy is still running */
+
+ if (sockfd < 0)
+ openntp();
+
+#ifdef SYS_WINNT
+ hReadWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+#endif /* SYS_WINNT */
+
+ /*
+ * Try to clear out any previously received traffic so it
+ * doesn't fool us. Note the socket is nonblocking.
+ */
+ tvout.tv_sec = 0;
+ tvout.tv_usec = 0;
+ FD_ZERO(&fdset);
+ FD_SET(sockfd, &fdset);
+ while (select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout) >
+ 0) {
+ recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);
+ FD_ZERO(&fdset);
+ FD_SET(sockfd, &fdset);
+ }
+
+ /*
+ * Make up a request packet with the configuration info
+ */
+ memset((char *)&reqpkt, 0, sizeof(reqpkt));
+
+ reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
+ reqpkt.auth_seq = AUTH_SEQ(1, 0); /* authenticated, no seq */
+ reqpkt.implementation = IMPL_XNTPD; /* local implementation */
+ reqpkt.request = REQ_HOSTNAME_ASSOCID; /* Hostname for associd */
+ reqpkt.err_nitems = ERR_NITEMS(0, 1); /* one item */
+ reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct info_dns_assoc));
+ memmove(reqpkt.data, (char *)conf, sizeof(struct info_dns_assoc));
+ reqpkt.keyid = htonl(req_keyid);
+
+ get_systime(&ts);
+ L_ADDUF(&ts, SKEWTIME);
+ HTONL_FP(&ts, &reqpkt.tstamp);
+ n = 0;
+ if (sys_authenticate)
+ n = authencrypt(req_keyid, (u_int32 *)&reqpkt, REQ_LEN_NOMAC);
+
+ /*
+ * Done. Send it.
+ */
+#ifndef SYS_WINNT
+ n = send(sockfd, (char *)&reqpkt, (unsigned)(REQ_LEN_NOMAC + n), 0);
+ if (n < 0) {
+ msyslog(LOG_ERR, "send to NTP server failed: %m");
+ return 0; /* maybe should exit */
+ }
+#else
+ /* In the NT world, documentation seems to indicate that there
+ * exist _write and _read routines that can be used to do blocking
+ * I/O on sockets. Problem is these routines require a socket
+ * handle obtained through the _open_osf_handle C run-time API
+ * of which there is no explanation in the documentation. We need
+ * nonblocking write's and read's anyway for our purpose here.
+ * We're therefore forced to deviate a little bit from the Unix
+ * model here and use the ReadFile and WriteFile Win32 I/O API's
+ * on the socket
+ */
+ overlap.Offset = overlap.OffsetHigh = (DWORD)0;
+ overlap.hEvent = hReadWriteEvent;
+ ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n,
+ (LPDWORD)&NumberOfBytesWritten, (LPOVERLAPPED)&overlap);
+ if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
+ msyslog(LOG_ERR, "send to NTP server failed: %m");
+ return 0;
+ }
+ dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
+ if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
+ if (dwWait == WAIT_FAILED)
+ msyslog(LOG_ERR, "WaitForSingleObject failed: %m");
+ return 0;
+ }
+#endif /* SYS_WINNT */
+
+
+ /*
+ * Wait for a response. A weakness of the mode 7 protocol used
+ * is that there is no way to associate a response with a
+ * particular request, i.e. the response to this configuration
+ * request is indistinguishable from that to any other. I should
+ * fix this some day. In any event, the time out is fairly
+ * pessimistic to make sure that if an answer is coming back
+ * at all, we get it.
+ */
+ for (;;) {
+ FD_ZERO(&fdset);
+ FD_SET(sockfd, &fdset);
+ tvout.tv_sec = TIMEOUT_SEC;
+ tvout.tv_usec = TIMEOUT_USEC;
+
+ n = select(sockfd + 1, &fdset, (fd_set *)0,
+ (fd_set *)0, &tvout);
+
+ if (n < 0)
+ {
+ msyslog(LOG_ERR, "select() fails: %m");
+ return 0;
+ }
+ else if (n == 0)
+ {
+ if(debug)
+ msyslog(LOG_INFO, "select() returned 0.");
+ return 0;
+ }
+
+#ifndef SYS_WINNT
+ n = recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0);
+ if (n <= 0) {
+ if (n < 0) {
+ msyslog(LOG_ERR, "recv() fails: %m");
+ return 0;
+ }
+ continue;
+ }
+#else /* Overlapped I/O used on non-blocking sockets on Windows NT */
+ ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, (DWORD)REQ_LEN_MAC,
+ (LPDWORD)&NumberOfBytesRead, (LPOVERLAPPED)&overlap);
+ if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
+ msyslog(LOG_ERR, "ReadFile() fails: %m");
+ return 0;
+ }
+ dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
+ if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
+ if (dwWait == WAIT_FAILED) {
+ msyslog(LOG_ERR, "WaitForSingleObject fails: %m");
+ return 0;
+ }
+ continue;
+ }
+ n = NumberOfBytesRead;
+#endif /* SYS_WINNT */
+
+ /*
+ * Got one. Check through to make sure it is what
+ * we expect.
+ */
+ if (n < RESP_HEADER_SIZE) {
+ msyslog(LOG_ERR, "received runt response (%d octets)",
+ n);
+ continue;
+ }
+
+ if (!ISRESPONSE(reqpkt.rm_vn_mode)) {
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO, "received non-response packet");
+#endif
+ continue;
+ }
+
+ if (ISMORE(reqpkt.rm_vn_mode)) {
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO, "received fragmented packet");
+#endif
+ continue;
+ }
+
+ if ( ( (INFO_VERSION(reqpkt.rm_vn_mode) < 2)
+ || (INFO_VERSION(reqpkt.rm_vn_mode) > NTP_VERSION))
+ || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO,
+ "version (%d/%d) or mode (%d/%d) incorrect",
+ INFO_VERSION(reqpkt.rm_vn_mode),
+ NTP_VERSION,
+ INFO_MODE(reqpkt.rm_vn_mode),
+ MODE_PRIVATE);
+#endif
+ continue;
+ }
+
+ if (INFO_SEQ(reqpkt.auth_seq) != 0) {
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO,
+ "nonzero sequence number (%d)",
+ INFO_SEQ(reqpkt.auth_seq));
+#endif
+ continue;
+ }
+
+ if (reqpkt.implementation != IMPL_XNTPD ||
+ reqpkt.request != REQ_HOSTNAME_ASSOCID) {
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO,
+ "implementation (%d/%d) or request (%d/%d) incorrect",
+ reqpkt.implementation, IMPL_XNTPD,
+ reqpkt.request, REQ_HOSTNAME_ASSOCID);
+#endif
+ continue;
+ }
+
+ if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||
+ INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||
+ INFO_ITEMSIZE(reqpkt.mbz_itemsize) != 0) {
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_INFO,
+ "nitems (%d) mbz (%d) or itemsize (%d) nonzero",
+ INFO_NITEMS(reqpkt.err_nitems),
+ INFO_MBZ(reqpkt.mbz_itemsize),
+ INFO_ITEMSIZE(reqpkt.mbz_itemsize));
+#endif
+ continue;
+ }
+
+ n = INFO_ERR(reqpkt.err_nitems);
+ switch (n) {
+ case INFO_OKAY:
+ /* success */
+ return 1;
+
+ case INFO_ERR_IMPL:
+ msyslog(LOG_ERR,
+ "server reports implementation mismatch!!");
+ return 0;
+
+ case INFO_ERR_REQ:
+ msyslog(LOG_ERR,
+ "server claims configuration request is unknown");
+ return 0;
+
+ case INFO_ERR_FMT:
+ msyslog(LOG_ERR,
+ "server indicates a format error occurred(!!)");
+ return 0;
+
+ case INFO_ERR_NODATA:
+ msyslog(LOG_ERR,
+ "server indicates no data available (shouldn't happen)");
+ return 0;
+
+ case INFO_ERR_AUTH:
+ msyslog(LOG_ERR,
+ "server returns a permission denied error");
+ return 0;
+
+ default:
+ msyslog(LOG_ERR,
+ "server returns unknown error code %d", n);
+ return 0;
+ }
+ }
+}
+
+
+/*
+ * doconfigure - attempt to resolve names/addresses
+ */
+static void
+doconfigure(
+ int dores
+ )
+{
+ register struct dns_entry *de;
+ register struct dns_entry *deremove;
+ char *done_msg = "";
+
+ de = dns_entries;
+ while (de != NULL) {
+#ifdef DEBUG
+ if (debug > 1) {
+ struct in_addr si;
+
+ si.s_addr = de->de_peeraddr;
+ msyslog(LOG_INFO,
+ "doconfigure: name: <%s> peeraddr: %s",
+ de->de_hostname, inet_ntoa(si));
+ }
+#endif
+ if (dores && (de->de_hostname[0] == 0 || de->de_peeraddr == 0)) {
+ findhostaddr(de);
+ }
+
+ switch (de->de_done & DE_RESULT) {
+ case DE_PENDING:
+ done_msg = "";
+ break;
+ case DE_GOT:
+ done_msg = "succeeded";
+ break;
+ case DE_FAIL:
+ done_msg = "failed";
+ break;
+ default:
+ done_msg = "(error - shouldn't happen)";
+ break;
+ }
+ if (done_msg[0]) {
+ /* Send the answer */
+ if (tell_ntpd(&de->de_info)) {
+ struct in_addr si;
+
+ si.s_addr = de->de_peeraddr;
+#ifdef DEBUG
+ if (debug > 1) {
+ msyslog(LOG_INFO,
+ "DNS resolution on <%s>/%s %s",
+ de->de_hostname, inet_ntoa(si),
+ done_msg);
+ }
+#endif
+ deremove = de;
+ de = deremove->de_next;
+ removeentry(deremove);
+ }
+ } else {
+ de = de->de_next;
+ }
+ }
+}
diff --git a/contrib/ntp/ntpd/ntp_timer.c b/contrib/ntp/ntpd/ntp_timer.c
index 0e2dc88..71a84e2 100644
--- a/contrib/ntp/ntpd/ntp_timer.c
+++ b/contrib/ntp/ntpd/ntp_timer.c
@@ -5,20 +5,26 @@
# include <config.h>
#endif
+#include "ntp_machine.h"
+#include "ntpd.h"
+#include "ntp_stdlib.h"
+
#include <stdio.h>
-#include <sys/types.h>
-#include <sys/time.h>
#include <signal.h>
#include <sys/signal.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_stdlib.h"
#if defined(HAVE_IO_COMPLETION_PORT)
# include "ntp_iocompletionport.h"
# include "ntp_timer.h"
#endif
+#ifdef PUBKEY
+#include "ntp_crypto.h"
+#endif /* PUBKEY */
+
/*
* These routines provide support for the event timer. The timer is
* implemented by an interrupt routine which sets a flag once every
@@ -41,8 +47,11 @@ 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 huffpuff_timer; /* huff-n'-puff timer */
+#ifdef AUTOKEY
static u_long revoke_timer; /* keys revoke timer */
-u_long sys_revoke = KEY_REVOKE; /* keys revoke timeout */
+u_long sys_revoke = 1 << KEY_REVOKE; /* keys revoke timeout */
+#endif /* AUTOKEY */
/*
* Statistics counter for the interested.
@@ -101,6 +110,7 @@ init_timer(void)
alarm_overflow = 0;
adjust_timer = 1;
hourly_timer = HOUR;
+ huffpuff_timer = 0;
current_time = 0;
timer_overflows = 0;
timer_xmtcalls = 0;
@@ -206,7 +216,7 @@ void
timer(void)
{
register struct peer *peer, *next_peer;
- int n;
+ u_int n;
current_time += (1<<EVENT_TIMEOUT);
@@ -250,12 +260,27 @@ timer(void)
}
/*
- * Garbage collect revoked keys
+ * Huff-n'-puff filter
+ */
+ if (huffpuff_timer <= current_time) {
+ huffpuff_timer += HUFFPUFF;
+ huffpuff();
+ }
+
+#ifdef AUTOKEY
+ /*
+ * Garbage collect old keys and generate new private value
*/
if (revoke_timer <= current_time) {
- revoke_timer += RANDPOLL(sys_revoke);
- key_expire_all();
+ revoke_timer += sys_revoke;
+ expire_all();
+#ifdef DEBUG
+ if (debug)
+ printf("key expire: at %lu next %lu\n",
+ current_time, revoke_timer);
+#endif
}
+#endif /* AUTOKEY */
/*
* Finally, call the hourly routine.
diff --git a/contrib/ntp/ntpd/ntp_util.c b/contrib/ntp/ntpd/ntp_util.c
index c53255a..f86e930 100644
--- a/contrib/ntp/ntpd/ntp_util.c
+++ b/contrib/ntp/ntpd/ntp_util.c
@@ -1,18 +1,11 @@
/*
* ntp_util.c - stuff I didn't have any other place for
*/
+
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-# endif
-# include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
@@ -20,6 +13,20 @@
#include "ntp_if.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h>
+#endif
+#ifdef HAVE_MATH_H
+# include <math.h>
+#endif
+
#ifdef DOSYNCTODR
#if !defined(VMS)
#include <sys/resource.h>
@@ -218,7 +225,8 @@ hourly_stats(void)
NLOG(NLOG_SYSSTATIST)
msyslog(LOG_INFO,
"offset %.6f sec freq %.3f ppm error %.6f poll %d",
- last_offset, drift_comp * 1e6, sys_error, sys_poll);
+ last_offset, drift_comp * 1e6, sys_jitter, sys_poll);
+
if (stats_drift_file != 0) {
if ((fp = fopen(stats_temp_file, "w")) == NULL) {
@@ -341,12 +349,27 @@ stats_config(
break;
}
if (fscanf(fp, "%lf", &old_drift) != 1) {
- msyslog(LOG_ERR, "invalid frequency from %s",
+ msyslog(LOG_ERR, "Un-parsable frequency in %s",
stats_drift_file);
(void) fclose(fp);
break;
}
(void) fclose(fp);
+ if (
+#ifdef HAVE_FINITE
+ !finite(old_drift)
+#else /* not HAVE_FINITE */
+# ifdef HAVE_ISFINITE
+ !isfinite(old_drift)
+# else /* not HAVE_ISFINITE */
+ 0
+# endif /* not HAVE_ISFINITE */
+#endif /* not HAVE_FINITE */
+ || (fabs(old_drift) > (NTP_MAXFREQ * 1e6))) {
+ msyslog(LOG_ERR, "invalid frequency (%f) in %s",
+ old_drift, stats_drift_file);
+ old_drift = 0.0;
+ }
msyslog(LOG_INFO, "frequency initialized %.3f from %s",
old_drift, stats_drift_file);
loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
@@ -466,7 +489,13 @@ record_peer_stats(
* time constant (log base 2)
*/
void
-record_loop_stats(void)
+record_loop_stats(
+ double offset,
+ double freq,
+ double jitter,
+ double stability,
+ int poll
+ )
{
struct timeval tv;
#ifdef HAVE_GETCLOCK
@@ -490,8 +519,8 @@ record_loop_stats(void)
filegen_setup(&loopstats, (u_long)(tv.tv_sec + JAN_1970));
if (loopstats.fp != NULL) {
fprintf(loopstats.fp, "%lu %lu.%03lu %.9f %.6f %.9f %.6f %d\n",
- day, sec, msec, last_offset, drift_comp * 1e6,
- sys_error, clock_stability * 1e6, sys_poll);
+ day, sec, msec, offset, freq * 1e6, jitter,
+ stability * 1e6, poll);
fflush(loopstats.fp);
}
}
diff --git a/contrib/ntp/ntpd/ntpd.c b/contrib/ntp/ntpd/ntpd.c
index 3dbef60..aab9881 100644
--- a/contrib/ntp/ntpd/ntpd.c
+++ b/contrib/ntp/ntpd/ntpd.c
@@ -1,11 +1,15 @@
/*
* ntpd.c - main program for the fixed point NTP daemon
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include <sys/types.h>
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_stdlib.h"
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -21,7 +25,6 @@
# ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
# endif /* HAVE_SYS_IOCTL_H */
-# include <sys/time.h>
# ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
# endif /* HAVE_SYS_RESOURCE_H */
@@ -68,11 +71,8 @@
# include <apollo/base.h>
#endif /* SYS_DOMAINOS */
-#include "ntpd.h"
-#include "ntp_io.h"
-
-#include "ntp_stdlib.h"
#include "recvbuff.h"
+#include "ntp_cmdargs.h"
#if 0 /* HMS: I don't think we need this. 961223 */
#ifdef LOCK_PROCESS
@@ -85,13 +85,17 @@
#endif
#ifdef _AIX
-#include <ulimit.h>
+# include <ulimit.h>
#endif /* _AIX */
#ifdef SCO5_CLOCK
-#include <sys/ci/ciioctl.h>
+# include <sys/ci/ciioctl.h>
#endif
+#ifdef PUBKEY
+#include "ntp_crypto.h"
+#endif /* PUBKEY */
+
/*
* Signals we catch for debugging. If not debugging we ignore them.
*/
@@ -102,10 +106,10 @@
* Signals which terminate us gracefully.
*/
#ifndef SYS_WINNT
-#define SIGDIE1 SIGHUP
-#define SIGDIE3 SIGQUIT
-#define SIGDIE2 SIGINT
-#define SIGDIE4 SIGTERM
+# define SIGDIE1 SIGHUP
+# define SIGDIE3 SIGQUIT
+# define SIGDIE2 SIGINT
+# define SIGDIE4 SIGTERM
#endif /* SYS_WINNT */
#if defined SYS_WINNT
@@ -122,7 +126,12 @@ static BOOL WINAPI OnConsoleEvent(DWORD dwCtrlType);
/*
* Scheduling priority we run at
*/
-# define NTPD_PRIO (-12)
+#define NTPD_PRIO (-12)
+
+int priority_done = 2; /* 0 - Set priority */
+ /* 1 - priority is OK where it is */
+ /* 2 - Don't set priority */
+ /* 1 and 2 are pretty much the same */
/*
* Debugging flag
@@ -223,39 +232,23 @@ catch_danger(int signo)
static void
set_process_priority(void)
{
- int done = 0;
-
-#ifdef SYS_WINNT
- DWORD SingleCPUMask = 0;
- DWORD ProcessAffinityMask, SystemAffinityMask;
- if (!GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask, &SystemAffinityMask))
- msyslog(LOG_ERR, "GetProcessAffinityMask: %m");
- else {
- SingleCPUMask = 1;
-# ifdef DEBUG
- msyslog(LOG_INFO, "System AffinityMask = %x", SystemAffinityMask );
-# endif
- }
- while (SingleCPUMask && !(SingleCPUMask & SystemAffinityMask)) {
- SingleCPUMask = SingleCPUMask << 1;
- }
- if (!SingleCPUMask)
- msyslog(LOG_ERR, "Can't set Processor Affinity Mask");
- else if (!SetProcessAffinityMask(GetCurrentProcess(), SingleCPUMask))
- msyslog(LOG_ERR, "SetProcessAffinityMask: %m");
-# ifdef DEBUG
- else msyslog(LOG_INFO,"ProcessorAffinity Mask: %x", SingleCPUMask );
-# endif
+#ifdef DEBUG
+ if (debug > 1)
+ msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>",
+ ((priority_done)
+ ? "Leave priority alone"
+ : "Attempt to set priority"
+ ),
+ priority_done);
+#endif /* DEBUG */
- if (!SetPriorityClass(GetCurrentProcess(), (DWORD) REALTIME_PRIORITY_CLASS))
- msyslog(LOG_ERR, "SetPriorityClass: %m");
- else
- ++done;
+#ifdef SYS_WINNT
+ priority_done += NT_set_process_priority();
#endif
-# if defined(HAVE_SCHED_SETSCHEDULER)
- if (!done) {
+#if defined(HAVE_SCHED_SETSCHEDULER)
+ if (!priority_done) {
extern int config_priority_override, config_priority;
int pmax, pmin;
struct sched_param sched;
@@ -274,12 +267,12 @@ set_process_priority(void)
if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 )
msyslog(LOG_ERR, "sched_setscheduler(): %m");
else
- ++done;
+ ++priority_done;
}
-# endif /* HAVE_SCHED_SETSCHEDULER */
-# if defined(HAVE_RTPRIO)
-# ifdef RTP_SET
- if (!done) {
+#endif /* HAVE_SCHED_SETSCHEDULER */
+#if defined(HAVE_RTPRIO)
+# ifdef RTP_SET
+ if (!priority_done) {
struct rtprio srtp;
srtp.type = RTP_PRIO_REALTIME; /* was: RTP_PRIO_NORMAL */
@@ -288,37 +281,37 @@ set_process_priority(void)
if (rtprio(RTP_SET, getpid(), &srtp) < 0)
msyslog(LOG_ERR, "rtprio() error: %m");
else
- ++done;
+ ++priority_done;
}
-# else /* not RTP_SET */
- if (!done) {
+# else /* not RTP_SET */
+ if (!priority_done) {
if (rtprio(0, 120) < 0)
msyslog(LOG_ERR, "rtprio() error: %m");
else
- ++done;
+ ++priority_done;
}
-# endif /* not RTP_SET */
-# endif /* HAVE_RTPRIO */
-# if defined(NTPD_PRIO) && NTPD_PRIO != 0
-# ifdef HAVE_ATT_NICE
- if (!done) {
+# endif /* not RTP_SET */
+#endif /* HAVE_RTPRIO */
+#if defined(NTPD_PRIO) && NTPD_PRIO != 0
+# ifdef HAVE_ATT_NICE
+ if (!priority_done) {
errno = 0;
if (-1 == nice (NTPD_PRIO) && errno != 0)
msyslog(LOG_ERR, "nice() error: %m");
else
- ++done;
+ ++priority_done;
}
-# endif /* HAVE_ATT_NICE */
-# ifdef HAVE_BSD_NICE
- if (!done) {
+# endif /* HAVE_ATT_NICE */
+# ifdef HAVE_BSD_NICE
+ if (!priority_done) {
if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO))
msyslog(LOG_ERR, "setpriority() error: %m");
else
- ++done;
+ ++priority_done;
}
-# endif /* HAVE_BSD_NICE */
-# endif /* NTPD_PRIO && NTPD_PRIO != 0 */
- if (!done)
+# endif /* HAVE_BSD_NICE */
+#endif /* NTPD_PRIO && NTPD_PRIO != 0 */
+ if (!priority_done)
msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority");
}
@@ -335,6 +328,10 @@ ntpdmain(
{
l_fp now;
char *cp;
+#ifdef AUTOKEY
+ u_int n;
+ char hostname[MAXFILENAME];
+#endif /* AUTOKEY */
struct recvbuf *rbuflist;
struct recvbuf *rbuf;
#ifdef _AIX /* HMS: ifdef SIGDANGER? */
@@ -347,7 +344,7 @@ ntpdmain(
#ifdef HAVE_UMASK
{
- unsigned int uv;
+ mode_t uv;
uv = umask(0);
if(uv)
@@ -378,10 +375,13 @@ ntpdmain(
}
addSourceToRegistry("NTP", szMsgPath);
#endif
+ getstartup(argc, argv); /* startup configuration, may set debug */
+ /*
+ * Initialize random generator and public key pair
+ */
get_systime(&now);
SRANDOM((int)(now.l_i * now.l_uf));
- getstartup(argc, argv); /* startup configuration, may set debug */
#if !defined(VMS)
# ifndef NODETACH
@@ -395,9 +395,9 @@ ntpdmain(
# endif /* DEBUG */
{
# ifndef SYS_WINNT
-# ifdef HAVE_DAEMON
+# ifdef HAVE_DAEMON
daemon(0, 0);
-# else /* not HAVE_DAEMON */
+# else /* not HAVE_DAEMON */
if (fork()) /* HMS: What about a -1? */
exit(0);
@@ -417,11 +417,11 @@ ntpdmain(
msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
#else /* not F_CLOSEM */
-#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
max_fd = sysconf(_SC_OPEN_MAX);
-#else /* HAVE_SYSCONF && _SC_OPEN_MAX */
+# else /* HAVE_SYSCONF && _SC_OPEN_MAX */
max_fd = getdtablesize();
-#endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
+# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
for (s = 0; s < max_fd; s++)
(void) close((int)s);
#endif /* not F_CLOSEM */
@@ -473,8 +473,8 @@ ntpdmain(
(void) sigaction(SIGDANGER, &sa, NULL);
#endif /* _AIX */
}
-#endif /* not HAVE_DAEMON */
-#else /* SYS_WINNT */
+# endif /* not HAVE_DAEMON */
+# else /* SYS_WINNT */
{
SERVICE_TABLE_ENTRY dispatchTable[] = {
@@ -489,10 +489,10 @@ ntpdmain(
ExitProcess(2);
}
}
-#endif /* SYS_WINNT */
+# endif /* SYS_WINNT */
}
-#endif /* NODETACH */
-#if defined(SYS_WINNT) && !defined(NODETACH)
+# endif /* NODETACH */
+# if defined(SYS_WINNT) && !defined(NODETACH)
else
service_main(argc, argv);
return 0; /* must return a value */
@@ -513,7 +513,10 @@ service_main(
char *cp;
struct recvbuf *rbuflist;
struct recvbuf *rbuf;
-
+#ifdef AUTOKEY
+ u_int n;
+ char hostname[MAXFILENAME];
+#endif /* AUTOKEY */
if(!debug)
{
/* register our service control handler */
@@ -541,7 +544,7 @@ service_main(
}
} /* debug */
-#endif /* defined(SYS_WINNT) && !defined(NODETACH) */
+# endif /* defined(SYS_WINNT) && !defined(NODETACH) */
#endif /* VMS */
/*
@@ -638,15 +641,15 @@ service_main(
if (plock(PROCLOCK) < 0)
msyslog(LOG_ERR, "plock(PROCLOCK): %m");
# else /* not PROCLOCK */
-# ifdef TXTLOCK
+# ifdef TXTLOCK
/*
* Lock text into ram
*/
if (plock(TXTLOCK) < 0)
msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
-# else /* not TXTLOCK */
+# else /* not TXTLOCK */
msyslog(LOG_ERR, "plock() - don't know what to lock!");
-# endif /* not TXTLOCK */
+# endif /* not TXTLOCK */
# endif /* not PROCLOCK */
# endif /* HAVE_PLOCK */
#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
@@ -715,27 +718,38 @@ service_main(
init_refclock();
#endif
set_process_priority();
- init_proto();
+ init_proto(); /* Call at high priority */
init_io();
init_loopfilter();
-
- mon_start(MON_ON); /* monitor on by default now */
+ mon_start(MON_ON); /* monitor on by default now */
/* turn off in config if unwanted */
/*
* Get configuration. This (including argument list parsing) is
* done in a separate module since this will definitely be different
- * for the gizmo board.
+ * for the gizmo board. While at it, save the host name for later
+ * along with the length. The crypto needs this.
*/
+#ifdef DEBUG
+ debug = 0;
+#endif
getconfig(argc, argv);
-
+#ifdef AUTOKEY
+ gethostname(hostname, MAXFILENAME);
+ n = strlen(hostname) + 1;
+ sys_hostname = emalloc(n);
+ memcpy(sys_hostname, hostname, n);
+#ifdef PUBKEY
+ crypto_setup();
+#endif /* PUBKEY */
+#endif /* AUTOKEY */
initializing = 0;
#if defined(SYS_WINNT) && !defined(NODETACH)
# if defined(DEBUG)
if(!debug)
{
-#endif
+# endif
/* report to the service control manager that the service is running */
ssStatus.dwCurrentState = SERVICE_RUNNING;
ssStatus.dwWin32ExitCode = NO_ERROR;
@@ -750,7 +764,7 @@ service_main(
}
# if defined(DEBUG)
}
-#endif
+# endif
#endif
/*
@@ -773,7 +787,7 @@ service_main(
* and - lacking a hardware reference clock - I have
* yet to learn about anything else that is.
*/
-# if defined(HAVE_IO_COMPLETION_PORT)
+#if defined(HAVE_IO_COMPLETION_PORT)
WaitHandles[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* exit reques */
WaitHandles[1] = get_timer_handle();
@@ -805,21 +819,21 @@ service_main(
} /* switch */
rbuflist = getrecvbufs(); /* get received buffers */
-# else /* normal I/O */
+#else /* normal I/O */
was_alarmed = 0;
rbuflist = (struct recvbuf *)0;
for (;;)
{
-# if !defined(HAVE_SIGNALED_IO)
+# if !defined(HAVE_SIGNALED_IO)
extern fd_set activefds;
extern int maxactivefd;
fd_set rdfdes;
int nfound;
-# elif defined(HAVE_SIGNALED_IO)
+# elif defined(HAVE_SIGNALED_IO)
block_io_and_alarm();
-# endif
+# endif
rbuflist = getrecvbufs(); /* get received buffers */
if (alarm_flag) /* alarmed? */
@@ -833,9 +847,9 @@ service_main(
/*
* Nothing to do. Wait for something.
*/
-#ifndef HAVE_SIGNALED_IO
+# ifndef HAVE_SIGNALED_IO
rdfdes = activefds;
-# if defined(VMS) || defined(SYS_VXWORKS)
+# if defined(VMS) || defined(SYS_VXWORKS)
/* make select() wake up after one second */
{
struct timeval t1;
@@ -844,10 +858,10 @@ service_main(
nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
(fd_set *)0, &t1);
}
-# else
+# else
nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
(fd_set *)0, (struct timeval *)0);
-# endif /* VMS */
+# endif /* VMS */
if (nfound > 0)
{
l_fp ts;
@@ -858,15 +872,13 @@ service_main(
}
else if (nfound == -1 && errno != EINTR)
msyslog(LOG_ERR, "select() error: %m");
- else if (debug) {
-# if !defined SYS_VXWORKS && !defined SCO5_CLOCK /* to unclutter log */
+ else if (debug > 2) {
msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
-# endif
}
-# else /* HAVE_SIGNALED_IO */
+# else /* HAVE_SIGNALED_IO */
wait_for_signal();
-# endif /* HAVE_SIGNALED_IO */
+# endif /* HAVE_SIGNALED_IO */
if (alarm_flag) /* alarmed? */
{
was_alarmed = 1;
@@ -888,7 +900,7 @@ service_main(
was_alarmed = 0;
}
-# endif /* HAVE_IO_COMPLETION_PORT */
+#endif /* HAVE_IO_COMPLETION_PORT */
/*
* Call the data procedure to handle each received
* packet.
@@ -900,11 +912,11 @@ service_main(
(rbuf->receiver)(rbuf);
freerecvbuf(rbuf);
}
-# if defined DEBUG && defined SYS_WINNT
+#if defined DEBUG && defined SYS_WINNT
if (debug > 4)
printf("getrecvbufs: %ld handler interrupts, %ld frames\n",
handler_calls, handler_pkts);
-# endif
+#endif
/*
* Go around again
@@ -929,11 +941,11 @@ finish(
switch (sig)
{
-#ifdef SIGBUS
+# ifdef SIGBUS
case SIGBUS:
printf("\nfinish(SIGBUS)\n");
exit(0);
-#endif
+# endif
case 0: /* Should never happen... */
return;
default:
diff --git a/contrib/ntp/ntpd/refclock_acts.c b/contrib/ntp/ntpd/refclock_acts.c
index 9c367b5..efdf536 100644
--- a/contrib/ntp/ntpd/refclock_acts.c
+++ b/contrib/ntp/ntpd/refclock_acts.c
@@ -9,13 +9,6 @@
#if defined(REFCLOCK) && (defined(CLOCK_ACTS) || defined(CLOCK_PTBACTS))
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
@@ -23,6 +16,12 @@
#include "ntp_stdlib.h"
#include "ntp_control.h"
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif /* HAVE_SYS_IOCTL_H */
+
/* MUST BE AFTER LAST #include <config.h> !!! */
#if defined(CLOCK_ACTS) && defined(CLOCK_PTBACTS)
@@ -655,19 +654,22 @@ acts_receive (
(void)write(pp->io.fd, &flag, 1);
/*
- * Yes, I know this code incorrectly thinks that 2000 is a leap
- * year. The ACTS timecode format croaks then anyway. Life is
- * short. Would only the timecode mavens resist the urge to
- * express months of the year and days of the month in favor of
- * days of the year.
- * NOTE: year 2000 IS a leap year!!! ghealton Y2KFixes
+ * The ACTS timecode format croaks in 2000. Life is short.
+ * Would only the timecode mavens resist the urge to express months
+ * of the year and days of the month in favor of days of the year.
*/
if (month < 1 || month > 12 || day < 1) {
refclock_report(peer, CEVNT_BADTIME);
return;
}
- if ( pp->year <= YEAR_PIVOT ) pp->year += 100; /* Y2KFixes */
- if ( !isleap_tm(pp->year) ) { /* Y2KFixes */
+
+ /*
+ * Depending on the driver, at this point we have a two-digit year
+ * or a four-digit year. Make sure we have a four-digit year.
+ */
+ if ( pp->year < YEAR_PIVOT ) pp->year += 100; /* Y2KFixes */
+ if ( pp->year < YEAR_BREAK ) pp->year += 1900; /* Y2KFixes */
+ if ( !isleap_4(pp->year) ) { /* Y2KFixes */
if (day > day1tab[month - 1]) {
refclock_report(peer, CEVNT_BADTIME);
return;
@@ -798,7 +800,7 @@ acts_timeout (
acts_disc(peer);
return;
}
- switch (peer->ttl) {
+ switch (peer->ttlmax) {
/*
* In manual mode the ACTS calling program is activated
diff --git a/contrib/ntp/ntpd/refclock_arbiter.c b/contrib/ntp/ntpd/refclock_arbiter.c
index 045a93a..cdbe2ee 100644
--- a/contrib/ntp/ntpd/refclock_arbiter.c
+++ b/contrib/ntp/ntpd/refclock_arbiter.c
@@ -9,15 +9,14 @@
#if defined(REFCLOCK) && defined(CLOCK_ARBITER)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/*
* This driver supports the Arbiter 1088A/B Satellite Controlled Clock.
* The claimed accuracy of this clock is 100 ns relative to the PPS
diff --git a/contrib/ntp/ntpd/refclock_arc.c b/contrib/ntp/ntpd/refclock_arc.c
index 1db8a9a..c771f47 100644
--- a/contrib/ntp/ntpd/refclock_arc.c
+++ b/contrib/ntp/ntpd/refclock_arc.c
@@ -303,10 +303,13 @@ Also note h<cr> command which starts a resync to MSF signal.
*/
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
#include <stdio.h>
#include <ctype.h>
-#include <sys/time.h>
#if defined(HAVE_BSD_TTYS)
#include <sgtty.h>
@@ -320,11 +323,6 @@ Also note h<cr> command which starts a resync to MSF signal.
#include <termios.h>
#endif
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
/*
* This driver supports the ARCRON MSF Radio Controlled Clock
*/
diff --git a/contrib/ntp/ntpd/refclock_as2201.c b/contrib/ntp/ntpd/refclock_as2201.c
index 2c10440..516f7ad 100644
--- a/contrib/ntp/ntpd/refclock_as2201.c
+++ b/contrib/ntp/ntpd/refclock_as2201.c
@@ -8,16 +8,15 @@
#if defined(REFCLOCK) && defined(CLOCK_AS2201)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/*
* This driver supports the Austron 2200A/2201A GPS Receiver with
* Buffered RS-232-C Interface Module. Note that the original 2200/2201
diff --git a/contrib/ntp/ntpd/refclock_atom.c b/contrib/ntp/ntpd/refclock_atom.c
index 764f6e0..56f86b3 100644
--- a/contrib/ntp/ntpd/refclock_atom.c
+++ b/contrib/ntp/ntpd/refclock_atom.c
@@ -5,8 +5,6 @@
#include <config.h>
#endif
-#if defined(REFCLOCK) && defined(CLOCK_ATOM)
-
#include <stdio.h>
#include <ctype.h>
@@ -16,15 +14,8 @@
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_TERMIOS_H
-# include <sys/termios.h>
-#endif
-#ifdef HAVE_SYS_PPSCLOCK_H
-# include <sys/ppsclock.h>
-#endif
+#if defined(REFCLOCK) && defined(CLOCK_ATOM)
+
#ifdef HAVE_PPSAPI
# ifdef HAVE_TIMEPPS_H
# include <timepps.h>
@@ -37,120 +28,109 @@
/*
* This driver furnishes an interface for pulse-per-second (PPS) signals
- * produced by a cesium clock, timing receiver or related equipment. It
+ * produced by a cesium clock, timing receiver or related equipment. It
* can be used to remove accumulated jitter and retime a secondary
* server when synchronized to a primary server over a congested, wide-
* area network and before redistributing the time to local clients.
*
- * In order for this driver to work, the local clock must be set to
+ * Before this driver becomes active, the local clock must be set to
* within +-500 ms by another means, such as a radio clock or NTP
- * itself. The 1-pps signal is connected via a serial port and gadget
- * box consisting of a one-shot flopflop and RS232 level converter.
- * Conntection is either via the carrier detect (DCD) lead or via the
- * receive data (RD) lead. The incidental jitter using the DCD lead is
- * essentially the interrupt latency. The incidental jitter using the RD
- * lead has an additional component due to the line sampling clock. When
- * operated at 38.4 kbps, this arrangement has a worst-case jitter less
- * than 26 us.
+ * itself. There are two ways to connect the PPS signal, normally at TTL
+ * levels, to the computer. One is to shift to EIA levels and connect to
+ * pin 8 (DCD) of a serial port. This requires a level converter and
+ * may require a one-shot flipflop to lengthen the pulse. The other is
+ * to connect the PPS signal directly to pin 10 (ACK) of a PC paralell
+ * port. These methods are architecture dependent.
*
- * There are four ways in which this driver can be used. They are
- * described in decreasing order of merit below. The first way uses the
- * ppsapi STREAMS module and the LDISC_PPS line discipline, while the
- * second way uses the ppsclock STREAMS module and the LDISC_PPS line
- * discipline. Either of these works only for the baseboard serial ports
- * of the Sun SPARC IPC and clones. However, the ppsapi uses the
- * proposed IETF interface expected to become standard for PPS signals.
- * The serial port to be used is specified by the pps command in the
- * configuration file. This driver reads the timestamp directly by a
- * designated ioctl() system call.
+ * Both methods require a modified device driver and kernel interface
+ * compatible with the Pulse-per-Second API for Unix-like Operating
+ * Systems, Version 1.0, RFC-2783 (PPSAPI). Implementations are
+ * available for FreeBSD, Linux, SunOS, Solaris and Alpha. However, at
+ * present only the Alpha implementation provides the full generality of
+ * the API with multiple PPS drivers and multiple handles per driver.
*
- * The third way uses the LDISC_CLKPPS line discipline and works for
- * any architecture supporting a serial port. If after a few seconds
- * this driver finds no ppsclock module configured, it attempts to open
- * a serial port device /dev/pps%d, where %d is the unit number, and
- * assign the LDISC_CLKPPS line discipline to it. If the line discipline
- * fails, no harm is done except the accuracy is reduced somewhat. The
- * pulse generator in the gadget box is adjusted to produce a start bit
- * of length 26 usec at 38400 bps. Used with the LDISC_CLKPPS line
- * discipline, this produces an ASCII DEL character ('\377') followed by
- * a timestamp at each seconds epoch.
+ * In many configurations a single port is used for the radio timecode
+ * and PPS signal. In order to provide for this configuration and others
+ * involving dedicated multiple serial/parallel ports, the driver first
+ * attempts to open the device /dev/pps%d, where %d is the unit number.
+ * If this fails, the driver attempts to open the device specified by
+ * the pps configuration command. If a port is to be shared, the pps
+ * command must be placed before the radio device(s) and the radio
+ * device(s) must be placed before the PPS driver(s) in the
+ * configuration file.
*
- * The fourth way involves an auxiliary radio clock driver which calls
- * the PPS driver with a timestamp captured by that driver. This use is
- * documented in the source code for the driver(s) involved. Note that
- * some drivers collect the sample information themselves before calling
- * pps_sample(), and others call knowing only that they are running
- * shortly after an on-time tick and they expect to retrieve the PPS
- * offset, fudge their result, and insert it into the timestream.
+ * This driver normally uses the PLL/FLL clock discipline implemented in
+ * the ntpd code. If kernel support is available, the kernel PLL/FLL
+ * clock discipline is used instead. The default configuration is not to
+ * use the kernel PPS discipline, if present. The kernel PPS discipline
+ * can be enabled using the pps command.
*
* Fudge Factors
*
* There are no special fudge factors other than the generic. The fudge
- * time1 parameter can be used to compensate for miscellaneous UART and
- * OS delays. Allow about 247 us for uart delays at 38400 bps and about
- * 1 ms for STREAMS nonsense with older workstations. Velocities may
- * vary with modern workstations.
+ * time1 parameter can be used to compensate for miscellaneous device
+ * driver and OS delays.
*/
/*
* Interface definitions
*/
#ifdef HAVE_PPSAPI
-extern int pps_assert;
+extern int pps_assert; /* selects rising or falling edge */
+extern int pps_hardpps; /* enables the kernel PPS interface */
+#define DEVICE "/dev/pps%d" /* device name and unit */
#endif /* HAVE_PPSAPI */
-#ifdef TTYCLK
-#define DEVICE "/dev/pps%d" /* device name and unit */
-#ifdef B38400
-#define SPEED232 B38400 /* uart speed (38400 baud) */
-#else
-#define SPEED232 EXTB /* as above */
-#endif
-#endif /* TTYCLK */
#define PRECISION (-20) /* precision assumed (about 1 us) */
#define REFID "PPS\0" /* reference ID */
#define DESCRIPTION "PPS Clock Discipline" /* WRU */
+#define NANOSECOND 1000000000 /* one second (ns) */
+#define RANGEGATE 500000 /* range gate (ns) */
+#define ASTAGE 8 /* filter stages */
-#define FLAG_TTY 0x01 /* tty_clk heard from */
-#define FLAG_PPS 0x02 /* ppsclock heard from */
-#define FLAG_AUX 0x04 /* auxiliary PPS source */
-
-static struct peer *pps_peer; /* atom driver for auxiliary PPS sources */
-
-#ifdef TTYCLK
-static void atom_receive P((struct recvbuf *));
-#endif /* TTYCLK */
+static struct peer *pps_peer; /* atom driver for PPS sources */
+#ifdef HAVE_PPSAPI
/*
- * Unit control structure
+ * PPS unit control structure
*/
-struct atomunit {
-#ifdef HAVE_PPSAPI
- pps_info_t pps_info; /* pps_info control */
-#endif /* HAVE_PPSAPI */
-#ifdef PPS
- struct ppsclockev ev; /* ppsclock control */
-#endif /* PPS */
- int flags; /* flags that wave */
+struct ppsunit {
+ struct timespec ts; /* last timestamp */
+ int fddev; /* pps device descriptor */
+ pps_params_t pps_params; /* pps parameters */
+ pps_info_t pps_info; /* last pps data */
+ pps_handle_t handle; /* pps handlebars */
};
+#endif /* HAVE_PPSAPI */
/*
* Function prototypes
*/
static int atom_start P((int, struct peer *));
-static void atom_shutdown P((int, struct peer *));
static void atom_poll P((int, struct peer *));
-#if defined(PPS) || defined(HAVE_PPSAPI)
+#ifdef HAVE_PPSAPI
+static void atom_shutdown P((int, struct peer *));
+static void atom_control P((int, struct refclockstat *, struct
+ refclockstat *, struct peer *));
static int atom_pps P((struct peer *));
-#endif /* PPS || HAVE_PPSAPI */
+static int atom_ppsapi P((struct peer *, int, int));
+#endif /* HAVE_PPSAPI */
/*
* Transfer vector
*/
struct refclock refclock_atom = {
atom_start, /* start up driver */
+#ifdef HAVE_PPSAPI
atom_shutdown, /* shut down driver */
+#else
+ noentry, /* shut down driver */
+#endif /* HAVE_PPSAPI */
atom_poll, /* transmit poll message */
- noentry, /* not used (old atom_control) */
+#ifdef HAVE_PPSAPI
+ atom_control, /* fudge control */
+#else
+ noentry, /* fudge control */
+#endif /* HAVE_PPSAPI */
noentry, /* initialize driver */
noentry, /* not used (old atom_buginfo) */
NOFLAGS /* not used */
@@ -162,74 +142,142 @@ struct refclock refclock_atom = {
*/
static int
atom_start(
- int unit,
- struct peer *peer
+ int unit, /* unit number (not used) */
+ struct peer *peer /* peer structure pointer */
)
{
- register struct atomunit *up;
struct refclockproc *pp;
- int flags;
-#ifdef TTYCLK
- int fd = 0;
- char device[20];
- int ldisc = LDISC_CLKPPS;
-#endif /* TTYCLK */
+#ifdef HAVE_PPSAPI
+ register struct ppsunit *up;
+ char device[80];
+#endif /* HAVE_PPSAPI */
+ /*
+ * Allocate and initialize unit structure
+ */
pps_peer = peer;
- flags = 0;
+ pp = peer->procptr;
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+ peer->burst = ASTAGE;
+ peer->stratum = STRATUM_UNSPEC;
+#ifdef HAVE_PPSAPI
+ up = emalloc(sizeof(struct ppsunit));
+ memset(up, 0, sizeof(struct ppsunit));
+ pp->unitptr = (caddr_t)up;
-#ifdef TTYCLK
-# if defined(SCO5_CLOCK)
- ldisc = LDISC_RAW; /* DCD timestamps without any line discipline */
-# endif
/*
- * Open serial port. Use LDISC_CLKPPS line discipline only
- * if the LDISC_PPS line discipline is not availble,
+ * Open PPS device. If this fails and some driver has already
+ * opened the associated radio device, fdpps has the file
+ * descriptor for it.
*/
-# if defined(PPS) || defined(HAVE_PPSAPI)
- if (fdpps <= 0)
-# endif
- {
- (void)sprintf(device, DEVICE, unit);
- if ((fd = refclock_open(device, SPEED232, ldisc)) != 0)
- flags |= FLAG_TTY;
+ sprintf(device, DEVICE, unit);
+ up->fddev = open(device, O_RDWR, 0777);
+ if (up->fddev <= 0 && fdpps > 0) {
+ strcpy(device, pps_device);
+ up->fddev = fdpps;
+ }
+ if (up->fddev <= 0) {
+ msyslog(LOG_ERR,
+ "refclock_atom: %s: %m", device);
+ return (0);
}
-#endif /* TTYCLK */
/*
- * Allocate and initialize unit structure
+ * Light off the PPSAPI interface. If this PPS device is shared
+ * with the radio device, take the default options from the pps
+ * command. This is for legacy purposes.
*/
- if (!(up = (struct atomunit *)emalloc(sizeof(struct atomunit)))) {
-#ifdef TTYCLK
- if (flags & FLAG_TTY)
- (void) close(fd);
-#endif /* TTYCLK */
+ if (time_pps_create(up->fddev, &up->handle) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_atom: time_pps_create failed: %m");
return (0);
}
- memset((char *)up, 0, sizeof(struct atomunit));
+ return (atom_ppsapi(peer, pps_assert, pps_hardpps));
+#else /* HAVE_PPSAPI */
+ return (1);
+#endif /* HAVE_PPSAPI */
+}
+
+
+#ifdef HAVE_PPSAPI
+/*
+ * atom_control - fudge control
+ */
+static void
+atom_control(
+ int unit, /* unit (not used */
+ struct refclockstat *in, /* input parameters (not uded) */
+ struct refclockstat *out, /* output parameters (not used) */
+ struct peer *peer /* peer structure pointer */
+ )
+{
+ struct refclockproc *pp;
+
pp = peer->procptr;
- pp->unitptr = (caddr_t)up;
-#ifdef TTYCLK
- if (flags & FLAG_TTY) {
- pp->io.clock_recv = atom_receive;
- pp->io.srcclock = (caddr_t)peer;
- pp->io.datalen = 0;
- pp->io.fd = fd;
- if (!io_addclock(&pp->io)) {
- (void) close(fd);
- free(up);
+ atom_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
+ pp->sloppyclockflag & CLK_FLAG3);
+}
+
+
+/*
+ * Initialize PPSAPI
+ */
+int
+atom_ppsapi(
+ struct peer *peer, /* peer structure pointer */
+ int enb_clear, /* clear enable */
+ int enb_hardpps /* hardpps enable */
+ )
+{
+ struct refclockproc *pp;
+ register struct ppsunit *up;
+ int capability;
+
+ pp = peer->procptr;
+ up = (struct ppsunit *)pp->unitptr;
+ if (time_pps_getcap(up->handle, &capability) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_atom: time_pps_getcap failed: %m");
+ return (0);
+ }
+ memset(&up->pps_params, 0, sizeof(pps_params_t));
+ if (enb_clear)
+ up->pps_params.mode = capability & PPS_CAPTURECLEAR;
+ else
+ up->pps_params.mode = capability & PPS_CAPTUREASSERT;
+ if (!up->pps_params.mode) {
+ msyslog(LOG_ERR,
+ "refclock_atom: invalid capture edge %d",
+ pps_assert);
+ return (0);
+ }
+ up->pps_params.mode |= PPS_TSFMT_TSPEC;
+ if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_atom: time_pps_setparams failed: %m");
+ return (0);
+ }
+ if (enb_hardpps) {
+ if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
+ up->pps_params.mode & ~PPS_TSFMT_TSPEC,
+ PPS_TSFMT_TSPEC) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_atom: time_pps_kcbind failed: %m");
return (0);
}
+ pps_enable = 1;
}
-#endif /* TTYCLK */
-
- /*
- * Initialize miscellaneous variables
- */
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- memcpy((char *)&pp->refid, REFID, 4);
- up->flags = flags;
+#if DEBUG
+ if (debug) {
+ time_pps_getparams(up->handle, &up->pps_params);
+ printf(
+ "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x kern %d\n",
+ up->fddev, capability, up->pps_params.api_version,
+ up->pps_params.mode, enb_hardpps);
+ }
+#endif
return (1);
}
@@ -239,181 +287,122 @@ atom_start(
*/
static void
atom_shutdown(
- int unit,
- struct peer *peer
+ int unit, /* unit number (not used) */
+ struct peer *peer /* peer structure pointer */
)
{
- register struct atomunit *up;
struct refclockproc *pp;
+ register struct ppsunit *up;
pp = peer->procptr;
- up = (struct atomunit *)pp->unitptr;
-#ifdef TTYCLK
- if (up->flags & FLAG_TTY)
- io_closeclock(&pp->io);
-#endif /* TTYCLK */
+ 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);
}
-#if defined(PPS) || defined(HAVE_PPSAPI)
/*
- * atom_pps - receive data from the LDISC_PPS discipline
+ * atom_pps - receive data from the PPSAPI interface
+ *
+ * This routine is called once per second when the PPSAPI interface is
+ * present. It snatches the PPS timestamp from the kernel and saves the
+ * sign-extended fraction in a circular buffer for processing at the
+ * next poll event.
*/
static int
atom_pps(
- struct peer *peer
+ struct peer *peer /* peer structure pointer */
)
{
- register struct atomunit *up;
+ register struct ppsunit *up;
struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
- struct timespec timeout;
-# ifdef HAVE_TIMESPEC
- struct timespec ts;
-# else
- struct timeval ts;
-# endif /* HAVE_TIMESPEC */
-#endif /* HAVE_PPSAPI */
- l_fp lftmp;
- double doffset;
- int i;
-#if !defined(HAVE_PPSAPI)
- int request =
-# ifdef HAVE_CIOGETEV
- CIOGETEV
-# endif
-# ifdef HAVE_TIOCGPPSEV
- TIOCGPPSEV
-# endif
- ;
-#endif /* HAVE_PPSAPI */
+ pps_info_t pps_info;
+ struct timespec timeout, ts;
+ double dtemp;
/*
- * This routine is called once per second when the LDISC_PPS
- * discipline is present. It snatches the pps timestamp from the
- * kernel and saves the sign-extended fraction in a circular
- * buffer for processing at the next poll event.
- */
- pp = peer->procptr;
- up = (struct atomunit *)pp->unitptr;
-
- /*
- * Convert the timeval to l_fp and save for billboards. Sign-
- * extend the fraction and stash in the buffer. No harm is done
- * if previous data are overwritten. If the discipline comes bum
- * or the data grow stale, just forget it. Round the nanoseconds
- * to microseconds with great care.
+ * Convert the timespec nanoseconds field to signed double and
+ * save in the median filter. for billboards. No harm is done if
+ * previous data are overwritten. If the discipline comes bum or
+ * the data grow stale, just forget it. A range gate rejects new
+ * samples if less than a jiggle time from the next second.
*/
- if (fdpps <= 0)
- return (1);
-#ifdef HAVE_PPSAPI
+ pp = peer->procptr;
+ up = (struct ppsunit *)pp->unitptr;
+ if (up->handle == 0)
+ return (-1);
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
- i = up->pps_info.assert_sequence;
- if (time_pps_fetch(fdpps, PPS_TSFMT_TSPEC, &up->pps_info, &timeout)
- < 0)
- return (2);
- if (i == up->pps_info.assert_sequence)
- return (3);
- if (pps_assert)
+ memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
+ if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
+ &timeout) < 0)
+ return (-1);
+ if (up->pps_params.mode & PPS_CAPTUREASSERT) {
+ if (pps_info.assert_sequence ==
+ up->pps_info.assert_sequence)
+ return (1);
ts = up->pps_info.assert_timestamp;
- else
+ } 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;
- pp->lastrec.l_ui = ts.tv_sec + JAN_1970;
- ts.tv_nsec = (ts.tv_nsec + 500) / 1000;
- if (ts.tv_nsec > 1000000) {
- ts.tv_nsec -= 1000000;
- ts.tv_sec++;
+ } else {
+ return (-1);
}
- TVUTOTSF(ts.tv_nsec, pp->lastrec.l_uf);
-#else
- i = up->ev.serial;
- if (ioctl(fdpps, request, (caddr_t)&up->ev) < 0)
- return (2);
- if (i == up->ev.serial)
- return (3);
- pp->lastrec.l_ui = up->ev.tv.tv_sec + JAN_1970;
- TVUTOTSF(up->ev.tv.tv_usec, pp->lastrec.l_uf);
-#endif /* HAVE_PPSAPI */
- up->flags |= FLAG_PPS;
- L_CLR(&lftmp);
- L_ADDF(&lftmp, pp->lastrec.l_f);
- LFPTOD(&lftmp, doffset);
- SAMPLE(-doffset + pp->fudgetime1);
+ if (!((ts.tv_sec == up->ts.tv_sec && ts.tv_nsec -
+ up->ts.tv_nsec > NANOSECOND - RANGEGATE) ||
+ (ts.tv_sec - up->ts.tv_sec == 1 && ts.tv_nsec -
+ up->ts.tv_nsec < RANGEGATE))) {
+ up->ts = ts;
+ return (1);
+ }
+ up->ts = ts;
+ pp->lastrec.l_ui = ts.tv_sec + JAN_1970;
+ dtemp = ts.tv_nsec * FRAC / 1e9;
+ if (dtemp >= FRAC)
+ pp->lastrec.l_ui++;
+ pp->lastrec.l_uf = (u_int32)dtemp;
+ if (ts.tv_nsec > NANOSECOND / 2)
+ ts.tv_nsec -= NANOSECOND;
+ dtemp = -(double)ts.tv_nsec / NANOSECOND;
+ SAMPLE(dtemp + pp->fudgetime1);
+#ifdef DEBUG
+ if (debug > 1)
+ printf("atom_pps %f %f\n", dtemp, pp->fudgetime1);
+#endif
return (0);
}
-#endif /* PPS || HAVE_PPSAPI */
-
-#ifdef TTYCLK
-/*
- * atom_receive - receive data from the LDISC_CLK discipline
- */
-static void
-atom_receive(
- struct recvbuf *rbufp
- )
-{
- register struct atomunit *up;
- struct refclockproc *pp;
- struct peer *peer;
- l_fp lftmp;
- double doffset;
-
- /*
- * This routine is called once per second when the serial
- * interface is in use. It snatches the timestamp from the
- * buffer and saves the sign-extended fraction in a circular
- * buffer for processing at the next poll event.
- */
- peer = (struct peer *)rbufp->recv_srcclock;
- pp = peer->procptr;
- up = (struct atomunit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
- &pp->lastrec);
+#endif /* HAVE_PPSAPI */
- /*
- * Save the timestamp for billboards. Sign-extend the fraction
- * and stash in the buffer. No harm is done if previous data are
- * overwritten. Do this only if the ppsclock gizmo is not
- * working.
- */
- if (up->flags & FLAG_PPS)
- return;
- L_CLR(&lftmp);
- L_ADDF(&lftmp, pp->lastrec.l_f);
- LFPTOD(&lftmp, doffset);
- SAMPLE(-doffset + pp->fudgetime1);
-}
-#endif /* TTYCLK */
/*
* pps_sample - receive PPS data from some other clock driver
+ *
+ * This routine is called once per second when the external clock driver
+ * processes PPS information. It processes the PPS timestamp and saves
+ * the sign-extended fraction in a circular buffer for processing at the
+ * next poll event. This works only for a single PPS device.
*/
int
pps_sample(
- l_fp *offset
+ l_fp *offset /* PPS offset */
)
{
register struct peer *peer;
- register struct atomunit *up;
struct refclockproc *pp;
l_fp lftmp;
double doffset;
- /*
- * This routine is called once per second when the external
- * clock driver processes PPS information. It processes the pps
- * timestamp and saves the sign-extended fraction in a circular
- * buffer for processing at the next poll event.
- */
peer = pps_peer;
if (peer == 0) /* nobody home */
- return 1;
+ return (1);
pp = peer->procptr;
- up = (struct atomunit *)pp->unitptr;
/*
* Convert the timeval to l_fp and save for billboards. Sign-
@@ -421,7 +410,6 @@ pps_sample(
* if previous data are overwritten. If the discipline comes bum
* or the data grow stale, just forget it.
*/
- up->flags |= FLAG_AUX;
pp->lastrec = *offset;
L_CLR(&lftmp);
L_ADDF(&lftmp, pp->lastrec.l_f);
@@ -432,63 +420,81 @@ pps_sample(
/*
* atom_poll - called by the transmit procedure
+ *
+ * This routine is called once per second when in burst mode to save PPS
+ * sample offsets in the median filter. At the end of the burst period
+ * the samples are processed as a heap and the clock filter updated.
*/
static void
atom_poll(
- int unit,
- struct peer *peer
+ int unit, /* unit number (not used) */
+ struct peer *peer /* peer structure pointer */
)
{
-#if defined(PPS) || defined(HAVE_PPSAPI)
- register struct atomunit *up;
-#endif /* PPS || HAVE_PPSAPI */
struct refclockproc *pp;
+#ifdef HAVE_PPSAPI
+ int err;
+#endif /* HAVE_PPSAPI */
/*
- * Accumulate samples in the median filter. At the end of each
- * poll interval, do a little bookeeping and process the
- * samples.
+ * 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;
-#if defined(PPS) || defined(HAVE_PPSAPI)
- up = (struct atomunit *)pp->unitptr;
- if (!(up->flags & !(FLAG_AUX | FLAG_TTY))) {
- int err;
-
- err = atom_pps(peer);
- if (err > 0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
- }
-#endif /* PPS || HAVE_PPSAPI */
pp->polls++;
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
+#ifdef HAVE_PPSAPI
+ err = atom_pps(peer);
+ if (err < 0) {
+ refclock_report(peer, CEVNT_FAULT);
return;
}
+#endif /* HAVE_PPSAPI */
/*
- * Valid time (leap bits zero) is returned only if the prefer
- * peer has survived the intersection algorithm and within
- * clock_max of local time and not too long ago. This ensures
- * the pps time is within +-0.5 s of the local time and the
- * seconds numbering is unambiguous.
+ * Valid time is returned only if the prefer peer has survived
+ * the intersection algorithm and within clock_max of local time
+ * and not too long ago. This ensures the PPS time is within
+ * +-0.5 s of the local time and the seconds numbering is
+ * unambiguous. Note that the leap bits are set no-warning on
+ * the first valid update and the stratum is set at the prefer
+ * peer.
*/
- if (pps_update) {
- pp->leap = LEAP_NOWARNING;
- } else {
- pp->leap = LEAP_NOTINSYNC;
+ if (peer->burst > 0)
+ return;
+ peer->stratum = STRATUM_UNSPEC;
+ if (pp->codeproc == pp->coderecv) {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ peer->burst = ASTAGE;
+ return;
+
+ } else if (!sys_prefer) {
+ pp->codeproc = pp->coderecv;
+ peer->burst = ASTAGE;
+ return;
+
+ } else if (fabs(sys_prefer->offset) > clock_max) {
+ pp->codeproc = pp->coderecv;
+ peer->burst = ASTAGE;
return;
}
- pp->variance = 0;
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ peer->stratum = sys_prefer->stratum;
+ if (peer->stratum <= 1)
+ peer->refid = pp->refid;
+ else
+ peer->refid = peer->srcadr.sin_addr.s_addr;
+ pp->leap = LEAP_NOWARNING;
refclock_receive(peer);
- peer->burst = MAXSTAGE;
+ peer->burst = ASTAGE;
}
-
#else
int refclock_atom_bs;
+int
+pps_sample(
+ l_fp *offset /* PPS offset */
+ )
+{
+ return 1;
+}
#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_bancomm.c b/contrib/ntp/ntpd/refclock_bancomm.c
index 95c211b..a3debcb 100644
--- a/contrib/ntp/ntpd/refclock_bancomm.c
+++ b/contrib/ntp/ntpd/refclock_bancomm.c
@@ -32,12 +32,6 @@
#endif
#if defined(REFCLOCK) && defined(CLOCK_BANC)
-#include <stdio.h>
-#include <syslog.h>
-#include <ctype.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/time.h>
#include "ntpd.h"
#include "ntp_io.h"
@@ -45,6 +39,10 @@
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+
/* STUFF BY RES */
struct btfp_time /* Structure for reading 5 time words */
/* in one ioctl(2) operation. */
@@ -83,11 +81,6 @@ struct vmedate { /* structure returned by get_vmetime.c */
/* END OF STUFF FROM RES */
/*
- * Definitions
- */
-#define MAXUNITS 2 /* max number of VME units */
-
-/*
* VME interface parameters.
*/
#define VMEPRECISION (-21) /* precision assumed (1 us) */
@@ -119,14 +112,6 @@ struct vmeunit {
};
/*
- * Keep the fudge factors separately so they can be set even
- * when no clock is configured.
- */
-static double fudgefactor[MAXUNITS];
-static u_char stratumtouse[MAXUNITS];
-static u_char sloppyclockflag[MAXUNITS];
-
-/*
* Function prototypes
*/
static void vme_init (void);
@@ -140,35 +125,18 @@ struct vmedate *get_datumtime(struct vmedate *);
* Transfer vector
*/
struct refclock refclock_bancomm = {
- vme_start,
- vme_shutdown,
- vme_poll,
- noentry, /* not used (old vme_control) */
- vme_init,
- noentry, /* not used (old vme_buginfo) */
- NOFLAGS
+ vme_start, /* start up driver */
+ vme_shutdown, /* shut down driver */
+ vme_poll, /* transmit poll message */
+ noentry, /* not used (old vme_control) */
+ noentry, /* initialize driver */
+ noentry, /* not used (old vme_buginfo) */
+ NOFLAGS /* not used */
};
int fd_vme; /* file descriptor for ioctls */
int regvalue;
-/*
- * vme_init - initialize internal vme driver data
- */
-static void
-vme_init(void)
-{
- register int i;
-
- /*
- * Initialize fudge factors to default.
- */
- for (i = 0; i < MAXUNITS; i++) {
- fudgefactor[i] = 0.0;
- stratumtouse[i] = 0;
- sloppyclockflag[i] = 0;
- }
-}
/*
* vme_start - open the VME device and initialize data for processing
@@ -185,14 +153,6 @@ vme_start(
char vmedev[20];
/*
- * Check configuration info.
- */
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_start: unit %d invalid", unit);
- return (0);
- }
-
- /*
* Open VME device
*/
#ifdef DEBUG
@@ -236,13 +196,8 @@ vme_start(
* return success. Note that root delay and root dispersion are
* always zero for this clock.
*/
- pp->leap = LEAP_NOWARNING;
peer->precision = VMEPRECISION;
- peer->stratum = stratumtouse[unit];
- memcpy( (char *)&peer->refid, USNOREFID,4);
-
- peer->refid = htonl(VMEHSREFID);
-
+ memcpy(&pp->refid, USNOREFID,4);
return (1);
}
@@ -258,17 +213,11 @@ vme_shutdown(
{
register struct vmeunit *vme;
struct refclockproc *pp;
-
- pp = peer->procptr;
-
- if (unit >= MAXUNITS) {
- msyslog(LOG_ERR, "vme_shutdown: unit %d invalid", unit);
- return;
- }
/*
* Tell the I/O module to turn us off. We're history.
*/
+ pp = peer->procptr;
vme = (struct vmeunit *)pp->unitptr;
io_closeclock(&pp->io);
pp->unitptr = NULL;
diff --git a/contrib/ntp/ntpd/refclock_chronolog.c b/contrib/ntp/ntpd/refclock_chronolog.c
index 2982ecc..9273a84 100644
--- a/contrib/ntp/ntpd/refclock_chronolog.c
+++ b/contrib/ntp/ntpd/refclock_chronolog.c
@@ -13,17 +13,15 @@
#if defined(REFCLOCK) && defined(CLOCK_CHRONOLOG)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/*
* This driver supports the Chronolog K-series WWVB receiver.
*
diff --git a/contrib/ntp/ntpd/refclock_chu.c b/contrib/ntp/ntpd/refclock_chu.c
index 4235b8e..10fcea5 100644
--- a/contrib/ntp/ntpd/refclock_chu.c
+++ b/contrib/ntp/ntpd/refclock_chu.c
@@ -7,20 +7,19 @@
#if defined(REFCLOCK) && defined(CLOCK_CHU)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <time.h>
-#include <math.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
-#ifdef AUDIO_CHU
+
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+
+#ifdef HAVE_AUDIO
#include "audio.h"
-#endif /* AUDIO_CHU */
+#endif /* HAVE_AUDIO */
#define ICOM 1 /* undefine to suppress ICOM code */
@@ -173,10 +172,18 @@
* Fudge flag3 enables audio monitoring of the input signal. For this
* purpose, the speaker volume must be set before the driver is started.
*
- * The ICOM code is normally compiled in the driver. It isn't used,
- * unless the mode keyword on the server configuration command specifies
- * a nonzero ICOM ID select code. The C-IV trace is turned on if the
- * debug level is greater than one.
+ * The audio codec code is normally compiled in the driver if the
+ * architecture supports it (HAVE_AUDIO defined), but is used only if the
+ * link /dev/chu_audio is defined and valid. The serial port
+ * code is alwasy compiled in the driver, but is used only if the autdio
+ * codec is not available and the link /dev/chu%d is defined and valid.
+ * The ICOM code is normally compiled in the driver if selected (ICOM
+ * defined), but is used only if the link /dev/icom%d is defined and
+ * valid and the mode keyword on the server configuration command
+ * specifies a nonzero mode (ICOM ID select code). The C-IV speed is
+ * 9600 bps if the high order 0x80 bit of the mode is zero and 1200 bps
+ * if one. The C-IV trace is turned on if the debug level is greater
+ * than one.
*/
/*
* Interface definitions
@@ -184,12 +191,13 @@
#define SPEED232 B300 /* uart speed (300 baud) */
#define PRECISION (-10) /* precision assumed (about 1 ms) */
#define REFID "CHU" /* reference ID */
+#define DEVICE "/dev/chu%d" /* device name and unit */
+#define SPEED232 B300 /* UART speed (300 baud) */
#ifdef ICOM
#define DWELL 5 /* minutes before qsy */
#define NCHAN 3 /* number of channels */
#endif /* ICOM */
-#ifdef AUDIO_CHU
-#define DESCRIPTION "CHU Modem Receiver" /* WRU */
+#ifdef HAVE_AUDIO
/*
* Audio demodulator definitions
@@ -202,11 +210,11 @@
#define LIMIT 1000. /* soft limiter threshold */
#define AGAIN 6. /* baseband gain */
#define LAG 10 /* discriminator lag */
+#define DEVICE_AUDIO "/dev/chu_audio" /* device name */
+#define DESCRIPTION "CHU Audio/Modem Receiver" /* WRU */
#else
-#define DEVICE "/dev/chu%d" /* device name and unit */
-#define SPEED232 B300 /* UART speed (300 baud) */
-#define DESCRIPTION "CHU Audio Receiver" /* WRU */
-#endif /* AUDIO_CHU */
+#define DESCRIPTION "CHU Modem Receiver" /* WRU */
+#endif /* HAVE_AUDIO */
/*
* Decoder definitions
@@ -255,14 +263,14 @@
#define DECERR 0x04 /* data decoding error */
#define TSPERR 0x08 /* insufficient data */
-#ifdef AUDIO_CHU
+#ifdef HAVE_AUDIO
struct surv {
double shift[12]; /* mark register */
double es_max, es_min; /* max/min envelope signals */
double dist; /* sample distance */
int uart; /* decoded character */
};
-#endif /* AUDIO_CHU */
+#endif /* HAVE_AUDIO */
/*
* CHU unit control structure
@@ -279,9 +287,9 @@ struct chuunit {
int bufptr; /* buffer index pointer */
char ident[10]; /* transmitter frequency */
#ifdef ICOM
+ int fd_icom; /* ICOM file descriptor */
int chan; /* frequency identifier */
int dwell; /* dwell minutes at current frequency */
- int fd_icom; /* ICOM file descriptor */
#endif /* ICOM */
/*
@@ -304,10 +312,11 @@ struct chuunit {
int tai; /* TAI - UTC correction */
int dst; /* Canadian DST code */
-#ifdef AUDIO_CHU
+#ifdef HAVE_AUDIO
/*
* Audio codec variables
*/
+ int fd_audio; /* audio port file descriptor */
double comp[SIZE]; /* decompanding table */
int port; /* codec port */
int gain; /* codec gain */
@@ -333,7 +342,7 @@ struct chuunit {
struct surv surv[8]; /* UART survivor structures */
int decptr; /* decode pointer */
int dbrk; /* holdoff counter */
-#endif /* AUDIO_CHU */
+#endif /* HAVE_AUDIO */
};
/*
@@ -354,11 +363,13 @@ static void chu_a P((struct peer *, int));
static void chu_b P((struct peer *, int));
static int chu_dist P((int, int));
static int chu_major P((struct peer *));
-#ifdef AUDIO_CHU
+#ifdef HAVE_AUDIO
static void chu_uart P((struct surv *, double));
static void chu_rf P((struct peer *, double));
static void chu_gain P((struct peer *));
-#endif /* AUDIO_CHU */
+static void chu_audio_receive P((struct recvbuf *rbufp));
+#endif /* HAVE_AUDIO */
+static void chu_serial_receive P((struct recvbuf *rbufp));
/*
* Global variables
@@ -393,43 +404,52 @@ chu_start(
{
struct chuunit *up;
struct refclockproc *pp;
+ char device[20]; /* device name */
int fd; /* file descriptor */
#ifdef ICOM
char tbuf[80]; /* trace buffer */
int temp;
#endif /* ICOM */
-#ifdef AUDIO_CHU
+#ifdef HAVE_AUDIO
+ int fd_audio; /* audio port file descriptor */
int i; /* index */
double step; /* codec adjustment */
/*
- * Open audio device
+ * Open audio device.
*/
- fd = audio_init();
- if (fd < 0)
- return (0);
+ fd_audio = audio_init(DEVICE_AUDIO);
#ifdef DEBUG
- if (debug)
+ if (fd_audio > 0 && debug)
audio_show();
#endif
-#else
- char device[20]; /* device name */
/*
* Open serial port in raw mode.
*/
- (void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, LDISC_RAW))) {
- return (0);
+ if (fd_audio > 0) {
+ fd = fd_audio;
+ } else {
+ sprintf(device, DEVICE, unit);
+ fd = refclock_open(device, SPEED232, LDISC_RAW);
}
-#endif /* AUDIO_CHU */
+#else /* HAVE_AUDIO */
+
+ /*
+ * Open serial port in raw mode.
+ */
+ sprintf(device, DEVICE, unit);
+ fd = refclock_open(device, SPEED232, LDISC_RAW);
+#endif /* HAVE_AUDIO */
+ if (fd <= 0)
+ return (0);
/*
* Allocate and initialize unit structure
*/
if (!(up = (struct chuunit *)
emalloc(sizeof(struct chuunit)))) {
- (void) close(fd);
+ close(fd);
return (0);
}
memset((char *)up, 0, sizeof(struct chuunit));
@@ -440,7 +460,7 @@ chu_start(
pp->io.datalen = 0;
pp->io.fd = fd;
if (!io_addclock(&pp->io)) {
- (void)close(fd);
+ close(fd);
free(up);
return (0);
}
@@ -452,13 +472,15 @@ chu_start(
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
DTOLFP(CHAR, &up->charstamp);
-#ifdef AUDIO_CHU
- up->gain = 127;
+#ifdef HAVE_AUDIO
/*
* The companded samples are encoded sign-magnitude. The table
- * contains all the 256 values in the interest of speed.
+ * contains all the 256 values in the interest of speed. We do
+ * this even if the audio codec is not available. C'est la lazy.
*/
+ up->fd_audio = fd_audio;
+ up->gain = 127;
up->comp[0] = up->comp[OFFSET] = 0.;
up->comp[1] = 1; up->comp[OFFSET + 1] = -1.;
up->comp[2] = 3; up->comp[OFFSET + 2] = -3.;
@@ -470,7 +492,7 @@ chu_start(
step *= 2.;
}
DTOLFP(1. / SECOND, &up->tick);
-#endif /* AUDIO_CHU */
+#endif /* HAVE_AUDIO */
strcpy(up->ident, "X");
#ifdef ICOM
temp = 0;
@@ -478,8 +500,8 @@ chu_start(
if (debug > 1)
temp = P_TRACE;
#endif
- if (peer->ttl > 0) {
- if (peer->ttl & 0x80)
+ if (peer->ttlmax > 0) {
+ if (peer->ttlmax & 0x80)
up->fd_icom = icom_init("/dev/icom", B1200,
temp);
else
@@ -487,7 +509,7 @@ chu_start(
temp);
}
if (up->fd_icom > 0) {
- if (icom_freq(up->fd_icom, peer->ttl & 0x7f,
+ if (icom_freq(up->fd_icom, peer->ttlmax & 0x7f,
qsy[up->chan]) < 0) {
NLOG(NLOG_SYNCEVENT | NLOG_SYSEVENT)
msyslog(LOG_ERR,
@@ -524,22 +546,58 @@ chu_shutdown(
pp = peer->procptr;
up = (struct chuunit *)pp->unitptr;
+ if (up == NULL)
+ return;
io_closeclock(&pp->io);
if (up->fd_icom > 0)
close(up->fd_icom);
free(up);
}
-#ifdef AUDIO_CHU
-
/*
- * chu_receive - receive data from the audio device
+ * chu_receive - receive data from the audio or serial device
*/
static void
chu_receive(
struct recvbuf *rbufp /* receive buffer structure pointer */
)
{
+#ifdef HAVE_AUDIO
+ struct chuunit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct chuunit *)pp->unitptr;
+
+ /*
+ * If the audio codec is warmed up, the buffer contains codec
+ * samples which need to be demodulated and decoded into CHU
+ * characters using the software UART. Otherwise, the buffer
+ * contains CHU characters from the serial port, so the software
+ * UART is bypassed. In this case the CPU will probably run a
+ * few degrees cooler.
+ */
+ if (up->fd_audio > 0)
+ chu_audio_receive(rbufp);
+ else
+ chu_serial_receive(rbufp);
+#else
+ chu_serial_receive(rbufp);
+#endif /* HAVE_AUDIO */
+}
+
+#ifdef HAVE_AUDIO
+
+/*
+ * chu_audio_receive - receive data from the audio device
+ */
+static void
+chu_audio_receive(
+ struct recvbuf *rbufp /* receive buffer structure pointer */
+ )
+{
struct chuunit *up;
struct refclockproc *pp;
struct peer *peer;
@@ -712,9 +770,9 @@ chu_rf(
up->disc[up->discptr] = limit;
up->discptr = (up->discptr + 1 ) % LAG;
if (disc >= 0)
- disc = sqrt(disc);
+ disc = SQRT(disc);
else
- disc = -sqrt(-disc);
+ disc = -SQRT(-disc);
/*
* Lowpass filter. Raised cosine, Ts = 1 / 300, beta = 0.1.
@@ -849,14 +907,14 @@ chu_uart(
sp->es_min = es_min;
sp->dist = dist / (11 * (es_max - es_min));
}
+#endif /* HAVE_AUDIO */
-#else /* AUDIO_CHU */
/*
- * chu_receive - receive data from the serial interface
+ * chu_serial_receive - receive data from the serial device
*/
static void
-chu_receive(
+chu_serial_receive(
struct recvbuf *rbufp /* receive buffer structure pointer */
)
{
@@ -877,11 +935,10 @@ chu_receive(
dpt = (u_char *)&rbufp->recv_space;
chu_decode(peer, *dpt);
}
-#endif /* AUDIO_CHU */
/*
- * chu_decode - decode the data
+ * chu_decode - decode the character data
*/
static void
chu_decode(
@@ -1108,14 +1165,20 @@ chu_a(
if (temp > 9 || k + 9 >= nchar || temp != ((up->cbuf[k + 9] >>
4) & 0xf))
temp = 0;
-#ifdef AUDIO_CHU
- sprintf(tbuf, "chuA %04x %4.0f %2d %2d %2d %2d %1d ",
- up->status, up->maxsignal, nchar, up->burdist, k,
- up->syndist, temp);
+#ifdef HAVE_AUDIO
+ if (up->fd_audio)
+ sprintf(tbuf, "chuA %04x %4.0f %2d %2d %2d %2d %1d ",
+ up->status, up->maxsignal, nchar, up->burdist, k,
+ up->syndist, temp);
+ else
+ sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ",
+ up->status, nchar, up->burdist, k, up->syndist,
+ temp);
+
#else
sprintf(tbuf, "chuA %04x %2d %2d %2d %2d %1d ", up->status,
nchar, up->burdist, k, up->syndist, temp);
-#endif /* AUDIO_CHU */
+#endif /* HAVE_AUDIO */
for (i = 0; i < nchar; i++)
sprintf(&tbuf[strlen(tbuf)], "%02x",
up->cbuf[i]);
@@ -1221,7 +1284,7 @@ chu_poll(
} else if (up->fd_icom > 0) {
up->dwell = 0;
up->chan = (up->chan + 1) % NCHAN;
- icom_freq(up->fd_icom, peer->ttl & 0x7f, qsy[up->chan]);
+ icom_freq(up->fd_icom, peer->ttlmax & 0x7f, qsy[up->chan]);
sprintf(up->ident, "%.3f", qsy[up->chan]);
sprintf(tbuf, "chu: QSY to %s MHz", up->ident);
record_clock_stats(&peer->srcadr, tbuf);
@@ -1255,19 +1318,28 @@ chu_poll(
} else {
pp->leap = LEAP_NOWARNING;
}
-#ifdef AUDIO_CHU
- sprintf(pp->a_lastcode,
- "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %d %s %d %d %d %d",
- synchar, qual, pp->year, pp->day, pp->hour, pp->minute,
- pp->second, leapchar, up->dst, up->dut, minset, up->gain,
- up->ident, up->tai, up->burstcnt, up->mindist, up->ntstamp);
+#ifdef HAVE_AUDIO
+ if (up->fd_audio)
+ sprintf(pp->a_lastcode,
+ "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %d %s %d %d %d %d",
+ synchar, qual, pp->year, pp->day, pp->hour,
+ pp->minute, pp->second, leapchar, up->dst, up->dut,
+ minset, up->gain, up->ident, up->tai, up->burstcnt,
+ up->mindist, up->ntstamp);
+ else
+ sprintf(pp->a_lastcode,
+ "%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %s %d %d %d %d",
+ synchar, qual, pp->year, pp->day, pp->hour,
+ pp->minute, pp->second, leapchar, up->dst, up->dut,
+ minset, up->ident, up->tai, up->burstcnt,
+ up->mindist, up->ntstamp);
#else
sprintf(pp->a_lastcode,
"%c%1X %4d %3d %02d:%02d:%02d.000 %c%x %+d %d %s %d %d %d %d",
synchar, qual, pp->year, pp->day, pp->hour, pp->minute,
pp->second, leapchar, up->dst, up->dut, minset,
up->ident, up->tai, up->burstcnt, up->mindist, up->ntstamp);
-#endif /* AUDIO_CHU */
+#endif /* HAVE_AUDIO */
pp->lencode = strlen(pp->a_lastcode);
/*
@@ -1390,7 +1462,6 @@ chu_major(
return (0);
}
pp->lastref = offset;
- pp->variance = 0;
for (i = 0; i < up->ntstamp; i++) {
toffset = offset;
L_SUB(&toffset, &up->tstamp[i]);
@@ -1462,7 +1533,7 @@ chu_dist(
}
-#ifdef AUDIO_CHU
+#ifdef HAVE_AUDIO
/*
* chu_gain - adjust codec gain
*
@@ -1500,7 +1571,7 @@ chu_gain(
audio_gain(up->gain, up->port);
up->clipcnt = 0;
}
-#endif /* AUDIO_CHU */
+#endif /* HAVE_AUDIO */
#else
diff --git a/contrib/ntp/ntpd/refclock_conf.c b/contrib/ntp/ntpd/refclock_conf.c
index 71140c8..0e6c927 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
-#ifdef CLOCK_TRAK
+#if defined(CLOCK_TRAK) && defined(PPS)
extern struct refclock refclock_trak;
#else
#define refclock_trak refclock_none
@@ -60,7 +60,7 @@ extern struct refclock refclock_parse;
#define refclock_parse refclock_none
#endif
-#if defined(CLOCK_MX4200) && defined(PPS)
+#if defined(CLOCK_MX4200) && defined(HAVE_PPSAPI)
extern struct refclock refclock_mx4200;
#else
#define refclock_mx4200 refclock_none
@@ -186,7 +186,7 @@ extern struct refclock refclock_palisade;
#define refclock_palisade refclock_none
#endif
-#ifdef CLOCK_ONCORE
+#if defined(CLOCK_ONCORE) && defined(HAVE_PPSAPI)
extern struct refclock refclock_oncore;
#else
#define refclock_oncore refclock_none
@@ -228,6 +228,17 @@ extern struct refclock refclock_fg;
#define refclock_fg refclock_none
#endif
+#ifdef CLOCK_HOPF_SERIAL
+extern struct refclock refclock_hopfser;
+#else
+#define refclock_hopfser refclock_none
+#endif
+
+#ifdef CLOCK_HOPF_PCI
+extern struct refclock refclock_hopfpci;
+#else
+#define refclock_hopfpci refclock_none
+#endif
/*
* Order is clock_start(), clock_shutdown(), clock_poll(),
@@ -273,7 +284,9 @@ struct refclock *refclock_conf[] = {
&refclock_ulink, /* 34 REFCLOCK_ULINK */
&refclock_pcf, /* 35 REFCLOCK_PCF */
&refclock_wwv, /* 36 REFCLOCK_WWV_AUDIO */
- &refclock_fg /* 37 REFCLOCK_FG */
+ &refclock_fg, /* 37 REFCLOCK_FG */
+ &refclock_hopfser, /* 38 REFCLK_HOPF_SERIAL */
+ &refclock_hopfpci /* 39 REFCLK_HOPF_PCI */
};
u_char num_refclock_conf = sizeof(refclock_conf)/sizeof(struct refclock *);
diff --git a/contrib/ntp/ntpd/refclock_datum.c b/contrib/ntp/ntpd/refclock_datum.c
index 74a37db..db03c95 100644
--- a/contrib/ntp/ntpd/refclock_datum.c
+++ b/contrib/ntp/ntpd/refclock_datum.c
@@ -17,16 +17,15 @@
** Include Files
*/
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
#if defined(HAVE_BSD_TTYS)
#include <sgtty.h>
#endif /* HAVE_BSD_TTYS */
@@ -45,10 +44,6 @@
#endif /* WWVBCLK */
#endif /* STREAM */
-#if defined (WWVBPPS)
-#include <sys/ppsclock.h>
-#endif /* WWVBPPS */
-
#include "ntp_stdlib.h"
/*
@@ -120,8 +115,8 @@
*/
-#define PTSPRECISION (-10) /* precision assumed 1/1024 ms */
-#define DATMREFID "DATM" /* reference id */
+#define PRECISION (-10) /* precision assumed 1/1024 ms */
+#define REFID "DATM" /* reference id */
#define DATUM_DISPERSION 0 /* fixed dispersion = 0 ms */
#define DATUM_MAX_ERROR 0.100 /* limits on sigma squared */
@@ -238,7 +233,6 @@ datum_pts_start(
{
struct datum_pts_unit **temp_datum_pts_unit;
struct datum_pts_unit *datum_pts;
-
#ifdef HAVE_TERMIOS
struct termios arg;
#endif
@@ -304,6 +298,10 @@ datum_pts_start(
msyslog(LOG_ERR, "Datum_PTS: Termios not supported in this driver");
(void)close(datum_pts->PTS_fd);
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ memcpy((char *)&pp->refid, REFID, 4);
+
return 0;
#endif
@@ -331,10 +329,6 @@ datum_pts_start(
return 0;
}
- peer->precision = PTSPRECISION;
- peer->stratum = 0;
- memcpy((char *)&peer->refid, DATMREFID, 4);
-
/*
** Now add one to the number of units and return a successful code
*/
@@ -438,7 +432,7 @@ datum_pts_poll(
)
{
int i;
- int index;
+ int unit_index;
int error_code;
struct datum_pts_unit *datum_pts;
@@ -451,10 +445,10 @@ datum_pts_poll(
** Find the right unit and send out a time request once it is found.
*/
- index = -1;
+ unit_index = -1;
for (i=0; i<nunits; i++) {
if (datum_pts_unit[i]->unit == unit) {
- index = i;
+ unit_index = i;
datum_pts = datum_pts_unit[i];
error_code = write(datum_pts->PTS_fd, TIME_REQUEST, 6);
if (error_code != 6) perror("TIME_REQUEST");
@@ -467,7 +461,7 @@ datum_pts_poll(
** Print out an error message if we could not find the right unit.
*/
- if (index == -1) {
+ if (unit_index == -1) {
#ifdef DEBUG_DATUM_PTC
if (debug)
diff --git a/contrib/ntp/ntpd/refclock_dumbclock.c b/contrib/ntp/ntpd/refclock_dumbclock.c
index 8138d9e..c439646 100644
--- a/contrib/ntp/ntpd/refclock_dumbclock.c
+++ b/contrib/ntp/ntpd/refclock_dumbclock.c
@@ -14,17 +14,15 @@
#if defined(REFCLOCK) && defined(CLOCK_DUMBCLOCK)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/*
* This driver supports a generic dumb clock that only outputs hh:mm:ss,
* in local time, no less.
diff --git a/contrib/ntp/ntpd/refclock_fg.c b/contrib/ntp/ntpd/refclock_fg.c
index f1320b0..655b6bc 100644
--- a/contrib/ntp/ntpd/refclock_fg.c
+++ b/contrib/ntp/ntpd/refclock_fg.c
@@ -8,8 +8,6 @@
#if defined(REFCLOCK) && defined(CLOCK_FG)
-#include <time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
diff --git a/contrib/ntp/ntpd/refclock_gpsvme.c b/contrib/ntp/ntpd/refclock_gpsvme.c
index b37466b..42eb2f9 100644
--- a/contrib/ntp/ntpd/refclock_gpsvme.c
+++ b/contrib/ntp/ntpd/refclock_gpsvme.c
@@ -16,19 +16,18 @@
#endif
#if defined(REFCLOCK) && defined(CLOCK_GPSVME)
-#include <stdio.h>
-#include <syslog.h>
-#include <ctype.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/time.h>
-#include "gps.h"
#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 */
diff --git a/contrib/ntp/ntpd/refclock_heath.c b/contrib/ntp/ntpd/refclock_heath.c
index 9d297d1..ef4db5a 100644
--- a/contrib/ntp/ntpd/refclock_heath.c
+++ b/contrib/ntp/ntpd/refclock_heath.c
@@ -1,5 +1,5 @@
/*
- * refclock_heath - clock driver for Heath GC-1000 Most Accurate Clock
+ * refclock_heath - clock driver for Heath GC-1000 and and GC-1000 II
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -7,27 +7,18 @@
#if defined(REFCLOCK) && defined(CLOCK_HEATH)
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
+
#include <stdio.h>
#include <ctype.h>
-#ifdef TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# ifdef TM_IN_SYS_TIME
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
+
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif /* not HAVE_SYS_IOCTL_H */
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
/*
* This driver supports the Heath GC-1000 Most Accurate Clock, with
* RS232C Output Accessory. This is a WWV/WWVH receiver somewhat less
@@ -41,15 +32,21 @@
* occasionally being rudely stepped when the offset exceeds the default
* clock_max of 128 ms.
*
- * The internal DIPswitches should be set to operate at 1200 baud in
- * MANUAL mode and the current year. The external DIPswitches should be
- * set to GMT and 24-hour format, or to the host local time zone (with
- * DST) and 12-hour format. It is very important that the year be
- * set correctly in the DIPswitches. Otherwise, the day of year will be
- * incorrect after 28 April[?] of a normal or leap year. In 12-hour mode
- * with DST selected the clock will be incorrect by an hour for an
- * indeterminate amount of time between 0000Z and 0200 on the day DST
- * changes.
+ * There are two GC-1000 versions supported by this driver. The original
+ * GC-1000 with RS-232 output first appeared in 1983, but dissapeared
+ * from the market a few years later. The GC-1000 II with RS-232 output
+ * first appeared circa 1990, but apparently is no longer manufactured.
+ * The two models differ considerably, both in interface and commands.
+ * The GC-1000 has a pseudo-bipolar timecode output triggered by a RTS
+ * transition. The timecode includes both the day of year and time of
+ * day. The GC-1000 II has a true bipolar output and a complement of
+ * single character commands. The timecode includes only the time of
+ * day.
+ *
+ * GC-1000
+ *
+ * The internal DIPswitches should be set to operate in MANUAL mode. The
+ * external DIPswitches should be set to GMT and 24-hour format.
*
* In MANUAL mode the clock responds to a rising edge of the request to
* send (RTS) modem control line by sending the timecode. Therefore, it
@@ -81,6 +78,72 @@
* established and hh:mm:ss.? once synchronization is established and
* then lost again for about a day.
*
+ * GC-1000 II
+ *
+ * Commands consist of a single letter and are case sensitive. When
+ * enterred in lower case, a description of the action performed is
+ * displayed. When enterred in upper case the action is performed.
+ * Following is a summary of descriptions as displayed by the clock:
+ *
+ * The clock responds with a command The 'A' command returns an ASCII
+ * local time string: HH:MM:SS.T xx<CR>, where
+ *
+ * HH = hours
+ * MM = minutes
+ * SS = seconds
+ * T = tenths-of-seconds
+ * xx = 'AM', 'PM', or ' '
+ * <CR> = carriage return
+ *
+ * The 'D' command returns 24 pairs of bytes containing the variable
+ * divisor value at the end of each of the previous 24 hours. This
+ * allows the timebase trimming process to be observed. UTC hour 00 is
+ * always returned first. The first byte of each pair is the high byte
+ * of (variable divisor * 16); the second byte is the low byte of
+ * (variable divisor * 16). For example, the byte pair 3C 10 would be
+ * returned for a divisor of 03C1 hex (961 decimal).
+ *
+ * The 'I' command returns: | TH | TL | ER | DH | DL | U1 | I1 | I2 | ,
+ * where
+ *
+ * TH = minutes since timebase last trimmed (high byte)
+ * TL = minutes since timebase last trimmed (low byte)
+ * ER = last accumulated error in 1.25 ms increments
+ * DH = high byte of (current variable divisor * 16)
+ * DL = low byte of (current variable divisor * 16)
+ * U1 = UT1 offset (/.1 s): | + | 4 | 2 | 1 | 0 | 0 | 0 | 0 |
+ * I1 = information byte 1: | W | C | D | I | U | T | Z | 1 | ,
+ * where
+ *
+ * W = set by WWV(H)
+ * C = CAPTURE LED on
+ * D = TRIM DN LED on
+ * I = HI SPEC LED on
+ * U = TRIM UP LED on
+ * T = DST switch on
+ * Z = UTC switch on
+ * 1 = UT1 switch on
+ *
+ * I2 = information byte 2: | 8 | 8 | 4 | 2 | 1 | D | d | S | ,
+ * where
+ *
+ * 8, 8, 4, 2, 1 = TIME ZONE switch settings
+ * D = DST bit (#55) in last-received frame
+ * d = DST bit (#2) in last-received frame
+ * S = clock is in simulation mode
+ *
+ * The 'P' command returns 24 bytes containing the number of frames
+ * received without error during UTC hours 00 through 23, providing an
+ * indication of hourly propagation. These bytes are updated each hour
+ * to reflect the previous 24 hour period. UTC hour 00 is always
+ * returned first.
+ *
+ * The 'T' command returns the UTC time: | HH | MM | SS | T0 | , where
+ * HH = tens-of-hours and hours (packed BCD)
+ * MM = tens-of-minutes and minutes (packed BCD)
+ * SS = tens-of-seconds and seconds (packed BCD)
+ * T = tenths-of-seconds (BCD)
+ *
* Fudge Factors
*
* A fudge time1 value of .04 s appears to center the clock offset
@@ -93,12 +156,12 @@
* Interface definitions
*/
#define DEVICE "/dev/heath%d" /* device name and unit */
-#define SPEED232 B1200 /* uart speed (1200 baud) */
#define PRECISION (-4) /* precision assumed (about 100 ms) */
#define REFID "WWV\0" /* reference ID */
#define DESCRIPTION "Heath GC-1000 Most Accurate Clock" /* WRU */
-#define LENHEATH 23 /* min timecode length */
+#define LENHEATH1 23 /* min timecode length */
+#define LENHEATH2 13 /* min timecode length */
/*
* Tables to compute the ddd of year form icky dd/mm timecode. Viva la
@@ -108,6 +171,12 @@ static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
/*
+ * Baud rate table. The GC-1000 supports 1200, 2400 and 4800; the
+ * GC-1000 II supports only 9600.
+ */
+static int speed[] = {B1200, B2400, B4800, B9600};
+
+/*
* Unit control structure
*/
struct heathunit {
@@ -136,65 +205,6 @@ struct refclock refclock_heath = {
NOFLAGS /* not used */
};
-#if 0
-/*
- * Gee, Unix so thoughfully omitted code to convert from a struct tm to
- * a long, so I'll just have to ferret out the inverse myself, the hard way.
- * (Newton's method.)
- */
-#define timelocal(x) invert(x, localtime)
-/*
- * comparetm compares two tm structures and returns -1 if the first
- * is less than the second, 0 if they are equal, and +1 if the first
- * is greater than the second. Only the year, month, day, hour, minute
- * and second are compared. The yearday (Julian), day of week, and isdst
- * are not compared.
- */
-
-static int
-comparetm(
- struct tm *a,
- struct tm *b
- )
-{
- if (a->tm_year < b->tm_year ) return -1;
- if (a->tm_year > b->tm_year ) return 1;
- if (a->tm_mon < b->tm_mon ) return -1;
- if (a->tm_mon > b->tm_mon ) return 1;
- if (a->tm_mday < b->tm_mday ) return -1;
- if (a->tm_mday > b->tm_mday ) return 1;
- if (a->tm_hour < b->tm_hour ) return -1;
- if (a->tm_hour > b->tm_hour ) return 1;
- if (a->tm_min < b->tm_min ) return -1;
- if (a->tm_min > b->tm_min ) return 1;
- if (a->tm_sec < b->tm_sec ) return -1;
- if (a->tm_sec > b->tm_sec ) return 1;
- return 0;
-}
-
-static long
-invert (
- struct tm *x,
- struct tm *(*func)()
- )
-{
- struct tm *y;
- int result;
- long trial;
- long lower=0L;
- long upper=(long)((unsigned long)(~lower) >> 1);
-
- do {
- trial = (upper + lower) / 2L;
- y = (*func)(&trial);
- result = comparetm(x, y);
- if (result < 0) upper = trial;
- if (result > 0) lower = trial;
- } while (result != 0);
- return trial;
-}
-#endif /* 0 */
-
/*
* heath_start - open the devices and initialize data for processing
@@ -214,7 +224,7 @@ heath_start(
* Open serial port
*/
(void)sprintf(device, DEVICE, unit);
- if (!(fd = refclock_open(device, SPEED232, 0)))
+ if (!(fd = refclock_open(device, speed[peer->ttlmax & 0x3], 0)))
return (0);
/*
@@ -291,7 +301,8 @@ heath_receive(
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct heathunit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
+ pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
+ &trtmp);
/*
* We get a buffer and timestamp for each <cr>; however, we use
@@ -314,76 +325,37 @@ heath_receive(
* its contents. If the timecode has invalid length or is not in
* proper format, we declare bad format and exit.
*/
- if (pp->lencode < LENHEATH) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
+ switch (pp->lencode) {
/*
- * Timecode format: "hh:mm:ss.f AM mm/dd/yy"
+ * GC-1000 timecode format: "hh:mm:ss.f AM mm/dd/yy"
+ * GC-1000 II timecode format: "hh:mm:ss.f "
*/
- if (sscanf(pp->a_lastcode, "%2d:%2d:%2d.%c%5c%2d/%2d/%2d",
- &pp->hour, &pp->minute, &pp->second, &dsec, a, &month, &day,
- &pp->year) != 8) {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
- }
-
- /*
- * If AM or PM is received, assume the clock is displaying local
- * time. First, convert to 24-hour format.
- */
-
- switch (a[1]) {
- case 'P':
- if (12 > pp->hour)
- pp->hour += 12;
- break;
-
- case 'A':
- if (12 == pp->hour)
- pp->hour -= 12;
+ case LENHEATH1:
+ if (sscanf(pp->a_lastcode,
+ "%2d:%2d:%2d.%c%5c%2d/%2d/%2d", &pp->hour,
+ &pp->minute, &pp->second, &dsec, a, &month, &day,
+ &pp->year) != 8) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
break;
- }
/*
- * Now make a struct tm out of it, convert to UTC, and
- * repopulate pp->
+ * GC-1000 II timecode format: "hh:mm:ss.f "
*/
-
- if (' ' != a[1]) {
- struct tm t, *q;
- time_t l;
-
- t.tm_sec = pp->second;
- t.tm_min = pp->minute;
- t.tm_hour = pp->hour;
- t.tm_mday = day; /* not converted to yday yet */
- t.tm_mon = month-1; /* ditto */
- t.tm_year = pp->year;
- if ( t.tm_year < YEAR_PIVOT ) t.tm_year += 100; /* Y2KFixes */
-
- t.tm_wday = -1; /* who knows? */
- t.tm_yday = -1; /* who knows? */
- t.tm_isdst = -1; /* who knows? */
-
- l = mktime(&t);
- if (l == -1) {
- /* HMS: do we want to do this? */
- refclock_report(peer, CEVNT_BADTIME);
+ 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;
}
- q = gmtime(&l);
-
- pp->year = q->tm_year;
- month = q->tm_mon+1;
- day = q->tm_mday; /* still not converted */
- pp->hour = q->tm_hour;
- /* pp->minute = q->tm_min; GC-1000 cannot adjust timezone */
- /* pp->second = q->tm_sec; by other than hour increments */
- }
+ break;
-
+ default:
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
/*
* We determine the day of the year from the DIPswitches. This
@@ -396,11 +368,6 @@ heath_receive(
* timecode accordingly. Icky pooh. This bit of nonsense could
* be avoided if the engineers had been required to write a
* device driver before finalizing the timecode format.
- *
- * Yes, I know this code incorrectly thinks that 2000 is a leap
- * year; but, the latest year that can be set by the DIPswitches
- * is 1997 anyay. Life is short.
- * Hey! Year 2000 IS a leap year! Y2KFixes
*/
if (month < 1 || month > 12 || day < 1) {
refclock_report(peer, CEVNT_BADTIME);
@@ -460,17 +427,20 @@ heath_poll(
pp->polls++;
/*
- * We toggle the RTS modem control lead to kick a timecode loose
- * from the radio. This code works only for POSIX and SYSV
- * interfaces. With bsd you are on your own. We take a timestamp
- * between the up and down edges to lengthen the pulse, which
- * should be about 50 usec on a Sun IPC. With hotshot CPUs, the
- * pulse might get too short. Later.
+ * We toggle the RTS modem control lead (GC-1000) and sent a T
+ * (GC-1000 II) to kick a timecode loose from the radio. This
+ * code works only for POSIX and SYSV interfaces. With bsd you
+ * are on your own. We take a timestamp between the up and down
+ * edges to lengthen the pulse, which should be about 50 usec on
+ * a Sun IPC. With hotshot CPUs, the pulse might get too short.
+ * Later.
*/
if (ioctl(pp->io.fd, TIOCMBIC, (char *)&bits) < 0)
refclock_report(peer, CEVNT_FAULT);
get_systime(&up->tstamp);
ioctl(pp->io.fd, TIOCMBIS, (char *)&bits);
+ if (write(pp->io.fd, "T", 1) != 1)
+ refclock_report(peer, CEVNT_FAULT);
if (peer->burst > 0)
return;
if (pp->coderecv == pp->codeproc) {
diff --git a/contrib/ntp/ntpd/refclock_hopfpci.c b/contrib/ntp/ntpd/refclock_hopfpci.c
new file mode 100644
index 0000000..a9deb21
--- /dev/null
+++ b/contrib/ntp/ntpd/refclock_hopfpci.c
@@ -0,0 +1,274 @@
+/*
+ * refclock_hopfpci.c
+ *
+ * - clock driver for hopf 6039 PCI board (GPS or DCF77)
+ * Bernd Altmeier altmeier@atlsoft.de
+ *
+ * latest source and further information can be found at:
+ * http://www.ATLSoft.de/ntp
+ *
+ * In order to run this driver you have to install and test
+ * the PCI-board driver for your system first.
+ *
+ * On Linux/UNIX
+ *
+ * The driver attempts to open the device /dev/hopf6039 .
+ * The device entry will be made by the installation process of
+ * the kernel module for the PCI-bus board. The driver sources
+ * belongs to the delivery equipment of the PCI-board.
+ *
+ * On Windows NT/2000
+ *
+ * The driver attempts to open the device by calling the function
+ * "OpenHopfDevice()". This function will be installed by the
+ * Device Driver for the PCI-bus board. The driver belongs to the
+ * delivery equipment of the PCI-board.
+ *
+ *
+ * Start 21.03.2000 Revision: 01.20
+ * changes 22.12.2000 Revision: 01.40 flag1 = 1 sync even if Quarz
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined(REFCLOCK) && defined(CLOCK_HOPF_PCI)
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_stdlib.h"
+
+#undef fileno
+#include <ctype.h>
+#undef fileno
+
+#ifndef SYS_WINNT
+# include <sys/ipc.h>
+# include <assert.h>
+# include <unistd.h>
+# include <stdio.h>
+# include "hopf6039.h"
+#else
+# include "hopf_PCI_io.h"
+#endif
+
+/*
+ * hopfpci interface definitions
+ */
+#define PRECISION (-10) /* precision assumed (1 ms) */
+#define REFID "hopf" /* reference ID */
+#define DESCRIPTION "hopf Elektronik PCI radio board"
+
+#define NSAMPLES 3 /* stages of median filter */
+#ifndef SYS_WINNT
+# define DEVICE "/dev/hopf6039" /* device name inode*/
+#else
+# define DEVICE "hopf6039" /* device name WinNT */
+#endif
+
+#define LEWAPWAR 0x20 /* leap second warning bit */
+
+#define HOPF_OPMODE 0xC0 /* operation mode mask */
+#define HOPF_INVALID 0x00 /* no time code available */
+#define HOPF_INTERNAL 0x40 /* internal clock */
+#define HOPF_RADIO 0x80 /* radio clock */
+#define HOPF_RADIOHP 0xC0 /* high precision radio clock */
+
+
+/*
+ * hopfclock unit control structure.
+ */
+struct hopfclock_unit {
+ short unit; /* NTP refclock unit number */
+ char leap_status; /* leap second flag */
+};
+int fd; /* file descr. */
+
+/*
+ * Function prototypes
+ */
+static int hopfpci_start (int, struct peer *);
+static void hopfpci_shutdown (int, struct peer *);
+static void hopfpci_poll (int unit, struct peer *);
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_hopfpci = {
+ hopfpci_start, /* start up driver */
+ hopfpci_shutdown, /* shut down driver */
+ hopfpci_poll, /* transmit poll message */
+ noentry, /* not used */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used */
+ NOFLAGS /* not used */
+};
+
+/*
+ * hopfpci_start - attach to hopf PCI board 6039
+ */
+static int
+hopfpci_start(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct refclockproc *pp;
+ struct hopfclock_unit *up;
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
+
+ if (!(up)) {
+ msyslog(LOG_ERR, "hopfPCIClock(%d) emalloc: %m",unit);
+#ifdef DEBUG
+ printf("hopfPCIClock(%d) emalloc\n",unit);
+#endif
+ return (0);
+ }
+ memset((char *)up, 0, sizeof(struct hopfclock_unit));
+
+#ifndef SYS_WINNT
+
+ fd = open(DEVICE,O_RDWR); /* try to open hopf clock device */
+
+#else
+ if (!OpenHopfDevice()){
+ msyslog(LOG_ERR,"Start: %s unit: %d failed!",DEVICE,unit);
+ return (0);
+ }
+#endif
+
+ pp = peer->procptr;
+ pp->io.clock_recv = noentry;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = -1;
+ pp->unitptr = (caddr_t)up;
+
+ get_systime(&pp->lastrec);
+
+ /*
+ * Initialize miscellaneous peer variables
+ */
+ if (pp->unitptr!=0) {
+ memcpy((char *)&pp->refid, REFID, 4);
+ peer->precision = PRECISION;
+ pp->clockdesc = DESCRIPTION;
+ up->leap_status = 0;
+ up->unit = (short) unit;
+ return (1);
+ }
+ else {
+ return 0;
+ }
+}
+
+
+/*
+ * hopfpci_shutdown - shut down the clock
+ */
+static void
+hopfpci_shutdown(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct refclockproc *pp;
+ register struct hopfpciTime *up;
+
+ pp = peer->procptr;
+ up = (struct hopfpciTime *)pp->unitptr;
+
+#ifndef SYS_WINNT
+ close(fd);
+#else
+ CloseHopfDevice();
+// UnmapViewOfFile (up);
+#endif
+}
+
+
+/*
+ * hopfpci_poll - called by the transmit procedure
+ */
+static void
+hopfpci_poll(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct refclockproc *pp;
+ register struct hopfpciTime *up;
+ HOPFTIME m_time;
+
+ pp = peer->procptr;
+ up = (struct hopfpciTime *)pp->unitptr;
+
+#ifndef SYS_WINNT
+ ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
+#else
+ GetHopfSystemTime(&m_time);
+#endif
+ pp->polls++;
+
+ pp->day = ymd2yd(m_time.wYear,m_time.wMonth,m_time.wDay);
+ pp->hour = m_time.wHour;
+ pp->minute = m_time.wMinute;
+ pp->second = m_time.wSecond;
+ pp->msec=m_time.wMilliseconds;
+ pp->usec=0;
+ if (m_time.wStatus & LEWAPWAR)
+ pp->leap = LEAP_ADDSECOND;
+ else
+ pp->leap = LEAP_NOWARNING;
+
+ sprintf(pp->a_lastcode,"ST: %02X T: %02d:%02d:%02d.%03d D: %02d.%02d.%04d",
+ m_time.wStatus, pp->hour, pp->minute, pp->second, pp->msec,
+ m_time.wDay, m_time.wMonth, m_time.wYear);
+ pp->lencode = strlen(pp->a_lastcode);
+
+ get_systime(&pp->lastrec);
+
+ /*
+ * If clock has no valid status then report error and exit
+ */
+ if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) { /* time ok? */
+ refclock_report(peer, CEVNT_BADTIME);
+ pp->leap = LEAP_NOTINSYNC;
+ return;
+ }
+
+ /*
+ * Test if time is running on internal quarz
+ * if CLK_FLAG1 is set, sychronize even if no radio operation
+ */
+
+ if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INTERNAL){
+ if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
+ refclock_report(peer, CEVNT_BADTIME);
+ pp->leap = LEAP_NOTINSYNC;
+ return;
+ }
+ }
+
+ if (!refclock_process(pp)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ refclock_receive(peer);
+
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+
+ return;
+}
+
+#else
+int refclock_hopfpci_bs;
+#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_hopfser.c b/contrib/ntp/ntpd/refclock_hopfser.c
new file mode 100644
index 0000000..a9d74dd
--- /dev/null
+++ b/contrib/ntp/ntpd/refclock_hopfser.c
@@ -0,0 +1,372 @@
+/*
+ *
+ * refclock_hopfser.c
+ * - clock driver for hopf serial boards (GPS or DCF77)
+ *
+ * Date: 30.03.2000 Revision: 01.10
+ *
+ * latest source and further information can be found at:
+ * http://www.ATLSoft.de/ntp
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if defined(REFCLOCK) && (defined(CLOCK_HOPF_SERIAL))
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_control.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_stdlib.h"
+
+#if defined HAVE_SYS_MODEM_H
+# include <sys/modem.h>
+# define TIOCMSET MCSETA
+# define TIOCMGET MCGETA
+# define TIOCM_RTS MRTS
+#endif
+
+#ifdef HAVE_TERMIOS_H
+# ifdef TERMIOS_NEEDS__SVID3
+# define _SVID3
+# endif
+# include <termios.h>
+# ifdef TERMIOS_NEEDS__SVID3
+# undef _SVID3
+# endif
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+
+/*
+ * clock definitions
+ */
+#define DESCRIPTION "hopf Elektronik serial clock" /* Long name */
+#define PRECISION (-10) /* precision assumed (about 1 ms) */
+#define REFID "hopf\0" /* reference ID */
+/*
+ * I/O definitions
+ */
+#define DEVICE "/dev/hopfclock%d" /* device name and unit */
+#define SPEED232 B9600 /* uart speed (9600 baud) */
+
+
+#define STX 0x02
+#define ETX 0x03
+#define CR 0x0c
+#define LF 0x0a
+
+/* parse states */
+#define REC_QUEUE_EMPTY 0
+#define REC_QUEUE_FULL 1
+
+#define HOPF_OPMODE 0x0C /* operation mode mask */
+#define HOPF_INVALID 0x00 /* no time code available */
+#define HOPF_INTERNAL 0x04 /* internal clock */
+#define HOPF_RADIO 0x08 /* radio clock */
+#define HOPF_RADIOHP 0x0C /* high precision radio clock */
+
+/*
+ * hopfclock unit control structure.
+ */
+struct hopfclock_unit {
+ l_fp laststamp; /* last receive timestamp */
+ short unit; /* NTP refclock unit number */
+ u_long polled; /* flag to detect noreplies */
+ char leap_status; /* leap second flag */
+ int rpt_next;
+};
+
+/*
+ * Function prototypes
+ */
+
+static int hopfserial_start P((int, struct peer *));
+static void hopfserial_shutdown P((int, struct peer *));
+static void hopfserial_receive P((struct recvbuf *));
+static void hopfserial_poll P((int, struct peer *));
+/* static void hopfserial_io P((struct recvbuf *)); */
+/*
+ * Transfer vector
+ */
+struct refclock refclock_hopfser = {
+ hopfserial_start, /* start up driver */
+ hopfserial_shutdown, /* shut down driver */
+ hopfserial_poll, /* transmit poll message */
+ noentry, /* not used */
+ noentry, /* initialize driver (not used) */
+ noentry, /* not used */
+ NOFLAGS /* not used */
+};
+
+/*
+ * hopfserial_start - open the devices and initialize data for processing
+ */
+static int
+hopfserial_start (
+ int unit,
+ struct peer *peer
+ )
+{
+ register struct hopfclock_unit *up;
+ struct refclockproc *pp;
+ int fd;
+ char gpsdev[20];
+
+#ifdef SYS_WINNT
+ (void) sprintf(gpsdev, "COM%d:", unit);
+#else
+ (void) sprintf(gpsdev, DEVICE, unit);
+#endif
+ /* LDISC_STD, LDISC_RAW
+ * Open serial port. Use CLK line discipline, if available.
+ */
+ fd = refclock_open(gpsdev, SPEED232, LDISC_CLK);
+ if (fd <= 0) {
+#ifdef DEBUG
+ printf("hopfSerialClock(%d) start: open %s failed\n", unit, gpsdev);
+#endif
+ return 0;
+ }
+
+ msyslog(LOG_NOTICE, "hopfSerialClock(%d) fd: %d dev: %s", unit, fd,
+ gpsdev);
+
+ /*
+ * Allocate and initialize unit structure
+ */
+ up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
+
+ if (!(up)) {
+ msyslog(LOG_ERR, "hopfSerialClock(%d) emalloc: %m",unit);
+#ifdef DEBUG
+ printf("hopfSerialClock(%d) emalloc\n",unit);
+#endif
+ (void) close(fd);
+ return (0);
+ }
+
+ memset((char *)up, 0, sizeof(struct hopfclock_unit));
+ pp = peer->procptr;
+ pp->unitptr = (caddr_t)up;
+ pp->io.clock_recv = hopfserial_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd;
+ if (!io_addclock(&pp->io)) {
+#ifdef DEBUG
+ printf("hopfSerialClock(%d) io_addclock\n",unit);
+#endif
+ (void) close(fd);
+ free(up);
+ return (0);
+ }
+
+ /*
+ * Initialize miscellaneous variables
+ */
+ pp->clockdesc = DESCRIPTION;
+ peer->precision = PRECISION;
+ peer->burst = NSTAGE;
+ memcpy((char *)&pp->refid, REFID, 4);
+
+ up->leap_status = 0;
+ up->unit = (short) unit;
+
+ return (1);
+}
+
+
+/*
+ * hopfserial_shutdown - shut down the clock
+ */
+static void
+hopfserial_shutdown (
+ int unit,
+ struct peer *peer
+ )
+{
+ register struct hopfclock_unit *up;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ up = (struct hopfclock_unit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ free(up);
+}
+
+
+
+/*
+ * hopfserial_receive - receive data from the serial interface
+ */
+
+static void
+hopfserial_receive (
+ struct recvbuf *rbufp
+ )
+{
+ struct hopfclock_unit *up;
+ struct refclockproc *pp;
+ struct peer *peer;
+
+ int sync; /* synchronization indicator */
+ int DoW; /* Dow */
+
+ int day, month; /* ddd conversion */
+
+ /*
+ * Initialize pointers and read the timecode and timestamp.
+ */
+ peer = (struct peer *)rbufp->recv_srcclock;
+ pp = peer->procptr;
+ up = (struct hopfclock_unit *)pp->unitptr;
+
+ if (up->rpt_next == 0 )
+ return;
+
+
+ up->rpt_next = 0; /* wait until next poll interval occur */
+
+ pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
+
+ if (pp->lencode == 0)
+ return;
+
+ sscanf(pp->a_lastcode,
+#if 1
+ "%1x%1x%2d%2d%2d%2d%2d%2d", /* ...cr,lf */
+#else
+ "%*c%1x%1x%2d%2d%2d%2d%2d%2d", /* stx...cr,lf,etx */
+#endif
+ &sync,
+ &DoW,
+ &pp->hour,
+ &pp->minute,
+ &pp->second,
+ &day,
+ &month,
+ &pp->year);
+
+
+ /*
+ Validate received values at least enough to prevent internal
+ array-bounds problems, etc.
+ */
+ if((pp->hour < 0) || (pp->hour > 23) ||
+ (pp->minute < 0) || (pp->minute > 59) ||
+ (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||
+ (day < 1) || (day > 31) ||
+ (month < 1) || (month > 12) ||
+ (pp->year < 0) || (pp->year > 99)) {
+ /* Data out of range. */
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+ /*
+ some preparations
+ */
+ pp->day = ymd2yd(pp->year,month,day);
+ pp->leap=0;
+
+ /* Year-2000 check! */
+ /* wrap 2-digit date into 4-digit */
+
+ if(pp->year < YEAR_PIVOT) { pp->year += 100; } /* < 98 */
+ pp->year += 1900;
+
+ /* preparation for timecode ntpq rl command ! */
+
+#if 0
+ wsprintf(pp->a_lastcode,
+ "STATUS: %1X%1X, DATE: %02d.%02d.%04d TIME: %02d:%02d:%02d",
+ sync,
+ DoW,
+ day,
+ month,
+ pp->year,
+ pp->hour,
+ pp->minute,
+ pp->second);
+
+ pp->lencode = strlen(pp->a_lastcode);
+ if ((sync && 0xc) == 0 ){ /* time ok? */
+ refclock_report(peer, CEVNT_BADTIME);
+ pp->leap = LEAP_NOTINSYNC;
+ return;
+ }
+#endif
+ /*
+ * If clock has no valid status then report error and exit
+ */
+ if ((sync & HOPF_OPMODE) == HOPF_INVALID ){ /* time ok? */
+ refclock_report(peer, CEVNT_BADTIME);
+ pp->leap = LEAP_NOTINSYNC;
+ return;
+ }
+
+ /*
+ * Test if time is running on internal quarz
+ * if CLK_FLAG1 is set, sychronize even if no radio operation
+ */
+
+ if ((sync & HOPF_OPMODE) == HOPF_INTERNAL){
+ if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
+ refclock_report(peer, CEVNT_BADTIME);
+ pp->leap = LEAP_NOTINSYNC;
+ return;
+ }
+ }
+
+
+ if (!refclock_process(pp)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ refclock_receive(peer);
+
+#if 0
+ msyslog(LOG_ERR, " D:%x D:%d D:%d",sync,pp->minute,pp->second);
+#endif
+
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+
+ return;
+}
+
+
+/*
+ * hopfserial_poll - called by the transmit procedure
+ *
+ */
+static void
+hopfserial_poll (
+ int unit,
+ struct peer *peer
+ )
+{
+ register struct hopfclock_unit *up;
+ struct refclockproc *pp;
+ pp = peer->procptr;
+
+ up = (struct hopfclock_unit *)pp->unitptr;
+
+ pp->polls++;
+ up->rpt_next = 1;
+
+#if 0
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+#endif
+
+ return;
+}
+
+#else
+int refclock_hopfser_bs;
+#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_hpgps.c b/contrib/ntp/ntpd/refclock_hpgps.c
index 30aa494..7a506cf 100644
--- a/contrib/ntp/ntpd/refclock_hpgps.c
+++ b/contrib/ntp/ntpd/refclock_hpgps.c
@@ -1,21 +1,21 @@
/*
* refclock_hpgps - clock driver for HP 58503A GPS receiver
*/
+
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_HPGPS)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/* Version 0.1 April 1, 1995
* 0.2 April 25, 1995
* tolerant of missing timecode response prompt and sends
diff --git a/contrib/ntp/ntpd/refclock_irig.c b/contrib/ntp/ntpd/refclock_irig.c
index ab4b525..7efd57e 100644
--- a/contrib/ntp/ntpd/refclock_irig.c
+++ b/contrib/ntp/ntpd/refclock_irig.c
@@ -7,19 +7,19 @@
#if defined(REFCLOCK) && defined(CLOCK_IRIG)
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_calendar.h"
+#include "ntp_stdlib.h"
+
#include <stdio.h>
#include <ctype.h>
-#include <sys/time.h>
#include <math.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif /* HAVE_SYS_IOCTL_H */
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_refclock.h"
-#include "ntp_calendar.h"
-#include "ntp_stdlib.h"
#include "audio.h"
/*
@@ -140,6 +140,7 @@
/*
* Interface definitions
*/
+#define DEVICE_AUDIO "/dev/audio" /* audio device name */
#define PRECISION (-17) /* precision assumed (about 10 us) */
#define REFID "IRIG" /* reference ID */
#define DESCRIPTION "Generic IRIG Audio Driver" /* WRU */
@@ -310,7 +311,7 @@ irig_start(
/*
* Open audio device
*/
- fd = audio_init();
+ fd = audio_init(DEVICE_AUDIO);
if (fd < 0)
return (0);
#ifdef DEBUG
diff --git a/contrib/ntp/ntpd/refclock_jupiter.c b/contrib/ntp/ntpd/refclock_jupiter.c
index b337e0c..4d1d4c2 100644
--- a/contrib/ntp/ntpd/refclock_jupiter.c
+++ b/contrib/ntp/ntpd/refclock_jupiter.c
@@ -37,10 +37,6 @@
#if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(PPS)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
@@ -48,6 +44,9 @@
#include "ntp_stdlib.h"
#include "ntp_calendar.h"
+#include <stdio.h>
+#include <ctype.h>
+
#include "jupiter.h"
#include <sys/ppsclock.h>
@@ -681,7 +680,7 @@ jupiter_process(register struct peer *peer)
*/
for (i = 0; i < NSAMPLES; i++)
off[i] = up->filter[i];
- qsort((char *)off, NSAMPLES, sizeof(l_fp), jupiter_cmpl_fp);
+ qsort((char *)off, (size_t)NSAMPLES, sizeof(l_fp), jupiter_cmpl_fp);
/*
* Reject the furthest from the median of NSAMPLES samples until
diff --git a/contrib/ntp/ntpd/refclock_leitch.c b/contrib/ntp/ntpd/refclock_leitch.c
index edee3f8..42b02fc 100644
--- a/contrib/ntp/ntpd/refclock_leitch.c
+++ b/contrib/ntp/ntpd/refclock_leitch.c
@@ -1,21 +1,21 @@
/*
* refclock_leitch - clock driver for the Leitch CSD-5300 Master Clock
*/
+
#ifdef HAVE_CONFIG_H
-#include <config.h>
+# include <config.h>
#endif
#if defined(REFCLOCK) && defined(CLOCK_LEITCH)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
+#include <stdio.h>
+#include <ctype.h>
+
#ifdef STREAM
#include <stropts.h>
#if defined(LEITCHCLK)
diff --git a/contrib/ntp/ntpd/refclock_local.c b/contrib/ntp/ntpd/refclock_local.c
index 12184db..a3e5773 100644
--- a/contrib/ntp/ntpd/refclock_local.c
+++ b/contrib/ntp/ntpd/refclock_local.c
@@ -8,14 +8,14 @@
#endif
#ifdef REFCLOCK
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
#include "ntpd.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
#ifdef KERNEL_PLL
#include "ntp_syscall.h"
#endif
@@ -34,7 +34,7 @@
* particular server's clock as the clock of last resort when all other
* normal synchronization sources have gone away. This is especially
* useful if that server has an ovenized oscillator. For this you would
- * configure this driver at a higher stratum (say 3 or 4) to prevent the
+ * configure this driver at a higher stratum (say 5) to prevent the
* server's stratum from falling below that.
*
* A third application for this driver is when an external discipline
@@ -69,7 +69,7 @@
*
* Fudge Factors
*
- * The stratum for this driver set at 3 by default, but it can be changed
+ * The stratum for this driver set at 5 by default, but it can be changed
* by the fudge command and/or the ntpdc utility. The reference ID is
* "LCL" by default, but can be changed using the same mechanism. *NEVER*
* configure this driver to operate at a stratum which might possibly
@@ -96,7 +96,7 @@
#define REFID "LCL\0" /* reference ID */
#define DESCRIPTION "Undisciplined local clock" /* WRU */
-#define STRATUM 3 /* default stratum */
+#define STRATUM 5 /* default stratum */
#define DISPERSION .01 /* default dispersion (10 ms) */
/*
@@ -213,7 +213,7 @@ local_poll(
refclock_process_offset(pp, pp->lastrec, pp->lastrec, pp->fudgetime1);
pp->leap = LEAP_NOWARNING;
pp->disp = DISPERSION;
- pp->variance = 0;
+ pp->jitter = 0;
#if defined(KERNEL_PLL) && defined(STA_CLK)
/*
@@ -246,7 +246,7 @@ local_poll(
pp->leap = LEAP_NOTINSYNC;
}
pp->disp = ntv.maxerror / 1e6;
- pp->variance = SQUARE(ntv.esterror / 1e6);
+ pp->jitter = SQUARE(ntv.esterror / 1e6);
}
} else {
ext_enable = 0;
diff --git a/contrib/ntp/ntpd/refclock_msfees.c b/contrib/ntp/ntpd/refclock_msfees.c
index db6c6b1..b1aaa56 100644
--- a/contrib/ntp/ntpd/refclock_msfees.c
+++ b/contrib/ntp/ntpd/refclock_msfees.c
@@ -11,16 +11,13 @@
* (hence probably didn't work). Still in RCS file at cl.cam.ac.uk
*/
-#include <ctype.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
#include "ntp_calendar.h"
+
+#include <ctype.h>
#if defined(HAVE_BSD_TTYS)
#include <sgtty.h>
#endif /* HAVE_BSD_TTYS */
@@ -1287,7 +1284,7 @@ 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, (u_int)samples, sizeof(l_fp), offcompare);
+ qsort((char *) coffs, (size_t)samples, sizeof(l_fp), offcompare);
noff = samples;
i = 0;
diff --git a/contrib/ntp/ntpd/refclock_mx4200.c b/contrib/ntp/ntpd/refclock_mx4200.c
index f08bb23..3c520b0 100644
--- a/contrib/ntp/ntpd/refclock_mx4200.c
+++ b/contrib/ntp/ntpd/refclock_mx4200.c
@@ -47,11 +47,7 @@
# include <config.h>
#endif
-#if defined(REFCLOCK) && defined(CLOCK_MX4200) && defined(PPS)
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
+#if defined(REFCLOCK) && defined(CLOCK_MX4200) && defined(HAVE_PPSAPI)
#include "ntpd.h"
#include "ntp_io.h"
@@ -59,11 +55,11 @@
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
#include "mx4200.h"
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
#ifdef HAVE_SYS_TERMIOS_H
# include <sys/termios.h>
#endif
@@ -73,7 +69,7 @@
#ifndef HAVE_STRUCT_PPSCLOCKEV
struct ppsclockev {
-# ifdef HAVE_TIMESPEC
+# ifdef HAVE_STRUCT_TIMESPEC
struct timespec tv;
# else
struct timeval tv;
@@ -82,6 +78,14 @@ 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
+
/*
* This driver supports the Magnavox Model MX 4200 GPS Receiver
* adapted to precision timing applications. It requires the
@@ -97,7 +101,7 @@ struct ppsclockev {
/*
* Check this every time you edit the code!
*/
-#define YEAR_RIGHT_NOW 1998
+#define YEAR_LAST_MODIFIED 2000
/*
* GPS Definitions
@@ -117,13 +121,6 @@ struct ppsclockev {
/*
* Position Averaging.
- * Reference: Dr. Thomas A. Clark's Totally Accurate Clock (TAC) files at
- * ftp://aleph.gsfc.nasa.gov/GPS/totally.accurate.clock/
- * For a 6-channel Motorola Oncore, he indicates that good nominal
- * HDOP and VDOP are 1.50 and 2.00 respectively. Given the relationship
- * HDOP^2 = NDOP^2 + EDOP^2 and assuming EDOP and NDOP are equal, we
- * have a nominal NDOP = EDOP = sqrt((HDOP*HDOP)/2). An 8-channel
- * Oncore does well with HDOP=1.20 and VDOP=1.70.
*/
#define INTERVAL 1 /* Interval between position measurements (s) */
#define AVGING_TIME 24 /* Number of hours to average */
@@ -141,18 +138,16 @@ struct mx4200unit {
double avg_lon; /* average longitude */
double avg_alt; /* average height */
double central_meridian; /* central meridian */
- double filt_lat; /* latitude filter length */
- double filt_lon; /* longitude filter length */
- double filt_alt; /* height filter length */
- double edop; /* EDOP (east DOP) */
- double ndop; /* NDOP (north DOP) */
- double vdop; /* VDOP (vertical DOP) */
+ double N_fixes; /* Number of position measurements */
int last_leap; /* leap second warning */
u_int moving; /* mobile platform? */
u_long sloppyclockflag; /* fudge flags */
u_int known; /* position known yet? */
u_long clamp_time; /* when to stop postion averaging */
u_long log_time; /* when to print receiver status */
+ pps_handle_t pps_h;
+ pps_params_t pps_p;
+ pps_info_t pps_i;
};
static char pmvxg[] = "PMVXG";
@@ -181,14 +176,13 @@ static void mx4200_poll P((int, struct peer *));
static char * mx4200_parse_t P((struct peer *));
static char * mx4200_parse_p P((struct peer *));
-static char * mx4200_parse_d P((struct peer *));
static char * mx4200_parse_s P((struct peer *));
#ifdef QSORT_USES_VOID_P
int mx4200_cmpl_fp P((const void *, const void *));
#else
int mx4200_cmpl_fp P((const l_fp *, const l_fp *));
#endif /* not QSORT_USES_VOID_P */
-static void mx4200_config P((struct peer *));
+static int mx4200_config P((struct peer *));
static void mx4200_ref P((struct peer *));
static void mx4200_send P((struct peer *, char *, ...))
__attribute__ ((format (printf, 2, 3)));
@@ -239,6 +233,7 @@ mx4200_start(
* Allocate unit structure
*/
if (!(up = (struct mx4200unit *) emalloc(sizeof(struct mx4200unit)))) {
+ perror("emalloc");
(void) close(fd);
return (0);
}
@@ -263,8 +258,7 @@ mx4200_start(
memcpy((char *)&pp->refid, REFID, 4);
/* Ensure the receiver is properly configured */
- mx4200_config(peer);
- return (1);
+ return mx4200_config(peer);
}
@@ -290,7 +284,7 @@ mx4200_shutdown(
/*
* mx4200_config - Configure the receiver
*/
-static void
+static int
mx4200_config(
struct peer *peer
)
@@ -299,6 +293,7 @@ mx4200_config(
int add_mode;
register struct mx4200unit *up;
struct refclockproc *pp;
+ int mode;
pp = peer->procptr;
up = (struct mx4200unit *)pp->unitptr;
@@ -324,16 +319,52 @@ mx4200_config(
up->avg_lon = 0.0;
up->avg_alt = 0.0;
up->central_meridian = NOT_INITIALIZED;
- up->filt_lat = 0.0;
- up->filt_lon = 0.0;
- up->filt_alt = 0.0;
- up->edop = 1;
- up->ndop = 1;
- up->vdop = 1;
+ up->N_fixes = 0.0;
up->last_leap = 0; /* LEAP_NOWARNING */
up->clamp_time = current_time + (AVGING_TIME * 60 * 60);
up->log_time = current_time + SLEEPTIME;
+ if (time_pps_create(pp->io.fd, &up->pps_h) < 0) {
+ perror("time_pps_create");
+ msyslog(LOG_ERR,
+ "mx4200_config: time_pps_create failed: %m");
+ return (0);
+ }
+ if (time_pps_getcap(up->pps_h, &mode) < 0) {
+ msyslog(LOG_ERR,
+ "mx4200_config: time_pps_getcap failed: %m");
+ return (0);
+ }
+
+ if (time_pps_getparams(up->pps_h, &up->pps_p) < 0) {
+ msyslog(LOG_ERR,
+ "mx4200_config: time_pps_getparams failed: %m");
+ return (0);
+ }
+
+ /* nb. only turn things on, if someone else has turned something
+ * on before we get here, leave it alone!
+ */
+
+ up->pps_p.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
+ up->pps_p.mode &= mode; /* only set what is legal */
+
+ if (time_pps_setparams(up->pps_h, &up->pps_p) < 0) {
+ perror("time_pps_setparams");
+ msyslog(LOG_ERR,
+ "mx4200_config: time_pps_setparams failed: %m");
+ exit(1);
+ }
+
+ if (time_pps_kcbind(up->pps_h, PPS_KC_HARDPPS, PPS_CAPTUREASSERT,
+ PPS_TSFMT_TSPEC) < 0) {
+ perror("time_pps_kcbind");
+ msyslog(LOG_ERR,
+ "mx4200_config: time_pps_kcbind failed: %m");
+ exit(1);
+ }
+
+
/*
* "007" Control Port Configuration
* Zero the output list (do it twice to flush possible junk)
@@ -419,7 +450,7 @@ mx4200_config(
500, /* max time error in ns */
0, /* user bias in ns */
1); /* output "830" sentences to control port */
- /* Multi-satellite mode */
+ /* Multi-satellite mode */
/*
* Output position information (to calculate fixed installation
@@ -431,21 +462,6 @@ mx4200_config(
add_mode = 1; /* add to list */
}
- /*
- * "007" Control Port Configuration
- * Output "022" DOPs
- */
- mx4200_send(peer, "%s,%03d,%03d,%d,%d,,%d,,,", pmvxg,
- PMVXG_S_PORTCONF,
- PMVXG_D_DOPS, /* control port output block Label */
- 0, /* clear current output control list (0=no) */
- add_mode, /* add/delete sentences from list (1=add, 2=del) */
- /* must be null */
- INTERVAL); /* sentence output rate (sec) */
- /* precision for position output */
- /* nmea version for cga & gll output */
- /* pass-through control */
-
/*
* "007" Control Port Configuration
@@ -456,11 +472,13 @@ mx4200_config(
PMVXG_D_PHV, /* control port output block Label */
0, /* clear current output control list (0=no) */
add_mode, /* add/delete sentences from list (1=add, 2=del) */
- /* must be null */
+ /* must be null */
INTERVAL); /* sentence output rate (sec) */
- /* precision for position output */
- /* nmea version for cga & gll output */
- /* pass-through control */
+ /* precision for position output */
+ /* nmea version for cga & gll output */
+ /* pass-through control */
+
+ return (1);
}
/*
@@ -490,21 +508,6 @@ mx4200_ref(
/*
* "007" Control Port Configuration
- * Stop outputting "022" DOPs
- */
- mx4200_send(peer, "%s,%03d,%03d,%d,%d,,,,,", pmvxg,
- PMVXG_S_PORTCONF,
- PMVXG_D_DOPS, /* control port output block Label */
- 0, /* clear current output control list (0=no) */
- 2); /* add/delete sentences from list (2=delete) */
- /* must be null */
- /* sentence output rate (sec) */
- /* precision for position output */
- /* nmea version for cga & gll output */
- /* pass-through control */
-
- /*
- * "007" Control Port Configuration
* Stop outputting "021" position, height, velocity reports
*/
mx4200_send(peer, "%s,%03d,%03d,%d,%d,,,,,", pmvxg,
@@ -590,7 +593,7 @@ mx4200_ref(
lons, /* longitude DDDMM.MMMM */
ewc, /* east/west */
alt, /* Altitude */
- 1); /* Altitude Reference (0=WGS84 ellipsoid, 1=MSL geoid) */
+ 1); /* Altitude Reference (0=WGS84 ellipsoid, 1=MSL geoid)*/
msyslog(LOG_DEBUG,
"mx4200: reconfig to fixed location: %s %c, %s %c, %.2f m",
@@ -766,10 +769,14 @@ mx4200_receive(
sentence_type = strtol(cp, &cp, 10);
/*
- * "000" Status message
+ * Process the sentence according to its type.
*/
+ switch (sentence_type) {
- if (sentence_type == PMVXG_D_STATUS) {
+ /*
+ * "000" Status message
+ */
+ case PMVXG_D_STATUS:
/*
* XXX
* Since we configure the receiver to not give us status
@@ -785,52 +792,35 @@ mx4200_receive(
}
mx4200_debug(peer, "mx4200_receive: reset receiver\n");
mx4200_config(peer);
- return;
- }
+ break;
/*
* "021" Position, Height, Velocity message,
* if we are still averaging our position
*/
- if (sentence_type == PMVXG_D_PHV && !up->known) {
- /*
- * Parse the message, calculating our averaged position.
- */
- if ((cp = mx4200_parse_p(peer)) != NULL) {
- mx4200_debug(peer, "mx4200_receive: pos: %s\n", cp);
- return;
- }
- mx4200_debug(peer,
- "mx4200_receive: position avg %.9f %.9f %.4f\n",
- up->avg_lat, up->avg_lon, up->avg_alt);
- mx4200_debug(peer,
- "mx4200_receive: position len %.4f %.4f %.4f\n",
- up->filt_lat, up->filt_lon, up->filt_alt);
- mx4200_debug(peer,
- "mx4200_receive: position dop %.1f %.1f %.1f\n",
- up->ndop, up->edop, up->vdop);
- /*
- * Reinitialize as a reference station
- * if position is well known.
- */
- if (current_time > up->clamp_time) {
- up->known++;
- mx4200_debug(peer, "mx4200_receive: reconfiguring!\n");
- mx4200_ref(peer);
- }
- return;
- }
-
- /*
- * "022" DOPs, if we are still averaging our position
- */
- if (sentence_type == PMVXG_D_DOPS && !up->known) {
- if ((cp = mx4200_parse_d(peer)) != NULL) {
- mx4200_debug(peer, "mx4200_receive: dop: %s\n", cp);
- return;
+ case PMVXG_D_PHV:
+ if (!up->known) {
+ /*
+ * Parse the message, calculating our averaged position.
+ */
+ if ((cp = mx4200_parse_p(peer)) != NULL) {
+ mx4200_debug(peer, "mx4200_receive: pos: %s\n", cp);
+ return;
+ }
+ mx4200_debug(peer,
+ "mx4200_receive: position avg %f %.9f %.9f %.4f\n",
+ up->N_fixes, up->avg_lat, up->avg_lon, up->avg_alt);
+ /*
+ * Reinitialize as a reference station
+ * if position is well known.
+ */
+ if (current_time > up->clamp_time) {
+ up->known++;
+ mx4200_debug(peer, "mx4200_receive: reconfiguring!\n");
+ mx4200_ref(peer);
+ }
}
- return;
- }
+ break;
/*
* Print to the syslog:
@@ -838,21 +828,20 @@ mx4200_receive(
* "030" Software Configuration
* "523" Time Recovery Parameters Currently in Use
*/
- if (sentence_type == PMVXG_D_MODEDATA ||
- sentence_type == PMVXG_D_SOFTCONF ||
- sentence_type == PMVXG_D_TRECOVUSEAGE ) {
+ case PMVXG_D_MODEDATA:
+ case PMVXG_D_SOFTCONF:
+ case PMVXG_D_TRECOVUSEAGE:
+
if ((cp = mx4200_parse_s(peer)) != NULL) {
mx4200_debug(peer,
"mx4200_receive: multi-record: %s\n", cp);
- return;
}
- return;
- }
+ break;
/*
* "830" Time Recovery Results message
*/
- if (sentence_type == PMVXG_D_TRECOVOUT) {
+ case PMVXG_D_TRECOVOUT:
/*
* Capture the last PPS signal.
@@ -911,12 +900,16 @@ mx4200_receive(
* Turn off the flag and return
*/
up->polled = 0;
- return;
- }
+ break;
/*
* Ignore all other sentence types
*/
+ default:
+ break;
+
+ } /* switch (sentence_type) */
+
return;
}
@@ -969,17 +962,19 @@ mx4200_parse_t(
struct mx4200unit *up;
char time_mark_valid, time_sync, op_mode;
int sentence_type, valid;
- int year, day_of_year, month, day_of_month, hour, minute, second, leapsec;
+ int year, day_of_year, month, day_of_month;
+ int hour, minute, second, leapsec;
int oscillator_offset, time_mark_error, time_bias;
pp = peer->procptr;
up = (struct mx4200unit *)pp->unitptr;
leapsec = 0; /* Not all receivers output leap second warnings (!) */
- sscanf(pp->a_lastcode, "$PMVXG,%d,%c,%d,%d,%d,%d:%d:%d,%c,%c,%d,%d,%d,%d",
+ sscanf(pp->a_lastcode,
+ "$PMVXG,%d,%c,%d,%d,%d,%d:%d:%d,%c,%c,%d,%d,%d,%d",
&sentence_type, &time_mark_valid, &year, &month, &day_of_month,
- &hour, &minute, &second, &time_sync, &op_mode, &oscillator_offset,
- &time_mark_error, &time_bias, &leapsec);
+ &hour, &minute, &second, &time_sync, &op_mode,
+ &oscillator_offset, &time_mark_error, &time_bias, &leapsec);
if (sentence_type != PMVXG_D_TRECOVOUT)
return ("wrong rec-type");
@@ -1029,7 +1024,7 @@ mx4200_parse_t(
* (Certainly can't be any year before this code was last altered!)
*/
if (day_of_month > 31 || month > 12 ||
- day_of_month < 1 || month < 1 || year < YEAR_RIGHT_NOW) {
+ day_of_month < 1 || month < 1 || year < YEAR_LAST_MODIFIED) {
mx4200_debug(peer,
"mx4200_parse_t: bad date (%4d-%02d-%02d)\n",
year, month, day_of_month);
@@ -1250,7 +1245,7 @@ mx4200_parse_p(
struct refclockproc *pp;
struct mx4200unit *up;
int sentence_type, mode;
- double mtime, lat, lon, alt, geoid, vele, veln, weight;
+ double mtime, lat, lon, alt, geoid, vele, veln;
char north_south, east_west;
pp = peer->procptr;
@@ -1259,9 +1254,10 @@ mx4200_parse_p(
/* Should never happen! */
if (up->moving) return ("mobile platform - no pos!");
- sscanf ( pp->a_lastcode, "$PMVXG,%d,%lf,%lf,%c,%lf,%c,%lf,%lf,%lf,%lf,%d",
- &sentence_type, &mtime, &lat, &north_south, &lon, &east_west, &alt,
- &geoid, &vele, &veln, &mode);
+ sscanf ( pp->a_lastcode,
+ "$PMVXG,%d,%lf,%lf,%c,%lf,%c,%lf,%lf,%lf,%lf,%d",
+ &sentence_type, &mtime, &lat, &north_south, &lon, &east_west,
+ &alt, &geoid, &vele, &veln, &mode);
/* Sentence type */
if (sentence_type != PMVXG_D_PHV)
@@ -1324,92 +1320,22 @@ mx4200_parse_p(
if (lon > 180.0) lon -= 360.0;
/*
- * Calculate running weighted averages
+ * Calculate running averages
*/
- weight = 1. / up->edop;
- weight *= weight;
- up->avg_lon = (up->filt_lon * up->avg_lon) + (weight * lon);
- up->filt_lon += weight;
- up->avg_lon = up->avg_lon / up->filt_lon;
-
- weight = 1. / up->ndop;
- weight *= weight;
- up->avg_lat = (up->filt_lat * up->avg_lat) + (weight * lat);
- up->filt_lat += weight;
- up->avg_lat = up->avg_lat / up->filt_lat;
-
- weight = 1. / up->vdop;
- weight *= weight;
- up->avg_alt = (up->filt_alt * up->avg_alt) + (weight * alt);
- up->filt_alt += weight;
- up->avg_alt = up->avg_alt / up->filt_alt;
- mx4200_debug(peer,
- "mx4200_receive: position rdg %.9f %.9f %.4f (CM=%.9f)\n",
- lat, lon, alt, up->central_meridian);
+ up->avg_lon = (up->N_fixes * up->avg_lon) + lon;
+ up->avg_lat = (up->N_fixes * up->avg_lat) + lat;
+ up->avg_alt = (up->N_fixes * up->avg_alt) + alt;
- return (NULL);
-}
+ up->N_fixes += 1.0;
-/*
- * Parse a mx4200 DOP sentence.
- *
- * A typical message looks like this. Checksum has already been stripped.
- *
- * $PMVXG,022,SSSSSS.SSEE.E,NN.N,VV.V,XX,XX,XX,XX,XX,XX
- *
- * Field Field Contents
- * ----- --------------
- * Block Label: $PMVXG
- * Sentence Type: 022=DOPs. The DOP values in this sentence
- * correspond to the satellites listed. The PRNs in
- * the message are listed in receiver channel number order
- * 1 UTC measurement time (seconds into week)
- * 2 EDOP (east DOP)
- * 3 NDOP (north DOP)
- * 4 VDOP (vertical DOP)
- * 5 PRN on channel 1
- * 6 PRN on channel 2
- * 7 PRN on channel 3
- * 8 PRN on channel 4
- * 9 PRN on channel 5
- * 10 PRN on channel 6
- * 11 PRN on channel 7 (12-channel receivers only)
- * 12 PRN on channel 8 (12-channel receivers only)
- * 13 PRN on channel 9 (12-channel receivers only)
- * 14 PRN on channel 10 (12-channel receivers only)
- * 15 PRN on channel 11 (12-channel receivers only)
- * 16 PRN on channel 12 (12-channel receivers only)
- */
-static char *
-mx4200_parse_d(
- struct peer *peer
- )
-{
- struct refclockproc *pp;
- struct mx4200unit *up;
- int sentence_type;
- double mtime, edop, ndop, vdop;
+ up->avg_lon /= up->N_fixes;
+ up->avg_lat /= up->N_fixes;
+ up->avg_alt /= up->N_fixes;
- pp = peer->procptr;
- up = (struct mx4200unit *)pp->unitptr;
-
- /* Should never happen! */
- if (up->moving) return ("mobile platform - no dop!");
-
- sscanf ( pp->a_lastcode, "$PMVXG,%d,%lf,%lf,%lf,%lf",
- &sentence_type, &mtime, &edop, &ndop, &vdop);
-
- /* Sentence type */
- if (sentence_type != PMVXG_D_DOPS)
- return ("wrong rec-type");
-
- /* Update values */
- if (edop <= 0.0 || ndop <= 0.0 || vdop <= 0.0)
- return ("nonpositive dop");
- up->edop = edop;
- up->ndop = ndop;
- up->vdop = vdop;
+ mx4200_debug(peer,
+ "mx4200_receive: position rdg %.0f: %.9f %.9f %.4f (CM=%.9f)\n",
+ up->N_fixes, lat, lon, alt, up->central_meridian);
return (NULL);
}
@@ -1551,19 +1477,19 @@ mx4200_parse_s(
case PMVXG_D_STATUS:
msyslog(LOG_DEBUG,
- "mx4200: status: %s", pp->a_lastcode);
+ "mx4200: status: %s", pp->a_lastcode);
break;
case PMVXG_D_MODEDATA:
msyslog(LOG_DEBUG,
- "mx4200: mode data: %s", pp->a_lastcode);
+ "mx4200: mode data: %s", pp->a_lastcode);
break;
case PMVXG_D_SOFTCONF:
msyslog(LOG_DEBUG,
- "mx4200: firmware configuration: %s", pp->a_lastcode);
+ "mx4200: firmware configuration: %s", pp->a_lastcode);
break;
case PMVXG_D_TRECOVUSEAGE:
msyslog(LOG_DEBUG,
- "mx4200: time recovery parms: %s", pp->a_lastcode);
+ "mx4200: time recovery parms: %s", pp->a_lastcode);
break;
default:
return ("wrong rec-type");
@@ -1573,7 +1499,7 @@ mx4200_parse_s(
}
/*
- * Process a PPS signal, returning a timestamp.
+ * Process a PPS signal, placing a timestamp in pp->lastrec.
*/
static int
mx4200_pps(
@@ -1584,13 +1510,7 @@ mx4200_pps(
struct refclockproc *pp;
struct mx4200unit *up;
- int request;
-#ifdef HAVE_CIOGETEV
- request = CIOGETEV;
-#endif
-#ifdef HAVE_TIOCGPPSEV
- request = TIOCGPPSEV;
-#endif
+ struct timespec timeout;
pp = peer->procptr;
up = (struct mx4200unit *)pp->unitptr;
@@ -1598,41 +1518,47 @@ mx4200_pps(
/*
* Grab the timestamp of the PPS signal.
*/
- temp_serial = up->ppsev.serial;
- if (ioctl(fdpps, request, (caddr_t)&up->ppsev) < 0) {
- /* XXX Actually, if this fails, we're pretty much screwed */
+ temp_serial = up->pps_i.assert_sequence;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 0;
+ if (time_pps_fetch(up->pps_h, PPS_TSFMT_TSPEC, &(up->pps_i),
+ &timeout) < 0) {
mx4200_debug(peer,
- "mx4200_pps: CIOGETEV/TIOCGPPSEV: serial=%d, fdpps=%d, %s\n",
- up->ppsev.serial, fdpps, strerror(errno));
+ "mx4200_pps: time_pps_fetch: serial=%d, %s\n",
+ up->pps_i.assert_sequence, strerror(errno));
refclock_report(peer, CEVNT_FAULT);
return(1);
}
- if (temp_serial == up->ppsev.serial) {
+ if (temp_serial == up->pps_i.assert_sequence) {
mx4200_debug(peer,
- "mx4200_pps: ppsev serial not incrementing: %d\n",
- up->ppsev.serial);
+ "mx4200_pps: assert_sequence serial not incrementing: %d\n",
+ up->pps_i.assert_sequence);
refclock_report(peer, CEVNT_FAULT);
return(1);
}
-
/*
* Check pps serial number against last one
*/
- if (up->lastserial + 1 != up->ppsev.serial && up->lastserial != 0) {
- if (up->ppsev.serial == up->lastserial)
+ if (up->lastserial + 1 != up->pps_i.assert_sequence &&
+ up->lastserial != 0) {
+ if (up->pps_i.assert_sequence == up->lastserial) {
mx4200_debug(peer, "mx4200_pps: no new pps event\n");
- else
+ } else {
mx4200_debug(peer, "mx4200_pps: missed %d pps events\n",
- up->ppsev.serial - up->lastserial - 1);
+ up->pps_i.assert_sequence - up->lastserial - 1);
+ }
refclock_report(peer, CEVNT_FAULT);
}
- up->lastserial = up->ppsev.serial;
+ up->lastserial = up->pps_i.assert_sequence;
/*
* Return the timestamp in pp->lastrec
*/
- up->ppsev.tv.tv_sec += (u_int32) JAN_1970;
- TVTOTS(&up->ppsev.tv,&pp->lastrec);
+
+ pp->lastrec.l_ui = up->pps_i.assert_timestamp.tv_sec +
+ (u_int32) JAN_1970;
+ pp->lastrec.l_uf = ((double)(up->pps_i.assert_timestamp.tv_nsec) *
+ 4.2949672960) + 0.5;
return(0);
}
diff --git a/contrib/ntp/ntpd/refclock_nmea.c b/contrib/ntp/ntpd/refclock_nmea.c
index d90f71c..e9304ee 100644
--- a/contrib/ntp/ntpd/refclock_nmea.c
+++ b/contrib/ntp/ntpd/refclock_nmea.c
@@ -9,16 +9,25 @@
#if defined(REFCLOCK) && defined(CLOCK_NMEA)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <time.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
+#endif /* HAVE_PPSAPI */
+
/*
* This driver supports the NMEA GPS Receiver with
*
@@ -27,6 +36,23 @@
* The receiver used spits out the NMEA sentences for boat navigation.
* And you thought it was an information superhighway. Try a raging river
* filled with rapids and whirlpools that rip away your data and warp time.
+ *
+ * If HAVE_PPSAPI is defined code to use the PPSAPI will be compiled in.
+ * On startup if initialization of the PPSAPI fails, it will fall back
+ * to the "normal" timestamps.
+ *
+ * The PPSAPI part of the driver understands fudge flag2 and flag3. If
+ * flag2 is set, it will use the clear edge of the pulse. If flag3 is
+ * set, kernel hardpps is enabled.
+ *
+ * GPS sentences other than RMC (the default) may be enabled by setting
+ * the relevent bits of 'mode' in the server configuration line
+ * server 127.127.20.x mode X
+ *
+ * bit 0 - enables RMC (1)
+ * bit 1 - enables GGA (2)
+ * bit 2 - enables GLL (4)
+ * multiple sentences may be selected
*/
/*
@@ -39,9 +65,11 @@
#endif
#define SPEED232 B4800 /* uart speed (4800 bps) */
#define PRECISION (-9) /* precision assumed (about 2 ms) */
-#define DCD_PRECISION (-20) /* precision assumed (about 1 us) */
+#define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
#define REFID "GPS\0" /* reference id */
#define DESCRIPTION "NMEA GPS Clock" /* who we are */
+#define NANOSECOND 1000000000 /* one second (ns) */
+#define RANGEGATE 500000 /* range gate (ns) */
#define LENNMEA 75 /* min timecode length */
@@ -59,6 +87,12 @@ struct nmeaunit {
int pollcnt; /* poll message counter */
int polled; /* Hand in a sample? */
l_fp tstamp; /* timestamp of last poll */
+#ifdef HAVE_PPSAPI
+ struct timespec ts; /* last timestamp */
+ pps_params_t pps_params; /* pps parameters */
+ pps_info_t pps_info; /* last pps data */
+ pps_handle_t handle; /* pps handlebars */
+#endif /* HAVE_PPSAPI */
};
/*
@@ -66,6 +100,12 @@ struct nmeaunit {
*/
static int nmea_start P((int, struct peer *));
static void nmea_shutdown P((int, struct peer *));
+#ifdef HAVE_PPSAPI
+static void nmea_control P((int, struct refclockstat *, struct
+ refclockstat *, struct peer *));
+static int nmea_ppsapi P((struct peer *, int, int));
+static int nmea_pps P((struct nmeaunit *, l_fp *));
+#endif /* HAVE_PPSAPI */
static void nmea_receive P((struct recvbuf *));
static void nmea_poll P((int, struct peer *));
static void gps_send P((int, const char *, struct peer *));
@@ -78,7 +118,11 @@ struct refclock refclock_nmea = {
nmea_start, /* start up driver */
nmea_shutdown, /* shut down driver */
nmea_poll, /* transmit poll message */
- noentry, /* handle control */
+#ifdef HAVE_PPSAPI
+ nmea_control, /* fudge control */
+#else
+ noentry, /* fudge control */
+#endif /* HAVE_PPSAPI */
noentry, /* initialize driver */
noentry, /* buginfo */
NOFLAGS /* not used */
@@ -130,13 +174,27 @@ nmea_start(
/*
* Initialize miscellaneous variables
*/
- peer->precision = DCD_PRECISION;
+ peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
up->pollcnt = 2;
gps_send(pp->io.fd,"$PMOTG,RMC,0000*1D\r\n", peer);
+#ifdef HAVE_PPSAPI
+ /*
+ * Start the PPSAPI interface if it is there. Default to use
+ * the assert edge and do not enable the kernel hardpps.
+ */
+ if (time_pps_create(fd, &up->handle) < 0) {
+ up->handle = 0;
+ msyslog(LOG_ERR,
+ "refclock_nmea: time_pps_create failed: %m");
+ return (1);
+ }
+ return(nmea_ppsapi(peer, 0, 0));
+#else
return (1);
+#endif /* HAVE_PPSAPI */
}
/*
@@ -153,10 +211,149 @@ nmea_shutdown(
pp = peer->procptr;
up = (struct nmeaunit *)pp->unitptr;
+#ifdef HAVE_PPSAPI
+ if (up->handle != 0)
+ time_pps_destroy(up->handle);
+#endif /* HAVE_PPSAPI */
io_closeclock(&pp->io);
free(up);
}
+#ifdef HAVE_PPSAPI
+/*
+ * nmea_control - fudge control
+ */
+static void
+nmea_control(
+ int unit, /* unit (not used */
+ struct refclockstat *in, /* input parameters (not uded) */
+ struct refclockstat *out, /* output parameters (not used) */
+ struct peer *peer /* peer structure pointer */
+ )
+{
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+ nmea_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
+ pp->sloppyclockflag & CLK_FLAG3);
+}
+
+
+/*
+ * Initialize PPSAPI
+ */
+int
+nmea_ppsapi(
+ struct peer *peer, /* peer structure pointer */
+ int enb_clear, /* clear enable */
+ int enb_hardpps /* hardpps enable */
+ )
+{
+ struct refclockproc *pp;
+ struct nmeaunit *up;
+ int capability;
+
+ pp = peer->procptr;
+ up = (struct nmeaunit *)pp->unitptr;
+ if (time_pps_getcap(up->handle, &capability) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_nmea: time_pps_getcap failed: %m");
+ return (0);
+ }
+ memset(&up->pps_params, 0, sizeof(pps_params_t));
+ if (enb_clear)
+ up->pps_params.mode = capability & PPS_CAPTURECLEAR;
+ else
+ up->pps_params.mode = capability & PPS_CAPTUREASSERT;
+ if (!up->pps_params.mode) {
+ msyslog(LOG_ERR,
+ "refclock_nmea: invalid capture edge %d",
+ !enb_clear);
+ return (0);
+ }
+ up->pps_params.mode |= PPS_TSFMT_TSPEC;
+ if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_nmea: time_pps_setparams failed: %m");
+ return (0);
+ }
+ if (enb_hardpps) {
+ if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
+ up->pps_params.mode & ~PPS_TSFMT_TSPEC,
+ PPS_TSFMT_TSPEC) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_nmea: time_pps_kcbind failed: %m");
+ return (0);
+ }
+ pps_enable = 1;
+ }
+ peer->precision = PPS_PRECISION;
+
+#if DEBUG
+ if (debug) {
+ time_pps_getparams(up->handle, &up->pps_params);
+ printf(
+ "refclock_ppsapi: capability 0x%x version %d mode 0x%x kern %d\n",
+ capability, up->pps_params.api_version,
+ up->pps_params.mode, enb_hardpps);
+ }
+#endif
+
+ return (1);
+}
+
+/*
+ * Get PPSAPI timestamps.
+ *
+ * Return 0 on failure and 1 on success.
+ */
+static int
+nmea_pps(
+ struct nmeaunit *up,
+ l_fp *tsptr
+ )
+{
+ pps_info_t pps_info;
+ struct timespec timeout, ts;
+ double dtemp;
+ l_fp tstmp;
+
+ /*
+ * Convert the timespec nanoseconds field to ntp l_fp units.
+ */
+ if (up->handle == 0)
+ return (0);
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 0;
+ memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
+ if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
+ &timeout) < 0)
+ return (0);
+ if (up->pps_params.mode & PPS_CAPTUREASSERT) {
+ if (pps_info.assert_sequence ==
+ up->pps_info.assert_sequence)
+ return (0);
+ ts = up->pps_info.assert_timestamp;
+ } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
+ if (pps_info.clear_sequence ==
+ up->pps_info.clear_sequence)
+ return (0);
+ ts = up->pps_info.clear_timestamp;
+ } else {
+ return (0);
+ }
+ if ((up->ts.tv_sec == ts.tv_sec) && (up->ts.tv_nsec == ts.tv_nsec))
+ return (0);
+ up->ts = ts;
+
+ tstmp.l_ui = ts.tv_sec + JAN_1970;
+ dtemp = ts.tv_nsec * FRAC / 1e9;
+ tstmp.l_uf = (u_int32)dtemp;
+ *tsptr = tstmp;
+ return (1);
+}
+#endif /* HAVE_PPSAPI */
+
/*
* nmea_receive - receive data from the serial interface
*/
@@ -168,11 +365,14 @@ nmea_receive(
register struct nmeaunit *up;
struct refclockproc *pp;
struct peer *peer;
- l_fp trtmp;
int month, day;
int i;
char *cp, *dp;
int cmdtype;
+ /* Use these variables to hold data until we decide its worth keeping */
+ char rd_lastcode[BMAX];
+ l_fp rd_tmp;
+ u_short rd_lencode;
/*
* Initialize pointers and read the timecode and timestamp
@@ -180,23 +380,18 @@ nmea_receive(
peer = (struct peer *)rbufp->recv_srcclock;
pp = peer->procptr;
up = (struct nmeaunit *)pp->unitptr;
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
+ rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
/*
* There is a case that a <CR><LF> gives back a "blank" line
*/
- if (pp->lencode == 0)
+ if (rd_lencode == 0)
return;
- /*
- * We get a buffer and timestamp for each <cr>.
- */
- pp->lastrec = up->tstamp = trtmp;
- up->pollcnt = 2;
#ifdef DEBUG
if (debug)
- printf("nmea: timecode %d %s\n", pp->lencode,
- pp->a_lastcode);
+ printf("nmea: gpsread %d %s\n", rd_lencode,
+ rd_lastcode);
#endif
/*
@@ -204,18 +399,31 @@ nmea_receive(
* we only care about a few of them. The most important being
* the $GPRMC format
* $GPRMC,hhmmss,a,fddmm.xx,n,dddmmm.xx,w,zz.z,yyy.,ddmmyy,dd,v*CC
- * $GPGGA,162617.0,4548.339,N,00837.719,E,1,07,0.97,00262,M,048,M,,*5D
+ * For Magellan (ColorTrak) GLL probably datum (order of sentences)
+ * also mode (0,1,2,3) select sentence ANY/ALL, RMC, GGA, GLL
+ * $GPGLL,3513.8385,S,14900.7851,E,232420.594,A*21
+ * $GPGGA,232420.59,3513.8385,S,14900.7851,E,1,05,3.4,00519,M,,,,*3F
+ * $GPRMB,...
+ * $GPRMC,232418.19,A,3513.8386,S,14900.7853,E,00.0,000.0,121199,12.,E*77
+ * $GPAPB,...
+ * $GPGSA,...
+ * $GPGSV,...
+ * $GPGSV,...
*/
-#define GPRMC 0
-#define GPXXX 1
-#define GPGCA 2
- cp = pp->a_lastcode;
+#define GPXXX 0
+#define GPRMC 1
+#define GPGGA 2
+#define GPGLL 4
+ cp = rd_lastcode;
cmdtype=0;
if(strncmp(cp,"$GPRMC",6)==0) {
cmdtype=GPRMC;
}
else if(strncmp(cp,"$GPGGA",6)==0) {
- cmdtype=GPGCA;
+ cmdtype=GPGGA;
+ }
+ else if(strncmp(cp,"$GPGLL",6)==0) {
+ cmdtype=GPGLL;
}
else if(strncmp(cp,"$GPXXX",6)==0) {
cmdtype=GPXXX;
@@ -223,14 +431,84 @@ nmea_receive(
else
return;
+
+ /* See if I want to process this message type */
+ if ( ((peer->ttlmax == 0) && (cmdtype != GPRMC))
+ || ((peer->ttlmax != 0) && !(cmdtype & peer->ttlmax)) )
+ return;
+
+ pp->lencode = rd_lencode;
+ strcpy(pp->a_lastcode,rd_lastcode);
+ cp = pp->a_lastcode;
+
+ pp->lastrec = up->tstamp = rd_tmp;
+ up->pollcnt = 2;
+
+#ifdef DEBUG
+ if (debug)
+ printf("nmea: timecode %d %s\n", pp->lencode,
+ pp->a_lastcode);
+#endif
+
+
+ /* Grab field depending on clock string type */
switch( cmdtype ) {
case GPRMC:
- case GPGCA:
/*
- * Check time code format of NMEA
+ * Test for synchronization. Check for quality byte.
+ */
+ dp = field_parse(cp,2);
+ if( dp[0] != 'A')
+ pp->leap = LEAP_NOTINSYNC;
+ else
+ pp->leap = LEAP_NOWARNING;
+
+ /* Now point at the time field */
+ dp = field_parse(cp,1);
+ break;
+
+
+ case GPGGA:
+ /*
+ * Test for synchronization. Check for quality byte.
*/
+ dp = field_parse(cp,6);
+ if( dp[0] == '0')
+ pp->leap = LEAP_NOTINSYNC;
+ else
+ pp->leap = LEAP_NOWARNING;
+ /* Now point at the time field */
dp = field_parse(cp,1);
+ break;
+
+
+ case GPGLL:
+ /*
+ * Test for synchronization. Check for quality byte.
+ */
+ dp = field_parse(cp,6);
+ if( dp[0] != 'A')
+ pp->leap = LEAP_NOTINSYNC;
+ else
+ pp->leap = LEAP_NOWARNING;
+
+ /* Now point at the time field */
+ dp = field_parse(cp,5);
+ break;
+
+
+ case GPXXX:
+ return;
+ default:
+ return;
+
+ }
+
+ /*
+ * Check time code format of NMEA
+ */
+
if( !isdigit((int)dp[0]) ||
!isdigit((int)dp[1]) ||
!isdigit((int)dp[2]) ||
@@ -242,40 +520,55 @@ nmea_receive(
return;
}
- /*
- * Test for synchronization. Check for quality byte.
- */
- dp = field_parse(cp,2);
- if( dp[0] != 'A') {
- refclock_report(peer, CEVNT_BADREPLY);
- return;
+
+ /*
+ * Convert time and check values.
+ */
+ pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
+ pp->minute = ((dp[2] - '0') * 10) + dp[3] - '0';
+ pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
+ /* Default to 0 milliseconds, if decimal convert milliseconds in
+ one, two or three digits
+ */
+ pp->msec = 0;
+ if (dp[6] == '.') {
+ if (isdigit((int)dp[7])) {
+ pp->msec = (dp[7] - '0') * 100;
+ if (isdigit((int)dp[8])) {
+ pp->msec += (dp[8] - '0') * 10;
+ if (isdigit((int)dp[9])) {
+ pp->msec += (dp[9] - '0');
+ }
+ }
}
- break;
- case GPXXX:
- return;
- default:
- return;
+ }
+ if (pp->hour > 23 || pp->minute > 59 || pp->second > 59
+ || pp->msec > 1000) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
}
- if (cmdtype ==GPGCA) {
- /* only time */
- time_t tt = time(NULL);
- struct tm * t = gmtime(&tt);
- day = t->tm_mday;
- month = t->tm_mon + 1;
- pp->year= t->tm_year;
- } else {
- dp = field_parse(cp,9);
+
/*
* Convert date and check values.
*/
- day = dp[0] - '0';
- day = (day * 10) + dp[1] - '0';
- month = dp[2] - '0';
- month = (month * 10) + dp[3] - '0';
- pp->year = dp[4] - '0';
- pp->year = (pp->year * 10) + dp[5] - '0';
+ if (cmdtype==GPRMC) {
+ dp = field_parse(cp,9);
+ day = dp[0] - '0';
+ day = (day * 10) + dp[1] - '0';
+ month = dp[2] - '0';
+ month = (month * 10) + dp[3] - '0';
+ pp->year = dp[4] - '0';
+ pp->year = (pp->year * 10) + dp[5] - '0';
+ }
+ else {
+ /* only time */
+ time_t tt = time(NULL);
+ struct tm * t = gmtime(&tt);
+ day = t->tm_mday;
+ month = t->tm_mon + 1;
+ pp->year= t->tm_year;
}
if (month < 1 || month > 12 || day < 1) {
@@ -283,6 +576,9 @@ nmea_receive(
return;
}
+ /* Hmmmm this will be a nono for 2100,2200,2300 but I don't think I'll be here */
+ /* good thing that 2000 is a leap year */
+ /* pp->year will be 00-99 if read from GPS, 00-> (years since 1900) from tm_year */
if (pp->year % 4) {
if (day > day1tab[month - 1]) {
refclock_report(peer, CEVNT_BADTIME);
@@ -300,19 +596,17 @@ nmea_receive(
}
pp->day = day;
- dp = field_parse(cp,1);
+
+#ifdef HAVE_PPSAPI
/*
- * Convert time and check values.
+ * If the PPSAPI is working, rather use its timestamps.
+ * assume that the PPS occurs on the second so blow any msec
*/
- pp->hour = ((dp[0] - '0') * 10) + dp[1] - '0';
- pp->minute = ((dp[2] - '0') * 10) + dp[3] - '0';
- pp->second = ((dp[4] - '0') * 10) + dp[5] - '0';
- pp->msec = 0;
-
- if (pp->hour > 23 || pp->minute > 59 || pp->second > 59) {
- refclock_report(peer, CEVNT_BADTIME);
- return;
+ if (nmea_pps(up, &rd_tmp) == 1) {
+ pp->lastrec = up->tstamp = rd_tmp;
+ pp->msec = 0;
}
+#endif /* HAVE_PPSAPI */
/*
* Process the new sample in the median filter and determine the
@@ -322,11 +616,14 @@ nmea_receive(
* time, which may cause a paranoid protocol module to chuck out
* the data.
*/
+
if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
return;
}
+
+
/*
* Only go on if we had been polled.
*/
@@ -336,7 +633,11 @@ nmea_receive(
refclock_receive(peer);
+ /* If we get here - what we got from the clock is OK, so say so */
+ refclock_report(peer, CEVNT_NOMINAL);
+
record_clock_stats(&peer->srcadr, pp->a_lastcode);
+
}
/*
diff --git a/contrib/ntp/ntpd/refclock_oncore.c b/contrib/ntp/ntpd/refclock_oncore.c
index e0ba177..dbb9f5d 100644
--- a/contrib/ntp/ntpd/refclock_oncore.c
+++ b/contrib/ntp/ntpd/refclock_oncore.c
@@ -9,6 +9,9 @@
* refclock_oncore.c
*
* Driver for some of the various the Motorola Oncore GPS receivers.
+ * should work with Basic, PVT6, VP, UT, UT+, GT, GT+, SL, M12.
+ * The receivers with TRAIM (VP, UT, UT+), will be more accurate than the others.
+ * The receivers without position hold (GT, GT+) will be less accurate.
*
* Tested with:
*
@@ -24,28 +27,40 @@
* MANUFACTUR DATE 6H07 MANUFACTUR DATE 7E02
* OPTIONS LIST IB
*
+ * (Basic) (M12)
+ * COPYRIGHT 1991-1996 MOTOROLA INC. COPYRIGHT 1991-2000 MOTOROLA INC.
+ * SFTW P/N # 98-P36830P SFTW P/N # 61-G10002A
+ * SOFTWARE VER # 8 SOFTWARE VER # 1
+ * SOFTWARE REV # 8 SOFTWARE REV # 3
+ * SOFTWARE DATE 06 Aug 1996 SOFTWARE DATE Mar 13 2000
+ * MODEL # B4121P1155 MODEL # P143T12NR1
+ * HDWR P/N # _ HWDR P/N # 1
+ * SERIAL # SSG0226478 SERIAL # P003UD
+ * MANUFACTUR DATE 7E02 MANUFACTUR DATE 0C27
+ * OPTIONS LIST IB
+ *
* --------------------------------------------------------------------------
* This code uses the two devices
- * /dev/oncore.serial.n
- * /dev/oncore.pps.n
+ * /dev/oncore.serial.n
+ * /dev/oncore.pps.n
* which may be linked to the same device.
* and can read initialization data from the file
- * /etc/ntp.oncoreN (where n and N are the unit number, viz 127.127.30.N)
- * or /etc/ntp.oncore
+ * /etc/ntp.oncoreN, /etc/ntp.oncore.N, or /etc/ntp.oncore, where
+ * n or N are the unit number, viz 127.127.30.N.
* --------------------------------------------------------------------------
* Reg.Clemens <reg@dwf.com> Sep98.
* Original code written for FreeBSD.
- * With these mods it works on SunOS, Solaris (untested) and Linux
- * (RedHat 5.1 2.0.35 + PPSKit, 2.1.126 + changes).
+ * With these mods it works on FreeBSD, SunOS, Solaris and Linux
+ * (SunOS 4.1.3 + ppsclock)
+ * (Solaris7 + MU4)
+ * (RedHat 5.1 2.0.35 + PPSKit, 2.1.126 + or later).
*
* Lat,Long,Ht, cable-delay, offset, and the ReceiverID (along with the
* state machine state) are printed to CLOCKSTATS if that file is enabled
* in /etc/ntp.conf.
*
* --------------------------------------------------------------------------
- */
-
-/*
+ *
* According to the ONCORE manual (TRM0003, Rev 3.2, June 1998, page 3.13)
* doing an average of 10000 valid 2D and 3D fixes is what the automatic
* site survey mode does. Looking at the output from the receiver
@@ -58,20 +73,26 @@
/*
* ONCORE_SHMEM_STATUS will create a mmap(2)'ed file named according to a
* "STATUS" line in the oncore config file, which contains the most recent
- * copy of all types of messages we recognize. This file can be mmap(2)'ed
+ * copy of all types of messages we recognize. This file can be mmap(2)'ed
* by monitoring and statistics programs.
+ *
+ * See separate HTML documentation for this option.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-#if defined(REFCLOCK) && defined(CLOCK_ONCORE)
+#if defined(REFCLOCK) && defined(CLOCK_ONCORE) && defined(HAVE_PPSAPI)
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_unixtime.h"
+#include "ntp_refclock.h"
+#include "ntp_stdlib.h"
#include <stdio.h>
#include <ctype.h>
-#include <sys/types.h>
-#include <sys/time.h>
#include <sys/stat.h>
#ifdef ONCORE_SHMEM_STATUS
# ifdef HAVE_SYS_MMAN_H
@@ -83,11 +104,11 @@
#endif /* ONCORE_SHMEM_STATUS */
#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
+# ifdef HAVE_TIMEPPS_H
+# include <timepps.h>
# else
# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
+# include <sys/timepps.h>
# endif
# endif
#endif
@@ -96,14 +117,8 @@
# include <sys/sio.h>
#endif
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
#ifdef HAVE_SYS_TERMIOS_H
-#include <sys/termios.h>
+# include <sys/termios.h>
#endif
#ifdef HAVE_SYS_PPSCLOCK_H
@@ -112,7 +127,7 @@
#ifndef HAVE_STRUCT_PPSCLOCKEV
struct ppsclockev {
-# ifdef HAVE_TIMESPEC
+# ifdef HAVE_STRUCT_TIMESPEC
struct timespec tv;
# else
struct timeval tv;
@@ -123,90 +138,163 @@ struct ppsclockev {
enum receive_state {
ONCORE_NO_IDEA,
+ ONCORE_ID_SENT,
ONCORE_RESET_SENT,
ONCORE_TEST_SENT,
- ONCORE_ID_SENT,
+ ONCORE_INIT,
ONCORE_ALMANAC,
ONCORE_RUN
};
enum site_survey_state {
ONCORE_SS_UNKNOWN,
+ ONCORE_SS_TESTING,
ONCORE_SS_HW,
ONCORE_SS_SW,
ONCORE_SS_DONE
};
+/* Model Name, derived from the @@Cj message.
+ * Used to initialize some variables.
+ */
+
+enum oncore_model {
+ ONCORE_BASIC,
+ ONCORE_PVT6,
+ ONCORE_VP,
+ ONCORE_UT,
+ ONCORE_UTPLUS,
+ ONCORE_GT,
+ ONCORE_GTPLUS,
+ ONCORE_SL,
+ ONCORE_M12,
+ ONCORE_UNKNOWN
+};
+
+/* the bits that describe these properties are in the same place
+ * on the VP/UT, but have moved on the M12. As such we extract
+ * them, and use them from this struct.
+ *
+ */
+
+struct RSM {
+ u_char posn0D;
+ u_char posn2D;
+ u_char posn3D;
+ u_char bad_almanac;
+ u_char bad_fix;
+};
+
+/* It is possible to test the VP/UT each cycle (@@Ea or equivalent) to
+ * see what mode it is in. The bits on the M12 are multiplexed with
+ * other messages, so we have to 'keep' the last known mode here.
+ */
+
+enum posn_mode {
+ MODE_UNKNOWN,
+ MODE_0D,
+ MODE_2D,
+ MODE_3D
+};
+
struct instance {
int unit; /* 127.127.30.unit */
+ struct refclockproc *pp;
+ struct peer *peer;
+
int ttyfd; /* TTY file descriptor */
int ppsfd; /* PPS file descriptor */
int statusfd; /* Status shm descriptor */
- u_char *shmem;
#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 */
- struct refclockproc *pp;
- struct peer *peer;
-
int Bj_day;
- long delay; /* ns */
+ u_long delay; /* ns */
long offset; /* ns */
+ u_char *shmem;
+ char *shmem_fname;
+ u_int shmem_Cb;
+ u_int shmem_Ba;
+ u_int shmem_Ea;
+ u_int shmem_Ha;
+ u_char shmem_first;
+ u_char shmem_reset;
+ u_char shmem_Posn;
+
double ss_lat;
double ss_long;
double ss_ht;
+ double dH;
int ss_count;
- u_char ss_ht_type;
- u_char posn_set;
+ u_char posn_set;
- u_char printed;
- u_char polled;
+ enum oncore_model model;
+ u_int version;
+ u_int revision;
+
+ u_char chan; /* 6 for PVT6 or BASIC, 8 for UT/VP, 12 for m12, 0 if unknown */
+ s_char traim; /* do we have traim? yes UT/VP, no BASIC, GT, -1 unknown, 0 no, +1 yes */
+ u_char traim_delay; /* seconds counter, waiting for reply */
+
+ struct RSM rsm; /* bits extracted from Receiver Status Msg in @@Ea */
+ u_char printed;
+ u_char polled;
int pollcnt;
u_int ev_serial;
int Rcvptr;
u_char Rcvbuf[500];
- u_char Ea[77];
- u_char En[70];
+ u_char Ea[160]; /* Ba, Ea or Ha */
+ u_char En[70]; /* Bn or En */
u_char Cj[300];
u_char As;
u_char Ay;
u_char Az;
+ u_char have_dH;
u_char init_type;
s_char saw_tooth;
- u_char timeout; /* flag to retry Cj after Fa reset */
- s_char assert;
+ u_int timeout; /* count to retry Cj after Fa self-test */
+ u_char count; /* cycles thru Ea before starting */
+ s_char assert;
+ u_int saw_At;
};
#define rcvbuf instance->Rcvbuf
#define rcvptr instance->Rcvptr
-static void oncore_consume P((struct instance *));
-static void oncore_poll P((int, struct peer *));
-static void oncore_read_config P((struct instance *));
-static void oncore_receive P((struct recvbuf *));
-static void oncore_sendmsg P((int fd, u_char *, u_int));
-static void oncore_shutdown P((int, struct peer *));
-static int oncore_start P((int, struct peer *));
-
-static void oncore_msg_any P((struct instance *, u_char *, u_int, int));
-static void oncore_msg_As P((struct instance *, u_char *, u_int));
-static void oncore_msg_At P((struct instance *, u_char *, u_int));
-static void oncore_msg_Ay P((struct instance *, u_char *, u_int));
-static void oncore_msg_Az P((struct instance *, u_char *, u_int));
-static void oncore_msg_Bj P((struct instance *, u_char *, u_int));
-static void oncore_msg_Cb P((struct instance *, u_char *, u_int));
-static void oncore_msg_Cf P((struct instance *, u_char *, u_int));
-static void oncore_msg_Cj P((struct instance *, u_char *, u_int));
-static void oncore_msg_Ea P((struct instance *, u_char *, u_int));
-static void oncore_msg_En P((struct instance *, u_char *, u_int));
-static void oncore_msg_Fa P((struct instance *, u_char *, u_int));
+static void oncore_consume P((struct instance *));
+static void oncore_poll P((int, struct peer *));
+static void oncore_read_config P((struct instance *));
+static void oncore_receive P((struct recvbuf *));
+static void oncore_sendmsg P((int fd, u_char *, size_t));
+static void oncore_shutdown P((int, struct peer *));
+static int oncore_start P((int, struct peer *));
+static void oncore_get_timestamp P((struct instance *, long, long));
+static void oncore_init_shmem P((struct instance *));
+static void oncore_print_As P((struct instance *));
+
+static void oncore_msg_any P((struct instance *, u_char *, size_t, int));
+static void oncore_msg_As P((struct instance *, u_char *, size_t));
+static void oncore_msg_At P((struct instance *, u_char *, size_t));
+static void oncore_msg_Ay P((struct instance *, u_char *, size_t));
+static void oncore_msg_Az P((struct instance *, u_char *, size_t));
+static void oncore_msg_BaEaHa P((struct instance *, u_char *, size_t));
+static void oncore_msg_Bj P((struct instance *, u_char *, size_t));
+static void oncore_msg_BnEn P((struct instance *, u_char *, size_t));
+static void oncore_msg_CaFaIa P((struct instance *, u_char *, size_t));
+static void oncore_msg_Cb P((struct instance *, u_char *, size_t));
+static void oncore_msg_Cf P((struct instance *, u_char *, size_t));
+static void oncore_msg_Cj P((struct instance *, u_char *, size_t));
+static void oncore_msg_Cj_id P((struct instance *, u_char *, size_t));
+static void oncore_msg_Cj_init P((struct instance *, u_char *, size_t));
+static void oncore_msg_Gj P((struct instance *, u_char *, size_t));
+static void oncore_msg_Sz P((struct instance *, u_char *, size_t));
struct refclock refclock_oncore = {
oncore_start, /* start up driver */
@@ -220,65 +308,83 @@ struct refclock refclock_oncore = {
/*
* Understanding the next bit here is not easy unless you have a manual
- * for the the UT or VP Oncore.
+ * for the the various Oncore Models.
*/
static struct msg_desc {
const char flag[3];
const int len;
- void (*handler) P((struct instance *, u_char *, u_int));
+ void (*handler) P((struct instance *, u_char *, size_t));
const char *fmt;
int shmem;
} oncore_messages[] = {
- /* Ea and En first since they're most common */
- { "Ea", 76, oncore_msg_Ea, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" },
- { "En", 69, oncore_msg_En, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC" },
- { "Ab", 10, 0, "" },
- { "Ac", 11, 0, "" },
- { "Ad", 11, 0, "" },
- { "Ae", 11, 0, "" },
- { "Af", 15, 0, "" },
- { "As", 20, oncore_msg_As, "" },
- { "At", 8, oncore_msg_At, "" },
- { "Aw", 8, 0, "" },
- { "Ay", 11, oncore_msg_Ay, "" },
- { "Az", 11, oncore_msg_Az, "" },
- { "AB", 8, 0, "" },
- { "Bb", 92, 0, "" },
- { "Bj", 8, oncore_msg_Bj, "" },
- { "Cb", 33, oncore_msg_Cb, "" },
- { "Cf", 7, oncore_msg_Cf, "" },
- { "Cg", 8, 0, "" },
- { "Ch", 9, 0, "" },
- { "Cj", 294, oncore_msg_Cj, "" },
- { "Ek", 71, 0, "" },
- { "Fa", 9, oncore_msg_Fa, "" },
- { "Sz", 8, 0, "" },
- { {0}, 7, 0, ""}
+ /* Ea and En first since they're most common */
+ { "Ea", 76, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC" },
+ { "Ba", 68, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdsC" },
+ { "Ha", 154, oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmaaaaoooohhhhmmmmVVvvhhddntimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddssrrccooooTTushmvvvvvvC" },
+ { "En", 69, oncore_msg_BnEn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC" },
+ { "Bn", 59, oncore_msg_BnEn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffC" },
+ { "Ab", 10, 0, "" },
+ { "Ac", 11, 0, "" },
+ { "Ad", 11, 0, "" },
+ { "Ae", 11, 0, "" },
+ { "Af", 15, 0, "" },
+ { "As", 20, oncore_msg_As, "" },
+ { "At", 8, oncore_msg_At, "" },
+ { "Au", 12, 0, "" },
+ { "Av", 8, 0, "" },
+ { "Aw", 8, 0, "" },
+ { "Ay", 11, oncore_msg_Ay, "" },
+ { "Az", 11, oncore_msg_Az, "" },
+ { "AB", 8, 0, "" },
+ { "Bb", 92, 0, "" },
+ { "Bj", 8, oncore_msg_Bj, "" },
+ { "Ca", 9, oncore_msg_CaFaIa, "" },
+ { "Cb", 33, oncore_msg_Cb, "" },
+ { "Cf", 7, oncore_msg_Cf, "" },
+ { "Cg", 8, 0, "" },
+ { "Ch", 9, 0, "" },
+ { "Cj", 294, oncore_msg_Cj, "" },
+ { "Ek", 71, 0, "" },
+ { "Fa", 9, oncore_msg_CaFaIa, "" },
+ { "Gd", 8, 0, "" },
+ { "Gj", 21, oncore_msg_Gj, "" },
+ { "Ia", 10, oncore_msg_CaFaIa, "" },
+ { "Sz", 8, oncore_msg_Sz, "" },
+ { {0}, 7, 0, "" }
};
-static unsigned int oncore_shmem_Cb;
-
/*
* Position Set.
*/
u_char oncore_cmd_Ad[] = { 'A', 'd', 0,0,0,0 };
u_char oncore_cmd_Ae[] = { 'A', 'e', 0,0,0,0 };
u_char oncore_cmd_Af[] = { 'A', 'f', 0,0,0,0, 0 };
+u_char oncore_cmd_Ga[] = { 'G', 'a', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
/*
* Position-Hold Mode
* Start automatic site survey
*/
-static u_char oncore_cmd_At[] = { 'A', 't', 2 };
+static u_char oncore_cmd_At0[] = { 'A', 't', 0 }; /* Posn Hold off */
+static u_char oncore_cmd_At1[] = { 'A', 't', 1 }; /* Posn Hold on */
+static u_char oncore_cmd_At2[] = { 'A', 't', 2 }; /* Start Site Survey */
/*
- * Position-Hold Position
+ * 0D/2D Position and Set.
*/
u_char oncore_cmd_As[] = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };
u_char oncore_cmd_Asx[]= { 'A', 's', 0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff,
0x7f, 0xff, 0xff, 0xff, 0xff };
+u_char oncore_cmd_Au[] = { 'A', 'u', 0,0,0,0,0 };
+
+u_char oncore_cmd_Av0[] = { 'A', 'v', 0 };
+u_char oncore_cmd_Av1[] = { 'A', 'v', 1 };
+
+u_char oncore_cmd_Gd0[] = { 'G', 'd', 0 }; /* 3D */
+u_char oncore_cmd_Gd1[] = { 'G', 'd', 1 }; /* 0D */
+u_char oncore_cmd_Gd2[] = { 'G', 'd', 2 }; /* 2D */
/*
* Set to UTC time (not GPS).
@@ -317,6 +423,7 @@ u_char oncore_cmd_Bb[] = { 'B', 'b', 1 };
* Request message once
*/
u_char oncore_cmd_Bj[] = { 'B', 'j', 0 };
+u_char oncore_cmd_Gj[] = { 'G', 'j' };
/*
* Set to Defaults
@@ -337,7 +444,11 @@ static u_char oncore_cmd_Cj[] = { 'C', 'j' };
* Position/Status/Data message
* Send once per second
*/
-static u_char oncore_cmd_Ea[] = { 'E', 'a', 1 };
+static u_char oncore_cmd_Ea[] = { 'E', 'a', 1 };
+static u_char oncore_cmd_Ba[] = { 'B', 'a', 1 };
+static u_char oncore_cmd_Ha[] = { 'H', 'a', 1 };
+static u_char oncore_cmd_Ea0[] = { 'E', 'a', 0 };
+static u_char oncore_cmd_Ba0[] = { 'B', 'a', 0 };
/*
* Position/Status Extension Msg
@@ -351,12 +462,17 @@ u_char oncore_cmd_Ek[] = { 'E', 'k', 0 }; /* just turn off */
* Alarm limit 1us
* PPS on when we have the first sat
*/
-static u_char oncore_cmd_En[] = { 'E', 'n', 1, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static u_char oncore_cmd_En[] = { 'E', 'n', 1, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static u_char oncore_cmd_En0[] = { 'E', 'n', 0, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static u_char oncore_cmd_Bn[] = { 'B', 'n', 1, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static u_char oncore_cmd_Bn0[] = { 'B', 'n', 0, 1, 0,10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/*
* Self-test
*/
-static u_char oncore_cmd_Fa[] = { 'F', 'a' };
+static u_char oncore_cmd_Ca[] = { 'C', 'a' }; /* 6 Chan */
+static u_char oncore_cmd_Fa[] = { 'F', 'a' }; /* 8 Chan */
+static u_char oncore_cmd_Ia[] = { 'I', 'a' }; /* 12 Chan */
#define DEVICE1 "/dev/oncore.serial.%d" /* name of serial device */
#define DEVICE2 "/dev/oncore.pps.%d" /* name of pps device */
@@ -370,7 +486,7 @@ static u_char oncore_cmd_Fa[] = { 'F', 'a' };
*/
/* to buffer, int w, u_char *buf */
-#define w32_buf(buf,w) { unsigned int i_tmp; \
+#define w32_buf(buf,w) { u_int i_tmp; \
i_tmp = (w<0) ? (~(-w)+1) : (w); \
(buf)[0] = (i_tmp >> 24) & 0xff; \
(buf)[1] = (i_tmp >> 16) & 0xff; \
@@ -390,9 +506,11 @@ extern int pps_assert;
extern int pps_hardpps;
+
/*
* oncore_start - initialize data for processing
*/
+
static int
oncore_start(
int unit,
@@ -452,22 +570,44 @@ oncore_start(
}
}
- /* Devices now open, initialize instance structure */
+ /* Devices now open, create instance structure for this unit */
- if (!(instance = (struct instance *)emalloc(sizeof *instance))) {
+ if (!(instance = (struct instance *) malloc(sizeof *instance))) {
perror("malloc");
close(fd1);
return (0);
}
memset((char *) instance, 0, sizeof *instance);
+
+ /* link instance up and down */
+
pp = peer->procptr;
- pp->unitptr = (caddr_t)instance;
- instance->unit = unit;
+ pp->unitptr = (caddr_t) instance;
+ instance->pp = pp;
+ instance->unit = unit;
+ instance->peer = peer;
+
+ /* initialize miscellaneous variables */
+
+ 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->assert = pps_assert;
+ instance->traim = -1;
+ instance->model = ONCORE_UNKNOWN;
+ instance->mode = MODE_UNKNOWN;
+ instance->site_survey = ONCORE_SS_UNKNOWN;
+
+ peer->precision = -26;
+ peer->minpoll = 4;
+ peer->maxpoll = 4;
+ pp->clockdesc = "Motorola Oncore GPS Receiver";
+ memcpy((char *)&pp->refid, "GPS\0", (size_t) 4);
/* go read any input data in /etc/ntp.oncoreX */
@@ -492,10 +632,10 @@ oncore_start(
}
/* nb. only turn things on, if someone else has turned something
- * on before we get here, leave it alone!
+ * on before we get here, leave it alone!
*/
- if (instance->assert) { /* nb, default or ON */
+ 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;
@@ -505,7 +645,7 @@ oncore_start(
instance->pps_p.clear_offset.tv_nsec = 0;
}
instance->pps_p.mode |= PPS_TSFMT_TSPEC;
- instance->pps_p.mode &= mode; /* only do it if it is legal */
+ instance->pps_p.mode &= mode; /* only set what is legal */
if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) {
perror("time_pps_setparams");
@@ -517,17 +657,17 @@ oncore_start(
perror("ONCORE: stat pps_device");
return(0);
}
-
+
/* must have hardpps ON, and fd2 must be the same device as on the pps line */
-
+
if (pps_hardpps && ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino))) {
- int i;
-
+ int i;
+
if (instance->assert)
i = PPS_CAPTUREASSERT;
else
i = PPS_CAPTURECLEAR;
-
+
if (i&mode) {
if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i,
PPS_TSFMT_TSPEC) < 0) {
@@ -535,27 +675,12 @@ oncore_start(
"refclock_ioctl: time_pps_kcbind failed: %m");
return (0);
}
+ pps_enable = 1;
}
}
}
#endif
- instance->pp = pp;
- instance->peer = peer;
- instance->o_state = ONCORE_NO_IDEA;
- cp = "state = ONCORE_NO_IDEA";
- record_clock_stats(&(instance->peer->srcadr), cp);
-
- /*
- * Initialize miscellaneous variables
- */
-
- peer->precision = -26;
- peer->minpoll = 4;
- peer->maxpoll = 4;
- pp->clockdesc = "Motorola UT/VP Oncore GPS Receiver";
- memcpy((char *)&pp->refid, "GPS\0", 4);
-
pp->io.clock_recv = oncore_receive;
pp->io.srcclock = (caddr_t)peer;
pp->io.datalen = 0;
@@ -566,26 +691,16 @@ oncore_start(
free(instance);
return (0);
}
- pp->unitptr = (caddr_t)instance;
/*
- * This will start the Oncore receiver.
- * We send info from config to Oncore later.
+ * This will return the Model Number of the Oncore receiver.
*/
- instance->timeout = 1;
- mode = instance->init_type;
- if (mode == 3 || mode == 4) {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cf, sizeof oncore_cmd_Cf);
- instance->o_state = ONCORE_RESET_SENT;
- cp = "state = ONCORE_RESET_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- } else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof oncore_cmd_Fa);
- instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ instance->o_state = ONCORE_ID_SENT;
+ cp = "state = ONCORE_ID SENT";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ instance->timeout = 4;
instance->pollcnt = 2;
return (1);
@@ -593,94 +708,25 @@ oncore_start(
-static void
-oncore_init_shmem(struct instance *instance, char *filename)
-{
-#ifdef ONCORE_SHMEM_STATUS
- int i, l, n;
- char *buf;
- struct msg_desc *mp;
- static unsigned int oncore_shmem_length;
-
- if (oncore_messages[0].shmem == 0) {
- n = 1;
- for (mp = oncore_messages; mp->flag[0]; mp++) {
- mp->shmem = n;
- /* Allocate space for multiplexed almanac */
- if (!strcmp(mp->flag, "Cb")) {
- oncore_shmem_Cb = n;
- n += (mp->len + 2) * 34;
- }
- n += mp->len + 2;
- }
- oncore_shmem_length = n + 2;
- fprintf(stderr, "ONCORE: SHMEM length: %d bytes\n", oncore_shmem_length);
- }
- instance->statusfd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644);
- if (instance->statusfd < 0) {
- perror(filename);
- exit(4);
- }
- buf = malloc(oncore_shmem_length);
- if (buf == NULL) {
- perror("malloc");
- exit(4);
- }
- memset(buf, 0, sizeof(buf));
- i = write(instance->statusfd, buf, oncore_shmem_length);
- if (i != oncore_shmem_length) {
- perror(filename);
- exit(4);
- }
- free(buf);
- instance->shmem = (u_char *) mmap(0, oncore_shmem_length,
- PROT_READ | PROT_WRITE,
-#ifdef MAP_HASSEMAPHORE
- MAP_HASSEMAPHORE |
-#endif
- MAP_SHARED,
- instance->statusfd, (off_t)0);
- if (instance->shmem == MAP_FAILED) {
- instance->shmem = 0;
- close (instance->statusfd);
- exit(4);
- }
- for (mp = oncore_messages; mp->flag[0]; mp++) {
- l = mp->shmem;
- instance->shmem[l + 0] = mp->len >> 8;
- instance->shmem[l + 1] = mp->len & 0xff;
- instance->shmem[l + 2] = '@';
- instance->shmem[l + 3] = '@';
- instance->shmem[l + 4] = mp->flag[0];
- instance->shmem[l + 5] = mp->flag[1];
- if (!strcmp(mp->flag, "Cb")) {
- for (i = 1; i < 35; i++) {
- instance->shmem[l + i * 35 + 0] = mp->len >> 8;
- instance->shmem[l + i * 35 + 1] = mp->len & 0xff;
- instance->shmem[l + i * 35 + 2] = '@';
- instance->shmem[l + i * 35 + 3] = '@';
- instance->shmem[l + i * 35 + 4] = mp->flag[0];
- instance->shmem[l + i * 35 + 5] = mp->flag[1];
- }
- }
- }
-#endif /* ONCORE_SHMEM_STATUS */
-}
-
/*
* Read Input file if it exists.
*/
+
static void
oncore_read_config(
struct instance *instance
)
{
/*
- * First we try to open the configuration file /etc/ntp.oncoreN, where
- * N is the unit number viz 127.127.30.N.
- * If we don't find it, then we try the file /etc/ntp.oncore.
+ * First we try to open the configuration file
+ * /etc/oncoreN
+ * where N is the unit number viz 127.127.30.N.
+ * If we don't find it we try
+ * /etc/ntp.oncore.N
+ * and then
+ * /etc/ntp.oncore
*
- * If we find NEITHER then we don't have the cable delay or PPS offset
+ * If we don't find any then we don't have the cable delay or PPS offset
* and we choose MODE (4) below.
*
* Five Choices for MODE
@@ -705,7 +751,8 @@ oncore_read_config(
* -------------------------------------------------------------------------------
*
* If we open one or the other of the files, we read it looking for
- * MODE, LAT, LON, (HT, HTGPS, HTMSL), DELAY, OFFSET
+ * MODE, LAT, LON, (HT, HTGPS, HTMSL), DELAY, OFFSET, ASSERT, CLEAR, STATUS,
+ * POSN3D, POSN2D, CHAN, TRAIM
* then initialize using method MODE. For Mode = (1,3) all of (LAT, LON, HT) must
* be present or mode reverts to (2,4).
*
@@ -723,26 +770,47 @@ oncore_read_config(
* DDD MMM.mmm
* DDD MMM SSS.sss
*
- * Expect to see one line with 'HT' (or 'HTMSL' or 'HTGPS') as first field.
- * followed by 1-2 fields. First is a number, the second is 'FT' or 'M'.
- * for feet or meters. HT is the same as HTGPS.
- * HTMSL = HT above mean_sea_level,
- * HTGPS = HT above GPS ellipse.
+ * Expect to see one line with 'HT' as first field,
+ * followed by 1-2 fields. First is a number, the second is 'FT' or 'M'
+ * for feet or meters. HT is the height above the GPS ellipsoid.
+ * If the reciever reports height in both GPS and MSL, then we will report
+ * the difference GPS-MSL on the clockstats file.
*
- * There are two optional lines, starting with DELAY and OFFSET, followed
+ * There is an optional line, starting with DELAY, followed
* by 1 or two fields. The first is a number (a time) the second is
* 'MS', 'US' or 'NS' for miliseconds, microseconds or nanoseconds.
- * DELAY is cable delay, typically a few tens of ns.
- * OFFSET is the offset of the PPS pulse from 0. (only fully implemented
+ * DELAY is cable delay, typically a few tens of ns.
+ *
+ * There is an optional line, starting with OFFSET, followed
+ * by 1 or two fields. The first is a number (a time) the second is
+ * 'MS', 'US' or 'NS' for miliseconds, microseconds or nanoseconds.
+ * OFFSET is the offset of the PPS pulse from 0. (only fully implemented
* with the PPSAPI, we need to be able to tell the Kernel about this
* offset if the Kernel PLL is in use, but can only do this presently
* when using the PPSAPI interface. If not using the Kernel PLL,
* then there is no problem.
*
- * There is another optional line, with either ASSERT or CLEAR on it, which
+ * There is an optional line, with either ASSERT or CLEAR on it, which
* determine which transition of the PPS signal is used for timing by the
* PPSAPI. If neither is present, then ASSERT is assumed.
*
+ * There are three options that have to do with using the shared memory opition.
+ * First, to enable the option there must be an ASSERT line with a file name.
+ * The file name is the file associated with the shared memory.
+ *
+ * In the shared memory there are three 'records' containing the @@Ea (or equivalent)
+ * data, and this contains the position data. There will always be data in the
+ * record cooresponding to the '0D' @@Ea record, and the user has a choice of
+ * filling the '3D' @@Ea record by specifying POSN3D, or the '2D' record by
+ * specifying POSN2D. In either case the '2D' or '3D' record is filled once
+ * every 15s.
+ *
+ * Two additional variables that can be set are CHAN and TRAIM. These should be
+ * set correctly by the code examining the @@Cj record, but we bring them out here
+ * to allow the user to override either the # of channels, or the existance of TRAIM.
+ * CHAN expects to be followed by in integer: 6, 8, or 12. TRAIM expects to be
+ * followed by YES or NO.
+ *
* So acceptable input would be
* # these are my coordinates (RWC)
* LON -106 34.610
@@ -752,16 +820,20 @@ oncore_read_config(
*/
FILE *fd;
- char *cp, *cc, *ca, line[100], units[2], device[20];
+ char *cp, *cc, *ca, line[100], units[2], device[20], Msg[160];
int i, sign, lat_flg, long_flg, ht_flg, mode;
double f1, f2, f3;
- sprintf(device, "%s%d", INIT_FILE, instance->unit);
- if ((fd=fopen(device, "r")) == NULL)
- if ((fd=fopen(INIT_FILE, "r")) == NULL) {
- instance->init_type = 4;
- return;
+ sprintf(device, "%s%d", INIT_FILE, instance->unit); /* try "ntp.oncore0" first */
+ if ((fd=fopen(device, "r")) == NULL) { /* it was in the original documentation */
+ sprintf(device, "%s.%d", INIT_FILE, instance->unit); /* then try "ntp.oncore.0 */
+ if ((fd=fopen(device, "r")) == NULL) {
+ if ((fd=fopen(INIT_FILE, "r")) == NULL) { /* and finally "ntp.oncore" */
+ instance->init_type = 4;
+ return;
+ }
}
+ }
mode = 0;
lat_flg = long_flg = ht_flg = 0;
@@ -770,7 +842,7 @@ oncore_read_config(
/* Remove comments */
if ((cp = strchr(line, '#')))
*cp = '\0';
-
+
/* Remove trailing space */
for (i = strlen(line);
i > 0 && isascii((int)line[i - 1]) && isspace((int)line[i - 1]);
@@ -785,24 +857,30 @@ oncore_read_config(
if (!*cc)
continue;
- /* Lowercase the command and find the arg */
+ /* Uppercase the command and find the arg */
for (ca = cc; *ca; ca++) {
- if (isascii((int)*ca) && islower((int)*ca)) {
- *ca = toupper(*ca);
- } else if (isascii((int)*ca) && isspace((int)*ca)) {
- break;
- } else if (*ca == '=') {
- *ca = ' ';
- break;
+ if (isascii((int)*ca)) {
+ if (islower((int)*ca)) {
+ *ca = toupper(*ca);
+ } else if (isspace((int)*ca) || (*ca == '='))
+ break;
}
}
-
- /* Remove space leading the arg */
- for (; *ca && isascii((int)*ca) && isspace((int)*ca); ca++)
+
+ /* Remove space (and possible =) leading the arg */
+ for (; *ca && isascii((int)*ca) && (isspace((int)*ca) || (*ca == '=')); ca++)
continue;
- if (!strncmp(cc, "STATUS", 6)) {
- oncore_init_shmem(instance, ca);
+ /*
+ * move call to oncore_shmem_init() from here to after
+ * we have determined Oncore Model, so we can ignore
+ * request if model doesnt 'support' it
+ */
+
+ if (!strncmp(cc, "STATUS", (size_t) 6) || !strncmp(cc, "SHMEM", (size_t) 5)) {
+ i = strlen(ca);
+ instance->shmem_fname = (char *) malloc((unsigned) (i+1));
+ strcpy(instance->shmem_fname, ca);
continue;
}
@@ -811,7 +889,7 @@ oncore_read_config(
if (isascii((int)*cp) && islower((int)*cp))
*cp = toupper(*cp);
- if (!strncmp(cc, "LAT", 3)) {
+ if (!strncmp(cc, "LAT", (size_t) 3)) {
f1 = f2 = f3 = 0;
sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3);
sign = 1;
@@ -821,7 +899,7 @@ oncore_read_config(
}
instance->ss_lat = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/
lat_flg++;
- } else if (!strncmp(cc, "LON", 3)) {
+ } else if (!strncmp(cc, "LON", (size_t) 3)) {
f1 = f2 = f3 = 0;
sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3);
sign = 1;
@@ -831,13 +909,7 @@ oncore_read_config(
}
instance->ss_long = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/
long_flg++;
- } else if (!strncmp(cc, "HT", 2)) {
- if (!strncmp(cc, "HTGPS", 5))
- instance->ss_ht_type = 0;
- else if (!strncmp(cc, "HTMSL", 5))
- instance->ss_ht_type = 1;
- else
- instance->ss_ht_type = 0;
+ } else if (!strncmp(cc, "HT", (size_t) 2)) {
f1 = 0;
units[0] = '\0';
sscanf(ca, "%lf %1s", &f1, units);
@@ -845,7 +917,7 @@ oncore_read_config(
f1 = 0.3048 * f1;
instance->ss_ht = 100 * f1; /* cm */
ht_flg++;
- } else if (!strncmp(cc, "DELAY", 5)) {
+ } else if (!strncmp(cc, "DELAY", (size_t) 5)) {
f1 = 0;
units[0] = '\0';
sscanf(ca, "%lf %1s", &f1, units);
@@ -859,8 +931,12 @@ oncore_read_config(
f1 = 1000000000 * f1;
if (f1 < 0 || f1 > 1.e9)
f1 = 0;
- instance->delay = f1; /* delay in ns */
- } else if (!strncmp(cc, "OFFSET", 6)) {
+ if (f1 < 0 || f1 > 999999) {
+ sprintf(Msg, "PPS Cable delay of %fns out of Range, ignored", f1);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ } else
+ instance->delay = f1; /* delay in ns */
+ } else if (!strncmp(cc, "OFFSET", (size_t) 6)) {
f1 = 0;
units[0] = '\0';
sscanf(ca, "%lf %1s", &f1, units);
@@ -874,16 +950,31 @@ oncore_read_config(
f1 = 1000000000 * f1;
if (f1 < 0 || f1 > 1.e9)
f1 = 0;
- instance->offset = f1; /* offset in ns */
- } else if (!strncmp(cc, "MODE", 4)) {
+ if (f1 < 0 || f1 > 999999999.) {
+ sprintf(Msg, "PPS Offset of %fns out of Range, ignored", f1);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ } else
+ instance->offset = f1; /* offset in ns */
+ } else if (!strncmp(cc, "MODE", (size_t) 4)) {
sscanf(ca, "%d", &mode);
if (mode < 0 || mode > 4)
mode = 4;
- instance->init_type = mode;
- } else if (!strncmp(cc, "ASSERT", 6)) {
+ } else if (!strncmp(cc, "ASSERT", (size_t) 6)) {
instance->assert = 1;
- } else if (!strncmp(cc, "CLEAR", 5)) {
+ } else if (!strncmp(cc, "CLEAR", (size_t) 5)) {
instance->assert = 0;
+ } else if (!strncmp(cc, "POSN2D", (size_t) 6)) {
+ instance->shmem_Posn = 2;
+ } else if (!strncmp(cc, "POSN3D", (size_t) 6)) {
+ instance->shmem_Posn = 3;
+ } else if (!strncmp(cc, "CHAN", (size_t) 4)) {
+ sscanf(ca, "%d", &i);
+ if ((i == 6) || (i == 8) || (i == 12))
+ instance->chan = i;
+ } else if (!strncmp(cc, "TRAIM", (size_t) 5)) {
+ instance->traim = 1; /* so TRAIM alone is YES */
+ if (!strcmp(ca, "NO") || !strcmp(ca, "OFF")) /* Yes/No, On/Off */
+ instance->traim = 0;
}
}
fclose(fd);
@@ -897,9 +988,116 @@ oncore_read_config(
if ((lat_flg || long_flg || ht_flg) && !(lat_flg * long_flg * ht_flg)) {
printf("ONCORE: incomplete data on %s\n", INIT_FILE);
instance->posn_set = 0;
- if (mode == 1 || mode == 3)
- instance->init_type++;
+ if (mode == 1 || mode == 3) {
+ sprintf(Msg, "Input Mode = %d, but no/incomplete position, mode set to %d", mode, mode+1);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ mode++;
+ }
}
+ instance->init_type = mode;
+
+ sprintf(Msg, "Input mode = %d", mode);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+}
+
+
+
+static void
+oncore_init_shmem(
+ struct instance *instance
+ )
+{
+#ifdef ONCORE_SHMEM_STATUS
+ int i, l, n;
+ char *buf;
+ struct msg_desc *mp;
+ size_t oncore_shmem_length;
+
+ if (instance->shmem_first)
+ return;
+
+ instance->shmem_first++;
+
+ if ((instance->statusfd = open(instance->shmem_fname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
+ perror(instance->shmem_fname);
+ return;
+ }
+
+ n = 1;
+ for (mp = oncore_messages; mp->flag[0]; mp++) {
+ mp->shmem = n;
+ /* Allocate space for multiplexed almanac, and 0D/2D/3D @@Ea records */
+ if (!strcmp(mp->flag, "Cb")) {
+ instance->shmem_Cb = n;
+ n += (mp->len + 3) * 34;
+ }
+ if (!strcmp(mp->flag, "Ba")) {
+ instance->shmem_Ba = n;
+ n += (mp->len + 3) * 3;
+ }
+ if (!strcmp(mp->flag, "Ea")) {
+ instance->shmem_Ea = n;
+ n += (mp->len + 3) * 3;
+ }
+ if (!strcmp(mp->flag, "Ha")) {
+ instance->shmem_Ha = n;
+ n += (mp->len + 3) * 3;
+ }
+ n += (mp->len + 3);
+ }
+ oncore_shmem_length = n + 2;
+ fprintf(stderr, "ONCORE: SHMEM length: %d bytes\n", (int) oncore_shmem_length);
+
+ buf = malloc(oncore_shmem_length);
+ if (buf == NULL) {
+ perror("malloc");
+ return;
+ }
+ memset(buf, 0, sizeof(buf));
+ i = write(instance->statusfd, buf, oncore_shmem_length);
+ if (i != oncore_shmem_length) {
+ perror(instance->shmem_fname);
+ return;
+ }
+ free(buf);
+ instance->shmem = (u_char *) mmap(0, oncore_shmem_length,
+ PROT_READ | PROT_WRITE,
+#ifdef MAP_HASSEMAPHORE
+ MAP_HASSEMAPHORE |
+#endif
+ MAP_SHARED,
+ instance->statusfd, (off_t)0);
+ if (instance->shmem == (u_char *)MAP_FAILED) {
+ instance->shmem = 0;
+ close (instance->statusfd);
+ return;
+ }
+ for (mp = oncore_messages; mp->flag[0]; mp++) {
+ l = mp->shmem;
+ instance->shmem[l + 0] = mp->len >> 8;
+ instance->shmem[l + 1] = mp->len & 0xff;
+ instance->shmem[l + 2] = 0;
+ instance->shmem[l + 3] = '@';
+ instance->shmem[l + 4] = '@';
+ instance->shmem[l + 5] = mp->flag[0];
+ instance->shmem[l + 6] = mp->flag[1];
+ if (!strcmp(mp->flag, "Cb") || !strcmp(mp->flag, "Ba") || !strcmp(mp->flag, "Ea") || !strcmp(mp->flag, "Ha")) {
+ if (!strcmp(mp->flag, "Cb"))
+ n = 35;
+ else
+ n = 4;
+ for (i = 1; i < n; i++) {
+ instance->shmem[l + i * (mp->len+3) + 0] = mp->len >> 8;
+ instance->shmem[l + i * (mp->len+3) + 1] = mp->len & 0xff;
+ instance->shmem[l + i * (mp->len+3) + 2] = 0;
+ instance->shmem[l + i * (mp->len+3) + 3] = '@';
+ instance->shmem[l + i * (mp->len+3) + 4] = '@';
+ instance->shmem[l + i * (mp->len+3) + 5] = mp->flag[0];
+ instance->shmem[l + i * (mp->len+3) + 6] = mp->flag[1];
+ }
+ }
+ }
+#endif /* ONCORE_SHMEM_STATUS */
}
@@ -907,6 +1105,7 @@ oncore_read_config(
/*
* oncore_shutdown - shut down the clock
*/
+
static void
oncore_shutdown(
int unit,
@@ -918,6 +1117,9 @@ oncore_shutdown(
pp = peer->procptr;
instance = (struct instance *) pp->unitptr;
+
+ io_closeclock(&pp->io);
+
free(instance);
}
@@ -926,6 +1128,7 @@ oncore_shutdown(
/*
* oncore_poll - called by the transmit procedure
*/
+
static void
oncore_poll(
int unit,
@@ -936,12 +1139,18 @@ oncore_poll(
instance = (struct instance *) peer->procptr->unitptr;
if (instance->timeout) {
- char *cp;
+ char *cp;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof oncore_cmd_Cj);
- instance->o_state = ONCORE_ID_SENT;
- cp = "state = ONCORE_ID_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
+ instance->timeout--;
+ if (instance->timeout == 0) {
+ cp = "Oncore: No response from @@Cj, shutting down driver";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_shutdown(unit, peer);
+ } else {
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ cp = "Oncore: Resend @@Cj";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ }
return;
}
@@ -956,14 +1165,15 @@ oncore_poll(
/*
- * move dta from NTP to buffer (toss in unlikely case it wont fit)
+ * move data from NTP to buffer (toss in unlikely case it wont fit)
*/
+
static void
oncore_receive(
struct recvbuf *rbufp
)
{
- u_int i;
+ size_t i;
u_char *p;
struct peer *peer;
struct instance *instance;
@@ -999,6 +1209,7 @@ oncore_receive(
/*
* Deal with any complete messages
*/
+
static void
oncore_consume(
struct instance *instance
@@ -1014,49 +1225,65 @@ oncore_consume(
if (rcvbuf[i] == '@' && rcvbuf[i+1] == '@')
break;
if (debug > 4)
- printf("ONCORE: >>> skipping %d chars\n", i);
+ printf("ONCORE[%d]: >>> skipping %d chars\n", instance->unit, i);
if (i != rcvptr)
- memcpy(rcvbuf, rcvbuf+i, (unsigned)(rcvptr-i));
+ memcpy(rcvbuf, rcvbuf+i, (size_t)(rcvptr-i));
rcvptr -= i;
+ continue;
}
/* Ok, we have a header now */
l = sizeof(oncore_messages)/sizeof(oncore_messages[0]) -1;
for(m=0; m<l; m++)
- if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), 2))
+ if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), (size_t) 2))
break;
+ if (m == l) {
+ if (debug > 4)
+ printf("ONCORE[%d]: >>> Unknown MSG, skipping 4 (%c%c)\n", instance->unit, rcvbuf[2], rcvbuf[3]);
+ memcpy(rcvbuf, rcvbuf+4, (size_t) 4);
+ rcvptr -= 4;
+ continue;
+ }
+
l = oncore_messages[m].len;
#if 0
if (debug > 3)
- printf("ONCORE: GOT: %c%c %d of %d entry %d\n", rcvbuf[2], rcvbuf[3], rcvptr, l, m);
+ printf("ONCORE[%d]: GOT: %c%c %d of %d entry %d\n", instance->unit, rcvbuf[2], rcvbuf[3], rcvptr, l, m);
#endif
/* Got the entire message ? */
if (rcvptr < l)
return;
- /* Check the checksum */
-
- j = 0;
- for (i = 2; i < l-3; i++)
- j ^= rcvbuf[i];
- if (j == rcvbuf[l-3]) {
- if (instance->shmem != NULL)
- memcpy(instance->shmem + oncore_messages[m].shmem + 2,
- rcvbuf, l);
- oncore_msg_any(instance, rcvbuf, (unsigned) (l-3), m);
- if (oncore_messages[m].handler)
- oncore_messages[m].handler(instance, rcvbuf, (unsigned) (l-3));
- } else if (debug) {
- printf("ONCORE: Checksum mismatch! calc %o is %o\n", j, rcvbuf[l-3]);
- printf("ONCORE: @@%c%c ", rcvbuf[2], rcvbuf[3]);
- for (i=4; i<l; i++)
- printf("%03o ", rcvbuf[i]);
- printf("\n");
+ /* are we at the end of message? should be <Cksum><CR><LF> */
+
+ if (rcvbuf[l-2] != '\r' || rcvbuf[l-1] != '\n') {
+ if (debug)
+ printf("ONCORE[%d]: NO <CR><LF> at end of message\n", instance->unit);
+ } else { /* check the CheckSum */
+ j = 0;
+ for (i = 2; i < l-3; i++)
+ j ^= rcvbuf[i];
+ if (j == rcvbuf[l-3]) {
+ if (instance->shmem != NULL) {
+ instance->shmem[oncore_messages[m].shmem + 2]++;
+ memcpy(instance->shmem + oncore_messages[m].shmem + 3,
+ rcvbuf, (size_t) l);
+ }
+ oncore_msg_any(instance, rcvbuf, (size_t) (l-3), m);
+ if (oncore_messages[m].handler)
+ oncore_messages[m].handler(instance, rcvbuf, (size_t) (l-3));
+ } else if (debug) {
+ printf("ONCORE[%d]: Checksum mismatch! calc %o is %o\n", instance->unit, j, rcvbuf[l-3]);
+ printf("ONCORE[%d]: @@%c%c ", instance->unit, rcvbuf[2], rcvbuf[3]);
+ for (i=4; i<l; i++)
+ printf("%03o ", rcvbuf[i]);
+ printf("\n");
+ }
}
if (l != rcvptr)
- memcpy(rcvbuf, rcvbuf+l, (unsigned) (rcvptr-l));
+ memcpy(rcvbuf, rcvbuf+l, (size_t) (rcvptr-l));
rcvptr -= l;
}
}
@@ -1066,42 +1293,56 @@ oncore_consume(
/*
* write message to Oncore.
*/
+
static void
oncore_sendmsg(
int fd,
u_char *ptr,
- u_int len
+ size_t len
)
{
u_char cs = 0;
- printf("ONCORE: Send @@%c%c %d\n", ptr[0], ptr[1], len);
- write(fd, "@@", 2);
+ printf("ONCORE: Send @@%c%c %d\n", ptr[0], ptr[1], (int) len);
+ write(fd, "@@", (size_t) 2);
write(fd, ptr, len);
while (len--)
cs ^= *ptr++;
- write(fd, &cs, 1);
- write(fd, "\r\n", 2);
+ write(fd, &cs, (size_t) 1);
+ write(fd, "\r\n", (size_t) 2);
}
+/*
+ * print Oncore response message.
+ */
+
static void
oncore_msg_any(
struct instance *instance,
u_char *buf,
- u_int len,
+ size_t len,
int idx
)
{
int i;
const char *fmt = oncore_messages[idx].fmt;
const char *p;
+#ifdef HAVE_GETCLOCK
+ struct timespec ts;
+#endif
struct timeval tv;
if (debug > 3) {
+#ifdef HAVE_GETCLOCK
+ (void) getclock(TIMEOFDAY, &ts);
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000;
+#else
GETTIMEOFDAY(&tv, 0);
- printf("ONCORE: %ld.%06ld\n", (long) tv.tv_sec, (long) tv.tv_usec);
+#endif
+ printf("ONCORE[%d]: %ld.%06ld\n", instance->unit, (long) tv.tv_sec, (long) tv.tv_usec);
if (!*fmt) {
printf(">>@@%c%c ", buf[2], buf[3]);
@@ -1130,11 +1371,12 @@ oncore_msg_any(
/*
* Demultiplex the almanac into shmem
*/
+
static void
oncore_msg_Cb(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
int i;
@@ -1142,7 +1384,7 @@ oncore_msg_Cb(
if (instance->shmem == NULL)
return;
- if (buf[4] == 5)
+ if (buf[4] == 5)
i = buf[5];
else if (buf[4] == 4 && buf[5] <= 5)
i = buf[5] + 24;
@@ -1150,88 +1392,63 @@ oncore_msg_Cb(
i = buf[5] + 23;
else
i = 34;
- i *= 35;
- memcpy(instance->shmem + oncore_shmem_Cb + i + 2, buf, len + 3);
+ i *= 36;
+ instance->shmem[instance->shmem_Cb + i + 2]++;
+ memcpy(instance->shmem + instance->shmem_Cb + i + 3, buf, (size_t) (len + 3));
}
-/*
- * Set to Factory Defaults (Reasonable for UT w/ no Battery Backup
- * not so for VP (eeprom) or UT with battery
- */
-static void
-oncore_msg_Cf(
- struct instance *instance,
- u_char *buf,
- u_int len
- )
-{
- const char *cp;
- if (instance->o_state == ONCORE_RESET_SENT) {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof oncore_cmd_Fa);
- instance->o_state = ONCORE_TEST_SENT;
- cp = "state = ONCORE_TEST_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
-}
+/*
+ * We do an @@Cj twice in the initialization sequence.
+ * o Once at the very beginning to get the Model number so we know what commands
+ * we can issue,
+ * o And once later after we have done a reset and test, (which may hang),
+ * as we are about to initialize the Oncore and start it running.
+ * o We have one routine below for each case.
+ */
-/* there are good reasons NOT to do a @@Fa command with the ONCORE.
- * Doing it, it was found that under some circumstances the following
- * command would fail if issued immediately after the return from the
- * @@Fa, but a 2sec delay seemed to fix things. Since simply calling
- * sleep(2) is wastefull, and may cause trouble for some OS's, repeating
- * itimer, we set a flag, and test it at the next POLL. If it hasnt
- * been cleared, we reissue the @@Ca that is issued below.
+/*
+ * Determine the Type from the Model #, this determines #chan and if TRAIM is
+ * available. We use ONLY the #chans, and determint TRAIM by trying it.
*/
static void
-oncore_msg_Fa(
+oncore_msg_Cj(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
- const char *cp;
-
- if (instance->o_state == ONCORE_TEST_SENT) {
- if (debug > 2)
- printf("ONCORE: >>@@Fa %x %x\n", buf[4], buf[5]);
- if (buf[4] || buf[5]) {
- printf("ONCORE: SELF TEST FAILED\n");
- exit(1);
- }
+ memcpy(instance->Cj, buf, len);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof oncore_cmd_Cj);
- instance->o_state = ONCORE_ID_SENT;
- cp = "state = ONCORE_ID_SENT";
- record_clock_stats(&(instance->peer->srcadr), cp);
- }
+ instance->timeout = 0;
+ if (instance->o_state == ONCORE_ID_SENT)
+ oncore_msg_Cj_id(instance, buf, len);
+ else if (instance->o_state == ONCORE_INIT)
+ oncore_msg_Cj_init(instance, buf, len);
}
-/*
- * preliminaries out of the way, this is the REAL start of initialization
+/* The information on determing a Oncore 'Model', viz VP, UT, etc, from
+ * the Model Number comes from "Richard M. Hambly" <rick@cnssys.com>
+ * and from Motorola. Until recently Rick was the only source of
+ * this information as Motorola didnt give the information out.
*/
+
static void
-oncore_msg_Cj(
+oncore_msg_Cj_id(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
- char *cp, *cp1;
+ char *cp, *cp1, *cp2, Model[21], Msg[160];
int mode;
- instance->timeout = 0;
- if (instance->o_state != ONCORE_ID_SENT)
- return;
-
- memcpy(instance->Cj, buf, len);
-
- /* Write Receiver ID to clockstats file */
+ /* Write Receiver ID message to clockstats file */
instance->Cj[294] = '\0';
for (cp=(char *)instance->Cj; cp< (char *) &instance->Cj[294]; ) {
@@ -1243,6 +1460,114 @@ oncore_msg_Cj(
*cp1 = '\r';
cp = cp1+2;
}
+
+ /* next, the Firmware Version and Revision numbers */
+
+ instance->version = atoi(&instance->Cj[83]);
+ instance->revision = atoi(&instance->Cj[111]);
+
+ /* from model number decide which Oncore this is,
+ and then the number of channels */
+
+ for (cp=&instance->Cj[160]; *cp == ' '; cp++) /* start right after 'Model #' */
+ ;
+ cp1 = cp;
+ cp2 = Model;
+ for (; !isspace((int)*cp) && cp-cp1 < 20; cp++, cp2++)
+ *cp2 = *cp;
+ *cp2 = '\0';
+
+ cp = 0;
+ if (!strncmp(Model, "PVT6", (size_t) 4)) {
+ cp = "PVT6";
+ instance->model = ONCORE_PVT6;
+ } else if (Model[0] == 'A') {
+ cp = "Basic";
+ instance->model = ONCORE_BASIC;
+ } else if (Model[0] == 'B' || !strncmp(Model, "T8", (size_t) 2)) {
+ cp = "VP";
+ instance->model = ONCORE_VP;
+ } else if (!strncmp(Model, "P1", (size_t) 2)) {
+ cp = "M12";
+ instance->model = ONCORE_M12;
+ } else if (Model[0] == 'R') {
+ if (Model[5] == 'N') {
+ cp = "GT";
+ instance->model = ONCORE_GT;
+ } else if ((Model[1] == '3' || Model[1] == '4') && Model[5] == 'G') {
+ cp = "GT+";
+ instance->model = ONCORE_GTPLUS;
+ } else if ((Model[1] == '5' && Model[5] == 'U') || (Model[1] == '1' && Model[5] == 'A')) {
+ cp = "UT";
+ instance->model = ONCORE_UT;
+ } else if (Model[1] == '5' && Model[5] == 'G') {
+ cp = "UT+";
+ instance->model = ONCORE_UTPLUS;
+ } else if (Model[1] == '6' && Model[5] == 'G') {
+ cp = "SL";
+ instance->model = ONCORE_SL;
+ } else {
+ cp = "Unknown";
+ instance->model = ONCORE_UNKNOWN;
+ }
+ } else {
+ cp = "Unknown";
+ instance->model = ONCORE_UNKNOWN;
+ }
+
+ sprintf(Msg, "This looks like an Oncore %s with version %d.%d firmware.", cp, instance->version, instance->revision);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+
+ if (instance->chan == 0) { /* dont reset if set in input data */
+ instance->chan = 8; /* default */
+ if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
+ instance->chan = 6;
+ else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
+ instance->chan = 8;
+ else if (instance->model == ONCORE_M12)
+ instance->chan = 12;
+ }
+
+ if (instance->traim == -1) { /* dont reset if set in input data */
+ instance->traim = 0; /* default */
+ if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
+ instance->traim = 0;
+ else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
+ instance->traim = 1;
+ else if (instance->model == ONCORE_M12)
+ instance->traim = 0;
+ }
+
+ sprintf(Msg, "Channels = %d, TRAIM = %s", instance->chan,
+ ((instance->traim < 0) ? "UNKNOWN" : ((instance->traim > 0) ? "ON" : "OFF")));
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+
+ /* The M12 with 1.3 Firmware, looses track of all Satellites and has to
+ * start again if we go from 0D -> 3D, then looses them again when we
+ * go from 3D -> 0D. We do this to get a @@Ea message for SHMEM.
+ * For NOW we have SHMEM turned off for the M12, v1.3
+ */
+
+/*BAD M12*/ if (instance->model == ONCORE_M12 && instance->version == 1 && instance->revision <= 3) {
+ instance->shmem_fname = 0;
+ cp = "*** SHMEM turned off for ONCORE M12 ***";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ }
+
+ /*
+ * we now know model number and have zeroed
+ * instance->shmem_fname if SHMEM is not supported
+ */
+
+ if (instance->shmem_fname);
+ oncore_init_shmem(instance);
+
+ if (instance->shmem)
+ cp = "SHMEM is available";
+ else
+ cp = "SHMEM is NOT available";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+
#ifdef HAVE_PPSAPI
if (instance->assert)
cp = "Timing on Assert.";
@@ -1251,72 +1576,180 @@ oncore_msg_Cj(
record_clock_stats(&(instance->peer->srcadr), cp);
#endif
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof oncore_cmd_Cg); /* Set Posn Fix mode (not Idle (VP)) */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bb, sizeof oncore_cmd_Bb); /* turn off */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ek, sizeof oncore_cmd_Ek); /* turn off */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Aw, sizeof oncore_cmd_Aw); /* UTC time */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_AB, sizeof oncore_cmd_AB); /* Appl type static */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Be, sizeof oncore_cmd_Be); /* Tell us the Almanac */
+ mode = instance->init_type;
+ if (mode == 3 || mode == 4) { /* Cf will call Fa */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cf, sizeof(oncore_cmd_Cf));
+ instance->o_state = ONCORE_RESET_SENT;
+ cp = "state = ONCORE_RESET_SENT";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ } else {
+ if (instance->chan == 6)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ca, sizeof(oncore_cmd_Ca));
+ else if (instance->chan == 8)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof(oncore_cmd_Fa));
+ else if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ia, sizeof(oncore_cmd_Ia));
+
+ instance->o_state = ONCORE_TEST_SENT;
+ cp = "state = ONCORE_TEST_SENT";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ instance->timeout = 4;
+ }
+}
+
+
+
+static void
+oncore_msg_Cj_init(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ char *cp, Cmd[20], Msg[160];
+ int mode;
+
+ /* OK, know type of Oncore, have possibly reset, and have tested.
+ * If we have or don't have TRAIM and position hold may still be unknown.
+ * Now initialize.
+ */
+
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Set Posn Fix mode (not Idle (VP)) */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Bb, sizeof(oncore_cmd_Bb)); /* turn on for shmem */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ek, sizeof(oncore_cmd_Ek)); /* turn off */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Aw, sizeof(oncore_cmd_Aw)); /* UTC time */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_AB, sizeof(oncore_cmd_AB)); /* Appl type static */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Be, sizeof(oncore_cmd_Be)); /* Tell us the Almanac for shmem */
+
+ /* Turn OFF position hold, it needs to be off to set position (for some units),
+ will get set ON in @@Ea later */
+
+ if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0));
+ else {
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
+ }
mode = instance->init_type;
- if (debug)
- printf("ONCORE: INIT mode = %d\n", mode);
+ if (debug) {
+ printf("ONCORE[%d]: INIT mode = %d\n", instance->unit, mode);
+ printf("ONCORE[%d]: chan = %d\n", instance->unit, instance->chan);
+ }
/* If there is Position input in the Config file
* and mode = (1,3) set it as posn hold posn, goto 0D mode.
- * or mode = (2,4) set it as INITIAL position, and Site Survey.
+ * or mode = (2,4) set it as INITIAL position, and do Site Survey.
*/
+
+ if (instance->posn_set) {
+ switch (mode) { /* if we have a position, put it in as posn and posn-hold posn */
+ case 0:
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ memcpy(Cmd, oncore_cmd_As, sizeof(oncore_cmd_As)); /* dont modify static variables */
+ w32_buf(&Cmd[2], (int) instance->ss_lat);
+ w32_buf(&Cmd[6], (int) instance->ss_long);
+ w32_buf(&Cmd[10], (int) instance->ss_ht);
+ Cmd[14] = 0;
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_As));
+
+ memcpy(Cmd, oncore_cmd_Au, sizeof(oncore_cmd_Au));
+ w32_buf(&Cmd[2], (int) instance->ss_ht);
+ Cmd[6] = 0;
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Au));
+
+ if (instance->chan == 12) {
+ memcpy(Cmd, oncore_cmd_Ga, sizeof(oncore_cmd_Ga));
+ w32_buf(&Cmd[2], (int) instance->ss_lat);
+ w32_buf(&Cmd[6], (int) instance->ss_long);
+ w32_buf(&Cmd[10], (int) instance->ss_ht);
+ Cmd[14] = 0;
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ga));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
+ } else {
+ memcpy(Cmd, oncore_cmd_Ad, sizeof(oncore_cmd_Ad));
+ w32_buf(&Cmd[2], (int) instance->ss_lat);
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ad));
+
+ memcpy(Cmd, oncore_cmd_Ae, sizeof(oncore_cmd_Ae));
+ w32_buf(&Cmd[2], (int) instance->ss_long);
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ae));
+
+ memcpy(Cmd, oncore_cmd_Af, sizeof(oncore_cmd_Af));
+ w32_buf(&Cmd[2], (int) instance->ss_ht);
+ Cmd[6] = 0;
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Af));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1));
+ }
+ break;
+ }
+ }
+
+
switch (mode) {
case 0: /* NO initialization, don't change anything */
instance->site_survey = ONCORE_SS_DONE;
break;
case 1:
- case 3:
- w32_buf(&oncore_cmd_As[2], (int) instance->ss_lat);
- w32_buf(&oncore_cmd_As[6], (int) instance->ss_long);
- w32_buf(&oncore_cmd_As[10], (int) instance->ss_ht);
- oncore_cmd_As[14] = instance->ss_ht_type;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_As, sizeof oncore_cmd_As);
-
+ case 3: /* Use given Position */
instance->site_survey = ONCORE_SS_DONE;
- oncore_cmd_At[2] = 1;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
- record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
break;
case 2:
- case 4:
- if (instance->posn_set) {
- w32_buf(&oncore_cmd_Ad[2], (int) instance->ss_lat);
- w32_buf(&oncore_cmd_Ae[2], (int) instance->ss_long);
- w32_buf(&oncore_cmd_Af[2], (int) instance->ss_ht);
- oncore_cmd_Af[6] = instance->ss_ht_type;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ad, sizeof oncore_cmd_Ad);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ae, sizeof oncore_cmd_Ae);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Af, sizeof oncore_cmd_Af);
+ case 4: /* Site Survey */
+ if (instance->chan == 12) { /* no 12chan site survey command */
+ instance->site_survey = ONCORE_SS_SW;
+ sprintf(Msg, "Initiating software 3D site survey (%d samples)", POS_HOLD_AVERAGE);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ } else {
+ instance->site_survey = ONCORE_SS_TESTING;
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At2, sizeof(oncore_cmd_At2));
}
- instance->site_survey = ONCORE_SS_UNKNOWN;
- oncore_cmd_At[2] = 2;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
break;
}
if (mode != 0) {
/* cable delay in ns */
- w32_buf(&oncore_cmd_Az[2], instance->delay);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Az, sizeof oncore_cmd_Az);
+ memcpy(Cmd, oncore_cmd_Az, sizeof(oncore_cmd_Az));
+ w32_buf(&Cmd[2], instance->delay);
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Az));
/* PPS offset in ns */
- w32_buf(&oncore_cmd_Ay[2], instance->offset);
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ay, sizeof oncore_cmd_Ay);
+ if (instance->offset) {
+ if (instance->model == ONCORE_VP || instance->model == ONCORE_UT ||
+ instance->model == ONCORE_UTPLUS) {
+ memcpy(Cmd, oncore_cmd_Ay, sizeof(oncore_cmd_Ay));
+ w32_buf(&Cmd[2], instance->offset);
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Ay));
+ } else {
+ cp = "Can only set PPS OFFSET for VP/UT/UT+, offset ignored";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ instance->offset = 0;
+ }
+ }
}
- /* 8chan - Position/Status/Data Output Message, 1/s */
-
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof oncore_cmd_Ea);
-
+ /* 6, 8 12 chan - Position/Status/Data Output Message, 1/s */
+ /* now we're really running */
+
+ if (instance->chan == 6) { /* kill 8 chan commands, possibly testing VP in 6chan mode */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba, sizeof(oncore_cmd_Ba));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_En0, sizeof(oncore_cmd_En0));
+ } else if (instance->chan == 8) { /* kill 6chan commands */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ea, sizeof(oncore_cmd_Ea));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
+ } else if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ha, sizeof(oncore_cmd_Ha));
+
+ instance->count = 1;
instance->o_state = ONCORE_ALMANAC;
cp = "state = ONCORE_ALMANAC";
record_clock_stats(&(instance->peer->srcadr), cp);
@@ -1324,104 +1757,412 @@ oncore_msg_Cj(
+/*
+ * Set to Factory Defaults (Reasonable for UT w/ no Battery Backup
+ * not so for VP (eeprom) or any unit with a battery
+ */
+
+static void
+oncore_msg_Cf(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ const char *cp;
+
+ if (instance->o_state == ONCORE_RESET_SENT) {
+ if (instance->chan == 6)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ca, sizeof(oncore_cmd_Ca));
+ else if (instance->chan == 8)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Fa, sizeof(oncore_cmd_Fa));
+ else if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ia, sizeof(oncore_cmd_Ia));
+
+ instance->o_state = ONCORE_TEST_SENT;
+ cp = "state = ONCORE_TEST_SENT";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ }
+}
+
+
+
+/* Here for @@Ca, @@Fa and @@Ia messages */
+
+/* There are good reasons NOT to do a @@Ca or @@Fa command with the ONCORE.
+ * Doing it, it was found that under some circumstances the following
+ * command would fail if issued immediately after the return from the
+ * @@Fa, but a 2sec delay seemed to fix things. Since simply calling
+ * sleep(2) is wastefull, and may cause trouble for some OS's, repeating
+ * itimer, we set a flag, and test it at the next POLL. If it hasnt
+ * been cleared, we reissue the @@Cj that is issued below.
+ * Note that we do a @@Cj at the beginning, and again here.
+ * The first is to get the info, the 2nd is just used as a safe command
+ * after the @@Fa for all Oncores (and it was in this posn in the
+ * original code).
+ */
+
+static void
+oncore_msg_CaFaIa(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ char *cp;
+
+ if (instance->o_state == ONCORE_TEST_SENT) {
+ int antenna;
+
+ instance->timeout = 0;
+
+ if (debug > 2) {
+ if (buf[2] == 'I')
+ printf("ONCORE[%d]: >>@@%ca %x %x %x\n", instance->unit, buf[2], buf[4], buf[5], buf[6]);
+ else
+ printf("ONCORE[%d]: >>@@%ca %x %x\n", instance->unit, buf[2], buf[4], buf[5]);
+ }
+
+ antenna = buf[4] & 0xc0;
+ antenna >>= 6;
+ buf[4] &= ~0xc0;
+
+ if (buf[4] || buf[5] || ((buf[2] == 'I') && buf[6])) {
+ cp = "ONCORE: Self Test Failed, shutting down driver";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_shutdown(instance->unit, instance->peer);
+ return;
+ }
+ if (antenna) {
+ char *cp1, Msg[160];
+
+ cp1 = (antenna == 0x1) ? "(Over Current)" :
+ ((antenna == 0x2) ? "(Under Current)" : "(No Voltage)");
+
+ cp = "ONCORE: Self Test, NonFatal Antenna Problems ";
+ strcpy(Msg, cp);
+ strcat(Msg, cp1);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ }
+
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
+ instance->o_state = ONCORE_INIT;
+ cp = "state = ONCORE_INIT";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ }
+}
+
+
+
+/* Ba, Ea and Ha come here */
+
static void
-oncore_msg_Ea(
+oncore_msg_BaEaHa(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
const char *cp;
- char Msg[160];
+ char Msg[160], Cmd[20];
+ u_char *vp; /* pointer to start of shared mem for Ba/Ea/Ha */
+ size_t Len;
+
+ /* At the beginning of Ea here there are various 'timers'.
+ * We enter Ea 1/sec, and since the upper levels of NTP have usurped
+ * the use of timers, we use the 1/sec entry to Ea to do things that
+ * we would normally do with timers...
+ */
+
+ if (instance->count) {
+ if (instance->count++ < 5) /* make sure results are stable, using position */
+ return;
+ instance->count = 0;
+ }
if (instance->o_state != ONCORE_ALMANAC && instance->o_state != ONCORE_RUN)
return;
- memcpy(instance->Ea, buf, len);
+ Len = len+3; /* message length @@ -> CR,LF */
+ memcpy(instance->Ea, buf, Len); /* Ba, Ea or Ha */
+
+ if (buf[2] == 'B') { /* 6chan */
+ if (instance->Ea[64]&0x8)
+ instance->mode = MODE_0D;
+ else if (instance->Ea[64]&0x10)
+ instance->mode = MODE_2D;
+ else if (instance->Ea[64]&0x20)
+ instance->mode = MODE_3D;
+ } else if (buf[2] == 'E') { /* 8chan */
+ if (instance->Ea[72]&0x8)
+ instance->mode = MODE_0D;
+ else if (instance->Ea[72]&0x10)
+ instance->mode = MODE_2D;
+ else if (instance->Ea[72]&0x20)
+ instance->mode = MODE_3D;
+ } else if (buf[2] == 'H') { /* 12chan */
+ int bits;
+
+ bits = (instance->Ea[129]>>5) & 0x7; /* actually Ha */
+ if (bits == 0x4)
+ instance->mode = MODE_0D;
+ else if (bits == 0x6)
+ instance->mode = MODE_2D;
+ else if (bits == 0x7)
+ instance->mode = MODE_3D;
+ }
+
+ vp = (u_char) 0; /* just to keep compiler happy */
+ if (instance->chan == 6) {
+ instance->rsm.bad_almanac = instance->Ea[64]&0x1;
+ instance->rsm.bad_fix = instance->Ea[64]&0x52;
+ vp = &instance->shmem[instance->shmem_Ba];
+ } else if (instance->chan == 8) {
+ instance->rsm.bad_almanac = instance->Ea[72]&0x1;
+ instance->rsm.bad_fix = instance->Ea[72]&0x52;
+ vp = &instance->shmem[instance->shmem_Ea];
+ } else if (instance->chan == 12) {
+ int bits1, bits2;
+
+ bits1 = (instance->Ea[129]>>5) & 0x7; /* actually Ha */
+ bits2 = instance->Ea[130];
+ instance->rsm.bad_almanac = (bits2 & 0x80);
+ instance->rsm.bad_fix = (bits2 & 0x8) || (bits1 == 0x2);
+ /* too few sat Bad Geom */
+ vp = &instance->shmem[instance->shmem_Ha];
+#if 0
+fprintf(stderr, "ONCORE: DEBUG BITS: (%x %x), (%x %x), %x %x %x %x %x\n",
+ instance->Ea[129], instance->Ea[130], bits1, bits2, instance->mode == MODE_0D, instance->mode == MODE_2D,
+ instance->mode == MODE_3D, instance->rsm.bad_almanac, instance->rsm.bad_fix);
+#endif
+ }
+
+ /* Here calculate dH = GPS - MSL for output message */
+ /* also set Altitude Hold mode if GT */
+
+ if (!instance->have_dH) {
+ int GPS, MSL;
+
+ instance->have_dH++;
+ if (instance->chan == 12) {
+ GPS = buf_w32(&instance->Ea[39]);
+ MSL = buf_w32(&instance->Ea[43]);
+ } else {
+ GPS = buf_w32(&instance->Ea[23]);
+ MSL = buf_w32(&instance->Ea[27]);
+ }
+ instance->dH = GPS - MSL;
+ instance->dH /= 100.;
+
+ if (MSL) { /* not set ! */
+ sprintf(Msg, "dH = (GPS - MSL) = %.2fm", instance->dH);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ }
- /* When we have an almanac, start the En messages */
+ /* stuck in here as it only gets done once */
+
+ if (instance->chan != 12 && !instance->saw_At) {
+ cp = "Not Good, no @@At command, must be a GT/GT+";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
+ }
+ }
+
+ /*
+ * For instance->site_survey to be ONCORE_SS_TESTING, this must be the first
+ * time thru @@Ea. There are two choices
+ * (a) We did not get a response to the @@At0 or @@At2 commands,
+ * must be a GT/GT+/SL with no position hold mode.
+ * (b) Saw the @@At0, @@At2 commands, but @@At2 failed,
+ * must be a VP or older UT which doesnt have Site Survey mode.
+ * We will have to do it ourselves.
+ */
+
+ if (instance->site_survey == ONCORE_SS_TESTING) { /* first time thru Ea */
+ sprintf(Msg, "Initiating software 3D site survey (%d samples)",
+ POS_HOLD_AVERAGE);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ instance->site_survey = ONCORE_SS_SW;
+
+ instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* disable */
+ }
+
+ if (instance->shmem) {
+ int i;
+
+ i = 0;
+ if (instance->mode == MODE_0D) /* 0D, Position Hold */
+ i = 1;
+ else if (instance->mode == MODE_2D) /* 2D, Altitude Hold */
+ i = 2;
+ else if (instance->mode == MODE_3D) /* 3D fix */
+ i = 3;
+ if (i) {
+ i *= (Len+3);
+ vp[i + 2]++;
+ memcpy(&vp[i+3], buf, Len);
+ }
+ }
+
+ /* Almanac mode, waiting for Almanac, cant do anything till we have it */
+ /* When we have an almanac, start the En/Bn messages */
if (instance->o_state == ONCORE_ALMANAC) {
- if ((instance->Ea[72] & 1)) {
+ if (instance->rsm.bad_almanac) {
if (debug)
printf("ONCORE: waiting for almanac\n");
return;
- } else {
- oncore_sendmsg(instance->ttyfd, oncore_cmd_En, sizeof oncore_cmd_En);
+ } else { /* Here we have almanac.
+ Start TRAIM (@@En/@@Bn) dependant on TRAIM flag.
+ If flag == -1, then we dont know if this unit supports
+ traim, and we issue the command and then wait up to
+ 5sec to see if we get a reply */
+
+ if (instance->traim != 0) { /* either yes or unknown */
+ if (instance->chan == 6)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Bn, sizeof(oncore_cmd_Bn));
+ else if (instance->chan == 8)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_En, sizeof(oncore_cmd_En));
+
+ if (instance->traim == -1)
+ instance->traim_delay = 1;
+ }
instance->o_state = ONCORE_RUN;
cp = "state = ONCORE_RUN";
record_clock_stats(&(instance->peer->srcadr), cp);
}
}
- /* must be ONCORE_RUN if we are here */
- /* First check if Hardware SiteSurvey has Finished */
+ /*
+ * check if timer active
+ * if it hasnt been cleared, then @@En/@@Bn did not respond
+ */
+
+ if (instance->traim_delay) {
+ if (instance->traim_delay++ > 5) {
+ instance->traim = 0;
+ instance->traim_delay = 0;
+ cp = "ONCORE: Did not detect TRAIM response, TRAIM = OFF";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ }
+ }
+
+ /*
+ * must be ONCORE_RUN if we are here.
+ */
+
+ instance->pp->year = buf[6]*256+buf[7];
+ instance->pp->day = ymd2yd(buf[6]*256+buf[7], buf[4], buf[5]);
+ instance->pp->hour = buf[8];
+ instance->pp->minute = buf[9];
+ instance->pp->second = buf[10];
+
+ /*
+ * Check to see if Hardware SiteSurvey has Finished.
+ */
if ((instance->site_survey == ONCORE_SS_HW) && !(instance->Ea[37] & 0x20)) {
- instance->site_survey = ONCORE_SS_DONE;
record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
+ instance->site_survey = ONCORE_SS_DONE;
}
- if (!instance->printed && instance->site_survey == ONCORE_SS_DONE) { /* will print to clockstat when all */
- instance->printed = 1; /* three messages respond */
- /* Read back Position Hold Params */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Asx, sizeof oncore_cmd_Asx);
+ if (!instance->printed && instance->site_survey == ONCORE_SS_DONE) {
+ instance->printed = 1;
+ /* Read back Position Hold Params (cant for GT) */
+ if (instance->saw_At)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Asx, sizeof(oncore_cmd_Asx));
+ else
+ oncore_print_As(instance);
+
/* Read back PPS Offset for Output */
- /* Nb. This will fail silently for early UT (no plus) model */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Ayx, sizeof oncore_cmd_Ayx);
+ /* Nb. This will fail silently for early UT (no plus) and M12 models */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Ayx, sizeof(oncore_cmd_Ayx));
+
/* Read back Cable Delay for Output */
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Azx, sizeof oncore_cmd_Azx);
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Azx, sizeof(oncore_cmd_Azx));
}
- /* Check the leap second status once per day */
+ /*
+ * Check the leap second status once per day.
+ */
+
+ if (instance->Bj_day != buf[5]) { /* do this 1/day */
+ instance->Bj_day = buf[5];
+
+ if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gj, sizeof(oncore_cmd_Gj));
+ else {
+ /*
+ * The following additional check, checking for June/December, is a
+ * workaround for incorrect ONCORE firmware. The oncore starts
+ * reporting the leap second when the GPS satellite data message
+ * (page 18, subframe 4) is updated to a date in the future, which
+ * can be several months before the leap second. WWV and other
+ * services seem to wait until the month of the event to turn
+ * on their indicators (which is usually a single bit).
+ */
+
+ if ((buf[4] == 6) || (buf[4] == 12))
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
+ }
+ }
/*
- * The following additional check, checking for June/December, is a
- * workaround for incorrect ONCORE firmware. The oncore starts
- * reporting the leap second when the GPS satellite data message
- * (page 18, subframe 4) is updated to a date in the future, which
- * which can be several months before the leap second. WWV and other
- * services seem to wait until the month of the event to turn
- * on their indicators (which are usually a single bit).
+ * if SHMEM active, every 15s, steal one 'tick' to get 2D or 3D posn.
*/
- if ((buf[4] == 6) || (buf[4] == 12)) {
- if (instance->Bj_day != buf[5]) { /* do this 1/day */
- instance->Bj_day = buf[5];
- oncore_sendmsg(instance->ttyfd, oncore_cmd_Bj, sizeof oncore_cmd_Bj);
+ if (instance->shmem && instance->shmem_Posn && (instance->site_survey == ONCORE_SS_DONE)) { /* dont screw up the SS by changing mode */
+ if (instance->pp->second%15 == 3) { /* start the sequence */
+ instance->shmem_reset = 1;
+ if (instance->chan == 12) {
+ if (instance->shmem_Posn == 2)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd2, sizeof(oncore_cmd_Gd2)); /* 2D */
+ else
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* 3D */
+ } else {
+ if (instance->saw_At) {
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* out of 0D to 3D mode */
+ if (instance->shmem_Posn == 2)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1)); /* 3D to 2D mode */
+ } else
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
+ }
+ } else if (instance->shmem_reset || (instance->mode != MODE_0D)) {
+ instance->shmem_reset = 0;
+ if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1)); /* 0D */
+ else {
+ if (instance->saw_At) {
+ if (instance->mode == MODE_2D)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* 2D -> 3D or 0D */
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1)); /* to 0D mode */
+ } else
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
+ }
}
}
- instance->pp->year = buf[6]*256+buf[7];
- instance->pp->day = ymd2yd(buf[6]*256+buf[7], buf[4], buf[5]);
- instance->pp->hour = buf[8];
- instance->pp->minute = buf[9];
- instance->pp->second = buf[10];
+
+ if (instance->traim == 0) /* NO traim, go get tick */
+ oncore_get_timestamp(instance, instance->offset, instance->offset);
if (instance->site_survey != ONCORE_SS_SW)
return;
/*
* We have to average our own position for the Position Hold Mode
+ * We use Heights from the GPS ellipsoid.
*/
- /* We only take PDOP/3D fixes */
-
- if (instance->Ea[37] & 1)
+ if (instance->rsm.bad_fix) /* Not if poor geometry or less than 3 sats */
return;
- /* Not if poor geometry or less than 3 sats */
-
- if (instance->Ea[72] & 0x52)
- return;
-
- /* Only 3D fix */
-
- if (!(instance->Ea[72] & 0x20))
+ if (instance->mode != MODE_3D) /* Only 3D Fix */
return;
instance->ss_lat += buf_w32(&instance->Ea[15]);
instance->ss_long += buf_w32(&instance->Ea[19]);
- instance->ss_ht += buf_w32(&instance->Ea[23]); /* GPS ellipse */
+ instance->ss_ht += buf_w32(&instance->Ea[23]); /* GPS ellipsoid */
instance->ss_count++;
if (instance->ss_count != POS_HOLD_AVERAGE)
@@ -1435,14 +2176,33 @@ oncore_msg_Ea(
instance->ss_lat, instance->ss_long, instance->ss_ht);
record_clock_stats(&(instance->peer->srcadr), Msg);
- w32_buf(&oncore_cmd_As[2], (int) instance->ss_lat);
- w32_buf(&oncore_cmd_As[6], (int) instance->ss_long);
- w32_buf(&oncore_cmd_As[10], (int) instance->ss_ht);
- oncore_cmd_As[14] = 0;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_As, sizeof oncore_cmd_As);
+ /* set newly determined position as 3D Position hold position */
+
+ memcpy(Cmd, oncore_cmd_As, sizeof(oncore_cmd_As));
+ w32_buf(&Cmd[2], (int) instance->ss_lat);
+ w32_buf(&Cmd[6], (int) instance->ss_long);
+ w32_buf(&Cmd[10], (int) instance->ss_ht);
+ Cmd[14] = 0;
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_As));
+
+ /* set height seperately for 2D */
+
+ memcpy(Cmd, oncore_cmd_Au, sizeof(oncore_cmd_Au));
+ w32_buf(&Cmd[2], (int) instance->ss_ht);
+ Cmd[6] = 0;
+ oncore_sendmsg(instance->ttyfd, Cmd, sizeof(oncore_cmd_Au));
+
+ /* and set Position Hold */
+
+ if (instance->chan == 12)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Gd1, sizeof(oncore_cmd_Gd1));
+ else {
+ if (instance->saw_At)
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_At1, sizeof(oncore_cmd_At1));
+ else
+ oncore_sendmsg(instance->ttyfd, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
+ }
- oncore_cmd_At[2] = 1;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
record_clock_stats(&(instance->peer->srcadr), "Now in 0D mode");
instance->site_survey = ONCORE_SS_DONE;
}
@@ -1450,21 +2210,60 @@ oncore_msg_Ea(
static void
-oncore_msg_En(
+oncore_msg_BnEn(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
- int j;
+ long dt1, dt2;
+ char *cp;
+
+ if (instance->o_state != ONCORE_RUN)
+ return;
+
+ if (instance->traim_delay) { /* flag that @@En/@@Bn returned */
+ instance->traim = 1;
+ instance->traim_delay = 0;
+ cp = "ONCORE: Detected TRAIM, TRAIM = ON";
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ }
+
+ memcpy(instance->En, buf, len); /* En or Bn */
+
+ /* If Time RAIM doesn't like it, don't trust it */
+
+ if (instance->En[21])
+ return;
+
+ dt1 = instance->saw_tooth + instance->offset; /* dt this time step */
+ instance->saw_tooth = (s_char) instance->En[25]; /* update for next time */
+ dt2 = instance->saw_tooth + instance->offset; /* dt next time step */
+
+ oncore_get_timestamp(instance, dt1, dt2);
+}
+
+
+
+static void
+oncore_get_timestamp(
+ struct instance *instance,
+ long dt1, /* tick offset THIS time step */
+ long dt2 /* tick offset NEXT time step */
+ )
+{
+ int Rsm;
+ u_long i, j;
l_fp ts, ts_tmp;
double dmy;
-#ifdef HAVE_TIMESPEC
+#ifdef HAVE_STRUCT_TIMESPEC
struct timespec *tsp = 0;
#else
struct timeval *tsp = 0;
#endif
#ifdef HAVE_PPSAPI
+ int current_mode;
+ pps_params_t current_params;
struct timespec timeout;
pps_info_t pps_i;
#else /* ! HAVE_PPSAPI */
@@ -1481,19 +2280,12 @@ oncore_msg_En(
#endif
#endif /* ! HAVE_PPS_API */
- if (instance->o_state != ONCORE_RUN)
+ if ((instance->site_survey == ONCORE_SS_DONE) && (instance->mode != MODE_0D))
return;
- memcpy(instance->En, buf, len);
-
/* Don't do anything without an almanac to define the GPS->UTC delta */
- if (instance->Ea[72] & 1)
- return;
-
- /* If Time RAIM doesn't like it, don't trust it */
-
- if (instance->En[21])
+ if (instance->rsm.bad_almanac)
return;
#ifdef HAVE_PPSAPI
@@ -1509,24 +2301,40 @@ oncore_msg_En(
if (instance->assert) {
tsp = &pps_i.assert_timestamp;
- if (debug > 2)
- printf("ONCORE: serial/j (%d, %d) %ld.%09ld\n",
- pps_i.assert_sequence, j, tsp->tv_sec, tsp->tv_nsec);
+ if (debug > 2) {
+ i = (u_long) pps_i.assert_sequence;
+#ifdef HAVE_STRUCT_TIMESPEC
+ printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%09ld\n",
+ instance->unit, i, j,
+ (long)tsp->tv_sec, (long)tsp->tv_nsec);
+#else
+ printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%06ld\n",
+ instance->unit, i, j,
+ (long)tsp->tv_sec, (long)tsp->tv_usec);
+#endif
+ }
if (pps_i.assert_sequence == j) {
- printf("ONCORE: oncore_msg_En, error serial pps\n");
+ printf("ONCORE: oncore_get_timestamp, error serial pps\n");
return;
}
instance->ev_serial = pps_i.assert_sequence;
} else {
tsp = &pps_i.clear_timestamp;
- if (debug > 2)
- printf("ONCORE: serial/j (%d, %d) %ld.%09ld\n",
- pps_i.clear_sequence, j, tsp->tv_sec, tsp->tv_nsec);
+ if (debug > 2) {
+ i = (u_long) pps_i.clear_sequence;
+#ifdef HAVE_STRUCT_TIMESPEC
+ printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%09ld\n",
+ instance->unit, i, j, (long)tsp->tv_sec, (long)tsp->tv_nsec);
+#else
+ printf("ONCORE[%d]: serial/j (%lu, %lu) %ld.%06ld\n",
+ instance->unit, i, j, (long)tsp->tv_sec, (long)tsp->tv_usec);
+#endif
+ }
if (pps_i.clear_sequence == j) {
- printf("ONCORE: oncore_msg_En, error serial pps\n");
+ printf("ONCORE: oncore_get_timestamp, error serial pps\n");
return;
}
instance->ev_serial = pps_i.clear_sequence;
@@ -1561,11 +2369,16 @@ oncore_msg_En(
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_msg_En, error serial pps\n");
+ printf("ONCORE: oncore_get_timestamp, error serial pps\n");
return;
}
instance->ev_serial = ev.serial;
@@ -1587,7 +2400,7 @@ oncore_msg_En(
# endif
#endif
/* now have timestamp in ts */
- /* add in saw_tooth and offset */
+ /* add in saw_tooth and offset, these will be ZERO if no TRAIM */
/* saw_tooth not really necessary if using TIMEVAL */
/* since its only precise to us, but do it anyway. */
@@ -1595,26 +2408,57 @@ oncore_msg_En(
/* offset in ns, and is positive (late), we subtract */
/* to put the PPS time transition back where it belongs */
- j = instance->saw_tooth + instance->offset;
- instance->saw_tooth = (s_char) buf[25]; /* update for next time */
#ifdef HAVE_PPSAPI
- /* must hand this offset off to the Kernel to do the addition */
- /* so that the Kernel PLL sees the offset too */
+ /* must hand the offset for the NEXT sec off to the Kernel to do */
+ /* the addition, so that the Kernel PLL sees the offset too */
- if (instance->assert) {
- instance->pps_p.assert_offset.tv_nsec =
- -(instance->saw_tooth + instance->offset);
- } else {
- instance->pps_p.clear_offset.tv_nsec =
- -(instance->saw_tooth + instance->offset);
+ if (instance->assert)
+ instance->pps_p.assert_offset.tv_nsec = -dt2;
+ else
+ instance->pps_p.clear_offset.tv_nsec = -dt2;
+
+ /* The following code is necessary, and not just a time_pps_setparams,
+ * using the saved instance->pps_p, since some other process on the
+ * machine may have diddled with the mode bits (say adding something
+ * that it needs). We take what is there and ADD what we need.
+ * [[ The results from the time_pps_getcap is unlikely to change so
+ * we could probably just save it, but I choose to do the call ]]
+ * Unfortunately, there is only ONE set of mode bits in the kernel per
+ * interface, and not one set for each open handle.
+ *
+ * There is still a race condition here where we might mess up someone
+ * elses mode, but if he is being careful too, he should survive.
+ */
+
+ if (time_pps_getcap(instance->pps_h, &current_mode) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_ioctl: time_pps_getcap failed: %m");
+ return;
+ }
+
+ if (time_pps_getparams(instance->pps_h, &current_params) < 0) {
+ msyslog(LOG_ERR,
+ "refclock_ioctl: time_pps_getparams failed: %m");
+ return;
}
- if (time_pps_setparams(instance->pps_h, &instance->pps_p))
+ /* or current and mine */
+ current_params.mode |= instance->pps_p.mode;
+ /* but only set whats legal */
+ current_params.mode &= current_mode;
+
+ current_params.assert_offset.tv_sec = 0;
+ current_params.assert_offset.tv_nsec = -dt2;
+ current_params.clear_offset.tv_sec = 0;
+ current_params.clear_offset.tv_nsec = -dt2;
+
+ if (time_pps_setparams(instance->pps_h, &current_params))
perror("time_pps_setparams");
#else
- /* if not PPSAPI, no way to inform kernel of OFFSET, just do it */
+ /* if not PPSAPI, no way to inform kernel of OFFSET, just add the */
+ /* offset for THIS second */
- dmy = -1.0e-9*j;
+ dmy = -1.0e-9*dt1;
DTOLFP(dmy, &ts_tmp);
L_ADD(&ts, &ts_tmp);
#endif
@@ -1625,28 +2469,55 @@ oncore_msg_En(
instance->pp->msec = 0;
ts_tmp = ts;
- ts_tmp.l_ui = 0; /* zero integer part */
- LFPTOD(&ts_tmp, dmy); /* convert fractional part to a double */
- j = 1.0e9*dmy; /* then to integer ns */
- sprintf(instance->pp->a_lastcode,
- "%u.%09u %d %d %2d %2d %2d %2ld rstat %02x dop %d nsat %2d,%d raim %d sigma %d neg-sawtooth %3d sat %d%d%d%d%d%d%d%d",
- ts.l_ui, j,
- instance->pp->year, instance->pp->day,
- instance->pp->hour, instance->pp->minute, instance->pp->second,
- (long) tsp->tv_sec % 60,
-
- instance->Ea[72], instance->Ea[37], instance->Ea[38], instance->Ea[39], instance->En[21],
- /*rstat dop nsat visible, nsat tracked, raim */
- instance->En[23]*256+instance->En[24], (s_char) buf[25],
- /* sigma neg-sawtooth */
- /*sat*/ instance->Ea[41], instance->Ea[45], instance->Ea[49], instance->Ea[53],
- instance->Ea[57], instance->Ea[61], instance->Ea[65], instance->Ea[69]
- );
+ ts_tmp.l_ui = 0; /* zero integer part */
+ LFPTOD(&ts_tmp, dmy); /* convert fractional part to a double */
+ j = 1.0e9*dmy; /* then to integer ns */
+
+ Rsm = 0;
+ if (instance->chan == 6)
+ Rsm = instance->Ea[64];
+ else if (instance->chan == 8)
+ Rsm = instance->Ea[72];
+ else if (instance->chan == 12)
+ Rsm = ((instance->Ea[129]<<8) | instance->Ea[130]);
+
+ if (instance->chan == 6 || instance->chan == 8) {
+ sprintf(instance->pp->a_lastcode, /* MAX length 128, currently at 117 */
+ "%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d sigma %d neg-sawtooth %3d sat %d%d%d%d%d%d%d%d",
+ ts.l_ui, j,
+ instance->pp->year, instance->pp->day,
+ instance->pp->hour, instance->pp->minute, instance->pp->second,
+ (long) tsp->tv_sec % 60,
+ Rsm, 0.1*(256*instance->Ea[35]+instance->Ea[36]),
+ /*rsat dop */
+ instance->Ea[38], instance->Ea[39], instance->En[21],
+ /* nsat visible, nsat tracked, traim */
+ instance->En[23]*256+instance->En[24], (s_char) instance->En[25],
+ /* sigma neg-sawtooth */
+ /*sat*/ instance->Ea[41], instance->Ea[45], instance->Ea[49], instance->Ea[53],
+ instance->Ea[57], instance->Ea[61], instance->Ea[65], instance->Ea[69]
+ ); /* will be 0 for 6 chan */
+ } else if (instance->chan == 12) {
+ sprintf(instance->pp->a_lastcode,
+ "%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d sat %d%d%d%d%d%d%d%d%d%d%d%d",
+ ts.l_ui, j,
+ instance->pp->year, instance->pp->day,
+ instance->pp->hour, instance->pp->minute, instance->pp->second,
+ (long) tsp->tv_sec % 60,
+ Rsm, 0.1*(256*instance->Ea[53]+instance->Ea[54]),
+ /*rsat dop */
+ instance->Ea[55], instance->Ea[56],
+ /* nsat visible, nsat tracked */
+ /*sat*/ instance->Ea[58], instance->Ea[64], instance->Ea[70], instance->Ea[76],
+ instance->Ea[82], instance->Ea[88], instance->Ea[94], instance->Ea[100],
+ instance->Ea[106], instance->Ea[112], instance->Ea[118], instance->Ea[124]
+ );
+ }
if (debug > 2) {
- int i;
- i = strlen(instance->pp->a_lastcode);
- printf("ONCORE: len = %d %s\n", i, instance->pp->a_lastcode);
+ int n;
+ n = strlen(instance->pp->a_lastcode);
+ printf("ONCORE[%d]: len = %d %s\n", instance->unit, n, instance->pp->a_lastcode);
}
if (!refclock_process(instance->pp)) {
@@ -1672,35 +2543,21 @@ oncore_msg_En(
* Try to use Oncore UT+ Auto Survey Feature
* If its not there (VP), set flag to do it ourselves.
*/
+
static void
oncore_msg_At(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
- if (instance->site_survey != ONCORE_SS_UNKNOWN)
- return;
-
- if (buf[4] == 2) {
- record_clock_stats(&(instance->peer->srcadr),
- "Initiating hardware 3D site survey");
- instance->site_survey = ONCORE_SS_HW;
- } else {
- char Msg[160];
- /*
- * Probably a VP or an older UT which can't do site-survey.
- * 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);
- instance->site_survey = ONCORE_SS_SW;
-
- oncore_cmd_At[2] = 0;
- instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
- oncore_sendmsg(instance->ttyfd, oncore_cmd_At, sizeof oncore_cmd_At);
+ instance->saw_At = 1;
+ if (instance->site_survey == ONCORE_SS_TESTING) {
+ if (buf[4] == 2) {
+ record_clock_stats(&(instance->peer->srcadr),
+ "Initiating hardware 3D site survey");
+ instance->site_survey = ONCORE_SS_HW;
+ }
}
}
@@ -1720,7 +2577,7 @@ static void
oncore_msg_Bj(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
const char *cp;
@@ -1743,41 +2600,97 @@ oncore_msg_Bj(
record_clock_stats(&(instance->peer->srcadr), cp);
}
+/* Leap Second for M12, gives all info from satellite message */
+
+static void
+oncore_msg_Gj(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ int dt;
+ char Msg[160], *cp;
+ static char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly",
+ "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ /* print the message to verify whats there */
+
+ dt = buf[5] - buf[4];
+
+#if 1
+ sprintf(Msg, "ONCORE[%d]: Leap Sec Msg: %d %d %d %d %d %d %d %d %d %d",
+ instance->unit,
+ buf[4], buf[5], 256*buf[6]+buf[7], buf[8], buf[9], buf[10],
+ (buf[14]+256*(buf[13]+256*(buf[12]+256*buf[11]))),
+ buf[15], buf[16], buf[17]);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+#endif
+ if (dt) {
+ sprintf(Msg, "ONCORE[%d]: Leap second (%d) scheduled for %d%s%d at %d:%d:%d",
+ instance->unit,
+ dt, buf[9], Month[buf[8]], 256*buf[6]+buf[7],
+ buf[15], buf[16], buf[17]);
+ record_clock_stats(&(instance->peer->srcadr), Msg);
+ }
+
+ /* Only raise warning within a month of the leap second */
+
+ instance->peer->leap = LEAP_NOWARNING;
+ cp = "Set peer.leap to LEAP_NOWARNING";
+
+ if (buf[6] == instance->Ea[6] && buf[7] == instance->Ea[7] && /* year */
+ buf[8] == instance->Ea[4]) { /* month */
+ if (dt) {
+ if (dt < 0) {
+ instance->peer->leap = LEAP_DELSECOND;
+ cp = "Set peer.leap to LEAP_DELSECOND";
+ } else {
+ instance->peer->leap = LEAP_ADDSECOND;
+ cp = "Set peer.leap to LEAP_ADDSECOND";
+ }
+ }
+ }
+ record_clock_stats(&(instance->peer->srcadr), cp);
+}
+
/*
* get Position hold position
*/
+
static void
oncore_msg_As(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
- char Msg[120], ew, ns;
- const char *Ht;
- double xd, xm, xs, yd, ym, ys, hm, hft;
- int idx, idy, is, imx, imy;
- long lat, lon, ht;
-
if (!instance->printed || instance->As)
return;
instance->As = 1;
- lat = buf_w32(&buf[4]);
- instance->ss_lat = lat;
+ instance->ss_lat = buf_w32(&buf[4]);
+ instance->ss_long = buf_w32(&buf[8]);
+ instance->ss_ht = buf_w32(&buf[12]);
- lon = buf_w32(&buf[8]);
- instance->ss_long = lon;
+ /* Print out Position */
+ oncore_print_As(instance);
+}
- ht = buf_w32(&buf[12]);
- instance->ss_ht = ht;
- instance->ss_ht_type = buf[16];
- /* Print out Position */
+static void
+oncore_print_As(
+ struct instance *instance
+ )
+{
+ char Msg[120], ew, ns;
+ double xd, xm, xs, yd, ym, ys, hm, hft;
+ int idx, idy, is, imx, imy;
+ long lat, lon;
record_clock_stats(&(instance->peer->srcadr), "Posn:");
ew = 'E';
@@ -1796,11 +2709,10 @@ oncore_msg_As(
hm = instance->ss_ht/100.;
hft= hm/0.3048;
- Ht = instance->ss_ht_type ? "MSL" : "GPS";
xd = lat/3600000.; /* lat, lon in int msec arc, ht in cm. */
yd = lon/3600000.;
- sprintf(Msg, "Lat = %c %11.7fdeg, Long = %c %11.7fdeg, Alt = %5.2fm (%5.2fft) %s", ns, xd, ew, yd, hm, hft, Ht);
+ sprintf(Msg, "Lat = %c %11.7fdeg, Long = %c %11.7fdeg, Alt = %5.2fm (%5.2fft) GPS", ns, xd, ew, yd, hm, hft);
record_clock_stats(&(instance->peer->srcadr), Msg);
idx = xd;
@@ -1809,7 +2721,7 @@ oncore_msg_As(
imy = lon%3600000;
xm = imx/60000.;
ym = imy/60000.;
- sprintf(Msg, "Lat = %c %3ddeg %7.4fm, Long = %c %3ddeg %8.5fm, Alt = %5.2fm (%5.2fft) %s", ns, idx, xm, ew, idy, ym, hm, hft, Ht);
+ sprintf(Msg, "Lat = %c %3ddeg %7.4fm, Long = %c %3ddeg %8.5fm, Alt = %7.2fm (%7.2fft) GPS", ns, idx, xm, ew, idy, ym, hm, hft);
record_clock_stats(&(instance->peer->srcadr), Msg);
imx = xm;
@@ -1818,7 +2730,7 @@ oncore_msg_As(
xs = is/1000.;
is = lon%60000;
ys = is/1000.;
- sprintf(Msg, "Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %5.2fm (%5.2fft) %s", ns, idx, imx, xs, ew, idy, imy, ys, hm, hft, Ht);
+ sprintf(Msg, "Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %7.2fm (%7.2fft) GPS", ns, idx, imx, xs, ew, idy, imy, ys, hm, hft);
record_clock_stats(&(instance->peer->srcadr), Msg);
}
@@ -1828,11 +2740,12 @@ oncore_msg_As(
* get PPS Offset
* Nb. @@Ay is not supported for early UT (no plus) model
*/
+
static void
oncore_msg_Ay(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
char Msg[120];
@@ -1853,11 +2766,12 @@ oncore_msg_Ay(
/*
* get Cable Delay
*/
+
static void
oncore_msg_Az(
struct instance *instance,
u_char *buf,
- u_int len
+ size_t len
)
{
char Msg[120];
@@ -1872,6 +2786,23 @@ oncore_msg_Az(
sprintf(Msg, "Cable delay is set to %ld ns", instance->delay);
record_clock_stats(&(instance->peer->srcadr), Msg);
}
+
+static void
+oncore_msg_Sz(
+ struct instance *instance,
+ u_char *buf,
+ size_t len
+ )
+{
+ const char *cp;
+
+ cp = "Oncore: System Failure at Power On";
+ if (instance && instance->peer) {
+ record_clock_stats(&(instance->peer->srcadr), cp);
+ oncore_shutdown(instance->unit, instance->peer);
+ }
+}
+
#else
int refclock_oncore_bs;
#endif /* REFCLOCK */
diff --git a/contrib/ntp/ntpd/refclock_palisade.c b/contrib/ntp/ntpd/refclock_palisade.c
index bedf6e8..d8ce411 100644
--- a/contrib/ntp/ntpd/refclock_palisade.c
+++ b/contrib/ntp/ntpd/refclock_palisade.c
@@ -2,7 +2,7 @@
* This software was developed by the Software and Component Technologies
* group of Trimble Navigation, Ltd.
*
- * Copyright (c) 1997, 1998, 1999 Trimble Navigation Ltd.
+ * Copyright (c) 1997, 1998, 1999, 2000 Trimble Navigation Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/contrib/ntp/ntpd/refclock_palisade.h b/contrib/ntp/ntpd/refclock_palisade.h
index b78d988..cc37716 100644
--- a/contrib/ntp/ntpd/refclock_palisade.h
+++ b/contrib/ntp/ntpd/refclock_palisade.h
@@ -2,7 +2,7 @@
* This software was developed by the Software and Component Technologies
* group of Trimble Navigation, Ltd.
*
- * Copyright (c) 1997, 1998, 1999 Trimble Navigation Ltd.
+ * Copyright (c) 1997, 1998, 1999, 2000 Trimble Navigation Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -91,8 +91,8 @@
#define DESCRIPTION "Trimble Palisade GPS" /* Long name */
#define PRECISION (-20) /* precision assumed (about 1 us) */
#define REFID "GPS\0" /* reference ID */
-#define TRMB_MINPOLL 5 /* 16 seconds */
-#define TRMB_MAXPOLL 7 /* 64 seconds */
+#define TRMB_MINPOLL 4 /* 16 seconds */
+#define TRMB_MAXPOLL 5 /* 32 seconds */
/*
* I/O Definitions
diff --git a/contrib/ntp/ntpd/refclock_parse.c b/contrib/ntp/ntpd/refclock_parse.c
index 95b93aa..cfb9904 100644
--- a/contrib/ntp/ntpd/refclock_parse.c
+++ b/contrib/ntp/ntpd/refclock_parse.c
@@ -767,8 +767,6 @@ static poll_info_t rcc8000_pollinfo = { RCC_POLLRATE, RCC_POLLCMD, RCC_CMDSIZE }
#define COMPUTIME_SAMPLES 5
#define COMPUTIME_KEEP 3
-static poll_info_t we400a_pollinfo = { 60, "T", 1 };
-
/*
* Varitext Radio Clock Receiver
*/
@@ -1169,18 +1167,18 @@ static struct parse_clockinfo
},
{ /* mode 15 */
0, /* operation flags (io modes) */
- poll_dpoll, /* active poll routine */
- poll_init, /* active poll init routine */
+ NO_POLL, /* active poll routine */
+ NO_INIT, /* active poll init routine */
NO_EVENT, /* special event handling (e.g. reset clock) */
NO_END, /* active poll end routine */
NO_MESSAGE, /* process a lower layer message */
- ((void *)(&we400a_pollinfo)), /* local data area for "poll" mechanism */
+ NO_DATA, /* local data area for "poll" mechanism */
0, /* rootdelay */
- 1.0 / 960, /* current offset by which the RS232
+ 11.0 /* bits */ / 9600, /* current offset by which the RS232
time code is delayed from the actual time */
DCF_ID, /* ID code */
"WHARTON 400A Series clock", /* device name */
- "WHARTON 400A Series clock Output Format 5", /* fixed format */
+ "WHARTON 400A Series clock Output Format 1", /* fixed format */
/* Must match a format-name in a libparse/clk_xxx.c file */
DCF_TYPE, /* clock type (ntp control) */
(1*60*60), /* time to trust oscillator after loosing synch */
@@ -1242,10 +1240,10 @@ static struct parse_clockinfo
static int ncltypes = sizeof(parse_clockinfo) / sizeof(struct parse_clockinfo);
-#define CLK_REALTYPE(x) ((int)(((x)->ttl) & 0x7F))
+#define CLK_REALTYPE(x) ((int)(((x)->ttlmax) & 0x7F))
#define CLK_TYPE(x) ((CLK_REALTYPE(x) >= ncltypes) ? ~0 : CLK_REALTYPE(x))
#define CLK_UNIT(x) ((int)REFCLOCKUNIT(&(x)->srcadr))
-#define CLK_PPS(x) (((x)->ttl) & 0x80)
+#define CLK_PPS(x) (((x)->ttlmax) & 0x80)
/*
* Other constant stuff
@@ -5150,16 +5148,24 @@ rawdcf_init_1(
struct parseunit *parse
)
{
+ /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
/*
* You can use the RS232 to supply the power for a DCF77 receiver.
* Here a voltage between the DTR and the RTS line is used. Unfortunately
* the name has changed from CIOCM_DTR to TIOCM_DTR recently.
*/
-
+ int sl232;
+
+ if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
+ {
+ msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_1: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_DTR): %m", CLK_UNIT(parse->peer));
+ return 0;
+ }
+
#ifdef TIOCM_DTR
- int sl232 = TIOCM_DTR; /* turn on DTR for power supply */
+ sl232 = (sl232 & ~TIOCM_RTS) | TIOCM_DTR; /* turn on DTR, clear RTS for power supply */
#else
- int sl232 = CIOCM_DTR; /* turn on DTR for power supply */
+ sl232 = (sl232 & ~CIOCM_RTS) | CIOCM_DTR; /* turn on DTR, clear RTS for power supply */
#endif
if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
@@ -5189,16 +5195,24 @@ rawdcf_init_2(
struct parseunit *parse
)
{
+ /* fixed 2000 for using with Linux by Wolfram Pienkoss <wp@bszh.de> */
/*
* You can use the RS232 to supply the power for a DCF77 receiver.
* Here a voltage between the DTR and the RTS line is used. Unfortunately
* the name has changed from CIOCM_DTR to TIOCM_DTR recently.
*/
-
+ int sl232;
+
+ if (ioctl(parse->generic->io.fd, TIOCMGET, (caddr_t)&sl232) == -1)
+ {
+ msyslog(LOG_NOTICE, "PARSE receiver #%d: rawdcf_init_2: WARNING: ioctl(fd, TIOCMGET, [C|T]IOCM_RTS): %m", CLK_UNIT(parse->peer));
+ return 0;
+ }
+
#ifdef TIOCM_RTS
- int sl232 = TIOCM_RTS; /* turn on RTS, clear DTR for power supply */
+ sl232 = (sl232 & ~TIOCM_DTR) | TIOCM_RTS; /* turn on RTS, clear DTR for power supply */
#else
- int sl232 = CIOCM_RTS; /* turn on DTR for power supply */
+ sl232 = (sl232 & ~CIOCM_DTR) | CIOCM_RTS; /* turn on RTS, clear DTR for power supply */
#endif
if (ioctl(parse->generic->io.fd, TIOCMSET, (caddr_t)&sl232) == -1)
diff --git a/contrib/ntp/ntpd/refclock_pcf.c b/contrib/ntp/ntpd/refclock_pcf.c
index c882404..ff2b28e 100644
--- a/contrib/ntp/ntpd/refclock_pcf.c
+++ b/contrib/ntp/ntpd/refclock_pcf.c
@@ -8,8 +8,6 @@
#if defined(REFCLOCK) && defined(CLOCK_PCF)
-#include <time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
@@ -17,18 +15,20 @@
#include "ntp_stdlib.h"
/*
- * This driver supports the parallel port radio clocks sold by Conrad
+ * This driver supports the parallel port radio clock sold by Conrad
* Electronic under order numbers 967602 and 642002.
*
* It requires that the local timezone be CET/CEST and that the pcfclock
- * device driver be installed. A device driver for Linux 2.2 is available
- * at http://home.pages.de/~voegele/pcf.html.
+ * device driver be installed. A device driver for Linux is available at
+ * http://home.pages.de/~voegele/pcf.html. Information about a FreeBSD
+ * driver is available at http://schumann.cx/pcfclock/.
*/
/*
* Interface definitions
*/
-#define DEVICE "/dev/pcfclock%d"
+#define DEVICE "/dev/pcfclocks/%d"
+#define OLDDEVICE "/dev/pcfclock%d"
#define PRECISION (-1) /* precision assumed (about 0.5 s) */
#define REFID "PCF"
#define DESCRIPTION "Conrad parallel port radio clock"
@@ -67,17 +67,22 @@ pcf_start(
{
struct refclockproc *pp;
int fd;
- char device[20];
+ char device[128];
/*
* Open device file for reading.
*/
(void)sprintf(device, DEVICE, unit);
+ fd = open(device, O_RDONLY);
+ if (fd == -1) {
+ (void)sprintf(device, OLDDEVICE, unit);
+ fd = open(device, O_RDONLY);
+ }
#ifdef DEBUG
if (debug)
printf ("starting PCF with device %s\n",device);
#endif
- if ((fd = open(device, O_RDONLY)) == -1) {
+ if (fd == -1) {
return (0);
}
@@ -92,6 +97,9 @@ pcf_start(
*/
peer->precision = PRECISION;
pp->clockdesc = DESCRIPTION;
+ /* one transmission takes 172.5 milliseconds since the radio clock
+ transmits 69 bits with a period of 2.5 milliseconds per bit */
+ pp->fudgetime1 = 0.1725;
memcpy((char *)&pp->refid, REFID, 4);
return (1);
@@ -142,7 +150,7 @@ pcf_poll(
tm.tm_hour = buf[7] * 10 + buf[6];
tm.tm_min = buf[5] * 10 + buf[4];
tm.tm_sec = buf[3] * 10 + buf[2];
- tm.tm_isdst = -1;
+ tm.tm_isdst = (buf[8] & 1) ? 1 : (buf[8] & 2) ? 0 : -1;
/*
* Y2K convert the 2-digit year
@@ -204,7 +212,7 @@ pcf_poll(
return;
}
record_clock_stats(&peer->srcadr, pp->a_lastcode);
- if (buf[1] & 1)
+ if ((buf[1] & 1) && !(pp->sloppyclockflag & CLK_FLAG2))
pp->leap = LEAP_NOTINSYNC;
else
pp->leap = LEAP_NOWARNING;
diff --git a/contrib/ntp/ntpd/refclock_pst.c b/contrib/ntp/ntpd/refclock_pst.c
index 6af4382..b92a2e0 100644
--- a/contrib/ntp/ntpd/refclock_pst.c
+++ b/contrib/ntp/ntpd/refclock_pst.c
@@ -8,15 +8,14 @@
#if defined(REFCLOCK) && defined(CLOCK_PST)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/*
* This driver supports the PSTI 1010 and Traconex 1020 WWV/WWVH
* Receivers. No specific claim of accuracy is made for these receiver,
diff --git a/contrib/ntp/ntpd/refclock_shm.c b/contrib/ntp/ntpd/refclock_shm.c
index a8094c8..3747ce0 100644
--- a/contrib/ntp/ntpd/refclock_shm.c
+++ b/contrib/ntp/ntpd/refclock_shm.c
@@ -13,12 +13,6 @@
#if defined(REFCLOCK) && defined(CLOCK_SHM)
-#undef fileno
-#include <ctype.h>
-#undef fileno
-#include <sys/time.h>
-#undef fileno
-
#include "ntpd.h"
#undef fileno
#include "ntp_io.h"
@@ -29,15 +23,16 @@
#undef fileno
#include "ntp_stdlib.h"
+#undef fileno
+#include <ctype.h>
+#undef fileno
+
#ifndef SYS_WINNT
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <assert.h>
-#include <time.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
+# include <sys/ipc.h>
+# include <sys/shm.h>
+# include <assert.h>
+# include <unistd.h>
+# include <stdio.h>
#endif
/*
@@ -94,35 +89,19 @@ struct shmTime {
};
struct shmTime *getShmTime (int unit) {
#ifndef SYS_WINNT
- extern char *sys_errlist[ ];
- extern int sys_nerr;
int shmid=0;
assert (unit<10); /* MAXUNIT is 4, so should never happen */
shmid=shmget (0x4e545030+unit, sizeof (struct shmTime),
IPC_CREAT|(unit<2?0700:0777));
if (shmid==-1) { /*error */
- char buf[20];
- char *pe=buf;
- if (errno<sys_nerr)
- pe=sys_errlist[errno];
- else {
- sprintf (buf,"errno=%d",errno);
- }
- msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,pe);
+ msyslog(LOG_ERR,"SHM shmget (unit %d): %s",unit,strerror(errno));
return 0;
}
else { /* no error */
struct shmTime *p=(struct shmTime *)shmat (shmid, 0, 0);
if ((int)(long)p==-1) { /* error */
- char buf[20];
- char *pe=buf;
- if (errno<sys_nerr)
- pe=sys_errlist[errno];
- else {
- sprintf (buf,"errno=%d",errno);
- }
- msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,pe);
+ msyslog(LOG_ERR,"SHM shmat (unit %d): %s",unit,strerror(errno));
return 0;
}
return p;
@@ -285,6 +264,7 @@ shm_poll(
up->valid=0;
if (ok) {
TVTOTS(&tvr,&pp->lastrec);
+ pp->lastrec.l_ui += JAN_1970;
/* pp->lasttime = current_time; */
pp->polls++;
t=gmtime (&tvt.tv_sec);
diff --git a/contrib/ntp/ntpd/refclock_tpro.c b/contrib/ntp/ntpd/refclock_tpro.c
index a29383a..159f817 100644
--- a/contrib/ntp/ntpd/refclock_tpro.c
+++ b/contrib/ntp/ntpd/refclock_tpro.c
@@ -8,10 +8,6 @@
#if defined(REFCLOCK) && defined(CLOCK_TPRO)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
@@ -19,6 +15,9 @@
#include "sys/tpro.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/*
* This driver supports the KSI/Odetecs TPRO-S IRIG-B reader and TPRO-
* SAT GPS receiver for the Sun Microsystems SBus. It requires that the
diff --git a/contrib/ntp/ntpd/refclock_trak.c b/contrib/ntp/ntpd/refclock_trak.c
index e7833af..326a8e9 100644
--- a/contrib/ntp/ntpd/refclock_trak.c
+++ b/contrib/ntp/ntpd/refclock_trak.c
@@ -10,13 +10,7 @@
#include <config.h>
#endif
-#if defined(REFCLOCK) && defined(CLOCK_TRAK)
-
-#include <stdio.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
+#if defined(REFCLOCK) && defined(CLOCK_TRAK) && defined(PPS)
#include "ntpd.h"
#include "ntp_io.h"
@@ -24,6 +18,9 @@
#include "ntp_stdlib.h"
#include "ntp_unixtime.h"
+#include <stdio.h>
+#include <ctype.h>
+
#ifdef HAVE_SYS_TERMIOS_H
# include <sys/termios.h>
#endif
diff --git a/contrib/ntp/ntpd/refclock_true.c b/contrib/ntp/ntpd/refclock_true.c
index b841f72..dcc362d 100644
--- a/contrib/ntp/ntpd/refclock_true.c
+++ b/contrib/ntp/ntpd/refclock_true.c
@@ -12,16 +12,15 @@
#if defined(REFCLOCK) && defined(CLOCK_TRUETIME)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/* This should be an atom clock but those are very hard to build.
*
* The PCL720 from P C Labs has an Intel 8253 lookalike, as well as a bunch
@@ -62,11 +61,12 @@
*
* Quality codes indicate possible error of
* 468-DC GOES Receiver:
- * GPS-TM/TMD Receiver:
- * ? +/- 500 milliseconds # +/- 50 milliseconds
- * * +/- 5 milliseconds . +/- 1 millisecond
- * space less than 1 millisecond
- * OM-DC OMEGA Receiver:
+ * GPS-TM/TMD Receiver: (default quality codes for XL-DC)
+ * ? +/- 1 milliseconds # +/- 100 microseconds
+ * * +/- 10 microseconds . +/- 1 microsecond
+ * space less than 1 microsecond
+ * OM-DC OMEGA Receiver: (default quality codes for OMEGA)
+ * WARNING OMEGA navigation system is no longer existent
* > >+- 5 seconds
* ? >+/- 500 milliseconds # >+/- 50 milliseconds
* * >+/- 5 milliseconds . >+/- 1 millisecond
@@ -109,6 +109,7 @@
* flag4 - use the PCL-720 (BSD/OS only)
*/
+
/*
* Definitions
*/
@@ -211,11 +212,12 @@ true_debug(struct peer *peer, const char *fmt, ...)
if (want_debugging != now_debugging)
{
if (want_debugging) {
- char filename[20];
+ char filename[40];
+ int fd;
- sprintf(filename, "/tmp/true%d.debug", up->unit);
- up->debug = fopen(filename, "w");
- if (up->debug) {
+ snprintf(filename, sizeof(filename), "/tmp/true%d.debug", up->unit);
+ fd = open(filename, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ if (fd >= 0 && (up->debug = fdopen(fd, "r+"))) {
#ifdef HAVE_SETVBUF
static char buf[BUFSIZ];
setvbuf(up->debug, buf, _IOLBF, BUFSIZ);
@@ -247,13 +249,13 @@ true_start(
{
register struct true_unit *up;
struct refclockproc *pp;
- char device[20];
+ char device[40];
int fd;
/*
* Open serial port
*/
- (void)sprintf(device, DEVICE, unit);
+ (void)snprintf(device, sizeof(device), DEVICE, unit);
if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
return (0);
@@ -325,6 +327,10 @@ true_receive(
char synced;
int i;
int lat, lon, off; /* GOES Satellite position */
+ /* Use these variable to hold data until we decide its worth keeping */
+ char rd_lastcode[BMAX];
+ l_fp rd_tmp;
+ u_short rd_lencode;
/*
* Get the clock this applies to and pointers to the data.
@@ -336,14 +342,17 @@ true_receive(
/*
* Read clock output. Automatically handles STREAMS, CLKLDISC.
*/
- pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &pp->lastrec);
+ rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
+ rd_lastcode[rd_lencode] = '\0';
/*
* There is a case where <cr><lf> generates 2 timestamps.
*/
- if (pp->lencode == 0)
- return;
- pp->a_lastcode[pp->lencode] = '\0';
+ if (rd_lencode == 0)
+ return;
+ pp->lencode = rd_lencode;
+ strcpy(pp->a_lastcode, rd_lastcode);
+ pp->lastrec = rd_tmp;
true_debug(peer, "receive(%s) [%d]\n", pp->a_lastcode, pp->lencode);
up->pollcnt = 2;
@@ -360,7 +369,8 @@ true_receive(
/*
* Clock misunderstood our last command?
*/
- if (pp->a_lastcode[0] == '?') {
+ if (pp->a_lastcode[0] == '?' ||
+ strcmp(pp->a_lastcode, "ERROR 05 NO SUCH FUNCTION") == 0) {
true_doevent(peer, e_Huh);
return;
}
@@ -428,13 +438,14 @@ true_receive(
}
/*
- * Timecode: " TRUETIME Mk III"
- * (from a TM/TMD clock during initialization.)
+ * Timecode: " TRUETIME Mk III" or " TRUETIME XL"
+ * (from a TM/TMD/XL clock during initialization.)
*/
- if (strcmp(pp->a_lastcode, " TRUETIME Mk III") == 0) {
+ if (strcmp(pp->a_lastcode, " TRUETIME Mk III") == 0 ||
+ strncmp(pp->a_lastcode, " TRUETIME XL", 12) == 0) {
true_doevent(peer, e_F18);
NLOG(NLOG_CLOCKSTATUS) {
- msyslog(LOG_INFO, "TM/TMD: %s", pp->a_lastcode);
+ msyslog(LOG_INFO, "TM/TMD/XL: %s", pp->a_lastcode);
}
return;
}
@@ -467,9 +478,12 @@ true_receive(
/*
* Adjust the synchronize indicator according to timecode
+ * say were OK, and then say not if we really are not OK
*/
- if (synced != ' ' && synced != '.' && synced != '*')
+ if (synced == '>' || synced == '#' || synced == '?')
pp->leap = LEAP_NOTINSYNC;
+ else
+ pp->leap = LEAP_NOWARNING;
true_doevent(peer, e_TS);
@@ -527,6 +541,11 @@ true_receive(
refclock_report(peer, CEVNT_BADTIME);
return;
}
+ /*
+ * If clock is good we send a NOMINAL message so that
+ * any previous BAD messages are nullified
+ */
+ refclock_report(peer, CEVNT_NOMINAL);
refclock_receive(peer);
/*
diff --git a/contrib/ntp/ntpd/refclock_ulink.c b/contrib/ntp/ntpd/refclock_ulink.c
index 347040d..5bf569a 100644
--- a/contrib/ntp/ntpd/refclock_ulink.c
+++ b/contrib/ntp/ntpd/refclock_ulink.c
@@ -1,12 +1,25 @@
/*
- * refclock_ulink - clock driver for Ultralink Model 320 WWVB receivers
- * By Dave Strout <dstrout@linuxfoundary.com>
- *
- * Latest version is always on www.linuxfoundary.com
- *
- * Based on the Spectracom driver
+ * refclock_ulink - clock driver for Ultralink WWVB receiver
+ *
*/
+/***********************************************************************
+ * *
+ * Copyright (c) David L. Mills 1992-1998 *
+ * *
+ * Permission to use, copy, modify, and distribute this software and *
+ * its documentation for any purpose and without fee is hereby *
+ * granted, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission *
+ * notice appear in supporting documentation, and that the name *
+ * University of Delaware not be used in advertising or publicity *
+ * pertaining to distribution of the software without specific, *
+ * written prior permission. The University of Delaware makes no *
+ * representations about the suitability this software for any *
+ * purpose. It is provided "as is" without express or implied *
+ * warranty. *
+ **********************************************************************/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -15,8 +28,6 @@
#include <stdio.h>
#include <ctype.h>
-#include <sys/time.h>
-#include <time.h>
#include "ntpd.h"
#include "ntp_io.h"
@@ -25,63 +36,66 @@
#include "ntp_stdlib.h"
/*
- * This driver supports the Ultralink Model 320 WWVB receiver. The Model 320 is
- * an RS-232 powered unit which consists of two parts: a DB-25 shell that contains
- * a microprocessor, and an approx 2"x4" plastic box that contains the antenna.
- * The two are connected by a 6-wire RJ-25 cable of length up to 1000'. The
- * microprocessor steals power from the RS-232 port, which means that the port must
- * be kept open all of the time. The unit also has an internal clock for loss of signal
- * periods. Claimed accuracy is 0.1 sec.
- *
- * The timecode format is:
+ * This driver supports ultralink Model 320,330,331,332 WWVB radios
*
- * <cr><lf>SQRYYYYDDD+HH:MM:SS.mmLT<cr>
+ * this driver was based on the refclock_wwvb.c driver
+ * in the ntp distribution.
*
- * where:
+ * Fudge Factors
*
- * S = 'S' -- sync'd in last hour, '0'-'9' - hours x 10 since last update, else '?'
- * Q = Number of correlating time-frames, from 0 to 5
- * R = 'R' -- reception in progress, 'N' -- Noisy reception, ' ' -- standby mode
- * YYYY = year from 1990 to 2089
- * DDD = current day from 1 to 366
- * + = '+' if current year is a leap year, else ' '
- * HH = UTC hour 0 to 23
- * MM = Minutes of current hour from 0 to 59
- * SS = Seconds of current minute from 0 to 59
- * mm = 10's milliseconds of the current second from 00 to 99
- * L = Leap second pending at end of month -- 'I' = inset, 'D'=delete
- * T = DST <-> STD transition indicators
+ * fudge flag1 0 don't poll clock
+ * 1 send poll character
*
- * Note that this driver does not do anything with the L or T flags.
+ * revision history:
+ * 99/9/09 j.c.lang original edit's
+ * 99/9/11 j.c.lang changed timecode parse to
+ * match what the radio actually
+ * sends.
+ * 99/10/11 j.c.lang added support for continous
+ * time code mode (dipsw2)
+ * 99/11/26 j.c.lang added support for 320 decoder
+ * (taken from Dave Strout's
+ * Model 320 driver)
+ * 99/11/29 j.c.lang added fudge flag 1 to control
+ * clock polling
+ * 99/12/15 j.c.lang fixed 320 quality flag
+ * 01/02/21 s.l.smith fixed 33x quality flag
+ * added more debugging stuff
+ * updated 33x time code explanation
*
- * The M320 also has a 'U' command which returns UT1 correction information. It
- * is not used in this driver.
+ * Questions, bugs, ideas send to:
+ * Joseph C. Lang
+ * tcnojl1@earthlink.net
*
- */
+ * Dave Strout
+ * dstrout@linuxfoundry.com
+ *
+ *
+ * on the Ultralink model 33X decoder Dip switch 2 controls
+ * polled or continous timecode
+ * set fudge flag1 if using polled (needed for model 320)
+ * dont set fudge flag1 if dip switch 2 is set on model 33x decoder
+*/
+
/*
* Interface definitions
*/
-#define DEVICE "/dev/ulink%d" /* device name and unit */
+#define DEVICE "/dev/wwvb%d" /* device name and unit */
#define SPEED232 B9600 /* uart speed (9600 baud) */
-#define PRECISION (-13) /* precision assumed (about 100 us) */
-#define REFID "M320" /* reference ID */
+#define PRECISION (-10) /* precision assumed (about 10 ms) */
+#define REFID "WWVB" /* reference ID */
#define DESCRIPTION "Ultralink WWVB Receiver" /* WRU */
-#define LENWWVB0 28 /* format 0 timecode length */
-#define LENWWVB2 24 /* format 2 timecode length */
-#define LENWWVB3 29 /* format 3 timecode length */
-
-#define MONLIN 15 /* number of monitoring lines */
+#define LEN33X 32 /* timecode length Model 325 & 33X */
+#define LEN320 24 /* timecode length Model 320 */
/*
- * ULINK unit control structure
+ * unit control structure
*/
struct ulinkunit {
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 */
};
/*
@@ -91,7 +105,6 @@ static int ulink_start P((int, struct peer *));
static void ulink_shutdown P((int, struct peer *));
static void ulink_receive P((struct recvbuf *));
static void ulink_poll P((int, struct peer *));
-static int fd; /* We need to keep the serial port open to power the ULM320 */
/*
* Transfer vector
@@ -100,10 +113,10 @@ struct refclock refclock_ulink = {
ulink_start, /* start up driver */
ulink_shutdown, /* shut down driver */
ulink_poll, /* transmit poll message */
- noentry, /* not used (old wwvb_control) */
- noentry, /* initialize driver (not used) */
- noentry, /* not used (old wwvb_buginfo) */
- NOFLAGS /* not used */
+ noentry, /* not used */
+ noentry, /* not used */
+ noentry, /* not used */
+ NOFLAGS
};
@@ -118,8 +131,9 @@ ulink_start(
{
register struct ulinkunit *up;
struct refclockproc *pp;
+ int fd;
char device[20];
- fprintf(stderr, "Starting Ulink driver\n");
+
/*
* Open serial port. Use CLK line discipline, if available.
*/
@@ -152,7 +166,6 @@ ulink_start(
* Initialize miscellaneous variables
*/
peer->precision = PRECISION;
- peer->flags |= FLAG_BURST;
peer->burst = NSTAGE;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
@@ -176,7 +189,6 @@ ulink_shutdown(
up = (struct ulinkunit *)pp->unitptr;
io_closeclock(&pp->io);
free(up);
- close(fd);
}
@@ -193,11 +205,12 @@ ulink_receive(
struct peer *peer;
l_fp trtmp; /* arrival timestamp */
+ int quality; /* quality indicator */
+ int temp; /* int temp */
char syncchar; /* synchronization indicator */
- char qualchar; /* quality indicator */
- char modechar; /* Modes: 'R'=rx, 'N'=noise, ' '=standby */
char leapchar; /* leap indicator */
- int temp; /* int temp */
+ char modechar; /* model 320 mode flag */
+ char char_quality[2]; /* temp quality flag */
/*
* Initialize pointers and read the timecode and timestamp
@@ -209,13 +222,7 @@ ulink_receive(
/*
* Note we get a buffer and timestamp for both a <cr> and <lf>,
- * but only the <cr> timestamp is retained. Note: in format 0 on
- * a Netclock/2 or upgraded 8170 the start bit is delayed 100
- * +-50 us relative to the pps; however, on an unmodified 8170
- * the start bit can be delayed up to 10 ms. In format 2 the
- * reading precision is only to the millisecond. Thus, unless
- * you have a pps gadget and don't have to have the year, format
- * 0 provides the lowest jitter.
+ * but only the <cr> timestamp is retained.
*/
if (temp == 0) {
if (up->tcswitch == 0) {
@@ -237,40 +244,217 @@ ulink_receive(
/*
* We get down to business, check the timecode format and decode
- * its contents. This code uses the timecode length to determine
- * whether format 0 or format 2. If the timecode has invalid
- * length or is not in proper format, we declare bad format and
- * exit.
+ * its contents. If the timecode has invalid length or is not in
+ * proper format, we declare bad format and exit.
*/
- syncchar = qualchar = leapchar = ' ';
+ syncchar = leapchar = modechar = ' ';
pp->msec = 0;
+
+ switch (pp->lencode ) {
+ case LEN33X:
+ /*
+ * Model 33X decoder:
+ * Timecode format from January 29, 2001 datasheet is:
+ * <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5
+ * S WWVB decoder sync indicator. S for in-sync(?)
+ * or N for noisy signal.
+ * 9+ RF signal level in S-units, 0-9 followed by
+ * a space (0x20). The space turns to '+' if the
+ * level is over 9.
+ * D Data bit 0, 1, 2 (position mark), or
+ * 3 (unknown).
+ * space Space character (0x20)
+ * 00 Hours since last good WWVB frame sync. Will
+ * be 00-23 hrs, or '1d' to '7d'. Will be 'Lk'
+ * if currently in sync.
+ * space Space character (0x20)
+ * YYYY Current year, 1990-2089
+ * + Leap year indicator. '+' if a leap year,
+ * a space (0x20) if not.
+ * DDD Day of year, 001 - 366.
+ * UTC Timezone (always 'UTC').
+ * S Daylight savings indicator
+ * S - standard time (STD) in effect
+ * O - during STD to DST day 0000-2400
+ * D - daylight savings time (DST) in effect
+ * I - during DST to STD day 0000-2400
+ * space Space character (0x20)
+ * HH Hours 00-23
+ * : This is the REAL in sync indicator (: = insync)
+ * MM Minutes 00-59
+ * : : = in sync ? = NOT in sync
+ * SS Seconds 00-59
+ * L Leap second flag. Changes from space (0x20)
+ * to '+' or '-' during month preceding leap
+ * second adjustment.
+ * +5 UT1 correction (sign + digit ))
+ */
+
+ if (sscanf(pp->a_lastcode,
+ "%*4c %2c %4d%*c%3d%*4c %2d%c%2d:%2d%c%*2c",
+ char_quality, &pp->year, &pp->day,
+ &pp->hour, &syncchar, &pp->minute, &pp->second,
+ &leapchar) == 8) {
+
+ if (char_quality[0] == 'L') {
+ quality = 0;
+ } else if (char_quality[0] == '0') {
+ quality = (char_quality[1] & 0x0f);
+ } else {
+ quality = 99;
+ }
+/*
+#ifdef DEBUG
+ if (debug) {
+ printf("ulink: char_quality %c %c\n",
+ char_quality[0], char_quality[1]);
+ printf("ulink: quality %d\n", quality);
+ printf("ulink: syncchar %x\n", syncchar);
+ printf("ulink: leapchar %x\n", leapchar);
+ }
+#endif
+*/
+
+ break;
+ }
+
+ case LEN320:
+ /*
+ * Model 320 Decoder
+ * The timecode format is:
+ *
+ * <cr><lf>SQRYYYYDDD+HH:MM:SS.mmLT<cr>
+ *
+ * where:
+ *
+ * S = 'S' -- sync'd in last hour,
+ * '0'-'9' - hours x 10 since last update,
+ * '?' -- not in sync
+ * Q = Number of correlating time-frames, from 0 to 5
+ * R = 'R' -- reception in progress,
+ * 'N' -- Noisy reception,
+ * ' ' -- standby mode
+ * YYYY = year from 1990 to 2089
+ * DDD = current day from 1 to 366
+ * + = '+' if current year is a leap year, else ' '
+ * HH = UTC hour 0 to 23
+ * MM = Minutes of current hour from 0 to 59
+ * SS = Seconds of current minute from 0 to 59
+ * mm = 10's milliseconds of the current second from 00 to 99
+ * L = Leap second pending at end of month
+ * 'I' = insert, 'D'= delete
+ * T = DST <-> STD transition indicators
+ *
+ */
+ if (sscanf(pp->a_lastcode, "%c%1d%c%4d%3d%*c%2d:%2d:%2d.%2d%c",
+ &syncchar, &quality, &modechar, &pp->year, &pp->day,
+ &pp->hour, &pp->minute, &pp->second,
+ &pp->msec,&leapchar) == 10) {
+ pp->msec *= 10; /* M320 returns 10's of msecs */
+ if (leapchar == 'I' ) leapchar = '+';
+ if (leapchar == 'D' ) leapchar = '-';
+ if (syncchar != '?' ) syncchar = ':';
+
+ break;
+ }
+
+ default:
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+
/*
- * Timecode format SQRYYYYDDD+HH:MM:SS.mmLT
+ * Decode quality indicator
+ * For the 325 & 33x series, the lower the number the "better"
+ * the time is. I used the dispersion as the measure of time
+ * quality. The quality indicator in the 320 is the number of
+ * correlating time frames (the more the better)
*/
- sscanf(pp->a_lastcode, "%c%c%c%4d%3d%c%2d:%2d:%2d.%2d",
- &syncchar, &qualchar, &modechar, &pp->year, &pp->day,
- &leapchar,&pp->hour, &pp->minute, &pp->second,&pp->msec);
- pp->msec *= 10; /* M320 returns 10's of msecs */
- qualchar = ' ';
+ /*
+ * The spec sheet for the 325 & 33x series states the clock will
+ * maintain +/-0.002 seconds accuracy when locked to WWVB. This
+ * is indicated by 'Lk' in the quality portion of the incoming
+ * string. When not in lock, a drift of +/-0.015 seconds should
+ * be allowed for.
+ * With the quality indicator decoding scheme above, the 'Lk'
+ * condition will produce a quality value of 0. If the quality
+ * indicator starts with '0' then the second character is the
+ * number of hours since we were last locked. If the first
+ * character is anything other than 'L' or '0' then we have been
+ * out of lock for more than 9 hours so we assume the worst and
+ * force a quality value that selects the 'default' maximum
+ * dispersion. The dispersion values below are what came with the
+ * driver. They're not unreasonable so they've not been changed.
+ */
+
+ if (pp->lencode == LEN33X) {
+ switch (quality) {
+ case 0 :
+ pp->disp=.002;
+ break;
+ case 1 :
+ pp->disp=.02;
+ break;
+ case 2 :
+ pp->disp=.04;
+ break;
+ case 3 :
+ pp->disp=.08;
+ break;
+ default:
+ pp->disp=MAXDISPERSE;
+ break;
+ }
+ } else {
+ switch (quality) {
+ case 5 :
+ pp->disp=.002;
+ break;
+ case 4 :
+ pp->disp=.02;
+ break;
+ case 3 :
+ pp->disp=.04;
+ break;
+ case 2 :
+ pp->disp=.08;
+ break;
+ case 1 :
+ pp->disp=.16;
+ break;
+ default:
+ pp->disp=MAXDISPERSE;
+ break;
+ }
+
+ }
/*
- * Decode synchronization, quality and leap characters. If
+ * Decode synchronization, and leap characters. If
* unsynchronized, set the leap bits accordingly and exit.
* Otherwise, set the leap bits according to the leap character.
- * Once synchronized, the dispersion depends only on the
- * quality character.
*/
- pp->disp = .001;
- pp->leap = LEAP_NOWARNING;
+
+ if (syncchar != ':')
+ pp->leap = LEAP_NOTINSYNC;
+ else if (leapchar == '+')
+ pp->leap = LEAP_ADDSECOND;
+ else if (leapchar == '-')
+ pp->leap = LEAP_DELSECOND;
+ else
+ pp->leap = LEAP_NOWARNING;
/*
* Process the new sample in the median filter and determine the
* timecode timestamp.
*/
- if (!refclock_process(pp))
+ if (!refclock_process(pp)) {
refclock_report(peer, CEVNT_BADTIME);
+ }
+
}
@@ -283,35 +467,30 @@ ulink_poll(
struct peer *peer
)
{
- register struct ulinkunit *up;
- struct refclockproc *pp;
- char pollchar;
-
- pp = peer->procptr;
- up = (struct ulinkunit *)pp->unitptr;
- pollchar = 'T';
- if (write(pp->io.fd, &pollchar, 1) != 1)
- refclock_report(peer, CEVNT_FAULT);
- else
- pp->polls++;
- if (peer->burst > 0)
- return;
- if (pp->coderecv == pp->codeproc) {
- refclock_report(peer, CEVNT_TIMEOUT);
- return;
+ struct refclockproc *pp;
+ char pollchar;
+
+ pp = peer->procptr;
+ pollchar = 'T';
+ if (pp->sloppyclockflag & CLK_FLAG1) {
+ if (write(pp->io.fd, &pollchar, 1) != 1)
+ refclock_report(peer, CEVNT_FAULT);
+ else
+ pp->polls++;
}
- record_clock_stats(&peer->srcadr, pp->a_lastcode);
- refclock_receive(peer);
- peer->burst = NSTAGE;
+ else
+ pp->polls++;
+
+ if (peer->burst > 0)
+ return;
+ if (pp->coderecv == pp->codeproc) {
+ refclock_report(peer, CEVNT_TIMEOUT);
+ return;
+ }
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ refclock_receive(peer);
+ peer->burst = NSTAGE;
- /*
- * 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
diff --git a/contrib/ntp/ntpd/refclock_usno.c b/contrib/ntp/ntpd/refclock_usno.c
index cf404e7..30a1330 100644
--- a/contrib/ntp/ntpd/refclock_usno.c
+++ b/contrib/ntp/ntpd/refclock_usno.c
@@ -9,13 +9,6 @@
#if defined(REFCLOCK) && defined(CLOCK_USNO)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
@@ -23,6 +16,12 @@
#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.
@@ -438,7 +437,7 @@ usno_timeout(
peer->nextdate = current_time + ANSWER;
return;
}
- switch (peer->ttl) {
+ switch (peer->ttlmax) {
/*
* In manual mode the calling program is activated
diff --git a/contrib/ntp/ntpd/refclock_wwv.c b/contrib/ntp/ntpd/refclock_wwv.c
index 52e76e6..b1d05c7 100644
--- a/contrib/ntp/ntpd/refclock_wwv.c
+++ b/contrib/ntp/ntpd/refclock_wwv.c
@@ -7,14 +7,6 @@
#if defined(REFCLOCK) && defined(CLOCK_WWV)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <math.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif /* HAVE_SYS_IOCTL_H */
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
@@ -22,6 +14,13 @@
#include "ntp_stdlib.h"
#include "audio.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <math.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif /* HAVE_SYS_IOCTL_H */
+
#define ICOM 1 /* undefine to suppress ICOM code */
#ifdef ICOM
@@ -64,6 +63,7 @@
/*
* Interface definitions
*/
+#define DEVICE_AUDIO "/dev/audio" /* audio device name */
#define PRECISION (-10) /* precision assumed (about 1 ms) */
#define REFID "NONE" /* reference ID */
#define DESCRIPTION "WWV/H Audio Demodulator/Decoder" /* WRU */
@@ -646,7 +646,7 @@ wwv_start(
/*
* Open audio device
*/
- fd = audio_init();
+ fd = audio_init(DEVICE_AUDIO);
if (fd < 0)
return (0);
#ifdef DEBUG
@@ -739,8 +739,8 @@ wwv_start(
if (debug > 1)
temp = P_TRACE;
#endif
- if (peer->ttl != 0) {
- if (peer->ttl & 0x80)
+ if (peer->ttlmax != 0) {
+ if (peer->ttlmax & 0x80)
up->fd_icom = icom_init("/dev/icom", B1200,
temp);
else
@@ -1443,8 +1443,8 @@ wwv_qrz(
sp->select &= ~JITRNG;
if (abs(sp->jitter) > AWND * MS)
sp->select |= JITRNG;
- sp->sigmax = sqrt(sp->sigmax);
- sp->noise = sqrt(sp->noise);
+ sp->sigmax = SQRT(sp->sigmax);
+ sp->noise = SQRT(sp->noise);
if (up->status & MSYNC) {
/*
@@ -1769,9 +1769,9 @@ wwv_epoch(
cp = &up->mitig[up->achan];
if (up->rphase == 800 * MS) {
sp = &cp->wwv;
- sp->synamp = sqrt(sp->amp);
+ sp->synamp = SQRT(sp->amp);
sp = &cp->wwvh;
- sp->synamp = sqrt(sp->amp);
+ sp->synamp = SQRT(sp->amp);
}
if (up->rsec == 0) {
@@ -1787,7 +1787,7 @@ wwv_epoch(
up->noiamp += (up->irig - up->noiamp) /
(MINAVG << up->avgint);
else
- cp->noiamp += (sqrt(up->irig *
+ cp->noiamp += (SQRT(up->irig *
up->irig + up->qrig * up->qrig) -
cp->noiamp) / 8;
@@ -1817,7 +1817,7 @@ wwv_epoch(
up->datapt += 80;
}
} else {
- up->sigamp = sqrt(up->irig * up->irig +
+ up->sigamp = SQRT(up->irig * up->irig +
up->qrig * up->qrig);
up->datsnr = wwv_snr(up->sigamp,
cp->noiamp);
@@ -2586,7 +2586,8 @@ wwv_newchan(
up->sptr = sp;
up->status |= sp->select & (SELV | SELH);
memcpy((char *)&pp->refid, sp->refid, 4);
- memcpy((char *)&peer->refid, sp->refid, 4);
+ if (peer->stratum <= 1)
+ memcpy((char *)&peer->refid, sp->refid, 4);
wwv_qsy(peer, up->dchan);
}
}
@@ -2614,7 +2615,7 @@ wwv_qsy(
up->mitig[up->achan].gain = up->gain;
#ifdef ICOM
if (up->fd_icom > 0)
- rval = icom_freq(up->fd_icom, peer->ttl & 0x7f,
+ rval = icom_freq(up->fd_icom, peer->ttlmax & 0x7f,
qsy[chan]);
#endif /* ICOM */
up->achan = chan;
@@ -2645,7 +2646,10 @@ wwv_qsy(
* agc audio gain (0-255)
* iden station identifier (station and frequency)
* comp minute sync compare counter
- * errs bit errors in last minute * freq frequency offset (PPM) * avgt averaging time (s) */
+ * errs bit errors in last minute
+ * freq frequency offset (PPM)
+ * avgt averaging time (s)
+ */
static int
timecode(
struct wwvunit *up, /* driver structure pointer */
diff --git a/contrib/ntp/ntpd/refclock_wwvb.c b/contrib/ntp/ntpd/refclock_wwvb.c
index 63d6e0b..0ca9f75 100644
--- a/contrib/ntp/ntpd/refclock_wwvb.c
+++ b/contrib/ntp/ntpd/refclock_wwvb.c
@@ -8,17 +8,15 @@
#if defined(REFCLOCK) && defined(CLOCK_SPECTRACOM)
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <time.h>
-
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_refclock.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
+#include <stdio.h>
+#include <ctype.h>
+
/*
* This driver supports the Spectracom Model 8170 and Netclock/2 WWVB
* Synchronized Clocks and the Netclock/GPS Master Clock. Both the WWVB
@@ -187,9 +185,9 @@ wwvb_start(
* Initialize miscellaneous variables
*/
peer->precision = PRECISION;
- peer->burst = NSTAGE;
pp->clockdesc = DESCRIPTION;
memcpy((char *)&pp->refid, REFID, 4);
+ peer->burst = NSTAGE;
return (1);
}
@@ -233,6 +231,7 @@ wwvb_receive(
char qualchar; /* quality indicator */
char leapchar; /* leap indicator */
char dstchar; /* daylight/standard indicator */
+ char tmpchar; /* trashbin */
/*
* Initialize pointers and read the timecode and timestamp
@@ -287,16 +286,15 @@ wwvb_receive(
* Timecode format 0: "I ddd hh:mm:ss DTZ=nn"
*/
if (sscanf(pp->a_lastcode,
- "%c %3d %2d:%2d:%2d %cTZ=%2d",
+ "%c %3d %2d:%2d:%2d%c%cTZ=%2d",
&syncchar, &pp->day, &pp->hour, &pp->minute,
- &pp->second, &dstchar, &tz) == 7)
+ &pp->second, &tmpchar, &dstchar, &tz) == 8)
break;
case LENWWVB2:
/*
- * Timecode format 2: "IQyy ddd hh:mm:ss.mmm LD"
- */
+ * Timecode format 2: "IQyy ddd hh:mm:ss.mmm LD" */
if (sscanf(pp->a_lastcode,
"%c%c %2d %3d %2d:%2d:%2d.%3d %c",
&syncchar, &qualchar, &pp->year, &pp->day,
OpenPOWER on IntegriCloud